X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2FSystem.Web%2FSystem.Web.UI%2FTemplateControl.jvm.cs;h=28a3f0f79701368095398228423a5c8e96c451a4;hb=879970ea20a49e63a5413adec014754b30a53e03;hp=1b574fc212046a386f9f1fb915b2c2825828dbc4;hpb=75df74a96c33af7a99e16e4281272f1b67334a48;p=mono.git diff --git a/mcs/class/System.Web/System.Web.UI/TemplateControl.jvm.cs b/mcs/class/System.Web/System.Web.UI/TemplateControl.jvm.cs index 1b574fc2120..28a3f0f7970 100644 --- a/mcs/class/System.Web/System.Web.UI/TemplateControl.jvm.cs +++ b/mcs/class/System.Web/System.Web.UI/TemplateControl.jvm.cs @@ -30,123 +30,137 @@ using System.Reflection; using System.Web; using System.IO; using System.Web.J2EE; +using System.Xml; using vmw.common; using System.Web.Util; +using System.Collections.Generic; namespace System.Web.UI { public abstract class TemplateControl : Control, INamingContainer { - static object abortTransaction = new object (); - static object commitTransaction = new object (); - static object error = new object (); - static string [] methodNames = { "Page_Init", + static readonly object abortTransaction = new object (); + static readonly object commitTransaction = new object (); + static readonly object error = new object (); + static readonly string [] methodNames = { "Page_Init", +#if NET_2_0 + "Page_PreInit", + "Page_PreLoad", + "Page_LoadComplete", + "Page_PreRenderComplete", + "Page_SaveStateComplete", + "Page_InitComplete", +#endif "Page_Load", "Page_DataBind", "Page_PreRender", "Page_Disposed", - "Page_Error", "Page_Unload", + "Page_Error", "Page_AbortTransaction", "Page_CommitTransaction" }; + static readonly object [] EventKeys = { + Control.InitEvent, +#if NET_2_0 + Page.PreInitEvent, + Page.PreLoadEvent, + Page.LoadCompleteEvent, + Page.PreRenderCompleteEvent, + Page.SaveStateCompleteEvent, + Page.InitCompleteEvent, +#endif + Control.LoadEvent, + Control.DataBindingEvent, + Control.PreRenderEvent, + Control.DisposedEvent, + Control.UnloadEvent, + error, + abortTransaction, + commitTransaction + }; + + enum LifeCycleEvent + { + Init, +#if NET_2_0 + PreInit, + PreLoad, + LoadComplete, + PreRenderComplete, + SaveStateComplete, + InitComplete, +#endif + Load, + DataBinding, + PreRender, + Disposed, + Unload, + Error, + AbortTransaction, + CommitTransaction + } + const BindingFlags bflags = BindingFlags.Public | - BindingFlags.NonPublic | - BindingFlags.Instance; + BindingFlags.NonPublic | + BindingFlags.Instance; - private string _templateSourceDir; - private static string hashTableMutex = "lock"; //used to sync access ResourceHash property - private byte[] GetResourceBytes(Type type) { - Hashtable table = (Hashtable)AppDomain.CurrentDomain.GetData("TemplateControl.RES_BYTES"); + byte [] GetResourceBytes (Type type) + { + Hashtable table = (Hashtable) AppDomain.CurrentDomain.GetData ("TemplateControl.RES_BYTES"); if (table == null) { return null; } - return (byte[])table[type]; + return (byte []) table [type]; } - private void SetResourceBytes(Type type, byte[] bytes) { - Hashtable table = (Hashtable)AppDomain.CurrentDomain.GetData("TemplateControl.RES_BYTES"); + void SetResourceBytes (Type type, byte [] bytes) + { + Hashtable table = (Hashtable) AppDomain.CurrentDomain.GetData ("TemplateControl.RES_BYTES"); if (table == null) { - table = new Hashtable(); - AppDomain.CurrentDomain.SetData("TemplateControl.RES_BYTES" , table); + table = new Hashtable (); + AppDomain.CurrentDomain.SetData ("TemplateControl.RES_BYTES", table); } - table[type] = bytes; + table [type] = bytes; return; } - private Hashtable ResourceHash { - get { - Hashtable table = (Hashtable)AppDomain.CurrentDomain.GetData("TemplateControl.RES_STRING"); + Hashtable ResourceHash + { + get + { + Hashtable table = (Hashtable) AppDomain.CurrentDomain.GetData ("TemplateControl.RES_STRING"); if (table == null) { - table = new Hashtable(); - AppDomain.CurrentDomain.SetData("TemplateControl.RES_STRING" , table); + table = new Hashtable (); + AppDomain.CurrentDomain.SetData ("TemplateControl.RES_STRING", table); } return table; } + set + { + AppDomain.CurrentDomain.SetData ("TemplateControl.RES_STRING", value); + } } - private string CachedString(string filename , int offset, int size) + string CachedString (Type type, int offset, int size) { - string key = filename + offset + size; - lock (hashTableMutex) - { - string strObj = (string)ResourceHash[key]; - if (strObj == null) - { - - char[] tmp = System.Text.Encoding.UTF8.GetChars(GetResourceBytes(this.GetType()) , offset , size); - strObj = new string(tmp); - ResourceHash.Add(key, strObj); - } - - return strObj; + CacheKey key = new CacheKey (type, offset, size); + + string strObj = (string) ResourceHash [key]; + if (strObj == null) { + char [] tmp = System.Text.Encoding.UTF8.GetChars (GetResourceBytes (this.GetType ()), offset, size); + strObj = new string (tmp); + + Hashtable tmpResourceHash = (Hashtable) ResourceHash.Clone (); + tmpResourceHash.Add (key, strObj); + ResourceHash = tmpResourceHash; } - + return strObj; } - public virtual string TemplateSourceDirectory_Private + public virtual string TemplateSourceDirectory_Private { get { return null; } } - [MonoTODO] - // This shouldnt be there, Page.TemplateSourceDirectory must know to get - // the right directory of the control. - public override string TemplateSourceDirectory - { - get { -#if NET_2_0 - if (this is MasterPage) - // because MasterPage also has implementation of this property, - // but not always gets the right directory, in case where master page - // is in the root of webapp and the page that uses it is in sub folder. - return base.TemplateSourceDirectory; -#endif - int location = 0; - if (_templateSourceDir == null) - { - string tempSrcDir = AppRelativeTemplateSourceDirectory; - if (tempSrcDir == null && Parent != null) - tempSrcDir = Parent.TemplateSourceDirectory; - if (tempSrcDir != null && tempSrcDir.Length > 1) - { - location = tempSrcDir.IndexOf('/',1); - if (location!= -1) - tempSrcDir = tempSrcDir.Substring(location+1); - else - tempSrcDir = string.Empty; - } - string answer = HttpRuntime.AppDomainAppVirtualPath; - if(tempSrcDir == null) - tempSrcDir = ""; - if (tempSrcDir.StartsWith("/") || tempSrcDir.Length == 0) - _templateSourceDir = answer + tempSrcDir; - else - _templateSourceDir = answer + "/"+ tempSrcDir; - } - return _templateSourceDir; - } - } - - #region Constructor protected TemplateControl () { @@ -157,13 +171,15 @@ namespace System.Web.UI { #region Properties [EditorBrowsable (EditorBrowsableState.Never)] - protected virtual int AutoHandlers { + protected virtual int AutoHandlers + { get { return 0; } set { } } [EditorBrowsable (EditorBrowsableState.Never)] - protected virtual bool SupportAutoEvents { + protected virtual bool SupportAutoEvents + { get { return true; } } @@ -177,57 +193,172 @@ namespace System.Web.UI { [MonoTODO] protected LiteralControl CreateResourceBasedLiteralControl (int offset, - int size, - bool fAsciiOnly) + int size, + bool fAsciiOnly) { - string str = CachedString(this.GetType().FullName, offset, size); - return new LiteralControl(str); + string str = CachedString (this.GetType (), offset, size); + return new LiteralControl (str); } - internal void WireupAutomaticEvents () + sealed class EventMethodMap { - if (!SupportAutoEvents || !AutoEventWireup) - return; + public EventMethodMap (LifeCycleEvent EventKeyIndex, MethodInfo Method, bool NoParameters) + { + this.EventKeyIndex = EventKeyIndex; + this.Method = Method; + this.NoParameters = NoParameters; + } - Type type = GetType (); - foreach (string methodName in methodNames) { - MethodInfo method = type.GetMethod (methodName, bflags); - if (method == null) - continue; + public readonly LifeCycleEvent EventKeyIndex; + public readonly MethodInfo Method; + public readonly bool NoParameters; + } -#if ONLY_1_1 - if (method.DeclaringType != type) { - if (!method.IsPublic && !method.IsFamilyOrAssembly && - !method.IsFamilyAndAssembly && !method.IsFamily) + // This hashtable cashes methods and events found in user code + const string eventMethodCacheKey = "eventMethodCacheKey"; + static Hashtable EventMethodCache + { + get { return (Hashtable) AppDomain.CurrentDomain.GetData (eventMethodCacheKey); } + set { AppDomain.CurrentDomain.SetData (eventMethodCacheKey, value); } + } + + internal void WireupAutomaticEvents () + { + Type cacheKey = this.GetType (); + Hashtable eventMethodCache = EventMethodCache; + ArrayList eventMethodList = eventMethodCache == null ? null : (ArrayList) eventMethodCache [cacheKey]; + + if (eventMethodList == null) { + eventMethodList = new ArrayList (); + + if (!SupportAutoEvents || !AutoEventWireup) + return; + + Type thisType = typeof (TemplateControl); + Type voidType = typeof (void); + Type [] DefaultParams = new Type [] { + typeof (object), + typeof (EventArgs) }; + + LifeCycleEvent[] _pageEvents = new LifeCycleEvent[] { + LifeCycleEvent.PreInit, + LifeCycleEvent.PreLoad, + LifeCycleEvent.LoadComplete, + LifeCycleEvent.PreRenderComplete, + LifeCycleEvent.SaveStateComplete, + LifeCycleEvent.InitComplete + }; + List pageEvents = new List(_pageEvents); + + bool isPage = Page.GetType().IsAssignableFrom(GetType()); + + for (int i = 0; i < methodNames.Length; i++) { + + // Don't look for page-only events in non-page controls. + if (!isPage && pageEvents.Contains((LifeCycleEvent)i)) + continue; + + string methodName = methodNames [i]; + MethodInfo method; + bool noParams = false; + Type type = GetType (); + do { + method = type.GetMethod (methodName, bflags, null, DefaultParams, null); + if (method != null) { + break; + } + + type = type.BaseType; + } + while (type != thisType); + + if (method == null) { + type = GetType (); + do { + method = type.GetMethod (methodName, bflags, null, Type.EmptyTypes, null); + if (method != null) { + noParams = true; + break; + } + + type = type.BaseType; + } + while (type != thisType); + + if (method == null) + continue; + } + if (method.ReturnType != voidType) continue; + + eventMethodList.Add (new EventMethodMap ((LifeCycleEvent) i, method, noParams)); } -#endif + // We copy to not lock - if (method.ReturnType != typeof (void)) - continue; + Hashtable newEventMethodCache = eventMethodCache == null ? new Hashtable () : (Hashtable) eventMethodCache.Clone (); + newEventMethodCache [cacheKey] = eventMethodList; + EventMethodCache = newEventMethodCache; + } - ParameterInfo [] parms = method.GetParameters (); - int length = parms.Length; - bool noParams = (length == 0); - if (!noParams && (length != 2 || - parms [0].ParameterType != typeof (object) || - parms [1].ParameterType != typeof (EventArgs))) - continue; + foreach (EventMethodMap eventMethod in eventMethodList) { + EventHandler handler = eventMethod.NoParameters ? + new NoParamsInvoker (this, eventMethod.Method).FakeDelegate : + (EventHandler)Delegate.CreateDelegate (typeof (EventHandler), this, eventMethod.Method); + + object eventKey = EventKeys [(int) eventMethod.EventKeyIndex]; - int pos = methodName.IndexOf ("_"); - string eventName = methodName.Substring (pos + 1); - EventInfo evt = type.GetEvent (eventName); - if (evt == null) { - /* This should never happen */ + Delegate existing = Events [eventKey]; + if (existing != null && handler.Equals(existing)) continue; - } - if (noParams) { - NoParamsInvoker npi = new NoParamsInvoker (this, methodName); - evt.AddEventHandler (this, npi.FakeDelegate); - } else { - evt.AddEventHandler (this, Delegate.CreateDelegate ( - typeof (EventHandler), this, methodName)); + switch (eventMethod.EventKeyIndex) { + case LifeCycleEvent.Init: + Init += handler; + break; +#if NET_2_0 + case LifeCycleEvent.PreInit: + ((Page)this).PreInit += handler; + break; + case LifeCycleEvent.PreLoad: + ((Page) this).PreLoad += handler; + break; + case LifeCycleEvent.LoadComplete: + ((Page) this).LoadComplete += handler; + break; + case LifeCycleEvent.PreRenderComplete: + ((Page) this).PreRenderComplete += handler; + break; + case LifeCycleEvent.SaveStateComplete: + ((Page) this).SaveStateComplete += handler; + break; + case LifeCycleEvent.InitComplete: + ((Page) this).InitComplete += handler; + break; +#endif + case LifeCycleEvent.Load: + Load += handler; + break; + case LifeCycleEvent.DataBinding: + DataBinding += handler; + break; + case LifeCycleEvent.PreRender: + PreRender += handler; + break; + case LifeCycleEvent.Disposed: + Disposed += handler; + break; + case LifeCycleEvent.Unload: + Unload += handler; + break; + case LifeCycleEvent.Error: + Error += handler; + break; + case LifeCycleEvent.AbortTransaction: + AbortTransaction += handler; + break; + case LifeCycleEvent.CommitTransaction: + CommitTransaction += handler; + break; } } } @@ -243,12 +374,35 @@ namespace System.Web.UI { throw new ArgumentNullException ("virtualPath"); string vpath = UrlUtils.Combine (TemplateSourceDirectory, virtualPath); - return PageMapper.GetObjectType(vpath); + return PageMapper.GetObjectType (Context, vpath); } public Control LoadControl (string virtualPath) { - object control = Activator.CreateInstance (GetTypeFromControlPath (virtualPath)); +#if NET_2_0 + if (virtualPath == null) + throw new ArgumentNullException ("virtualPath"); +#else + if (virtualPath == null) + throw new HttpException ("virtualPath is null"); +#endif + Type type = GetTypeFromControlPath (virtualPath); + return LoadControl (type, null); + } + + public Control LoadControl (Type type, object [] parameters) + { + object [] attrs = type.GetCustomAttributes (typeof (PartialCachingAttribute), true); + if (attrs != null && attrs.Length == 1) { + PartialCachingAttribute attr = (PartialCachingAttribute) attrs [0]; + PartialCachingControl ctrl = new PartialCachingControl (type, parameters); + ctrl.VaryByParams = attr.VaryByParams; + ctrl.VaryByControls = attr.VaryByControls; + ctrl.VaryByCustom = attr.VaryByCustom; + return ctrl; + } + + object control = Activator.CreateInstance (type, parameters); if (control is UserControl) ((UserControl) control).InitializeAsUserControl (Page); @@ -282,10 +436,16 @@ namespace System.Web.UI { eh (this, e); } - [MonoTODO] + [MonoNotSupported ("Not supported")] public Control ParseControl (string content) { - return null; + throw new NotSupportedException (); + } + + [MonoLimitation ("Always returns false")] + public virtual bool TestDeviceFilter (string filterName) + { + return false; } [MonoTODO] @@ -298,7 +458,7 @@ namespace System.Web.UI { [MonoTODO ("is this correct?")] public Object ReadStringResource () { - return this.GetType(); + return this.GetType (); } #endif [MonoTODO] @@ -306,48 +466,48 @@ namespace System.Web.UI { protected void SetStringResourcePointer (object stringResourcePointer, int maxResourceOffset) { - if ( GetResourceBytes(this.GetType()) != null) + if (GetResourceBytes (this.GetType ()) != null) return; - java.lang.Class c = vmw.common.TypeUtils.ToClass(stringResourcePointer); - java.lang.ClassLoader contextClassLoader = c.getClassLoader(); - string assemblyName = "dll.ghres"; - - java.io.InputStream inputStream = contextClassLoader.getResourceAsStream(assemblyName); + java.lang.Class c = vmw.common.TypeUtils.ToClass (stringResourcePointer); + java.lang.ClassLoader contextClassLoader = c.getClassLoader (); + + //TODO:move this code to page mapper + string assemblyName = PageMapper.GetAssemblyResource (Context, VirtualPathUtility.ToAbsolute (AppRelativeVirtualPath)); + if (assemblyName == null) + throw new HttpException (404, "The requested resource (" + this.AppRelativeVirtualPath + ") is not available."); + + java.io.InputStream inputStream = contextClassLoader.getResourceAsStream (assemblyName); + System.IO.Stream strim = null; if (inputStream == null) { - string descPath = String.Join("/", new string[]{"assemblies", this.GetType().Assembly.GetName().Name, assemblyName}); - try - { - strim = new StreamReader(HttpContext.Current.Request.MapPath("/" + descPath)).BaseStream; + string descPath = String.Join ("/", new string [] { "assemblies", this.GetType ().Assembly.GetName ().Name, assemblyName }); + try { + strim = new StreamReader (HttpContext.Current.Request.MapPath ("/" + descPath)).BaseStream; } - catch (Exception ex) - { - throw new System.IO.IOException("couldn't open resource file:" + assemblyName, ex); + catch (Exception ex) { + throw new System.IO.IOException ("couldn't open resource file:" + assemblyName, ex); } if (strim == null) - throw new System.IO.IOException("couldn't open resource file:" + assemblyName); + throw new System.IO.IOException ("couldn't open resource file:" + assemblyName); } - try - { + try { if (strim == null) - strim = (System.IO.Stream)vmw.common.IOUtils.getStream(inputStream); - int capacity = (int)strim.Length; - byte[] resourceBytes = new byte[capacity]; - strim.Read(resourceBytes,0,capacity); - SetResourceBytes(this.GetType(), resourceBytes); + strim = (System.IO.Stream) vmw.common.IOUtils.getStream (inputStream); + int capacity = (int) strim.Length; + byte [] resourceBytes = new byte [capacity]; + strim.Read (resourceBytes, 0, capacity); + SetResourceBytes (this.GetType (), resourceBytes); } - catch(Exception e) - { - throw new HttpException("problem with dll.ghres file", e); + catch (Exception e) { + throw new HttpException ("problem with dll.ghres file", e); } - finally - { - if(strim != null) - strim.Close(); - if (inputStream != null ) - inputStream.close(); + finally { + if (strim != null) + strim.Close (); + if (inputStream != null) + inputStream.close (); } } @@ -356,8 +516,8 @@ namespace System.Web.UI { protected void WriteUTF8ResourceString (HtmlTextWriter output, int offset, int size, bool fAsciiOnly) { - string str = CachedString(this.GetType().FullName, offset, size); - output.Write(str); + string str = CachedString (this.GetType (), offset, size); + output.Write (str); } #endregion @@ -365,19 +525,22 @@ namespace System.Web.UI { #region Events [WebSysDescription ("Raised when the user aborts a transaction.")] - public event EventHandler AbortTransaction { + public event EventHandler AbortTransaction + { add { Events.AddHandler (abortTransaction, value); } remove { Events.RemoveHandler (abortTransaction, value); } } [WebSysDescription ("Raised when the user initiates a transaction.")] - public event EventHandler CommitTransaction { + public event EventHandler CommitTransaction + { add { Events.AddHandler (commitTransaction, value); } remove { Events.RemoveHandler (commitTransaction, value); } } [WebSysDescription ("Raised when an exception occurs that cannot be handled.")] - public event EventHandler Error { + public event EventHandler Error + { add { Events.AddHandler (error, value); } remove { Events.RemoveHandler (error, value); } } @@ -401,50 +564,135 @@ namespace System.Web.UI { } } + sealed class CacheKey + { + readonly Type _type; + readonly int _offset; + readonly int _size; + + public CacheKey (Type type, int offset, int size) + { + _type = type; + _offset = offset; + _size = size; + } + + public override int GetHashCode () + { + return _type.GetHashCode () ^ _offset ^ _size; + } + + public override bool Equals (object obj) + { + if (obj == null || !(obj is CacheKey)) + return false; + + CacheKey key = (CacheKey) obj; + return key._type == _type && key._offset == _offset && key._size == _size; + } + } + #if NET_2_0 - string _appRelativeVirtualPath = null; + string _appRelativeVirtualPath = null; - public string AppRelativeVirtualPath - { - get { return _appRelativeVirtualPath; } - set + public string AppRelativeVirtualPath { - if (value == null) - throw new ArgumentNullException ("value"); - if (!UrlUtils.IsRooted (value) && !(value.Length > 0 && value[0] == '~')) - throw new ArgumentException ("The path that is set is not rooted"); - _appRelativeVirtualPath = value; + get { return _appRelativeVirtualPath; } + set + { + if (value == null) + throw new ArgumentNullException ("value"); + if (!UrlUtils.IsRooted (value) && !(value.Length > 0 && value [0] == '~')) + throw new ArgumentException ("The path that is set is not rooted"); + _appRelativeVirtualPath = value; + + int lastSlash = _appRelativeVirtualPath.LastIndexOf ('/'); + AppRelativeTemplateSourceDirectory = (lastSlash > 0) ? _appRelativeVirtualPath.Substring (0, lastSlash + 1) : "~/"; + } + } - int lastSlash = _appRelativeVirtualPath.LastIndexOf ('/'); - AppRelativeTemplateSourceDirectory = (lastSlash > 0) ? _appRelativeVirtualPath.Substring (0, lastSlash + 1) : "~/"; + internal override TemplateControl TemplateControlInternal { + get { return this; } } - } - protected object Eval (string expression) - { - return DataBinder.Eval (Page.GetDataItem (), expression); - } + protected internal object Eval (string expression) + { + return DataBinder.Eval (Page.GetDataItem (), expression); + } - protected string Eval (string expression, string format) - { - return DataBinder.Eval (Page.GetDataItem (), expression, format); - } + protected internal string Eval (string expression, string format) + { + return DataBinder.Eval (Page.GetDataItem (), expression, format); + } - protected object XPath (string xpathexpression) - { - return XPathBinder.Eval (Page.GetDataItem (), xpathexpression); - } + protected internal object XPath (string xpathexpression) + { + return XPathBinder.Eval (Page.GetDataItem (), xpathexpression); + } - protected string XPath (string xpathexpression, string format) - { - return XPathBinder.Eval (Page.GetDataItem (), xpathexpression, format); - } + protected internal object XPath (string xpathexpression, IXmlNamespaceResolver resolver) + { + return XPathBinder.Eval (Page.GetDataItem (), xpathexpression, null, resolver); + } + + protected internal string XPath (string xpathexpression, string format) + { + return XPathBinder.Eval (Page.GetDataItem (), xpathexpression, format); + } + + protected internal string XPath (string xpathexpression, string format, IXmlNamespaceResolver resolver) + { + return XPathBinder.Eval (Page.GetDataItem (), xpathexpression, format, resolver); + } + + protected internal IEnumerable XPathSelect (string xpathexpression) + { + return XPathBinder.Select (Page.GetDataItem (), xpathexpression); + } + + protected internal IEnumerable XPathSelect (string xpathexpression, IXmlNamespaceResolver resolver) + { + return XPathBinder.Select (Page.GetDataItem (), xpathexpression, resolver); + } + + protected object GetGlobalResourceObject (string className, string resourceKey) + { + return HttpContext.GetGlobalResourceObject (className, resourceKey); + } + + protected object GetGlobalResourceObject (string className, string resourceKey, Type objType, string propName) + { + return ConvertResource (GetGlobalResourceObject (className, resourceKey), objType, propName); + } + + protected Object GetLocalResourceObject (string resourceKey) + { + return HttpContext.GetLocalResourceObject (Context.Request.Path, resourceKey); + } + + protected Object GetLocalResourceObject (string resourceKey, Type objType, string propName) + { + return ConvertResource (GetLocalResourceObject (resourceKey), objType, propName); + } + + static Object ConvertResource (Object resource, Type objType, string propName) { + if (resource == null) + return resource; + + PropertyDescriptor pdesc = TypeDescriptor.GetProperties (objType) [propName]; + if (pdesc == null) + return resource; + + TypeConverter converter = pdesc.Converter; + if (converter == null) + return resource; + + return resource is string ? + converter.ConvertFromInvariantString ((string) resource) : + converter.ConvertFrom (resource); + } - protected IEnumerable XPathSelect (string xpathexpression) - { - return XPathBinder.Select (Page.GetDataItem (), xpathexpression); - } #endif }