2006-02-07 Chris Toshok <toshok@ximian.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
39 namespace System.Web.UI {
40
41         // CAS
42         [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
43         [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
44 #if NET_2_0
45         public abstract class TemplateControl : Control, INamingContainer, IFilterResolutionService {
46 #else
47         public abstract class TemplateControl : Control, INamingContainer {
48 #endif
49                 static object abortTransaction = new object ();
50                 static object commitTransaction = new object ();
51                 static object error = new object ();
52                 static string [] methodNames = { "Page_Init",
53                                                  "Page_Load",
54                                                  "Page_DataBind",
55                                                  "Page_PreRender",
56                                                  "Page_Disposed",
57                                                  "Page_Error",
58                                                  "Page_Unload",
59                                                  "Page_AbortTransaction",
60                                                  "Page_CommitTransaction" };
61
62                 const BindingFlags bflags = BindingFlags.Public |
63                                             BindingFlags.NonPublic |
64                                             BindingFlags.Instance;
65
66                 #region Constructor
67                 protected TemplateControl ()
68                 {
69                         Construct ();
70                 }
71
72                 #endregion
73
74                 #region Properties
75                 [EditorBrowsable (EditorBrowsableState.Never)]
76                 protected virtual int AutoHandlers {
77                         get { return 0; }
78                         set { }
79                 }
80
81                 [EditorBrowsable (EditorBrowsableState.Never)]
82                 protected virtual bool SupportAutoEvents {
83                         get { return true; }
84                 }
85
86                 #endregion
87
88                 #region Methods
89
90                 protected virtual void Construct ()
91                 {
92                 }
93
94                 [MonoTODO]
95                 protected LiteralControl CreateResourceBasedLiteralControl (int offset,
96                                                                                     int size,
97                                                                                     bool fAsciiOnly)
98                 {
99                         return null;
100                 }
101
102                 internal void WireupAutomaticEvents ()
103                 {
104                         if (!SupportAutoEvents || !AutoEventWireup)
105                                 return;
106
107                         Type type = GetType ();
108                         foreach (string methodName in methodNames) {
109                                 MethodInfo method = type.GetMethod (methodName, bflags);
110                                 if (method == null)
111                                         continue;
112
113                                 if (method.DeclaringType != type) {
114                                         if (!method.IsPublic && !method.IsFamilyOrAssembly &&
115                                             !method.IsFamilyAndAssembly && !method.IsFamily)
116                                                 continue;
117                                 }
118
119                                 if (method.ReturnType != typeof (void))
120                                         continue;
121
122                                 ParameterInfo [] parms = method.GetParameters ();
123                                 int length = parms.Length;
124                                 bool noParams = (length == 0);
125                                 if (!noParams && (length != 2 ||
126                                     parms [0].ParameterType != typeof (object) ||
127                                     parms [1].ParameterType != typeof (EventArgs)))
128                                     continue;
129
130                                 int pos = methodName.IndexOf ("_");
131                                 string eventName = methodName.Substring (pos + 1);
132                                 EventInfo evt = type.GetEvent (eventName);
133                                 if (evt == null) {
134                                         /* This should never happen */
135                                         continue;
136                                 }
137
138                                 if (noParams) {
139                                         NoParamsInvoker npi = new NoParamsInvoker (this, methodName);
140                                         evt.AddEventHandler (this, npi.FakeDelegate);
141                                 } else {
142                                         evt.AddEventHandler (this, Delegate.CreateDelegate (
143                                                         typeof (EventHandler), this, methodName));
144                                 }
145                         }
146                 }
147
148                 [EditorBrowsable (EditorBrowsableState.Never)]
149                 protected virtual void FrameworkInitialize ()
150                 {
151                 }
152
153                 Type GetTypeFromControlPath (string virtualPath)
154                 {
155                         if (virtualPath == null)
156                                 throw new ArgumentNullException ("virtualPath");
157
158                         string vpath = UrlUtils.Combine (TemplateSourceDirectory, virtualPath);
159                         string realpath = Context.Request.MapPath (vpath);
160                         return UserControlParser.GetCompiledType (vpath, realpath, Context);
161                 }
162
163                 public Control LoadControl (string virtualPath)
164                 {
165 #if NET_2_0
166                         if (virtualPath == null)
167                                 throw new ArgumentNullException ("virtualPath");
168 #else
169                         if (virtualPath == null)
170                                 throw new HttpException ("virtualPath is null");
171 #endif
172                         Type type = GetTypeFromControlPath (virtualPath);
173                         object [] attrs = type.GetCustomAttributes (typeof (PartialCachingAttribute), true);
174                         if (attrs != null && attrs.Length == 1) {
175                                 PartialCachingAttribute attr = (PartialCachingAttribute) attrs [0];
176                                 PartialCachingControl ctrl = new PartialCachingControl (type);
177                                 ctrl.VaryByParams = attr.VaryByParams;
178                                 ctrl.VaryByControls = attr.VaryByControls;
179                                 ctrl.VaryByCustom = attr.VaryByCustom;
180                                 return ctrl;
181                         }
182
183                         object control = Activator.CreateInstance (type);
184                         if (control is UserControl)
185                                 ((UserControl) control).InitializeAsUserControl (Page);
186
187                         return (Control) control;
188                 }
189
190                 public ITemplate LoadTemplate (string virtualPath)
191                 {
192 #if NET_2_0
193                         if (virtualPath == null)
194                                 throw new ArgumentNullException ("virtualPath");
195 #else
196                         if (virtualPath == null)
197                                 throw new HttpException ("virtualPath is null");
198 #endif
199                         Type t = GetTypeFromControlPath (virtualPath);
200                         return new SimpleTemplate (t);
201                 }
202
203                 protected virtual void OnAbortTransaction (EventArgs e)
204                 {
205                         EventHandler eh = Events [abortTransaction] as EventHandler;
206                         if (eh != null)
207                                 eh (this, e);
208                 }
209
210                 protected virtual void OnCommitTransaction (EventArgs e)
211                 {
212                         EventHandler eh = Events [commitTransaction] as EventHandler;
213                         if (eh != null)
214                                 eh (this, e);
215                 }
216
217                 protected virtual void OnError (EventArgs e)
218                 {
219                         EventHandler eh = Events [error] as EventHandler;
220                         if (eh != null)
221                                 eh (this, e);
222                 }
223
224                 [MonoTODO]
225                 public Control ParseControl (string content)
226                 {
227                         if (content == null)
228                                 throw new ArgumentNullException ("content");
229
230                         return null;
231                 }
232
233                 [EditorBrowsable (EditorBrowsableState.Never)]
234                 public static object ReadStringResource ()
235                 {
236                         throw new NotSupportedException ();
237                 }
238
239                 [EditorBrowsable (EditorBrowsableState.Never)]
240                 public static object ReadStringResource (Type t)
241                 {
242                         throw new NotSupportedException ();
243                 }
244
245                 [MonoTODO]
246                 [EditorBrowsable (EditorBrowsableState.Never)]
247                 protected void SetStringResourcePointer (object stringResourcePointer,
248                                                          int maxResourceOffset)
249                 {
250                 }
251
252                 [MonoTODO]
253                 [EditorBrowsable (EditorBrowsableState.Never)]
254                 protected void WriteUTF8ResourceString (HtmlTextWriter output, int offset,
255                                                         int size, bool fAsciiOnly)
256                 {
257                 }
258
259                 #endregion
260
261                 #region Events
262
263                 [WebSysDescription ("Raised when the user aborts a transaction.")]
264                 public event EventHandler AbortTransaction {
265                         add { Events.AddHandler (abortTransaction, value); }
266                         remove { Events.RemoveHandler (abortTransaction, value); }
267                 }
268
269                 [WebSysDescription ("Raised when the user initiates a transaction.")]
270                 public event EventHandler CommitTransaction {
271                         add { Events.AddHandler (commitTransaction, value); }
272                         remove { Events.RemoveHandler (commitTransaction, value); }
273                 }
274
275                 [WebSysDescription ("Raised when an exception occurs that cannot be handled.")]
276                 public event EventHandler Error {
277                         add { Events.AddHandler (error, value); }
278                         remove { Events.RemoveHandler (error, value); }
279                 }
280
281                 #endregion
282
283                 class SimpleTemplate : ITemplate
284                 {
285                         Type type;
286
287                         public SimpleTemplate (Type type)
288                         {
289                                 this.type = type;
290                         }
291
292                         public void InstantiateIn (Control control)
293                         {
294                                 Control template = Activator.CreateInstance (type) as Control;
295                                 template.SetBindingContainer (false);
296                                 control.Controls.Add (template);
297                         }
298                 }
299
300 #if NET_2_0
301
302                 Stack dataItemCtx;
303         
304                 internal void PushDataItemContext (object o)
305                 {
306                         if (dataItemCtx == null)
307                                 dataItemCtx = new Stack ();
308                 
309                         dataItemCtx.Push (o);
310                 }
311                 
312                 internal void PopDataItemContext ()
313                 {
314                         if (dataItemCtx == null)
315                                 throw new InvalidOperationException ();
316                 
317                         dataItemCtx.Pop ();
318                 }
319         
320                 internal object CurrentDataItem {
321                         get {
322                                 if (dataItemCtx == null || dataItemCtx.Count == 0)
323                                         throw new InvalidOperationException ("No data item");
324                         
325                                 return dataItemCtx.Peek ();
326                         }
327                 }
328         
329                 protected object Eval (string expression)
330                 {
331                         return DataBinder.Eval (CurrentDataItem, expression);
332                 }
333         
334                 protected object Eval (string expression, string format)
335                 {
336                         return DataBinder.Eval (CurrentDataItem, expression, format);
337                 }
338         
339                 protected object XPath (string xpathexpression)
340                 {
341                         return XPathBinder.Eval (CurrentDataItem, xpathexpression);
342                 }
343         
344                 protected object XPath (string xpathexpression, string format)
345                 {
346                         return XPathBinder.Eval (CurrentDataItem, xpathexpression, format);
347                 }
348         
349                 protected IEnumerable XPathSelect (string xpathexpression)
350                 {
351                         return XPathBinder.Select (CurrentDataItem, xpathexpression);
352                 }
353
354                 // IFilterResolutionService
355
356                 [MonoTODO]
357                 int IFilterResolutionService.CompareFilters (string filter1, string filter2)
358                 {
359                         throw new NotImplementedException ();
360                 }
361
362                 [MonoTODO]
363                 bool IFilterResolutionService.EvaluateFilter (string filterName)
364                 {
365                         throw new NotImplementedException ();
366                 }
367 #endif
368         }
369 }