2008-06-11 Marek Habersack <mhabersack@novell.com>
[mono.git] / mcs / class / System.Web / System.Web.UI / TemplateControl.cs
1 //
2 // System.Web.UI.TemplateControl.cs
3 //
4 // Authors:
5 //   Duncan Mak  (duncan@ximian.com)
6 //   Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 //   Andreas Nahr (ClassDevelopment@A-SoftTech.com)
8 //
9 // (C) 2002 Ximian, Inc. (http://www.ximian.com)
10 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 using System.Collections;
33 using System.ComponentModel;
34 using System.Reflection;
35 using System.Security.Permissions;
36 using System.Web.Compilation;
37 using System.Web.Util;
38 using System.Xml;
39 using System.IO;
40
41 namespace System.Web.UI {
42
43         // CAS
44         [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
45         [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
46 #if NET_2_0
47         public abstract class TemplateControl : Control, INamingContainer, IFilterResolutionService {
48 #else
49         public abstract class TemplateControl : Control, INamingContainer {
50 #endif
51                 static readonly Assembly _System_Web_Assembly = typeof (TemplateControl).Assembly;
52                 static object abortTransaction = new object ();
53                 static object commitTransaction = new object ();
54                 static object error = new object ();
55                 static string [] methodNames = { "Page_Init",
56 #if NET_2_0
57                                                  "Page_PreInit",
58                                                  "Page_PreLoad",
59                                                  "Page_LoadComplete",
60                                                  "Page_PreRenderComplete",
61                                                  "Page_SaveStateComplete",
62                                                  "Page_InitComplete",
63 #endif
64                                                  "Page_Load",
65                                                  "Page_DataBind",
66                                                  "Page_PreRender",
67                                                  "Page_Disposed",
68                                                  "Page_Error",
69                                                  "Page_Unload",
70                                                  "Page_AbortTransaction",
71                                                  "Page_CommitTransaction"};
72
73                 const BindingFlags bflags = BindingFlags.Public |
74                                             BindingFlags.NonPublic |
75                                             BindingFlags.Instance;
76
77 #if NET_2_0
78                 string _appRelativeVirtualPath;
79 #endif
80                 
81                 #region Constructor
82                 protected TemplateControl ()
83                 {
84 #if NET_2_0
85                         TemplateControl = this;
86 #endif
87                         Construct ();
88                 }
89
90                 #endregion
91
92                 #region Properties
93                 [EditorBrowsable (EditorBrowsableState.Never)]
94 #if NET_2_0
95                 [Obsolete]
96 #endif
97                 protected virtual int AutoHandlers {
98                         get { return 0; }
99                         set { }
100                 }
101
102                 [EditorBrowsable (EditorBrowsableState.Never)]
103                 protected virtual bool SupportAutoEvents {
104                         get { return true; }
105                 }
106
107 #if NET_2_0
108                 public string AppRelativeVirtualPath {
109                         get { return _appRelativeVirtualPath; }
110                         set { _appRelativeVirtualPath = value; }
111                 }
112 #endif
113
114                 #endregion
115
116                 #region Methods
117
118                 protected virtual void Construct ()
119                 {
120                 }
121
122                 [MonoTODO ("Not implemented")]
123                 protected LiteralControl CreateResourceBasedLiteralControl (int offset,
124                                                                                     int size,
125                                                                                     bool fAsciiOnly)
126                 {
127                         return null;
128                 }
129
130                 internal void WireupAutomaticEvents ()
131                 {
132                         if (!SupportAutoEvents || !AutoEventWireup)
133                                 return;
134
135                         foreach (string methodName in methodNames) {
136                                 MethodInfo method = null;
137                                 Type type;
138                                 for (type = GetType (); type.Assembly != _System_Web_Assembly; type = type.BaseType) {
139                                         method = type.GetMethod (methodName, bflags);
140                                         if (method != null)
141                                                 break;
142                                 }
143                                 if (method == null)
144                                         continue;
145
146                                 if (method.DeclaringType != type) {
147                                         if (!method.IsPublic && !method.IsFamilyOrAssembly &&
148                                             !method.IsFamilyAndAssembly && !method.IsFamily)
149                                                 continue;
150                                 }
151
152                                 if (method.ReturnType != typeof (void))
153                                         continue;
154
155                                 ParameterInfo [] parms = method.GetParameters ();
156                                 int length = parms.Length;
157                                 bool noParams = (length == 0);
158                                 if (!noParams && (length != 2 ||
159                                     parms [0].ParameterType != typeof (object) ||
160                                     parms [1].ParameterType != typeof (EventArgs)))
161                                     continue;
162
163                                 int pos = methodName.IndexOf ("_");
164                                 string eventName = methodName.Substring (pos + 1);
165                                 EventInfo evt = type.GetEvent (eventName);
166                                 if (evt == null) {
167                                         /* This should never happen */
168                                         continue;
169                                 }
170
171                                 if (noParams) {
172                                         NoParamsInvoker npi = new NoParamsInvoker (this, method);
173                                         evt.AddEventHandler (this, npi.FakeDelegate);
174                                 } else {
175                                         evt.AddEventHandler (this, Delegate.CreateDelegate (
176 #if NET_2_0
177                                                         typeof (EventHandler), this, method));
178 #else
179                                                         typeof (EventHandler), this, methodName));
180 #endif
181                                 }
182                         }
183                 }
184
185                 [EditorBrowsable (EditorBrowsableState.Never)]
186                 protected virtual void FrameworkInitialize ()
187                 {
188                 }
189
190                 Type GetTypeFromControlPath (string virtualPath)
191                 {
192                         if (virtualPath == null)
193                                 throw new ArgumentNullException ("virtualPath");
194
195                         string vpath = UrlUtils.Combine (TemplateSourceDirectory, virtualPath);
196                         string realpath = Context.Request.MapPath (vpath);
197 #if NET_2_0
198                         return BuildManager.GetCompiledType (vpath);
199 #else
200                         return UserControlParser.GetCompiledType (vpath, realpath, Context);
201 #endif
202                 }
203
204                 public Control LoadControl (string virtualPath)
205                 {
206 #if NET_2_0
207                         if (virtualPath == null)
208                                 throw new ArgumentNullException ("virtualPath");
209 #else
210                         if (virtualPath == null)
211                                 throw new HttpException ("virtualPath is null");
212 #endif
213                         Type type = GetTypeFromControlPath (virtualPath);
214                         
215                         return LoadControl (type, null);
216                 }
217
218                 public Control LoadControl (Type type, object[] parameters) 
219                 {
220                         object [] attrs = null;
221
222                         if (type != null)
223                                 type.GetCustomAttributes (typeof (PartialCachingAttribute), true);
224                         if (attrs != null && attrs.Length == 1) {
225                                 PartialCachingAttribute attr = (PartialCachingAttribute) attrs [0];
226                                 PartialCachingControl ctrl = new PartialCachingControl (type, parameters);
227                                 ctrl.VaryByParams = attr.VaryByParams;
228                                 ctrl.VaryByControls = attr.VaryByControls;
229                                 ctrl.VaryByCustom = attr.VaryByCustom;
230                                 return ctrl;
231                         }
232
233                         object control = Activator.CreateInstance (type, parameters);
234                         if (control is UserControl)
235                                 ((UserControl) control).InitializeAsUserControl (Page);
236
237                         return (Control) control;
238                 }
239
240                 public ITemplate LoadTemplate (string virtualPath)
241                 {
242 #if NET_2_0
243                         if (virtualPath == null)
244                                 throw new ArgumentNullException ("virtualPath");
245 #else
246                         if (virtualPath == null)
247                                 throw new HttpException ("virtualPath is null");
248 #endif
249                         Type t = GetTypeFromControlPath (virtualPath);
250                         return new SimpleTemplate (t);
251                 }
252
253                 protected virtual void OnAbortTransaction (EventArgs e)
254                 {
255                         EventHandler eh = Events [abortTransaction] as EventHandler;
256                         if (eh != null)
257                                 eh (this, e);
258                 }
259
260                 protected virtual void OnCommitTransaction (EventArgs e)
261                 {
262                         EventHandler eh = Events [commitTransaction] as EventHandler;
263                         if (eh != null)
264                                 eh (this, e);
265                 }
266
267                 protected virtual void OnError (EventArgs e)
268                 {
269                         EventHandler eh = Events [error] as EventHandler;
270                         if (eh != null)
271                                 eh (this, e);
272                 }
273
274 #if !NET_2_0
275                 [MonoTODO ("Not implemented, always returns null")]
276 #endif
277                 public Control ParseControl (string content)
278                 {
279                         if (content == null)
280                                 throw new ArgumentNullException ("content");
281
282 #if NET_2_0
283                         TextReader reader = new StringReader (content);
284                         Type control = UserControlParser.GetCompiledType (reader, HttpContext.Current);
285                         if (control == null)
286                                 return null;
287                         
288                         return Activator.CreateInstance (control, null) as Control;
289 #else
290                         return null;
291 #endif
292                 }
293
294 #if NET_2_0
295                 [MonoTODO ("Parser filters not implemented yet. Calls ParseControl (string) for now.")]
296                 public Control ParseControl (string content, bool ignoreParserFilter)
297                 {
298                         return ParseControl (content);
299                 }
300 #endif
301         
302                 [EditorBrowsable (EditorBrowsableState.Never)]
303                 public 
304 #if !NET_2_0
305                 static
306 #endif
307                 object ReadStringResource ()
308                 {
309                         throw new NotSupportedException ();
310                 }
311
312 #if NET_2_0
313                 protected object GetGlobalResourceObject (string className, string resourceKey)
314                 {
315                         return HttpContext.GetGlobalResourceObject (className, resourceKey);
316                 }
317
318                 protected object GetGlobalResourceObject (string className, string resourceKey, Type objType, string propName)
319                 {
320                         if (String.IsNullOrEmpty (resourceKey) || String.IsNullOrEmpty (propName) ||
321                             String.IsNullOrEmpty (className) || objType == null)
322                                 return null;
323
324                         object globalObject = GetGlobalResourceObject (className, resourceKey);
325                         if (globalObject == null)
326                                 return null;
327                         
328                         TypeConverter converter = TypeDescriptor.GetProperties (objType) [propName].Converter;
329                         if (converter == null || !converter.CanConvertFrom (globalObject.GetType ()))
330                                 return null;
331                         
332                         return converter.ConvertFrom (globalObject);
333                 }
334
335                 protected object GetLocalResourceObject (string resourceKey)
336                 {
337                         return HttpContext.GetLocalResourceObject (VirtualPathUtility.ToAbsolute (this.AppRelativeVirtualPath),
338                                                                    resourceKey);
339                 }
340                 
341                 protected object GetLocalResourceObject (string resourceKey, Type objType, string propName)
342                 {
343                         if (String.IsNullOrEmpty (resourceKey) || String.IsNullOrEmpty (propName) || objType == null)
344                                 return null;
345
346                         object localObject = GetLocalResourceObject (resourceKey);
347                         if (localObject == null)
348                                 return null;
349                         
350                         TypeConverter converter = TypeDescriptor.GetProperties (objType) [propName].Converter;
351                         if (converter == null || !converter.CanConvertFrom (localObject.GetType ()))
352                                 return null;
353                         
354                         return converter.ConvertFrom (localObject);
355                 }
356
357                 internal override TemplateControl TemplateControlInternal {
358                         get { return this; }
359                 }
360 #endif
361                 
362                 [EditorBrowsable (EditorBrowsableState.Never)]
363                 public static object ReadStringResource (Type t)
364                 {
365                         throw new NotSupportedException ();
366                 }
367
368                 [MonoTODO ("Not implemented, does nothing")]
369                 [EditorBrowsable (EditorBrowsableState.Never)]
370                 protected void SetStringResourcePointer (object stringResourcePointer,
371                                                          int maxResourceOffset)
372                 {
373                 }
374
375                 [MonoTODO ("Not implemented, does nothing")]
376                 [EditorBrowsable (EditorBrowsableState.Never)]
377                 protected void WriteUTF8ResourceString (HtmlTextWriter output, int offset,
378                                                         int size, bool fAsciiOnly)
379                 {
380                 }
381
382                 #endregion
383
384                 #region Events
385
386                 [WebSysDescription ("Raised when the user aborts a transaction.")]
387                 public event EventHandler AbortTransaction {
388                         add { Events.AddHandler (abortTransaction, value); }
389                         remove { Events.RemoveHandler (abortTransaction, value); }
390                 }
391
392                 [WebSysDescription ("Raised when the user initiates a transaction.")]
393                 public event EventHandler CommitTransaction {
394                         add { Events.AddHandler (commitTransaction, value); }
395                         remove { Events.RemoveHandler (commitTransaction, value); }
396                 }
397
398                 [WebSysDescription ("Raised when an exception occurs that cannot be handled.")]
399                 public event EventHandler Error {
400                         add { Events.AddHandler (error, value); }
401                         remove { Events.RemoveHandler (error, value); }
402                 }
403
404                 #endregion
405
406                 class SimpleTemplate : ITemplate
407                 {
408                         Type type;
409
410                         public SimpleTemplate (Type type)
411                         {
412                                 this.type = type;
413                         }
414
415                         public void InstantiateIn (Control control)
416                         {
417                                 Control template = Activator.CreateInstance (type) as Control;
418                                 template.SetBindingContainer (false);
419                                 control.Controls.Add (template);
420                         }
421                 }
422
423 #if NET_2_0
424                 protected internal object Eval (string expression)
425                 {
426                         return DataBinder.Eval (Page.GetDataItem(), expression);
427                 }
428         
429                 protected internal string Eval (string expression, string format)
430                 {
431                         return DataBinder.Eval (Page.GetDataItem(), expression, format);
432                 }
433         
434                 protected internal object XPath (string xpathexpression)
435                 {
436                         return XPathBinder.Eval (Page.GetDataItem(), xpathexpression);
437                 }
438         
439                 protected internal object XPath (string xpathexpression, IXmlNamespaceResolver resolver)
440                 {
441                         return XPathBinder.Eval (Page.GetDataItem (), xpathexpression, null, resolver);
442                 }
443
444                 protected internal string XPath (string xpathexpression, string format)
445                 {
446                         return XPathBinder.Eval (Page.GetDataItem(), xpathexpression, format);
447                 }
448         
449                 protected internal string XPath (string xpathexpression, string format, IXmlNamespaceResolver resolver)
450                 {
451                         return XPathBinder.Eval (Page.GetDataItem (), xpathexpression, format, resolver);
452                 }
453
454                 protected internal IEnumerable XPathSelect (string xpathexpression)
455                 {
456                         return XPathBinder.Select (Page.GetDataItem(), xpathexpression);
457                 }
458
459                 protected internal IEnumerable XPathSelect (string xpathexpression, IXmlNamespaceResolver resolver)
460                 {
461                         return XPathBinder.Select (Page.GetDataItem (), xpathexpression, resolver);
462                 }
463
464                 // IFilterResolutionService
465
466                 [MonoTODO ("Not implemented")]
467                 int IFilterResolutionService.CompareFilters (string filter1, string filter2)
468                 {
469                         throw new NotImplementedException ();
470                 }
471
472                 [MonoTODO ("Not implemented")]
473                 bool IFilterResolutionService.EvaluateFilter (string filterName)
474                 {
475                         throw new NotImplementedException ();
476                 }
477 #endif
478         }
479 }