2007-12-13 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
40 namespace System.Web.UI {
41
42         // CAS
43         [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
44         [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
45 #if NET_2_0
46         public abstract class TemplateControl : Control, INamingContainer, IFilterResolutionService {
47 #else
48         public abstract class TemplateControl : Control, INamingContainer {
49 #endif
50                 static readonly Assembly _System_Web_Assembly = typeof (TemplateControl).Assembly;
51                 static object abortTransaction = new object ();
52                 static object commitTransaction = new object ();
53                 static object error = new object ();
54                 static string [] methodNames = { "Page_Init",
55 #if NET_2_0
56                                                  "Page_PreInit",
57                                                  "Page_PreLoad",
58                                                  "Page_LoadComplete",
59                                                  "Page_PreRenderComplete",
60                                                  "Page_SaveStateComplete",
61                                                  "Page_InitComplete",
62 #endif
63                                                  "Page_Load",
64                                                  "Page_DataBind",
65                                                  "Page_PreRender",
66                                                  "Page_Disposed",
67                                                  "Page_Error",
68                                                  "Page_Unload",
69                                                  "Page_AbortTransaction",
70                                                  "Page_CommitTransaction"};
71
72                 const BindingFlags bflags = BindingFlags.Public |
73                                             BindingFlags.NonPublic |
74                                             BindingFlags.Instance;
75
76 #if NET_2_0
77                 string _appRelativeVirtualPath;
78 #endif
79                 
80                 #region Constructor
81                 protected TemplateControl ()
82                 {
83 #if NET_2_0
84                         TemplateControl = this;
85 #endif
86                         Construct ();
87                 }
88
89                 #endregion
90
91                 #region Properties
92                 [EditorBrowsable (EditorBrowsableState.Never)]
93 #if NET_2_0
94                 [Obsolete]
95 #endif
96                 protected virtual int AutoHandlers {
97                         get { return 0; }
98                         set { }
99                 }
100
101                 [EditorBrowsable (EditorBrowsableState.Never)]
102                 protected virtual bool SupportAutoEvents {
103                         get { return true; }
104                 }
105
106 #if NET_2_0
107                 public string AppRelativeVirtualPath {
108                         get { return _appRelativeVirtualPath; }
109                         set { _appRelativeVirtualPath = value; }
110                 }
111 #endif
112
113                 #endregion
114
115                 #region Methods
116
117                 protected virtual void Construct ()
118                 {
119                 }
120
121                 [MonoTODO ("Not implemented")]
122                 protected LiteralControl CreateResourceBasedLiteralControl (int offset,
123                                                                                     int size,
124                                                                                     bool fAsciiOnly)
125                 {
126                         return null;
127                 }
128
129                 internal void WireupAutomaticEvents ()
130                 {
131                         if (!SupportAutoEvents || !AutoEventWireup)
132                                 return;
133
134                         foreach (string methodName in methodNames) {
135                                 MethodInfo method = null;
136                                 Type type;
137                                 for (type = GetType (); type.Assembly != _System_Web_Assembly; type = type.BaseType) {
138                                         method = type.GetMethod (methodName, bflags);
139                                         if (method != null)
140                                                 break;
141                                 }
142                                 if (method == null)
143                                         continue;
144
145                                 if (method.DeclaringType != type) {
146                                         if (!method.IsPublic && !method.IsFamilyOrAssembly &&
147                                             !method.IsFamilyAndAssembly && !method.IsFamily)
148                                                 continue;
149                                 }
150
151                                 if (method.ReturnType != typeof (void))
152                                         continue;
153
154                                 ParameterInfo [] parms = method.GetParameters ();
155                                 int length = parms.Length;
156                                 bool noParams = (length == 0);
157                                 if (!noParams && (length != 2 ||
158                                     parms [0].ParameterType != typeof (object) ||
159                                     parms [1].ParameterType != typeof (EventArgs)))
160                                     continue;
161
162                                 int pos = methodName.IndexOf ("_");
163                                 string eventName = methodName.Substring (pos + 1);
164                                 EventInfo evt = type.GetEvent (eventName);
165                                 if (evt == null) {
166                                         /* This should never happen */
167                                         continue;
168                                 }
169
170                                 if (noParams) {
171                                         NoParamsInvoker npi = new NoParamsInvoker (this, method);
172                                         evt.AddEventHandler (this, npi.FakeDelegate);
173                                 } else {
174                                         evt.AddEventHandler (this, Delegate.CreateDelegate (
175 #if NET_2_0
176                                                         typeof (EventHandler), this, method));
177 #else
178                                                         typeof (EventHandler), this, methodName));
179 #endif
180                                 }
181                         }
182                 }
183
184                 [EditorBrowsable (EditorBrowsableState.Never)]
185                 protected virtual void FrameworkInitialize ()
186                 {
187                 }
188
189                 Type GetTypeFromControlPath (string virtualPath)
190                 {
191                         if (virtualPath == null)
192                                 throw new ArgumentNullException ("virtualPath");
193
194                         string vpath = UrlUtils.Combine (TemplateSourceDirectory, virtualPath);
195                         string realpath = Context.Request.MapPath (vpath);
196                         return UserControlParser.GetCompiledType (vpath, realpath, Context);
197                 }
198
199                 public Control LoadControl (string virtualPath)
200                 {
201 #if NET_2_0
202                         if (virtualPath == null)
203                                 throw new ArgumentNullException ("virtualPath");
204 #else
205                         if (virtualPath == null)
206                                 throw new HttpException ("virtualPath is null");
207 #endif
208                         Type type = GetTypeFromControlPath (virtualPath);
209                         return LoadControl (type, null);
210                 }
211
212                 public Control LoadControl (Type type, object[] parameters) 
213                 {
214                         object [] attrs = type.GetCustomAttributes (typeof (PartialCachingAttribute), true);
215                         if (attrs != null && attrs.Length == 1) {
216                                 PartialCachingAttribute attr = (PartialCachingAttribute) attrs [0];
217                                 PartialCachingControl ctrl = new PartialCachingControl (type, parameters);
218                                 ctrl.VaryByParams = attr.VaryByParams;
219                                 ctrl.VaryByControls = attr.VaryByControls;
220                                 ctrl.VaryByCustom = attr.VaryByCustom;
221                                 return ctrl;
222                         }
223
224                         object control = Activator.CreateInstance (type, parameters);
225                         if (control is UserControl)
226                                 ((UserControl) control).InitializeAsUserControl (Page);
227
228                         return (Control) control;
229                 }
230
231                 public ITemplate LoadTemplate (string virtualPath)
232                 {
233 #if NET_2_0
234                         if (virtualPath == null)
235                                 throw new ArgumentNullException ("virtualPath");
236 #else
237                         if (virtualPath == null)
238                                 throw new HttpException ("virtualPath is null");
239 #endif
240                         Type t = GetTypeFromControlPath (virtualPath);
241                         return new SimpleTemplate (t);
242                 }
243
244                 protected virtual void OnAbortTransaction (EventArgs e)
245                 {
246                         EventHandler eh = Events [abortTransaction] as EventHandler;
247                         if (eh != null)
248                                 eh (this, e);
249                 }
250
251                 protected virtual void OnCommitTransaction (EventArgs e)
252                 {
253                         EventHandler eh = Events [commitTransaction] as EventHandler;
254                         if (eh != null)
255                                 eh (this, e);
256                 }
257
258                 protected virtual void OnError (EventArgs e)
259                 {
260                         EventHandler eh = Events [error] as EventHandler;
261                         if (eh != null)
262                                 eh (this, e);
263                 }
264
265                 [MonoTODO ("Not implemented, always returns null")]
266                 public Control ParseControl (string content)
267                 {
268                         if (content == null)
269                                 throw new ArgumentNullException ("content");
270
271                         return null;
272                 }
273
274                 [EditorBrowsable (EditorBrowsableState.Never)]
275                 public 
276 #if !NET_2_0
277                 static
278 #endif
279                 object ReadStringResource ()
280                 {
281                         throw new NotSupportedException ();
282                 }
283
284 #if NET_2_0
285                 protected object GetGlobalResourceObject (string className, string resourceKey)
286                 {
287                         return HttpContext.GetGlobalResourceObject (className, resourceKey);
288                 }
289
290                 protected object GetGlobalResourceObject (string className, string resourceKey, Type objType, string propName)
291                 {
292                         if (String.IsNullOrEmpty (resourceKey) || String.IsNullOrEmpty (propName) ||
293                             String.IsNullOrEmpty (className) || objType == null)
294                                 return null;
295
296                         object globalObject = GetGlobalResourceObject (className, resourceKey);
297                         if (globalObject == null)
298                                 return null;
299                         
300                         TypeConverter converter = TypeDescriptor.GetProperties (objType) [propName].Converter;
301                         if (converter == null || !converter.CanConvertFrom (globalObject.GetType ()))
302                                 return null;
303                         
304                         return converter.ConvertFrom (globalObject);
305                 }
306
307                 protected object GetLocalResourceObject (string resourceKey)
308                 {
309                         return HttpContext.GetLocalResourceObject (VirtualPathUtility.ToAbsolute (this.AppRelativeVirtualPath),
310                                                                    resourceKey);
311                 }
312                 
313                 protected object GetLocalResourceObject (string resourceKey, Type objType, string propName)
314                 {
315                         if (String.IsNullOrEmpty (resourceKey) || String.IsNullOrEmpty (propName) || objType == null)
316                                 return null;
317
318                         object localObject = GetLocalResourceObject (resourceKey);
319                         if (localObject == null)
320                                 return null;
321                         
322                         TypeConverter converter = TypeDescriptor.GetProperties (objType) [propName].Converter;
323                         if (converter == null || !converter.CanConvertFrom (localObject.GetType ()))
324                                 return null;
325                         
326                         return converter.ConvertFrom (localObject);
327                 }
328
329                 internal override TemplateControl TemplateControlInternal {
330                         get { return this; }
331                 }
332 #endif
333                 
334                 [EditorBrowsable (EditorBrowsableState.Never)]
335                 public static object ReadStringResource (Type t)
336                 {
337                         throw new NotSupportedException ();
338                 }
339
340                 [MonoTODO ("Not implemented, does nothing")]
341                 [EditorBrowsable (EditorBrowsableState.Never)]
342                 protected void SetStringResourcePointer (object stringResourcePointer,
343                                                          int maxResourceOffset)
344                 {
345                 }
346
347                 [MonoTODO ("Not implemented, does nothing")]
348                 [EditorBrowsable (EditorBrowsableState.Never)]
349                 protected void WriteUTF8ResourceString (HtmlTextWriter output, int offset,
350                                                         int size, bool fAsciiOnly)
351                 {
352                 }
353
354                 #endregion
355
356                 #region Events
357
358                 [WebSysDescription ("Raised when the user aborts a transaction.")]
359                 public event EventHandler AbortTransaction {
360                         add { Events.AddHandler (abortTransaction, value); }
361                         remove { Events.RemoveHandler (abortTransaction, value); }
362                 }
363
364                 [WebSysDescription ("Raised when the user initiates a transaction.")]
365                 public event EventHandler CommitTransaction {
366                         add { Events.AddHandler (commitTransaction, value); }
367                         remove { Events.RemoveHandler (commitTransaction, value); }
368                 }
369
370                 [WebSysDescription ("Raised when an exception occurs that cannot be handled.")]
371                 public event EventHandler Error {
372                         add { Events.AddHandler (error, value); }
373                         remove { Events.RemoveHandler (error, value); }
374                 }
375
376                 #endregion
377
378                 class SimpleTemplate : ITemplate
379                 {
380                         Type type;
381
382                         public SimpleTemplate (Type type)
383                         {
384                                 this.type = type;
385                         }
386
387                         public void InstantiateIn (Control control)
388                         {
389                                 Control template = Activator.CreateInstance (type) as Control;
390                                 template.SetBindingContainer (false);
391                                 control.Controls.Add (template);
392                         }
393                 }
394
395 #if NET_2_0
396                 protected internal object Eval (string expression)
397                 {
398                         return DataBinder.Eval (Page.GetDataItem(), expression);
399                 }
400         
401                 protected internal string Eval (string expression, string format)
402                 {
403                         return DataBinder.Eval (Page.GetDataItem(), expression, format);
404                 }
405         
406                 protected internal object XPath (string xpathexpression)
407                 {
408                         return XPathBinder.Eval (Page.GetDataItem(), xpathexpression);
409                 }
410         
411                 protected internal object XPath (string xpathexpression, IXmlNamespaceResolver resolver)
412                 {
413                         return XPathBinder.Eval (Page.GetDataItem (), xpathexpression, null, resolver);
414                 }
415
416                 protected internal string XPath (string xpathexpression, string format)
417                 {
418                         return XPathBinder.Eval (Page.GetDataItem(), xpathexpression, format);
419                 }
420         
421                 protected internal string XPath (string xpathexpression, string format, IXmlNamespaceResolver resolver)
422                 {
423                         return XPathBinder.Eval (Page.GetDataItem (), xpathexpression, format, resolver);
424                 }
425
426                 protected internal IEnumerable XPathSelect (string xpathexpression)
427                 {
428                         return XPathBinder.Select (Page.GetDataItem(), xpathexpression);
429                 }
430
431                 protected internal IEnumerable XPathSelect (string xpathexpression, IXmlNamespaceResolver resolver)
432                 {
433                         return XPathBinder.Select (Page.GetDataItem (), xpathexpression, resolver);
434                 }
435
436                 // IFilterResolutionService
437
438                 [MonoTODO ("Not implemented")]
439                 int IFilterResolutionService.CompareFilters (string filter1, string filter2)
440                 {
441                         throw new NotImplementedException ();
442                 }
443
444                 [MonoTODO ("Not implemented")]
445                 bool IFilterResolutionService.EvaluateFilter (string filterName)
446                 {
447                         throw new NotImplementedException ();
448                 }
449 #endif
450         }
451 }