X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2FSystem.Web%2FSystem.Web.UI%2FTemplateControl.cs;h=6480b008bd983488f7a684fb58121c89be6db3d4;hb=879970ea20a49e63a5413adec014754b30a53e03;hp=e5d8ff843adf1e5f9a305782732f3161a8544c23;hpb=08f092551f5b4f9eb5c341afa56b61013c7abf1c;p=mono.git diff --git a/mcs/class/System.Web/System.Web.UI/TemplateControl.cs b/mcs/class/System.Web/System.Web.UI/TemplateControl.cs index e5d8ff843ad..6480b008bd9 100644 --- a/mcs/class/System.Web/System.Web.UI/TemplateControl.cs +++ b/mcs/class/System.Web/System.Web.UI/TemplateControl.cs @@ -7,7 +7,7 @@ // Andreas Nahr (ClassDevelopment@A-SoftTech.com) // // (C) 2002 Ximian, Inc. (http://www.ximian.com) -// Copyright (C) 2005 Novell, Inc (http://www.novell.com) +// Copyright (C) 2005-2010 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 @@ -33,33 +33,34 @@ using System.Collections; using System.ComponentModel; using System.Reflection; using System.Security.Permissions; +using System.Threading; using System.Web.Compilation; using System.Web.Util; using System.Xml; - -namespace System.Web.UI { - +using System.IO; +using System.Runtime.InteropServices; +using System.Text; +using System.Collections.Generic; +using System.Collections.Concurrent; + +namespace System.Web.UI +{ // CAS [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)] -#if NET_2_0 - public abstract class TemplateControl : Control, INamingContainer, IFilterResolutionService { -#else - public abstract class TemplateControl : Control, INamingContainer { -#endif + public abstract class TemplateControl : Control, INamingContainer, IFilterResolutionService + { static readonly Assembly _System_Web_Assembly = typeof (TemplateControl).Assembly; static object abortTransaction = new object (); static object commitTransaction = new object (); static object error = new object (); static 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", @@ -73,13 +74,13 @@ namespace System.Web.UI { BindingFlags.NonPublic | BindingFlags.Instance; -#if NET_2_0 string _appRelativeVirtualPath; -#endif + StringResourceData resource_data; #region Constructor protected TemplateControl () { + TemplateControl = this; Construct (); } @@ -87,9 +88,7 @@ namespace System.Web.UI { #region Properties [EditorBrowsable (EditorBrowsableState.Never)] -#if NET_2_0 [Obsolete] -#endif protected virtual int AutoHandlers { get { return 0; } set { } @@ -100,12 +99,10 @@ namespace System.Web.UI { get { return true; } } -#if NET_2_0 public string AppRelativeVirtualPath { get { return _appRelativeVirtualPath; } set { _appRelativeVirtualPath = value; } } -#endif #endregion @@ -115,19 +112,49 @@ namespace System.Web.UI { { } - [MonoTODO ("Not implemented")] - protected LiteralControl CreateResourceBasedLiteralControl (int offset, - int size, - bool fAsciiOnly) + protected LiteralControl CreateResourceBasedLiteralControl (int offset, int size, bool fAsciiOnly) { - return null; + if (resource_data == null) + return null; + + if (offset > resource_data.MaxOffset - size) + throw new ArgumentOutOfRangeException ("size"); + + IntPtr ptr = AddOffset (resource_data.Ptr, offset); + return new ResourceBasedLiteralControl (ptr, size); } + class EvtInfo { + public MethodInfo method; + public string methodName; + public EventInfo evt; + public bool noParams; + } + + static SplitOrderedList auto_event_info = new SplitOrderedList (EqualityComparer.Default); + internal void WireupAutomaticEvents () { if (!SupportAutoEvents || !AutoEventWireup) return; + /* Avoid expensive reflection operations by computing the event info only once */ + Type type = GetType (); + ArrayList events = auto_event_info.InsertOrGet ((uint)type.GetHashCode (), type, null, CollectAutomaticEventInfo); + + for (int i = 0; i < events.Count; ++i) { + EvtInfo evinfo = (EvtInfo)events [i]; + if (evinfo.noParams) { + NoParamsInvoker npi = new NoParamsInvoker (this, evinfo.method); + evinfo.evt.AddEventHandler (this, npi.FakeDelegate); + } else + evinfo.evt.AddEventHandler (this, Delegate.CreateDelegate (typeof (EventHandler), this, evinfo.method)); + } + } + + ArrayList CollectAutomaticEventInfo () { + ArrayList events = new ArrayList (); + foreach (string methodName in methodNames) { MethodInfo method = null; Type type; @@ -156,7 +183,7 @@ namespace System.Web.UI { parms [1].ParameterType != typeof (EventArgs))) continue; - int pos = methodName.IndexOf ("_"); + int pos = methodName.IndexOf ('_'); string eventName = methodName.Substring (pos + 1); EventInfo evt = type.GetEvent (eventName); if (evt == null) { @@ -164,18 +191,16 @@ namespace System.Web.UI { continue; } - if (noParams) { - NoParamsInvoker npi = new NoParamsInvoker (this, method); - evt.AddEventHandler (this, npi.FakeDelegate); - } else { - evt.AddEventHandler (this, Delegate.CreateDelegate ( -#if NET_2_0 - typeof (EventHandler), this, method)); -#else - typeof (EventHandler), this, methodName)); -#endif - } + EvtInfo evinfo = new EvtInfo (); + evinfo.method = method; + evinfo.methodName = methodName; + evinfo.evt = evt; + evinfo.noParams = noParams; + + events.Add (evinfo); } + + return events; } [EditorBrowsable (EditorBrowsableState.Never)] @@ -189,31 +214,34 @@ namespace System.Web.UI { throw new ArgumentNullException ("virtualPath"); string vpath = UrlUtils.Combine (TemplateSourceDirectory, virtualPath); - string realpath = Context.Request.MapPath (vpath); - return UserControlParser.GetCompiledType (vpath, realpath, Context); + return BuildManager.GetCompiledType (vpath); } public Control LoadControl (string 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); - object [] attrs = type.GetCustomAttributes (typeof (PartialCachingAttribute), true); + + return LoadControl (type, null); + } + + public Control LoadControl (Type type, object[] parameters) + { + object [] attrs = null; + + if (type != null) + type.GetCustomAttributes (typeof (PartialCachingAttribute), true); if (attrs != null && attrs.Length == 1) { PartialCachingAttribute attr = (PartialCachingAttribute) attrs [0]; - PartialCachingControl ctrl = new PartialCachingControl (type); + 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); + object control = Activator.CreateInstance (type, parameters); if (control is UserControl) ((UserControl) control).InitializeAsUserControl (Page); @@ -222,13 +250,8 @@ namespace System.Web.UI { public ITemplate LoadTemplate (string virtualPath) { -#if NET_2_0 if (virtualPath == null) throw new ArgumentNullException ("virtualPath"); -#else - if (virtualPath == null) - throw new HttpException ("virtualPath is null"); -#endif Type t = GetTypeFromControlPath (virtualPath); return new SimpleTemplate (t); } @@ -254,68 +277,171 @@ namespace System.Web.UI { eh (this, e); } - [MonoTODO ("Not implemented, always returns null")] public Control ParseControl (string content) { if (content == null) throw new ArgumentNullException ("content"); - return null; + // FIXME: This method needs to be rewritten in some sane way - the way it is now, + // is a kludge. New version should not use + // UserControlParser.GetCompiledType, but instead resort to some other way + // of creating the content (template instantiation? BuildManager? TBD) + TextReader reader = new StringReader (content); + Type control = UserControlParser.GetCompiledType (reader, content.GetHashCode (), HttpContext.Current); + if (control == null) + return null; + + TemplateControl parsedControl = Activator.CreateInstance (control, null) as TemplateControl; + if (parsedControl == null) + return null; + + if (this is System.Web.UI.Page) + parsedControl.Page = (System.Web.UI.Page) this; + parsedControl.FrameworkInitialize (); + + Control ret = new Control (); + int count = parsedControl.Controls.Count; + Control[] parsedControlControls = new Control [count]; + parsedControl.Controls.CopyTo (parsedControlControls, 0); + + for (int i = 0; i < count; i++) + ret.Controls.Add (parsedControlControls [i]); + + parsedControl = null; + return ret; + } + + [MonoTODO ("Parser filters not implemented yet. Calls ParseControl (string) for now.")] + public Control ParseControl (string content, bool ignoreParserFilter) + { + return ParseControl (content); } - + [EditorBrowsable (EditorBrowsableState.Never)] - public -#if !NET_2_0 - static -#endif - object ReadStringResource () + public object ReadStringResource () { - throw new NotSupportedException (); + return ReadStringResource (GetType ()); + } + + class StringResourceData { + public IntPtr Ptr; + public int Length; + public int MaxOffset; } -#if NET_2_0 protected object GetGlobalResourceObject (string className, string resourceKey) { 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(); + if (String.IsNullOrEmpty (resourceKey) || String.IsNullOrEmpty (propName) || + String.IsNullOrEmpty (className) || objType == null) + return null; + + object globalObject = GetGlobalResourceObject (className, resourceKey); + if (globalObject == null) + return null; + + TypeConverter converter = TypeDescriptor.GetProperties (objType) [propName].Converter; + if (converter == null || !converter.CanConvertFrom (globalObject.GetType ())) + return null; + + return converter.ConvertFrom (globalObject); } protected object GetLocalResourceObject (string resourceKey) { - return HttpContext.GetLocalResourceObject (Context.Request.CurrentExecutionFilePath, resourceKey); + return HttpContext.GetLocalResourceObject (VirtualPathUtility.ToAbsolute (this.AppRelativeVirtualPath), + resourceKey); } protected object GetLocalResourceObject (string resourceKey, Type objType, string propName) { - // FIXME: not sure how to implement that one yet - throw new NotSupportedException(); + if (String.IsNullOrEmpty (resourceKey) || String.IsNullOrEmpty (propName) || objType == null) + return null; + + object localObject = GetLocalResourceObject (resourceKey); + if (localObject == null) + return null; + + TypeConverter converter = TypeDescriptor.GetProperties (objType) [propName].Converter; + if (converter == null || !converter.CanConvertFrom (localObject.GetType ())) + return null; + + return converter.ConvertFrom (localObject); + } + + internal override TemplateControl TemplateControlInternal { + get { return this; } } -#endif [EditorBrowsable (EditorBrowsableState.Never)] public static object ReadStringResource (Type t) { - throw new NotSupportedException (); + StringResourceData data = new StringResourceData (); + if (ICalls.GetUnmanagedResourcesPtr (t.Assembly, out data.Ptr, out data.Length)) + return data; + + throw new HttpException ("Unable to load the string resources."); } - [MonoTODO ("Not implemented, does nothing")] [EditorBrowsable (EditorBrowsableState.Never)] protected void SetStringResourcePointer (object stringResourcePointer, int maxResourceOffset) { + StringResourceData rd = stringResourcePointer as StringResourceData; + if (rd == null) + return; + + if (maxResourceOffset < 0 || maxResourceOffset > rd.Length) + throw new ArgumentOutOfRangeException ("maxResourceOffset"); + + resource_data = new StringResourceData (); + resource_data.Ptr = rd.Ptr; + resource_data.Length = rd.Length; + resource_data.MaxOffset = maxResourceOffset > 0 ? Math.Min (maxResourceOffset, rd.Length) : rd.Length; + } + + static IntPtr AddOffset (IntPtr ptr, int offset) + { + if (offset == 0) + return ptr; + + if (IntPtr.Size == 4) { + int p = ptr.ToInt32 () + offset; + ptr = new IntPtr (p); + } else { + long p = ptr.ToInt64 () + offset; + ptr = new IntPtr (p); + } + return ptr; } - [MonoTODO ("Not implemented, does nothing")] [EditorBrowsable (EditorBrowsableState.Never)] - protected void WriteUTF8ResourceString (HtmlTextWriter output, int offset, - int size, bool fAsciiOnly) + protected void WriteUTF8ResourceString (HtmlTextWriter output, int offset, int size, bool fAsciiOnly) { + if (resource_data == null) + return; // throw? + if (output == null) + throw new ArgumentNullException ("output"); + if (offset > resource_data.MaxOffset - size) + throw new ArgumentOutOfRangeException ("size"); + + //TODO: fAsciiOnly? + IntPtr ptr = AddOffset (resource_data.Ptr, offset); + HttpWriter writer = output.GetHttpWriter (); + + if (writer == null || writer.Response.ContentEncoding.CodePage != 65001) { + byte [] bytes = new byte [size]; + Marshal.Copy (ptr, bytes, 0, size); + output.Write (Encoding.UTF8.GetString (bytes)); + bytes = null; + return; + } + + writer.WriteUTF8Ptr (ptr, size); } #endregion @@ -359,7 +485,6 @@ namespace System.Web.UI { } } -#if NET_2_0 protected internal object Eval (string expression) { return DataBinder.Eval (Page.GetDataItem(), expression); @@ -413,6 +538,5 @@ namespace System.Web.UI { { throw new NotImplementedException (); } -#endif } }