[asp.net] Fix for bug #685267. ClientScriptManager generates correct post-back event...
[mono.git] / mcs / class / System.Web / System.Web.UI / TemplateControl.cs
index 81d2eb6ebefc38ed47e6bf63f133e109c002a011..6480b008bd983488f7a684fb58121c89be6db3d4 100644 (file)
@@ -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,34 +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;
 using System.IO;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
 
-namespace System.Web.UI {
-
+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",
@@ -74,16 +74,13 @@ namespace System.Web.UI {
                                            BindingFlags.NonPublic |
                                            BindingFlags.Instance;
 
-#if NET_2_0
                string _appRelativeVirtualPath;
-#endif
+               StringResourceData resource_data;
                
                #region Constructor
                protected TemplateControl ()
                {
-#if NET_2_0
                        TemplateControl = this;
-#endif
                        Construct ();
                }
 
@@ -91,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 { }
@@ -104,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
 
@@ -119,12 +112,16 @@ 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 {
@@ -134,40 +131,24 @@ namespace System.Web.UI {
                        public bool noParams;
                }
 
-               static Hashtable auto_event_info;
-               static object auto_event_info_monitor = new Object ();
+               static SplitOrderedList<Type, ArrayList> auto_event_info = new SplitOrderedList<Type, ArrayList> (EqualityComparer<Type>.Default);
 
                internal void WireupAutomaticEvents ()
                {
                        if (!SupportAutoEvents || !AutoEventWireup)
                                return;
 
-                       ArrayList events = null;
-
                        /* Avoid expensive reflection operations by computing the event info only once */
-                       lock (auto_event_info_monitor) {
-                               if (auto_event_info == null)
-                                       auto_event_info = new Hashtable ();
-                               events = (ArrayList)auto_event_info [GetType ()];
-                               if (events == null) {
-                                       events = CollectAutomaticEventInfo ();
-                                       auto_event_info [GetType ()] = events;
-                               }
-                       }
+                       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 (
-#if NET_2_0
-                                                       typeof (EventHandler), this, evinfo.method));
-#else
-                                                       typeof (EventHandler), this, evinfo.methodName));
-#endif
-                               }
+                               } else
+                                       evinfo.evt.AddEventHandler (this, Delegate.CreateDelegate (typeof (EventHandler), this, evinfo.method));
                        }
                }
 
@@ -202,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) {
@@ -233,23 +214,13 @@ namespace System.Web.UI {
                                throw new ArgumentNullException ("virtualPath");
 
                        string vpath = UrlUtils.Combine (TemplateSourceDirectory, virtualPath);
-#if NET_2_0
                        return BuildManager.GetCompiledType (vpath);
-#else
-                       string realpath = Context.Request.MapPath (vpath);
-                       return UserControlParser.GetCompiledType (vpath, realpath, Context);
-#endif
                }
 
                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);
                        
                        return LoadControl (type, null);
@@ -279,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);
                }
@@ -311,15 +277,11 @@ namespace System.Web.UI {
                                eh (this, e);
                }
 
-#if !NET_2_0
-               [MonoTODO ("Not implemented, always returns null")]
-#endif
                public Control ParseControl (string content)
                {
                        if (content == null)
                                throw new ArgumentNullException ("content");
 
-#if NET_2_0
                        // 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
@@ -347,30 +309,26 @@ namespace System.Web.UI {
 
                        parsedControl = null;
                        return ret;
-#else
-                       return null;
-#endif
                }
 
-#if NET_2_0
                [MonoTODO ("Parser filters not implemented yet. Calls ParseControl (string) for now.")]
                public Control ParseControl (string content, bool ignoreParserFilter)
                {
                        return ParseControl (content);
                }
-#endif
        
                [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);
@@ -418,26 +376,72 @@ namespace System.Web.UI {
                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;
                }
 
-               [MonoTODO ("Not implemented, does nothing")]
-               [EditorBrowsable (EditorBrowsableState.Never)]
-               protected void WriteUTF8ResourceString (HtmlTextWriter output, int offset,
-                                                       int size, bool fAsciiOnly)
+               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;
+               }
+
+               [EditorBrowsable (EditorBrowsableState.Never)]
+               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
@@ -481,7 +485,6 @@ namespace System.Web.UI {
                        }
                }
 
-#if NET_2_0
                protected internal object Eval (string expression)
                {
                        return DataBinder.Eval (Page.GetDataItem(), expression);
@@ -535,6 +538,5 @@ namespace System.Web.UI {
                {
                        throw new NotImplementedException ();
                }
-#endif
        }
 }