3c1f479b9d
Former-commit-id: 806294f5ded97629b74c85c09952f2a74fe182d9
396 lines
11 KiB
C#
396 lines
11 KiB
C#
//
|
|
// System.Web.UI.WebControls.XmlDataSource
|
|
//
|
|
// Authors:
|
|
// Ben Maurer (bmaurer@users.sourceforge.net)
|
|
// Chris Toshok (toshok@ximian.com)
|
|
//
|
|
// (C) 2003 Ben Maurer
|
|
// (C) 2005 Novell, Inc (http://www.novell.com)
|
|
//
|
|
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining
|
|
// a copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
|
// permit persons to whom the Software is furnished to do so, subject to
|
|
// the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be
|
|
// included in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
//
|
|
|
|
using System.Collections;
|
|
using System.Collections.Specialized;
|
|
using System.Drawing;
|
|
using System.Text;
|
|
using System.Xml;
|
|
using System.Xml.Xsl;
|
|
using System.ComponentModel;
|
|
using System.IO;
|
|
using System.Web.Caching;
|
|
using System.Security.Permissions;
|
|
|
|
namespace System.Web.UI.WebControls {
|
|
|
|
// CAS
|
|
[AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
|
|
[AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
|
|
// attributes
|
|
[DesignerAttribute ("System.Web.UI.Design.WebControls.XmlDataSourceDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
|
|
[DefaultProperty ("DataFile")]
|
|
[DefaultEvent ("Transforming")]
|
|
[ParseChildren (true)]
|
|
[PersistChildren (false)]
|
|
[WebSysDescription ("Connect to an XML file.")]
|
|
// [WebSysDisplayName ("XML file")]
|
|
[ToolboxBitmap ("")]
|
|
public class XmlDataSource : HierarchicalDataSourceControl, IDataSource, IListSource {
|
|
|
|
string _data = string.Empty;
|
|
string _transform = string.Empty;
|
|
string _xpath = string.Empty;
|
|
string _dataFile = string.Empty;
|
|
string _transformFile = string.Empty;
|
|
string _cacheKeyDependency = string.Empty;
|
|
bool _enableCaching = true;
|
|
int _cacheDuration = 0;
|
|
bool _documentNeedsUpdate;
|
|
|
|
DataSourceCacheExpiry _cacheExpirationPolicy = DataSourceCacheExpiry.Absolute;
|
|
static readonly string [] emptyNames = new string [] { "DefaultView" };
|
|
|
|
event EventHandler IDataSource.DataSourceChanged {
|
|
add { ((IHierarchicalDataSource)this).DataSourceChanged += value; }
|
|
remove { ((IHierarchicalDataSource)this).DataSourceChanged -= value; }
|
|
}
|
|
|
|
static object EventTransforming = new object ();
|
|
public event EventHandler Transforming {
|
|
add { Events.AddHandler (EventTransforming, value); }
|
|
remove { Events.RemoveHandler (EventTransforming, value); }
|
|
}
|
|
|
|
protected virtual void OnTransforming (EventArgs e)
|
|
{
|
|
EventHandler eh = Events [EventTransforming] as EventHandler;
|
|
if (eh != null)
|
|
eh (this, e);
|
|
}
|
|
|
|
XmlDocument xmlDocument;
|
|
public XmlDocument GetXmlDocument ()
|
|
{
|
|
if (_documentNeedsUpdate)
|
|
UpdateXml ();
|
|
|
|
if (xmlDocument == null && EnableCaching)
|
|
xmlDocument = GetXmlDocumentFromCache ();
|
|
|
|
if (xmlDocument == null) {
|
|
xmlDocument = LoadXmlDocument ();
|
|
UpdateCache ();
|
|
}
|
|
|
|
return xmlDocument;
|
|
}
|
|
|
|
[MonoTODO ("schema")]
|
|
XmlDocument LoadXmlDocument ()
|
|
{
|
|
XmlDocument document = LoadFileOrData (DataFile, Data);
|
|
if (String.IsNullOrEmpty (TransformFile) && String.IsNullOrEmpty (Transform))
|
|
return document;
|
|
|
|
XslTransform xslTransform = new XslTransform ();
|
|
XmlDocument xsl = LoadFileOrData (TransformFile, Transform);
|
|
xslTransform.Load (xsl);
|
|
|
|
OnTransforming (EventArgs.Empty);
|
|
|
|
XmlDocument transofrResult = new XmlDocument ();
|
|
transofrResult.Load (xslTransform.Transform (document, TransformArgumentList));
|
|
|
|
return transofrResult;
|
|
}
|
|
|
|
XmlDocument LoadFileOrData (string filename, string data)
|
|
{
|
|
XmlDocument document = new XmlDocument ();
|
|
if (!String.IsNullOrEmpty (filename)) {
|
|
Uri uri;
|
|
if (Uri.TryCreate (filename, UriKind.Absolute, out uri))
|
|
document.Load (filename);
|
|
else
|
|
document.Load (MapPathSecure (filename));
|
|
} else
|
|
if (!String.IsNullOrEmpty (data))
|
|
document.LoadXml (data);
|
|
return document;
|
|
}
|
|
|
|
XmlDocument GetXmlDocumentFromCache ()
|
|
{
|
|
if (DataCache != null)
|
|
return (XmlDocument) DataCache [GetDataKey ()];
|
|
|
|
return null;
|
|
}
|
|
|
|
string GetDataKey ()
|
|
{
|
|
if (String.IsNullOrEmpty (DataFile) && !String.IsNullOrEmpty (Data)) {
|
|
string key = CacheKeyContext;
|
|
if (!String.IsNullOrEmpty (key))
|
|
return key;
|
|
}
|
|
Page page = Page;
|
|
string p = page != null ? page.ToString () : "NullPage";
|
|
|
|
return TemplateSourceDirectory + "_" + p + "_" + ID;
|
|
}
|
|
|
|
Cache DataCache
|
|
{
|
|
get
|
|
{
|
|
if (HttpContext.Current != null)
|
|
return HttpContext.Current.InternalCache;
|
|
|
|
return null;
|
|
}
|
|
}
|
|
|
|
void UpdateCache ()
|
|
{
|
|
if (!EnableCaching)
|
|
return;
|
|
|
|
if (DataCache == null)
|
|
return;
|
|
|
|
string dataKey = GetDataKey ();
|
|
if (DataCache [dataKey] != null)
|
|
DataCache.Remove (dataKey);
|
|
|
|
DateTime absoluteExpiration = Cache.NoAbsoluteExpiration;
|
|
TimeSpan slidindExpiraion = Cache.NoSlidingExpiration;
|
|
|
|
if (CacheDuration > 0) {
|
|
if (CacheExpirationPolicy == DataSourceCacheExpiry.Absolute)
|
|
absoluteExpiration = DateTime.Now.AddSeconds (CacheDuration);
|
|
else
|
|
slidindExpiraion = new TimeSpan (CacheDuration * 10000L);
|
|
}
|
|
|
|
CacheDependency dependency = null;
|
|
if (CacheKeyDependency.Length > 0)
|
|
dependency = new CacheDependency (new string [] { }, new string [] { CacheKeyDependency });
|
|
else
|
|
dependency = new CacheDependency (new string [] { }, new string [] { });
|
|
|
|
DataCache.Add (dataKey, xmlDocument, dependency,
|
|
absoluteExpiration, slidindExpiraion, CacheItemPriority.Default, null);
|
|
}
|
|
|
|
// If datafile changed, then DO NOT USE the cached data, but update it.
|
|
void UpdateXml()
|
|
{
|
|
xmlDocument = LoadXmlDocument ();
|
|
UpdateCache ();
|
|
_documentNeedsUpdate = false;
|
|
}
|
|
|
|
public void Save ()
|
|
{
|
|
if (!CanBeSaved)
|
|
throw new InvalidOperationException ();
|
|
|
|
if (xmlDocument != null)
|
|
xmlDocument.Save (MapPathSecure (DataFile));
|
|
}
|
|
|
|
bool CanBeSaved {
|
|
get {
|
|
return Transform == String.Empty && TransformFile == String.Empty && DataFile != String.Empty;
|
|
}
|
|
}
|
|
|
|
protected override HierarchicalDataSourceView GetHierarchicalView (string viewPath)
|
|
{
|
|
XmlNode doc = this.GetXmlDocument ();
|
|
XmlNodeList ret = null;
|
|
|
|
if (!String.IsNullOrEmpty (viewPath)) {
|
|
XmlNode n = doc.SelectSingleNode (viewPath);
|
|
if (n != null)
|
|
ret = n.ChildNodes;
|
|
} else if (!String.IsNullOrEmpty (XPath)) {
|
|
ret = doc.SelectNodes (XPath);
|
|
} else {
|
|
ret = doc.ChildNodes;
|
|
}
|
|
|
|
return new XmlHierarchicalDataSourceView (ret);
|
|
}
|
|
|
|
IList IListSource.GetList ()
|
|
{
|
|
return ListSourceHelper.GetList (this);
|
|
}
|
|
|
|
bool IListSource.ContainsListCollection {
|
|
get { return ListSourceHelper.ContainsListCollection (this); }
|
|
}
|
|
|
|
DataSourceView IDataSource.GetView (string viewName)
|
|
{
|
|
if (String.IsNullOrEmpty (viewName))
|
|
viewName = "DefaultView";
|
|
|
|
return new XmlDataSourceView (this, viewName);
|
|
}
|
|
|
|
ICollection IDataSource.GetViewNames ()
|
|
{
|
|
return emptyNames;
|
|
}
|
|
|
|
[DefaultValue (0)]
|
|
[TypeConverter (typeof(DataSourceCacheDurationConverter))]
|
|
public virtual int CacheDuration {
|
|
get {
|
|
return _cacheDuration;
|
|
}
|
|
set {
|
|
_cacheDuration = value;
|
|
}
|
|
}
|
|
|
|
[DefaultValue (DataSourceCacheExpiry.Absolute)]
|
|
public virtual DataSourceCacheExpiry CacheExpirationPolicy {
|
|
get {
|
|
return _cacheExpirationPolicy;
|
|
}
|
|
set {
|
|
_cacheExpirationPolicy = value;
|
|
}
|
|
}
|
|
|
|
[DefaultValue ("")]
|
|
public virtual string CacheKeyDependency {
|
|
get {
|
|
return _cacheKeyDependency;
|
|
}
|
|
set {
|
|
_cacheKeyDependency = value;
|
|
}
|
|
}
|
|
|
|
[DefaultValue (true)]
|
|
public virtual bool EnableCaching {
|
|
get {
|
|
return _enableCaching;
|
|
}
|
|
set {
|
|
_enableCaching = value;
|
|
}
|
|
}
|
|
|
|
[DefaultValue ("")]
|
|
[PersistenceMode (PersistenceMode.InnerProperty)]
|
|
[WebSysDescription ("Inline XML data.")]
|
|
[WebCategory ("Data")]
|
|
[EditorAttribute ("System.ComponentModel.Design.MultilineStringEditor," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
|
|
[TypeConverter (typeof(MultilineStringConverter))]
|
|
public virtual string Data {
|
|
get { return _data; }
|
|
set {
|
|
if (_data != value) {
|
|
_data = value;
|
|
_documentNeedsUpdate = true;
|
|
OnDataSourceChanged(EventArgs.Empty);
|
|
}
|
|
}
|
|
}
|
|
|
|
[DefaultValueAttribute ("")]
|
|
[EditorAttribute ("System.Web.UI.Design.XmlDataFileEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
|
|
[MonoLimitation ("Absolute path to the file system is not supported; use a relative URI instead.")]
|
|
public virtual string DataFile {
|
|
get { return _dataFile; }
|
|
set {
|
|
if (_dataFile != value) {
|
|
_dataFile = value;
|
|
_documentNeedsUpdate = true;
|
|
OnDataSourceChanged(EventArgs.Empty);
|
|
}
|
|
}
|
|
}
|
|
|
|
XsltArgumentList transformArgumentList;
|
|
|
|
[BrowsableAttribute (false)]
|
|
public virtual XsltArgumentList TransformArgumentList {
|
|
get { return transformArgumentList; }
|
|
set { transformArgumentList = value; }
|
|
}
|
|
|
|
[PersistenceModeAttribute (PersistenceMode.InnerProperty)]
|
|
[EditorAttribute ("System.ComponentModel.Design.MultilineStringEditor," + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
|
|
[DefaultValueAttribute ("")]
|
|
[TypeConverterAttribute (typeof(MultilineStringConverter))]
|
|
public virtual string Transform {
|
|
get { return _transform; }
|
|
set {
|
|
if (_transform != value) {
|
|
_transform = value;
|
|
_documentNeedsUpdate = true;
|
|
OnDataSourceChanged(EventArgs.Empty);
|
|
}
|
|
}
|
|
}
|
|
|
|
[EditorAttribute ("System.Web.UI.Design.XslTransformFileEditor, " + Consts.AssemblySystem_Design, "System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)]
|
|
[DefaultValueAttribute ("")]
|
|
[MonoLimitation ("Absolute path to the file system is not supported; use a relative URI instead.")]
|
|
public virtual string TransformFile {
|
|
get { return _transformFile; }
|
|
set {
|
|
if (_transformFile != value) {
|
|
_transformFile = value;
|
|
_documentNeedsUpdate = true;
|
|
OnDataSourceChanged(EventArgs.Empty);
|
|
}
|
|
}
|
|
}
|
|
|
|
[DefaultValueAttribute ("")]
|
|
public virtual string XPath {
|
|
get { return _xpath; }
|
|
set {
|
|
if (_xpath != value) {
|
|
_xpath = value;
|
|
OnDataSourceChanged(EventArgs.Empty);
|
|
}
|
|
}
|
|
}
|
|
[DefaultValue ("")]
|
|
public virtual string CacheKeyContext {
|
|
get { return ViewState.GetString ("CacheKeyContext", String.Empty); }
|
|
set { ViewState ["CacheKeyContext"] = value; }
|
|
}
|
|
}
|
|
}
|
|
|