Moved chain building and validation from Mono.Security to System
[mono.git] / mcs / class / System.Web / System.Web.UI / Control.cs
1 //
2 // System.Web.UI.Control.cs
3 //
4 // Authors:
5 //   Bob Smith <bob@thestuff.net>
6 //   Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 //   Andreas Nahr (ClassDevelopment@A-SoftTech.com)
8 //   Sanjay Gupta (gsanjay@novell.com)
9 //   Marek Habersack <mhabersack@novell.com>
10 //
11 // (C) Bob Smith
12 // (c) 2002,2003 Ximian, Inc. (http://www.ximian.com)
13 // (C) 2004-2010 Novell, Inc. (http://www.novell.com)
14 //
15
16 //
17 // Permission is hereby granted, free of charge, to any person obtaining
18 // a copy of this software and associated documentation files (the
19 // "Software"), to deal in the Software without restriction, including
20 // without limitation the rights to use, copy, modify, merge, publish,
21 // distribute, sublicense, and/or sell copies of the Software, and to
22 // permit persons to whom the Software is furnished to do so, subject to
23 // the following conditions:
24 // 
25 // The above copyright notice and this permission notice shall be
26 // included in all copies or substantial portions of the Software.
27 // 
28 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
32 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
33 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
34 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 //
36
37 using System.Collections;
38 using System.Collections.Generic;
39 using System.ComponentModel;
40 using System.ComponentModel.Design;
41 using System.ComponentModel.Design.Serialization;
42 using System.Globalization;
43 using System.IO;
44 using System.Security.Permissions;
45 using System.Web;
46 using System.Web.Util;
47 using System.Web.UI.Adapters;
48
49 namespace System.Web.UI
50 {
51         // CAS
52         [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
53         [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
54         // attributes
55         [DefaultProperty ("ID"), DesignerCategory ("Code"), ToolboxItemFilter ("System.Web.UI", ToolboxItemFilterType.Require)]
56         [ToolboxItem ("System.Web.UI.Design.WebControlToolboxItem, " + Consts.AssemblySystem_Design)]
57         [Designer ("System.Web.UI.Design.ControlDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
58         [DesignerSerializer ("Microsoft.VisualStudio.Web.WebForms.ControlCodeDomSerializer, " + Consts.AssemblyMicrosoft_VisualStudio_Web,
59                                 "System.ComponentModel.Design.Serialization.CodeDomSerializer, " + Consts.AssemblySystem_Design)]
60         [Bindable (true)]
61         [Themeable (false)]
62         public partial class Control : IComponent, IDisposable, IParserAccessor, IDataBindingsAccessor, IUrlResolutionService, IControlBuilderAccessor, IControlDesignerAccessor, IExpressionsAccessor
63         {
64                 internal static readonly object DataBindingEvent = new object ();
65                 internal static readonly object DisposedEvent = new object ();
66                 internal static readonly object InitEvent = new object ();
67                 internal static readonly object LoadEvent = new object ();
68                 internal static readonly object PreRenderEvent = new object ();
69                 internal static readonly object UnloadEvent = new object ();
70                 internal static string [] defaultNameArray;
71                 /* */
72                 int event_mask;
73                 const int databinding_mask = 1;
74                 const int disposed_mask = 1 << 1;
75                 const int init_mask = 1 << 2;
76                 const int load_mask = 1 << 3;
77                 const int prerender_mask = 1 << 4;
78                 const int unload_mask = 1 << 5;
79                 /* */
80
81                 [ThreadStatic]
82                 static Dictionary <Type, bool> loadViewStateByIDCache;
83                 bool? loadViewStateByID;
84                 string uniqueID;
85                 string _userId;
86                 ControlCollection _controls;
87                 Control _namingContainer;
88                 Page _page;
89                 Control _parent;
90                 ISite _site;
91                 StateBag _viewState;
92                 EventHandlerList _events;
93                 RenderMethod _renderMethodDelegate;
94                 Hashtable _controlsCache;
95                 int defaultNumberID;
96
97                 DataBindingCollection dataBindings;
98                 Hashtable pendingVS; // may hold unused viewstate data from child controls
99                 TemplateControl _templateControl;
100                 bool _isChildControlStateCleared;
101                 string _templateSourceDirectory;
102
103                 /*************/
104                 int stateMask;
105                 const int ENABLE_VIEWSTATE = 1;
106                 const int VISIBLE = 1 << 1;
107                 const int AUTOID = 1 << 2;
108                 const int CREATING_CONTROLS = 1 << 3;
109                 const int BINDING_CONTAINER = 1 << 4;
110                 const int AUTO_EVENT_WIREUP = 1 << 5;
111                 const int IS_NAMING_CONTAINER = 1 << 6;
112                 const int VISIBLE_CHANGED = 1 << 7;
113                 const int TRACK_VIEWSTATE = 1 << 8;
114                 const int CHILD_CONTROLS_CREATED = 1 << 9;
115                 const int ID_SET = 1 << 10;
116                 const int INITED = 1 << 11;
117                 const int INITING = 1 << 12;
118                 const int VIEWSTATE_LOADED = 1 << 13;
119                 const int LOADED = 1 << 14;
120                 const int PRERENDERED = 1 << 15;
121                 const int ENABLE_THEMING = 1 << 16;
122                 const int AUTOID_SET = 1 << 17;
123                 const int REMOVED = 1 << 18;
124                 /*************/
125
126                 static Control ()
127                 {
128                         defaultNameArray = new string [100];
129                         for (int i = 0; i < 100; i++)
130                                 defaultNameArray [i] = String.Concat ("ctl", i.ToString ("D2"));
131                 }
132
133                 public Control ()
134                 {
135                         stateMask = ENABLE_VIEWSTATE | VISIBLE | AUTOID | BINDING_CONTAINER | AUTO_EVENT_WIREUP;
136                         if (this is INamingContainer)
137                                 stateMask |= IS_NAMING_CONTAINER;
138                 }
139                 
140                 ControlAdapter adapter;
141                 bool did_adapter_lookup;
142                 protected internal ControlAdapter Adapter {
143                         get {
144                                 if (!did_adapter_lookup) {
145                                         adapter = ResolveAdapter ();
146                                         if (adapter != null)
147                                                 adapter.control = this;
148                                         did_adapter_lookup = true;
149                                 }
150                                 return adapter;
151                         }
152                 }
153
154                 string _appRelativeTemplateSourceDirectory = null;
155
156                 [EditorBrowsable (EditorBrowsableState.Advanced)]
157                 [Browsable (false)]
158                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
159                 public string AppRelativeTemplateSourceDirectory {
160                         get {
161                                 if (_appRelativeTemplateSourceDirectory != null)
162                                         return _appRelativeTemplateSourceDirectory;
163
164                                 string tempSrcDir = null;
165                                 TemplateControl templateControl = TemplateControl;
166                                 if (templateControl != null) {
167                                         string templateVirtualPath = templateControl.AppRelativeVirtualPath;
168                                         if (!String.IsNullOrEmpty (templateVirtualPath))
169                                                 tempSrcDir = VirtualPathUtility.GetDirectory (templateVirtualPath, false);
170                                 }
171                                 
172                                 _appRelativeTemplateSourceDirectory = (tempSrcDir != null) ? tempSrcDir : VirtualPathUtility.ToAppRelative (TemplateSourceDirectory);
173                                 return _appRelativeTemplateSourceDirectory;
174                         }
175                         [EditorBrowsable (EditorBrowsableState.Never)]
176                         set {
177                                 _appRelativeTemplateSourceDirectory = value;
178                                 _templateSourceDirectory = null;
179                         }
180                 }
181
182                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
183                 [EditorBrowsable (EditorBrowsableState.Never), Browsable (false)]
184                 public Control BindingContainer {
185                         get {
186                                 Control container = NamingContainer;
187                                 if (container != null && container is INonBindingContainer || (stateMask & BINDING_CONTAINER) == 0)
188                                         container = container.BindingContainer;
189
190                                 return container;
191                         }
192                 }
193
194                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
195                 [Browsable (false)]
196                 [WebSysDescription ("An Identification of the control that is rendered.")]
197                 public virtual string ClientID {
198                         get {
199                                 string client = UniqueID;
200
201                                 if (client != null)
202                                         client = UniqueID2ClientID (client);
203
204                                 stateMask |= ID_SET;
205                                 return client;
206                         }
207                 }
208
209                 internal string UniqueID2ClientID (string uniqueId)
210                 {
211                         return uniqueId.Replace (IdSeparator, ClientIDSeparator);
212                 }
213
214                 protected char ClientIDSeparator {
215                         get { return '_'; }
216                 }
217
218
219                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
220                 [Browsable (false)]
221                 [WebSysDescription ("The child controls of this control.")]
222                 public virtual ControlCollection Controls { //DIT
223                         get {
224                                 if (_controls == null)
225                                         _controls = CreateControlCollection ();
226                                 return _controls;
227                         }
228                 }
229
230                 [MonoTODO ("revisit once we have a real design strategy")]
231                 protected internal bool DesignMode {
232                         get { return false; }
233                 }
234
235                 [DefaultValue (true), WebCategory ("Behavior")]
236                 [WebSysDescription ("An Identification of the control that is rendered.")]
237                 [Themeable (false)]
238                 public virtual bool EnableViewState {
239                         get { return ((stateMask & ENABLE_VIEWSTATE) != 0); }
240                         set { SetMask (ENABLE_VIEWSTATE, value); }
241                 }
242
243                 [MergableProperty (false), ParenthesizePropertyName (true)]
244                 [WebSysDescription ("The name of the control that is rendered.")]
245                 [Filterable (false), Themeable (false)]
246                 public virtual string ID {
247                         get { return (((stateMask & ID_SET) != 0) ? _userId : null); }
248
249                         set {
250                                 if (value != null && value.Length == 0)
251                                         value = null;
252
253                                 stateMask |= ID_SET;
254                                 _userId = value;
255                                 NullifyUniqueID ();
256                         }
257                 }
258
259                 protected internal bool IsChildControlStateCleared {
260                         get { return _isChildControlStateCleared; }
261                 }
262
263                 protected bool LoadViewStateByID {
264                         get {
265                                 if (loadViewStateByID == null)
266                                         loadViewStateByID = IsLoadViewStateByID ();
267
268                                 return (bool)loadViewStateByID;
269                         }
270                 }
271
272                 protected internal bool IsViewStateEnabled {
273                         get {
274                                 for (Control control = this; control != null; control = control.Parent)
275                                         if (!control.EnableViewState)
276                                                 return false;
277
278                                 return true;
279                         }
280                 }
281
282                 protected char IdSeparator {
283                         get { return '$'; }
284                 }
285
286                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
287                 [Browsable (false)]
288                 [WebSysDescription ("The container that this control is part of. The control's name has to be unique within the container.")]
289                 public virtual Control NamingContainer {
290                         get {
291                                 if (_namingContainer == null && _parent != null) {
292                                         if ((_parent.stateMask & IS_NAMING_CONTAINER) == 0)
293                                                 _namingContainer = _parent.NamingContainer;
294                                         else
295                                                 _namingContainer = _parent;
296                                 }
297
298                                 return _namingContainer;
299                         }
300                 }
301
302                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
303                 [Browsable (false)]
304                 [WebSysDescription ("The webpage that this control resides on.")]
305                 [Bindable (false)]
306                 public virtual Page Page { //DIT
307                         get {
308                                 if (_page == null){
309                                         if (NamingContainer != null)
310                                                 _page = NamingContainer.Page;
311                                         else if (Parent != null)
312                                                 _page = Parent.Page;
313                                 }
314                                 return _page;
315                         }
316                         
317                         set { _page = value; }
318                 }
319
320                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
321                 [Browsable (false)]
322                 [WebSysDescription ("The parent control of this control.")]
323                 public virtual Control Parent { //DIT
324                         get { return _parent; }
325                 }
326
327                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
328                 [EditorBrowsable (EditorBrowsableState.Advanced), Browsable (false)]
329                 [WebSysDescription ("The site this control is part of.")]
330                 public ISite Site { //DIT
331                         get { return _site; }
332                         set { _site = value; }
333                 }
334
335                 [Browsable (false)]
336                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
337                 public TemplateControl TemplateControl {
338                         get { return TemplateControlInternal; }
339
340                         [EditorBrowsable (EditorBrowsableState.Never)]
341                         set { _templateControl = value; }
342                 }
343
344                 internal virtual TemplateControl TemplateControlInternal {
345                         get {
346                                 if (_templateControl != null)
347                                         return _templateControl;
348                                 if (_parent != null)
349                                         return _parent.TemplateControl;
350                                 return null;
351                         }
352                 }
353
354 #if !TARGET_J2EE
355                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
356                 [Browsable (false)]
357                 [WebSysDescription ("A virtual directory containing the parent of the control.")]
358                 public virtual string TemplateSourceDirectory {
359                         get {
360                                 if (_templateSourceDirectory == null) {
361                                         TemplateControl tc = TemplateControl;
362
363                                         if (tc == null) {
364                                                 HttpContext ctx = Context;
365                                                 if (ctx != null)
366                                                         _templateSourceDirectory = VirtualPathUtility.GetDirectory (ctx.Request.CurrentExecutionFilePath);
367                                         } else if (tc != this)
368                                                 _templateSourceDirectory = tc.TemplateSourceDirectory;
369
370                                         if (_templateSourceDirectory == null && this is TemplateControl) {
371                                                 string path = ((TemplateControl) this).AppRelativeVirtualPath;
372
373                                                 if (path != null) {
374                                                         string ret = VirtualPathUtility.GetDirectory (VirtualPathUtility.ToAbsolute (path));
375                                                         int len = ret.Length;
376                                                         if (len <= 1)
377                                                                 return ret;
378                                                         if (ret [--len] == '/')
379                                                                 _templateSourceDirectory = ret.Substring (0, len);
380                                                 } else
381                                                         _templateSourceDirectory = String.Empty;
382                                         }
383                                         if (_templateSourceDirectory == null)
384                                                 _templateSourceDirectory = String.Empty;
385                                 }
386
387                                 return _templateSourceDirectory;
388                         }
389                 }
390 #endif
391
392                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
393                 [Browsable (false)]
394                 [WebSysDescription ("The unique ID of the control.")]
395                 public virtual string UniqueID {
396                         get {
397                                 if (uniqueID != null)
398                                         return uniqueID;
399
400                                 if (NamingContainer == null)
401                                         return _userId;
402
403                                 EnsureIDInternal ();
404
405                                 string prefix = NamingContainer.UniqueID;
406                                 if (NamingContainer == Page || prefix == null) {
407                                         uniqueID = _userId;
408 #if TARGET_J2EE
409                                         if (getFacesContext () != null)
410                                                 uniqueID = getFacesContext ().getExternalContext ().encodeNamespace (uniqueID);
411 #endif
412                                         return uniqueID;
413                                 }
414
415                                 uniqueID = prefix + IdSeparator + _userId;
416                                 return uniqueID;
417                         }
418                 }
419
420                 void SetMask (int m, bool val) {
421                         if (val)
422                                 stateMask |= m;
423                         else
424                                 stateMask &= ~m;
425                 }
426
427                 [DefaultValue (true), Bindable (true), WebCategory ("Behavior")]
428                 [WebSysDescription ("Visiblity state of the control.")]
429                 public virtual bool Visible {
430                         get {
431                                 if ((stateMask & VISIBLE) == 0)
432                                         return false;
433
434                                 if (_parent != null)
435                                         return _parent.Visible;
436
437                                 return true;
438                         }
439
440                         set {
441                                 if ((value && (stateMask & VISIBLE) == 0) ||
442                                         (!value && (stateMask & VISIBLE) != 0)) {
443                                         if (IsTrackingViewState)
444                                                 stateMask |= VISIBLE_CHANGED;
445                                 }
446
447                                 SetMask (VISIBLE, value);
448                         }
449                 }
450
451                 protected bool ChildControlsCreated {
452                         get { return ((stateMask & CHILD_CONTROLS_CREATED) != 0); }
453                         set {
454                                 if (value == false && (stateMask & CHILD_CONTROLS_CREATED) != 0) {
455                                         if (_controls != null)
456                                                 _controls.Clear ();
457                                 }
458
459                                 SetMask (CHILD_CONTROLS_CREATED, value);
460                         }
461                 }
462
463                 [Browsable (false)]
464                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
465                 protected internal virtual HttpContext Context { //DIT
466                         get {
467                                 Page page = Page;
468                                 if (page != null)
469                                         return page.Context;
470                                 
471                                 return HttpContext.Current;
472                         }
473                 }
474
475                 protected EventHandlerList Events {
476                         get {
477                                 if (_events == null)
478                                         _events = new EventHandlerList ();
479                                 return _events;
480                         }
481                 }
482
483                 protected bool HasChildViewState {
484                         get { return (pendingVS != null && pendingVS.Count > 0); }
485                 }
486
487                 protected bool IsTrackingViewState {
488                         get { return ((stateMask & TRACK_VIEWSTATE) != 0); }
489                 }
490
491                 [Browsable (false)]
492                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
493                 [WebSysDescription ("ViewState")]
494                 protected virtual StateBag ViewState {
495                         get {
496                                 if (_viewState == null)
497                                         _viewState = new StateBag (ViewStateIgnoresCase);
498
499                                 if (IsTrackingViewState)
500                                         _viewState.TrackViewState ();
501
502                                 return _viewState;
503                         }
504                 }
505
506                 [Browsable (false)]
507                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
508                 protected virtual bool ViewStateIgnoresCase {
509                         get { return false; }
510                 }
511
512                 internal bool AutoEventWireup {
513                         get { return (stateMask & AUTO_EVENT_WIREUP) != 0; }
514                         set { SetMask (AUTO_EVENT_WIREUP, value); }
515                 }
516                 
517                 internal void SetBindingContainer (bool isBC)
518                 {
519                         SetMask (BINDING_CONTAINER, isBC);
520                 }
521
522                 internal void ResetChildNames ()
523                 {
524                         ResetChildNames (-1);
525                 }
526
527                 internal void ResetChildNames (int value)
528                 {
529                         if (value < 0)
530                                 defaultNumberID = 0;
531                         else
532                                 defaultNumberID = value;
533                 }
534
535                 internal int GetDefaultNumberID ()
536                 {
537                         return defaultNumberID;
538                 }
539
540                 string GetDefaultName ()
541                 {
542                         string defaultName;
543                         if (defaultNumberID > 99)
544                                 defaultName = "ctl" + defaultNumberID++;
545                         else
546                                 defaultName = defaultNameArray [defaultNumberID++];
547                         return defaultName;
548                 }
549
550                 void NullifyUniqueID ()
551                 {
552                         uniqueID = null;
553                         if (!HasControls ())
554                                 return;
555
556                         for (int i = 0; i < _controls.Count; i++)
557                                 _controls [i].NullifyUniqueID ();
558                 }
559
560                 bool IsLoadViewStateByID ()
561                 {
562                         if (loadViewStateByIDCache == null)
563                                 loadViewStateByIDCache = new Dictionary <Type, bool> ();
564
565                         bool ret;
566                         Type myType = GetType ();
567                         if (loadViewStateByIDCache.TryGetValue (myType, out ret))
568                                 return ret;
569
570                         System.ComponentModel.AttributeCollection attrs = TypeDescriptor.GetAttributes (myType);
571                         if (attrs != null || attrs.Count > 0) {
572                                 ret = false;
573                                 foreach (Attribute attr in attrs) {
574                                         if (attr is ViewStateModeByIdAttribute) {
575                                                 ret = true;
576                                                 break;
577                                         }
578                                 }
579                         } else
580                                 ret = false;
581                         
582                         loadViewStateByIDCache.Add (myType, ret);
583                         return ret;
584                 }
585                 
586                 protected internal virtual void AddedControl (Control control, int index)
587                 {
588                         ResetControlsCache ();
589
590                         /* Ensure the control don't have more than 1 parent */
591                         if (control._parent != null)
592                                 control._parent.Controls.Remove (control);
593
594                         control._parent = this;
595                         Control nc = ((stateMask & IS_NAMING_CONTAINER) != 0) ? this : NamingContainer;
596
597                         if ((stateMask & (INITING | INITED)) != 0) {
598                                 control.InitRecursive (nc);
599                                 control.SetMask (REMOVED, false);
600                         } else {
601                                 control.SetNamingContainer (nc);
602                                 control.SetMask (REMOVED, false);
603                                 return;
604                         }
605
606                         if ((stateMask & (VIEWSTATE_LOADED | LOADED)) != 0) {
607                                 if (pendingVS != null) {
608                                         object vs;
609                                         bool byId = LoadViewStateByID;
610                                         string id;
611                                         
612                                         if (byId) {
613                                                 control.EnsureID ();
614                                                 id = control.ID;
615                                                 vs = pendingVS [id];
616                                         } else {
617                                                 id = null;
618                                                 vs = pendingVS [index];
619                                         }
620                                         
621                                         if (vs != null) {
622                                                 if (byId)
623                                                         pendingVS.Remove (id);
624                                                 else
625                                                         pendingVS.Remove (index);
626                                                 
627                                                 if (pendingVS.Count == 0)
628                                                         pendingVS = null;
629
630                                                 control.LoadViewStateRecursive (vs);
631                                         }
632                                 }
633                         }
634
635                         if ((stateMask & LOADED) != 0)
636                                 control.LoadRecursive ();
637
638                         if ((stateMask & PRERENDERED) != 0)
639                                 control.PreRenderRecursiveInternal ();
640                 }
641                 
642                 void SetNamingContainer (Control nc)
643                 {
644                         if (nc != null) {
645                                 _namingContainer = nc;
646                                 if (AutoID)
647                                         EnsureIDInternal ();
648                         }
649                 }
650
651                 protected virtual void AddParsedSubObject (object obj) //DIT
652                 {
653                         Control c = obj as Control;
654                         if (c != null)
655                                 Controls.Add (c);
656                 }
657
658                 [EditorBrowsable (EditorBrowsableState.Advanced)]
659                 public virtual void ApplyStyleSheetSkin (Page page)
660                 {
661                         if (page == null)
662                                 return;
663
664                         if (!EnableTheming) /* this enough? */
665                                 return;
666
667                         /* apply the style sheet skin here */
668                         if (page.StyleSheetPageTheme != null) {
669                                 ControlSkin cs = page.StyleSheetPageTheme.GetControlSkin (GetType (), SkinID);
670                                 if (cs != null)
671                                         cs.ApplySkin (this);
672                         }
673                 }
674
675                 [MonoTODO]
676                 protected void BuildProfileTree (string parentId, bool calcViewState)
677                 {
678                 }
679
680                 protected void ClearChildControlState ()
681                 {
682                         _isChildControlStateCleared = true;
683                 }
684
685                 protected void ClearChildState ()
686                 {
687                         ClearChildViewState ();
688                         ClearChildControlState ();
689                 }
690
691                 protected void ClearChildViewState ()
692                 {
693                         pendingVS = null;
694                 }
695
696                 protected internal virtual void CreateChildControls () //DIT
697                 {
698                 }
699
700                 protected virtual ControlCollection CreateControlCollection () //DIT
701                 {
702                         return new ControlCollection (this);
703                 }
704
705                 protected virtual void EnsureChildControls ()
706                 {
707                         if (ChildControlsCreated == false && (stateMask & CREATING_CONTROLS) == 0) {
708                                 stateMask |= CREATING_CONTROLS;
709                                 if (Adapter != null)
710                                         Adapter.CreateChildControls ();
711                                 else
712                                         CreateChildControls ();
713                                 ChildControlsCreated = true;
714                                 stateMask &= ~CREATING_CONTROLS;
715                         }
716                 }
717
718                 void EnsureIDInternal ()
719                 {
720                         if (_userId != null)
721                                 return;
722
723                         _userId = NamingContainer.GetDefaultName ();
724                         SetMask (AUTOID_SET, true);
725                 }
726
727                 protected void EnsureID ()
728                 {
729                         if (NamingContainer == null)
730                                 return;
731                         EnsureIDInternal ();
732                         SetMask (ID_SET, true);
733                 }
734
735                 protected bool HasEvents ()
736                 {
737                         return _events != null;
738                 }
739
740                 void ResetControlsCache ()
741                 {
742                         _controlsCache = null;
743
744                         if ((this.stateMask & IS_NAMING_CONTAINER) == 0 && Parent != null)
745                                 Parent.ResetControlsCache ();
746                 }
747
748                 Hashtable InitControlsCache ()
749                 {
750                         if (_controlsCache != null)
751                                 return _controlsCache;
752
753                         if ((this.stateMask & IS_NAMING_CONTAINER) != 0 || Parent == null)
754                                 //LAMESPEC: MS' docs don't mention it, but FindControl is case insensitive.
755                                 _controlsCache = new Hashtable (StringComparer.OrdinalIgnoreCase);
756                         else
757                                 _controlsCache = Parent.InitControlsCache ();
758
759                         return _controlsCache;
760                 }
761
762                 void EnsureControlsCache ()
763                 {
764                         if (_controlsCache != null)
765                                 return;
766
767                         InitControlsCache ();
768                         FillControlCache (Controls);
769
770                 }
771
772                 void FillControlCache (ControlCollection controls)
773                 {
774                         foreach (Control c in controls) {
775                                 try {
776                                         if (c._userId != null)
777                                                 _controlsCache.Add (c._userId, c);
778                                 } catch (ArgumentException) {
779                                         throw new HttpException (
780                                                 "Multiple controls with the same ID '" + 
781                                                 c._userId + 
782                                                 "' were found. FindControl requires that controls have unique IDs. ");
783                                 }
784
785                                 if ((c.stateMask & IS_NAMING_CONTAINER) == 0 && c.HasControls ())
786                                         FillControlCache (c.Controls);
787                         }
788                 }
789
790                 protected bool IsLiteralContent ()
791                 {
792                         if (HasControls () && _controls.Count == 1 && (_controls [0] is LiteralControl))
793                                 return true;
794
795                         return false;
796                 }
797
798                 [WebSysDescription ("")]
799                 public virtual Control FindControl (string id)
800                 {
801                         return FindControl (id, 0);
802                 }
803
804                 Control LookForControlByName (string id)
805                 {
806                         EnsureControlsCache ();
807                         return (Control) _controlsCache [id];
808                 }
809
810                 protected virtual Control FindControl (string id, int pathOffset)
811                 {
812                         EnsureChildControls ();
813                         Control namingContainer = null;
814                         if ((stateMask & IS_NAMING_CONTAINER) == 0) {
815                                 namingContainer = NamingContainer;
816                                 if (namingContainer == null)
817                                         return null;
818                                 
819                                 return namingContainer.FindControl (id, pathOffset);
820                         }
821
822                         if (!HasControls ())
823                                 return null;
824                         
825                         int separatorIdx = id.IndexOf (IdSeparator, pathOffset);
826                         if (separatorIdx == -1)
827                                 return LookForControlByName (id.Substring (pathOffset));
828
829                         string idfound = id.Substring (pathOffset, separatorIdx - pathOffset);
830                         namingContainer = LookForControlByName (idfound);
831                         if (namingContainer == null)
832                                 return null;
833
834                         return namingContainer.FindControl (id, separatorIdx + 1);
835                 }
836
837                 protected virtual void LoadViewState (object savedState)
838                 {
839                         if (savedState != null) {
840                                 ViewState.LoadViewState (savedState);
841                                 object o = ViewState ["Visible"];
842                                 if (o != null) {
843                                         SetMask (VISIBLE, (bool) o);
844                                         stateMask |= VISIBLE_CHANGED;
845                                 }
846                         }
847                 }
848
849                 // [MonoTODO("Secure?")]
850                 protected string MapPathSecure (string virtualPath)
851                 {
852                         string combined = UrlUtils.Combine (TemplateSourceDirectory, virtualPath);
853                         return Context.Request.MapPath (combined);
854                 }
855
856                 protected virtual bool OnBubbleEvent (object source, EventArgs args) //DIT
857                 {
858 #if MONO_TRACE
859                         TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
860                         string type_name = null;
861                         if (trace != null) {
862                                 type_name = GetType ().Name;
863                                 trace.Write ("control", String.Concat ("OnBubbleEvent ", _userId, " ", type_name));
864                         }
865 #endif
866                         return false;
867                 }
868
869                 protected virtual void OnDataBinding (EventArgs e)
870                 {
871                         if ((event_mask & databinding_mask) != 0) {
872                                 EventHandler eh = (EventHandler) (_events [DataBindingEvent]);
873                                 if (eh != null) {
874 #if MONO_TRACE
875                                         TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
876                                         string type_name = null;
877                                         if (trace != null) {
878                                                 type_name = GetType ().Name;
879                                                 trace.Write ("control", String.Concat ("OnDataBinding ", _userId, " ", type_name));
880                                         }
881 #endif
882                                         eh (this, e);
883                                 }
884                         }
885                 }
886
887                 protected internal virtual void OnInit (EventArgs e)
888                 {
889                         if ((event_mask & init_mask) != 0) {
890                                 EventHandler eh = (EventHandler) (_events [InitEvent]);
891                                 if (eh != null) {
892 #if MONO_TRACE
893                                         TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
894                                         string type_name = null;
895                                         if (trace != null) {
896                                                 type_name = GetType ().Name;
897                                                 trace.Write ("control", String.Concat ("OnInit ", _userId, " ", type_name));
898                                         }
899 #endif
900                                         eh (this, e);
901                                 }
902                         }
903                 }
904
905                 protected internal virtual void OnLoad (EventArgs e)
906                 {
907                         if ((event_mask & load_mask) != 0) {
908                                 EventHandler eh = (EventHandler) (_events [LoadEvent]);
909                                 if (eh != null) {
910 #if MONO_TRACE
911                                         TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
912                                         string type_name = null;
913                                         if (trace != null) {
914                                                 type_name = GetType ().Name;
915                                                 trace.Write ("control", String.Concat ("OnLoad ", _userId, " ", type_name));
916                                         }
917 #endif
918                                         eh (this, e);
919                                 }
920                         }
921                 }
922
923                 protected internal virtual void OnPreRender (EventArgs e)
924                 {
925                         if ((event_mask & prerender_mask) != 0) {
926                                 EventHandler eh = (EventHandler) (_events [PreRenderEvent]);
927                                 if (eh != null) {
928 #if MONO_TRACE
929                                         TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
930                                         string type_name = null;
931                                         if (trace != null) {
932                                                 type_name = GetType ().Name;
933                                                 trace.Write ("control", String.Concat ("OnPreRender ", _userId, " ", type_name));
934                                         }
935 #endif
936                                         eh (this, e);
937                                 }
938                         }
939                 }
940
941                 protected internal virtual void OnUnload (EventArgs e)
942                 {
943                         if ((event_mask & unload_mask) != 0) {
944                                 EventHandler eh = (EventHandler) (_events [UnloadEvent]);
945                                 if (eh != null) {
946 #if MONO_TRACE
947                                         TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
948                                         string type_name = null;
949                                         if (trace != null) {
950                                                 type_name = GetType ().Name;
951                                                 trace.Write ("control", String.Concat ("OnUnload ", _userId, " ", type_name));
952                                         }
953 #endif
954                                         eh (this, e);
955                                 }
956                         }
957                 }
958
959                 protected internal Stream OpenFile (string path)
960                 {
961                         try {
962                                 string filePath = Context.Server.MapPath (path);
963                                 return File.OpenRead (filePath);
964                         }
965                         catch (UnauthorizedAccessException) {
966                                 throw new HttpException ("Access to the specified file was denied.");
967                         }
968                 }
969
970                 internal string GetPhysicalFilePath (string virtualPath)
971                 {
972                         Page page = Page;
973
974                         if (VirtualPathUtility.IsAbsolute (virtualPath))
975                                 return page != null ? page.MapPath (virtualPath) : Context.Server.MapPath (virtualPath);
976
977                         // We need to determine whether one of our parents is a
978                         // master page. If so, we need to map the path
979                         // relatively to the master page and not our containing
980                         // page/control. This is necessary for cases when a
981                         // relative path is used in a control placed in a master
982                         // page and the master page is referenced from a
983                         // location other than its own. In such cases MS.NET looks
984                         // for the file in the directory where the master page
985                         // is.
986                         //
987                         // An example of where it is needed is at
988                         //
989                         // http://quickstarts.asp.net/QuickStartv20/aspnet/samples/masterpages/masterpages_cs/pages/default.aspx
990                         //
991                         MasterPage master = null;
992                         Control ctrl = Parent;
993
994                         while (ctrl != null) {
995                                 if (ctrl is MasterPage) {
996                                         master = ctrl as MasterPage;
997                                         break;
998                                 }
999                                 ctrl = ctrl.Parent;
1000                         }
1001
1002                         string path;
1003                         if (master != null)
1004                                 path = VirtualPathUtility.Combine (master.TemplateSourceDirectory + "/", virtualPath);
1005                         else
1006                                 path = VirtualPathUtility.Combine (TemplateSourceDirectory + "/", virtualPath);
1007                         
1008                         return page != null ? page.MapPath (path) : Context.Server.MapPath (path);
1009                 }
1010
1011                 protected void RaiseBubbleEvent (object source, EventArgs args)
1012                 {
1013                         Control c = Parent;
1014                         while (c != null) {
1015 #if MONO_TRACE
1016                                 TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
1017                                 string type_name = null;
1018                                 if (trace != null) {
1019                                         type_name = GetType ().Name;
1020                                         trace.Write ("control", String.Concat ("RaiseBubbleEvent ", _userId, " ", type_name));
1021                                 }
1022 #endif
1023                                 if (c.OnBubbleEvent (source, args)) {
1024 #if MONO_TRACE
1025                                         if (trace != null)
1026                                                 trace.Write ("control", String.Concat ("End RaiseBubbleEvent (false) ", _userId, " ", type_name));
1027 #endif
1028                                         break;
1029                                 }
1030 #if MONO_TRACE
1031                                 if (trace != null)
1032                                         trace.Write ("control", String.Concat ("End RaiseBubbleEvent (true) ", _userId, " ", type_name));
1033 #endif
1034                                 c = c.Parent;
1035                         }
1036                 }
1037
1038                 protected internal virtual void Render (HtmlTextWriter writer) //DIT
1039                 {
1040                         RenderChildren (writer);
1041                 }
1042
1043                 protected internal virtual void RenderChildren (HtmlTextWriter writer) //DIT
1044                 {
1045                         if (_renderMethodDelegate != null) {
1046                                 _renderMethodDelegate (writer, this);
1047                         } else if (_controls != null) {
1048                                 int len = _controls.Count;
1049                                 Control c;
1050                                 for (int i = 0; i < len; i++) {
1051                                         c = _controls [i];
1052                                         if (c == null)
1053                                                 continue;
1054                                         ControlAdapter tmp = c.Adapter;
1055                                         if (tmp != null)
1056                                                 c.RenderControl (writer, tmp);
1057                                         else
1058                                                 c.RenderControl (writer);
1059                                 }
1060                         }
1061                 }
1062
1063                 protected virtual ControlAdapter ResolveAdapter ()
1064                 {
1065                         HttpContext context = Context;
1066
1067                         if (context == null)
1068                                 return null;
1069
1070                         if (!context.Request.BrowserMightHaveAdapters)
1071                                 return null;
1072                                 
1073                         // Search up the type hierarchy until we find a control with an adapter.
1074                         IDictionary typeMap = context.Request.Browser.Adapters;
1075                         Type controlType = GetType ();
1076                         Type adapterType = (Type)typeMap [controlType];
1077                         while (adapterType == null && controlType != typeof (Control)) {
1078                                 controlType = controlType.BaseType;
1079                                 adapterType = (Type)typeMap [controlType];
1080                         }
1081
1082                         ControlAdapter a = null;
1083                         if (adapterType != null)
1084                                 a = (ControlAdapter)Activator.CreateInstance (adapterType);
1085                         return a;
1086                 }
1087
1088                 protected virtual object SaveViewState ()
1089                 {
1090                         if ((stateMask & VISIBLE_CHANGED) != 0) {
1091                                 ViewState ["Visible"] = (stateMask & VISIBLE) != 0;
1092                         } else if (_viewState == null) {
1093                                 return null;
1094                         }
1095
1096                         return _viewState.SaveViewState ();
1097                 }
1098
1099                 protected virtual void TrackViewState ()
1100                 {
1101                         if (_viewState != null)
1102                                 _viewState.TrackViewState ();
1103
1104                         stateMask |= TRACK_VIEWSTATE;
1105                 }
1106
1107                 public virtual void Dispose ()
1108                 {
1109                         if ((event_mask & disposed_mask) != 0) {
1110                                 EventHandler eh = (EventHandler) (_events [DisposedEvent]);
1111                                 if (eh != null)
1112                                         eh (this, EventArgs.Empty);
1113                         }
1114                 }
1115
1116                 [WebCategory ("FIXME")]
1117                 [WebSysDescription ("Raised when the contols databound properties are evaluated.")]
1118                 public event EventHandler DataBinding {
1119                         add {
1120                                 event_mask |= databinding_mask;
1121                                 Events.AddHandler (DataBindingEvent, value);
1122                         }
1123                         remove { Events.RemoveHandler (DataBindingEvent, value); }
1124                 }
1125
1126                 [WebSysDescription ("Raised when the contol is disposed.")]
1127                 public event EventHandler Disposed {
1128                         add {
1129                                 event_mask |= disposed_mask;
1130                                 Events.AddHandler (DisposedEvent, value);
1131                         }
1132                         remove { Events.RemoveHandler (DisposedEvent, value); }
1133                 }
1134
1135                 [WebSysDescription ("Raised when the page containing the control is initialized.")]
1136                 public event EventHandler Init {
1137                         add {
1138                                 event_mask |= init_mask;
1139                                 Events.AddHandler (InitEvent, value);
1140                         }
1141                         remove { Events.RemoveHandler (InitEvent, value); }
1142                 }
1143
1144                 [WebSysDescription ("Raised after the page containing the control has been loaded.")]
1145                 public event EventHandler Load {
1146                         add {
1147                                 event_mask |= load_mask;
1148                                 Events.AddHandler (LoadEvent, value);
1149                         }
1150                         remove { Events.RemoveHandler (LoadEvent, value); }
1151                 }
1152
1153                 [WebSysDescription ("Raised before the page containing the control is rendered.")]
1154                 public event EventHandler PreRender {
1155                         add {
1156                                 event_mask |= prerender_mask;
1157                                 Events.AddHandler (PreRenderEvent, value);
1158                         }
1159                         remove { Events.RemoveHandler (PreRenderEvent, value); }
1160                 }
1161
1162                 [WebSysDescription ("Raised when the page containing the control is unloaded.")]
1163                 public event EventHandler Unload {
1164                         add {
1165                                 event_mask |= unload_mask;
1166                                 Events.AddHandler (UnloadEvent, value);
1167                         }
1168                         remove { Events.RemoveHandler (UnloadEvent, value); }
1169                 }
1170
1171                 public virtual void DataBind () //DIT
1172                 {
1173                         DataBind (true);
1174                 }
1175
1176                 protected virtual void DataBindChildren ()
1177                 {
1178                         if (!HasControls ())
1179                                 return;
1180
1181                         int len = _controls.Count;
1182                         for (int i = 0; i < len; i++) {
1183                                 Control c = _controls [i];
1184                                 c.DataBind ();
1185                         }
1186                 }
1187
1188                 public virtual bool HasControls ()
1189                 {
1190                         return (_controls != null && _controls.Count > 0);
1191                 }
1192
1193                 public virtual void RenderControl (HtmlTextWriter writer)
1194                 {
1195                         if (this.adapter != null) {
1196                                 RenderControl (writer, this.adapter);
1197                                 return;
1198                         }
1199
1200                         if ((stateMask & VISIBLE) != 0) {
1201                                 HttpContext ctx = Context;
1202                                 TraceContext trace = (ctx != null) ? ctx.Trace : null;
1203                                 int pos = 0;
1204                                 if ((trace != null) && trace.IsEnabled)
1205                                         pos = ctx.Response.GetOutputByteCount ();
1206
1207                                 Render (writer);
1208                                 if ((trace != null) && trace.IsEnabled) {
1209                                         int size = ctx.Response.GetOutputByteCount () - pos;
1210                                         trace.SaveSize (this, size >= 0 ? size : 0);
1211                                 }
1212                         }
1213                 }
1214
1215                 protected void RenderControl (HtmlTextWriter writer, ControlAdapter adapter)
1216                 {
1217                         if ((stateMask & VISIBLE) != 0) {
1218                                 adapter.BeginRender (writer);
1219                                 adapter.Render (writer);
1220                                 adapter.EndRender (writer);
1221                         }
1222                 }
1223
1224                 public string ResolveUrl (string relativeUrl)
1225                 {
1226                         if (relativeUrl == null)
1227                                 throw new ArgumentNullException ("relativeUrl");
1228
1229                         if (relativeUrl == String.Empty)
1230                                 return relativeUrl;
1231
1232                         if (VirtualPathUtility.IsAbsolute (relativeUrl))
1233                                 return relativeUrl;
1234
1235                         if (relativeUrl [0] == '#')
1236                                 return relativeUrl;
1237
1238                         string ts = AppRelativeTemplateSourceDirectory;
1239                         HttpContext ctx = Context;
1240                         HttpResponse resp = ctx != null ? ctx.Response : null;
1241                         if (ts == null || ts.Length == 0 || resp == null || relativeUrl.IndexOf (':') >= 0)
1242                                 return relativeUrl;
1243                         
1244                         if (!VirtualPathUtility.IsAppRelative (relativeUrl))
1245                                 relativeUrl = VirtualPathUtility.Combine (VirtualPathUtility.AppendTrailingSlash (ts), relativeUrl);
1246                         
1247                         return resp.ApplyAppPathModifier (relativeUrl);
1248                 }
1249
1250
1251                 public string ResolveClientUrl (string relativeUrl)
1252                 {
1253                         if (relativeUrl == null)
1254                                 throw new ArgumentNullException ("relativeUrl");
1255
1256                         if (relativeUrl.Length == 0)
1257                                 return String.Empty;
1258
1259 #if TARGET_J2EE
1260                         relativeUrl = ResolveClientUrlInternal (relativeUrl);
1261
1262                         javax.faces.context.FacesContext faces = getFacesContext ();
1263                         if (faces == null)
1264                                 return relativeUrl;
1265
1266                         string url;
1267                         if (relativeUrl.IndexOf (':') >= 0)
1268                                 url = ResolveAppRelativeFromFullPath (relativeUrl);
1269                         else if (VirtualPathUtility.IsAbsolute (relativeUrl))
1270                                 url = VirtualPathUtility.ToAppRelative (relativeUrl);
1271                         else
1272                                 return faces.getApplication ().getViewHandler ().getResourceURL (faces, relativeUrl);
1273
1274                         if (VirtualPathUtility.IsAppRelative (url)) {
1275                                 url = url.Substring (1);
1276                                 url = url.Length == 0 ? "/" : url;
1277                                 return faces.getApplication ().getViewHandler ().getResourceURL (faces, url);
1278                         }
1279                         return relativeUrl;
1280                 }
1281                 
1282                 string ResolveClientUrlInternal (string relativeUrl) {
1283                         if (relativeUrl.StartsWith (J2EE.J2EEConsts.ACTION_URL_PREFIX, StringComparison.Ordinal))
1284                                 return CreateActionUrl (relativeUrl.Substring (J2EE.J2EEConsts.ACTION_URL_PREFIX.Length));
1285
1286                         if (relativeUrl.StartsWith (J2EE.J2EEConsts.RENDER_URL_PREFIX, StringComparison.Ordinal))
1287                                 return ResolveClientUrl (relativeUrl.Substring (J2EE.J2EEConsts.RENDER_URL_PREFIX.Length));
1288
1289 #endif
1290                         if (VirtualPathUtility.IsAbsolute (relativeUrl) || relativeUrl.IndexOf (':') >= 0)
1291                                 return relativeUrl;
1292
1293                         HttpContext context = Context;
1294                         HttpRequest req = context != null ? context.Request : null;
1295                         if (req != null) {
1296                                 string templateSourceDirectory = TemplateSourceDirectory;
1297                                 if (templateSourceDirectory == null || templateSourceDirectory.Length == 0)
1298                                         return relativeUrl;
1299
1300                                 string basePath = req.ClientFilePath;
1301
1302                                 if (basePath.Length > 1 && basePath [basePath.Length - 1] != '/')
1303                                         basePath = VirtualPathUtility.GetDirectory (basePath, false);
1304
1305                                 if (VirtualPathUtility.IsAppRelative (relativeUrl))
1306                                         return VirtualPathUtility.MakeRelative (basePath, relativeUrl);
1307
1308                                 string templatePath = VirtualPathUtility.AppendTrailingSlash (templateSourceDirectory);
1309
1310                                 if (basePath.Length == templatePath.Length && String.CompareOrdinal (basePath, templatePath) == 0)
1311                                         return relativeUrl;
1312
1313                                 relativeUrl = VirtualPathUtility.Combine (templatePath, relativeUrl);
1314                                 return VirtualPathUtility.MakeRelative (basePath, relativeUrl);
1315                         }
1316                         return relativeUrl;
1317                 }
1318
1319                 internal bool HasRenderMethodDelegate ()
1320                 {
1321                         return _renderMethodDelegate != null;
1322                 }
1323
1324                 [EditorBrowsable (EditorBrowsableState.Advanced)]
1325                 public void SetRenderMethodDelegate (RenderMethod renderMethod) //DIT
1326                 {
1327                         _renderMethodDelegate = renderMethod;
1328                 }
1329
1330                 internal void LoadRecursive ()
1331                 {
1332 #if MONO_TRACE
1333                         TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
1334                         string type_name = null;
1335                         if (trace != null) {
1336                                 type_name = GetType ().Name;
1337                                 trace.Write ("control", String.Concat ("LoadRecursive ", _userId, " ", type_name));
1338                         }
1339 #endif
1340                         if (Adapter != null)
1341                                 Adapter.OnLoad (EventArgs.Empty);
1342                         else
1343                                 OnLoad (EventArgs.Empty);
1344                         if (HasControls ()) {
1345                                 int len = _controls.Count;
1346                                 for (int i = 0; i < len; i++) {
1347                                         Control c = _controls [i];
1348                                         c.LoadRecursive ();
1349                                 }
1350                         }
1351
1352 #if MONO_TRACE
1353                         if (trace != null)
1354                                 trace.Write ("control", String.Concat ("End LoadRecursive ", _userId, " ", type_name));
1355 #endif
1356                         stateMask |= LOADED;
1357                 }
1358
1359                 internal void UnloadRecursive (Boolean dispose)
1360                 {
1361 #if MONO_TRACE
1362                         TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
1363                         string type_name = null;
1364                         if (trace != null) {
1365                                 type_name = GetType ().Name;
1366                                 trace.Write ("control", String.Concat ("UnloadRecursive ", _userId, " ", type_name));
1367                         }
1368 #endif
1369                         if (HasControls ()) {
1370                                 int len = _controls.Count;
1371                                 for (int i = 0; i < len; i++) {
1372                                         Control c = _controls [i];
1373                                         c.UnloadRecursive (dispose);
1374                                 }
1375                         }
1376
1377 #if MONO_TRACE
1378                         if (trace != null)
1379                                 trace.Write ("control", String.Concat ("End UnloadRecursive ", _userId, " ", type_name));
1380 #endif
1381                         ControlAdapter tmp = Adapter;
1382                         if (tmp != null)
1383                                 tmp.OnUnload (EventArgs.Empty);
1384                         else
1385                                 OnUnload (EventArgs.Empty);
1386                         if (dispose)
1387                                 Dispose ();
1388                 }
1389
1390                 internal void PreRenderRecursiveInternal ()
1391                 {
1392                         bool visible;
1393
1394                         visible = Visible;                      
1395                         if (visible) {
1396                                 SetMask (VISIBLE, true);
1397                                 EnsureChildControls ();
1398 #if MONO_TRACE
1399                                 TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
1400                                 string type_name = null;
1401                                 if (trace != null) {
1402                                         type_name = GetType ().Name;
1403                                         trace.Write ("control", String.Concat ("PreRenderRecursive ", _userId, " ", type_name));
1404                                 }
1405 #endif
1406                                 if (Adapter != null)
1407                                         Adapter.OnPreRender (EventArgs.Empty);
1408                                 else
1409                                         OnPreRender (EventArgs.Empty);
1410                                 if (!HasControls ())
1411                                         return;
1412
1413                                 int len = _controls.Count;
1414                                 for (int i = 0; i < len; i++) {
1415                                         Control c = _controls [i];
1416                                         c.PreRenderRecursiveInternal ();
1417                                 }
1418 #if MONO_TRACE
1419                                 if (trace != null)
1420                                         trace.Write ("control", String.Concat ("End PreRenderRecursive ", _userId, " ", type_name));
1421 #endif
1422                         } else
1423                                 SetMask (VISIBLE, false);
1424                         
1425                         stateMask |= PRERENDERED;
1426                 }
1427
1428                 internal void InitRecursive (Control namingContainer)
1429                 {
1430 #if MONO_TRACE
1431                         TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
1432                         string type_name = null;
1433                         if (trace != null) {
1434                                 type_name = GetType ().Name;
1435                                 trace.Write ("control", String.Concat ("InitRecursive ", _userId, " ", type_name));
1436                         }
1437 #endif
1438                         SetNamingContainer (namingContainer);
1439
1440                         if (HasControls ()) {
1441                                 if ((stateMask & IS_NAMING_CONTAINER) != 0)
1442                                         namingContainer = this;
1443
1444                                 int len = _controls.Count;
1445                                 for (int i = 0; i < len; i++) {
1446                                         Control c = _controls [i];
1447                                         c.InitRecursive (namingContainer);
1448                                 }
1449                         }
1450
1451                         if ((stateMask & REMOVED) == 0 && (stateMask & INITED) != INITED) {
1452                                 stateMask |= INITING;
1453                                 ApplyTheme ();
1454                                 ControlAdapter tmp = Adapter;
1455                                 if (tmp != null)
1456                                         tmp.OnInit (EventArgs.Empty);
1457                                 else
1458                                         OnInit (EventArgs.Empty);
1459                                 TrackViewState ();
1460                                 stateMask |= INITED;
1461                                 stateMask &= ~INITING;
1462                         }
1463                         
1464 #if MONO_TRACE
1465                         if (trace != null)
1466                                 trace.Write ("control", String.Concat ("End InitRecursive ", _userId, " ", type_name));
1467 #endif
1468                 }
1469
1470                 internal object SaveViewStateRecursive ()
1471                 {
1472                         TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
1473 #if MONO_TRACE
1474                         string type_name = null;
1475                         if (trace != null) {
1476                                 type_name = GetType ().Name;
1477                                 trace.Write ("control", String.Concat ("SaveViewStateRecursive ", _userId, " ", type_name));
1478                         }
1479 #endif
1480
1481                         ArrayList controlStates = null;
1482                         bool byId = LoadViewStateByID;
1483                         if (HasControls ()) {
1484                                 int len = _controls.Count;
1485                                 for (int i = 0; i < len; i++) {
1486                                         Control ctrl = _controls [i];
1487                                         object ctrlState = ctrl.SaveViewStateRecursive ();
1488                                         if (ctrlState == null)
1489                                                 continue;
1490
1491                                         if (controlStates == null)
1492                                                 controlStates = new ArrayList ();
1493                                         if (byId) {
1494                                                 ctrl.EnsureID ();
1495                                                 controlStates.Add (new Pair (ctrl.ID, ctrlState));
1496                                         } else
1497                                                 controlStates.Add (new Pair (i, ctrlState));
1498                                 }
1499                         }
1500
1501                         object thisAdapterViewState = null;
1502                         if (Adapter != null)
1503                                 thisAdapterViewState = Adapter.SaveAdapterViewState ();
1504
1505                         object thisState = null;
1506
1507                         if (IsViewStateEnabled)
1508                                 thisState = SaveViewState ();
1509
1510                         if (thisState == null && controlStates == null) {
1511                                 if (trace != null) {
1512 #if MONO_TRACE
1513                                         trace.Write ("control", "End SaveViewStateRecursive " + _userId + " " + type_name + " saved nothing");
1514 #endif
1515                                         trace.SaveViewState (this, null);
1516                                 }
1517                                 return null;
1518                         }
1519
1520                         if (trace != null) {
1521 #if MONO_TRACE
1522                                 trace.Write ("control", "End SaveViewStateRecursive " + _userId + " " + type_name + " saved a Triplet");
1523 #endif
1524                                 trace.SaveViewState (this, thisState);
1525                         }
1526                         thisState = new object[] { thisState, thisAdapterViewState };
1527                         return new Pair (thisState, controlStates);
1528                 }
1529
1530                 internal void LoadViewStateRecursive (object savedState)
1531                 {
1532                         if (savedState == null)
1533                                 return;
1534
1535 #if MONO_TRACE
1536                         TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
1537                         string type_name = null;
1538                         if (trace != null) {
1539                                 type_name = GetType ().Name;
1540                                 trace.Write ("control", String.Concat ("LoadViewStateRecursive ", _userId, " ", type_name));
1541                         }
1542 #endif
1543                         Pair savedInfo = (Pair) savedState;
1544                         object[] controlAndAdapterViewStates = (object [])savedInfo.First;
1545                         if (Adapter != null)
1546                                 Adapter.LoadAdapterViewState (controlAndAdapterViewStates [1]);
1547                         LoadViewState (controlAndAdapterViewStates [0]);
1548
1549                         ArrayList controlStates = savedInfo.Second as ArrayList;
1550                         if (controlStates == null)
1551                                 return;
1552
1553                         int nControls = controlStates.Count;
1554                         bool byId = LoadViewStateByID;
1555                         for (int i = 0; i < nControls; i++) {
1556                                 Pair p = controlStates [i] as Pair;
1557                                 if (p == null)
1558                                         continue;
1559
1560                                 if (byId) {
1561                                         string id = (string)p.First;
1562                                         bool found = false;
1563                                         
1564                                         foreach (Control c in Controls) {
1565                                                 c.EnsureID ();
1566                                                 if (c.ID == id) {
1567                                                         found = true;
1568                                                         c.LoadViewStateRecursive (p.Second);
1569                                                         break;
1570                                                 }
1571                                         }
1572
1573                                         if (!found) {
1574                                                 if (pendingVS == null)
1575                                                         pendingVS = new Hashtable ();
1576                                                 pendingVS [id] = p.Second;
1577                                         }
1578                                 } else {
1579                                         int k = (int) p.First;
1580                                         if (k < Controls.Count) {
1581                                                 Control c = Controls [k];
1582                                                 c.LoadViewStateRecursive (p.Second);
1583                                         } else {
1584                                                 if (pendingVS == null)
1585                                                         pendingVS = new Hashtable ();
1586
1587                                                 pendingVS [k] = p.Second;
1588                                         }
1589                                 }
1590                         }
1591
1592 #if MONO_TRACE
1593                         if (trace != null)
1594                                 trace.Write ("control", String.Concat ("End LoadViewStateRecursive ", _userId, " ", type_name));
1595 #endif
1596                         stateMask |= VIEWSTATE_LOADED;
1597                 }
1598
1599                 internal ControlSkin controlSkin;
1600
1601                 internal void ApplyTheme ()
1602                 {
1603 #if MONO_TRACE
1604                         TraceContext trace = (Context != null && Context.Trace.IsEnabled) ? Context.Trace : null;
1605                         string type_name = null;
1606                         if (trace != null) {
1607                                 type_name = GetType ().Name;
1608                                 trace.Write ("control", String.Concat ("ApplyThemeRecursive ", _userId, " ", type_name));
1609                         }
1610 #endif
1611                         Page page = Page;
1612                         if (page != null && page.PageTheme != null && EnableTheming) {
1613                                 ControlSkin controlSkin = page.PageTheme.GetControlSkin (GetType (), SkinID);
1614                                 if (controlSkin != null)
1615                                         controlSkin.ApplySkin (this);
1616                         }
1617
1618 #if MONO_TRACE
1619                         if (trace != null)
1620                                 trace.Write ("control", String.Concat ("End ApplyThemeRecursive ", _userId, " ", type_name));
1621 #endif
1622                 }
1623
1624                 internal bool AutoID {
1625                         get { return (stateMask & AUTOID) != 0; }
1626                         set {
1627                                 if (value == false && (stateMask & IS_NAMING_CONTAINER) != 0)
1628                                         return;
1629
1630                                 SetMask (AUTOID, value);
1631                         }
1632                 }
1633
1634                 protected internal virtual void RemovedControl (Control control)
1635                 {
1636                         control.UnloadRecursive (false);
1637                         control._parent = null;
1638                         control._page = null;
1639                         control._namingContainer = null;
1640                         if ((control.stateMask & AUTOID_SET) != 0) {
1641                                 control._userId = null;
1642                                 control.SetMask (ID_SET, false);
1643                         }
1644                         control.NullifyUniqueID ();
1645                         control.SetMask (REMOVED, true);
1646                         ResetControlsCache ();
1647                 }
1648                 
1649                 string skinId = string.Empty;
1650                 bool _enableTheming = true;
1651
1652                 [Browsable (false)]
1653                 [Themeable (false)]
1654                 [DefaultValue (true)]
1655                 public virtual bool EnableTheming {
1656                         get {
1657                                 if ((stateMask & ENABLE_THEMING) != 0)
1658                                         return _enableTheming;
1659
1660                                 if (_parent != null)
1661                                         return _parent.EnableTheming;
1662
1663                                 return true;
1664                         }
1665                         set {
1666                                 SetMask (ENABLE_THEMING, true);
1667                                 _enableTheming = value;
1668                         }
1669                 }
1670
1671                 [Browsable (false)]
1672                 [DefaultValue ("")]
1673                 [Filterable (false)]
1674                 public virtual string SkinID {
1675                         get { return skinId; }
1676                         set { skinId = value; }
1677                 }
1678
1679                 ControlBuilder IControlBuilderAccessor.ControlBuilder {
1680                         get { throw new NotImplementedException (); }
1681                 }
1682
1683                 IDictionary IControlDesignerAccessor.GetDesignModeState ()
1684                 {
1685                         throw new NotImplementedException ();
1686                 }
1687
1688                 void IControlDesignerAccessor.SetDesignModeState (IDictionary designData)
1689                 {
1690                         SetDesignModeState (designData);
1691                 }
1692
1693                 void IControlDesignerAccessor.SetOwnerControl (Control control)
1694                 {
1695                         throw new NotImplementedException ();
1696                 }
1697
1698                 IDictionary IControlDesignerAccessor.UserData {
1699                         get { throw new NotImplementedException (); }
1700                 }
1701
1702                 ExpressionBindingCollection expressionBindings;
1703
1704                 ExpressionBindingCollection IExpressionsAccessor.Expressions {
1705                         get {
1706                                 if (expressionBindings == null)
1707                                         expressionBindings = new ExpressionBindingCollection ();
1708                                 return expressionBindings;
1709                         }
1710                 }
1711
1712                 bool IExpressionsAccessor.HasExpressions {
1713                         get { return (expressionBindings != null && expressionBindings.Count > 0); }
1714                 }
1715
1716                 public virtual void Focus ()
1717                 {
1718                         Page.SetFocus (this);
1719                 }
1720
1721                 protected internal virtual void LoadControlState (object state)
1722                 {
1723                 }
1724
1725                 protected internal virtual object SaveControlState ()
1726                 {
1727                         return null;
1728                 }
1729
1730                 protected virtual void DataBind (bool raiseOnDataBinding)
1731                 {
1732                         bool foundDataItem = false;
1733
1734                         if ((stateMask & IS_NAMING_CONTAINER) != 0 && Page != null) {
1735                                 object o = DataBinder.GetDataItem (this, out foundDataItem);
1736                                 if (foundDataItem)
1737                                         Page.PushDataItemContext (o);
1738                         }
1739
1740                         try {
1741                                 if (raiseOnDataBinding)
1742                                         OnDataBinding (EventArgs.Empty);
1743                                 DataBindChildren ();
1744                         } finally {
1745                                 if (foundDataItem)
1746                                         Page.PopDataItemContext ();
1747                         }
1748                 }
1749
1750                 protected virtual IDictionary GetDesignModeState ()
1751                 {
1752                         throw new NotImplementedException ();
1753                 }
1754
1755                 protected virtual void SetDesignModeState (IDictionary data)
1756                 {
1757                         throw new NotImplementedException ();
1758                 }
1759
1760                 internal bool IsInited {
1761                         get { return (stateMask & INITED) != 0; }
1762                 }
1763
1764                 internal bool IsLoaded {
1765                         get { return (stateMask & LOADED) != 0; }
1766                 }
1767
1768                 internal bool IsPrerendered {
1769                         get { return (stateMask & PRERENDERED) != 0; }
1770                 }
1771
1772                 bool CheckForValidationSupport ()
1773                 {
1774                         return GetType ().GetCustomAttributes (typeof (SupportsEventValidationAttribute), false).Length > 0;
1775                 }
1776
1777                 //
1778                 // Apparently this is where .NET routes validation from all the controls which
1779                 // support it. See:
1780                 //
1781                 //  http://odetocode.com/Blogs/scott/archive/2006/03/20/3145.aspx
1782                 //    Sample in here contains ValidateEvent in the stack trace
1783                 //
1784                 //  http://odetocode.com/blogs/scott/archive/2006/03/21/3153.aspx
1785                 //
1786                 //  http://www.alexthissen.nl/blogs/main/archive/2005/12/13/event-validation-of-controls-in-asp-net-2-0.aspx
1787                 //
1788                 // It also seems that it's the control's responsibility to call this method or
1789                 // validation won't take place. Also, the SupportsEventValidation attribute must be
1790                 // present on the control for validation to take place.
1791                 //
1792                 internal void ValidateEvent (String uniqueId, String argument)
1793                 {
1794                         Page page = Page;
1795                         
1796                         if (page != null && CheckForValidationSupport ())
1797                                 page.ClientScript.ValidateEvent (uniqueId, argument);
1798                 }
1799
1800                 void IParserAccessor.AddParsedSubObject (object obj)
1801                 {
1802                         this.AddParsedSubObject (obj);
1803                 }
1804
1805                 DataBindingCollection IDataBindingsAccessor.DataBindings {
1806                         get {
1807                                 if (dataBindings == null) {
1808                                         dataBindings = new DataBindingCollection ();
1809                                 }
1810                                 return dataBindings;
1811                         }
1812                 }
1813
1814                 bool IDataBindingsAccessor.HasDataBindings {
1815                         get {
1816                                 if (dataBindings != null && dataBindings.Count > 0) {
1817                                         return true;
1818                                 }
1819                                 return false;
1820                         }
1821                 }
1822         }
1823 }