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_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;
- static readonly Type [] NoParams = new Type [0];
- private static string hashTableMutex = "lock"; //used to sync access ResourceHash property
- private byte [] GetResourceBytes (Type type)
+ byte [] GetResourceBytes (Type type)
{
Hashtable table = (Hashtable) AppDomain.CurrentDomain.GetData ("TemplateControl.RES_BYTES");
if (table == null) {
}
return (byte []) table [type];
}
- private void SetResourceBytes (Type type, byte [] bytes)
+ void SetResourceBytes (Type type, byte [] bytes)
{
Hashtable table = (Hashtable) AppDomain.CurrentDomain.GetData ("TemplateControl.RES_BYTES");
if (table == null) {
return;
}
- private Hashtable ResourceHash
+ Hashtable ResourceHash
{
get
{
}
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) {
+ CacheKey key = new CacheKey (type, offset, size);
- char [] tmp = System.Text.Encoding.UTF8.GetChars (GetResourceBytes (this.GetType ()), offset, size);
- strObj = new string (tmp);
- ResourceHash.Add (key, strObj);
- }
+ string strObj = (string) ResourceHash [key];
+ if (strObj == null) {
+ char [] tmp = System.Text.Encoding.UTF8.GetChars (GetResourceBytes (this.GetType ()), offset, size);
+ strObj = new string (tmp);
- return strObj;
+ Hashtable tmpResourceHash = (Hashtable) ResourceHash.Clone ();
+ tmpResourceHash.Add (key, strObj);
+ ResourceHash = tmpResourceHash;
}
-
+ return strObj;
}
public virtual string TemplateSourceDirectory_Private
{
int size,
bool fAsciiOnly)
{
- string str = CachedString (this.GetType ().FullName, offset, size);
+ string str = CachedString (this.GetType (), offset, size);
return new LiteralControl (str);
}
+ sealed class EventMethodMap
+ {
+ public EventMethodMap (LifeCycleEvent EventKeyIndex, MethodInfo Method, bool NoParameters)
+ {
+ this.EventKeyIndex = EventKeyIndex;
+ this.Method = Method;
+ this.NoParameters = NoParameters;
+ }
+
+ public readonly LifeCycleEvent EventKeyIndex;
+ public readonly MethodInfo Method;
+ public readonly bool NoParameters;
+ }
+
+ // 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 ()
{
- if (!SupportAutoEvents || !AutoEventWireup)
- return;
+ Type cacheKey = this.GetType ();
+ Hashtable eventMethodCache = EventMethodCache;
+ ArrayList eventMethodList = eventMethodCache == null ? null : (ArrayList) eventMethodCache [cacheKey];
- Type thisType = typeof(TemplateControl);
- Type voidType = typeof (void);
- Type [] DefaultParams = new Type [] {
- typeof (object),
- typeof (EventArgs) };
+ if (eventMethodList == null) {
+ eventMethodList = new ArrayList ();
- foreach (string methodName in methodNames) {
- MethodInfo method;
- bool noParams = false;
- Type type = GetType ();
- do {
- method = type.GetMethod (methodName, bflags, null, DefaultParams, null);
- if (method != null)
- break;
+ if (!SupportAutoEvents || !AutoEventWireup)
+ return;
- type = type.BaseType;
- }
- while (type != thisType);
+ Type thisType = typeof (TemplateControl);
+ Type voidType = typeof (void);
+ Type [] DefaultParams = new Type [] {
+ typeof (object),
+ typeof (EventArgs) };
- if (method == null) {
- type = GetType ();
+ LifeCycleEvent[] _pageEvents = new LifeCycleEvent[] {
+ LifeCycleEvent.PreInit,
+ LifeCycleEvent.PreLoad,
+ LifeCycleEvent.LoadComplete,
+ LifeCycleEvent.PreRenderComplete,
+ LifeCycleEvent.SaveStateComplete,
+ LifeCycleEvent.InitComplete
+ };
+ List<LifeCycleEvent> pageEvents = new List<LifeCycleEvent>(_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, NoParams, null);
+ method = type.GetMethod (methodName, bflags, null, DefaultParams, null);
if (method != null) {
- noParams = true;
break;
}
}
while (type != thisType);
- if (method == null)
- continue;
- }
+ 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 ONLY_1_1
- if (method.DeclaringType != type) {
- if (!method.IsPublic && !method.IsFamilyOrAssembly &&
- !method.IsFamilyAndAssembly && !method.IsFamily)
+ 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 != voidType)
- continue;
+ Hashtable newEventMethodCache = eventMethodCache == null ? new Hashtable () : (Hashtable) eventMethodCache.Clone ();
+ newEventMethodCache [cacheKey] = eventMethodList;
+ EventMethodCache = newEventMethodCache;
+ }
+
+ foreach (EventMethodMap eventMethod in eventMethodList) {
+ EventHandler handler = eventMethod.NoParameters ?
+ new NoParamsInvoker (this, eventMethod.Method).FakeDelegate :
+ (EventHandler)Delegate.CreateDelegate (typeof (EventHandler), this, eventMethod.Method);
- int pos = methodName.IndexOf ("_");
- string eventName = methodName.Substring (pos + 1);
- EventInfo evt = GetType ().GetEvent (eventName);
- if (evt == null) {
- /* This should never happen */
+ object eventKey = EventKeys [(int) eventMethod.EventKeyIndex];
+
+ Delegate existing = Events [eventKey];
+ if (existing != null && handler.Equals(existing))
continue;
- }
- if (noParams) {
- NoParamsInvoker npi = new NoParamsInvoker (this, method);
- evt.AddEventHandler (this, npi.FakeDelegate);
- }
- else {
- evt.AddEventHandler (this, Delegate.CreateDelegate (
- typeof (EventHandler), this, method));
+ 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;
}
}
}
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);
java.lang.ClassLoader contextClassLoader = c.getClassLoader ();
//TODO:move this code to page mapper
- string assemblyName = PageMapper.GetAssemblyResource (this.AppRelativeVirtualPath);
+ 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);
protected void WriteUTF8ResourceString (HtmlTextWriter output, int offset,
int size, bool fAsciiOnly)
{
- string str = CachedString (this.GetType ().FullName, offset, size);
+ string str = CachedString (this.GetType (), offset, size);
output.Write (str);
}
}
}
+ 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;
}
}
+ internal override TemplateControl TemplateControlInternal {
+ get { return this; }
+ }
+
protected internal object Eval (string expression)
{
return DataBinder.Eval (Page.GetDataItem (), expression);
return HttpContext.GetGlobalResourceObject (className, resourceKey);
}
- [MonoTODO ("Not implemented")]
protected object GetGlobalResourceObject (string className, string resourceKey, Type objType, string propName)
{
- // FIXME: not sure how to implement that one yet
- throw new NotSupportedException ();
+ return ConvertResource (GetGlobalResourceObject (className, resourceKey), objType, propName);
}
protected Object GetLocalResourceObject (string resourceKey)
return HttpContext.GetLocalResourceObject (Context.Request.Path, resourceKey);
}
- [MonoTODO ("Not implemented")]
protected Object GetLocalResourceObject (string resourceKey, Type objType, string propName)
{
- // FIXME: not sure how to implement that one yet
- throw new NotSupportedException ();
+ 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);
}
#endif