931c79b4fd6571b8cb047a3d0bb44468496f6164
[mono.git] / mcs / class / System.Web / System.Web.UI / TemplateControl.jvm.cs
1 //
2 // (C) 2005 Mainsoft Corporation (http://www.mainsoft.com)
3 //
4
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining
7 // a copy of this software and associated documentation files (the
8 // "Software"), to deal in the Software without restriction, including
9 // without limitation the rights to use, copy, modify, merge, publish,
10 // distribute, sublicense, and/or sell copies of the Software, and to
11 // permit persons to whom the Software is furnished to do so, subject to
12 // the following conditions:
13 //
14 // The above copyright notice and this permission notice shall be
15 // included in all copies or substantial portions of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 //
25
26 using System;
27 using System.Collections;
28 using System.ComponentModel;
29 using System.Reflection;
30 using System.Web;
31 using System.IO;
32 using System.Web.J2EE;
33 using vmw.common;
34 using System.Web.Util;
35
36 namespace System.Web.UI {
37
38         public abstract class TemplateControl : Control, INamingContainer
39         {
40                 static object abortTransaction = new object ();
41                 static object commitTransaction = new object ();
42                 static object error = new object ();
43                 static string [] methodNames = { "Page_Init",
44                                                  "Page_Load",
45                                                  "Page_DataBind",
46                                                  "Page_PreRender",
47                                                  "Page_Disposed",
48                                                  "Page_Error",
49                                                  "Page_Unload",
50                                                  "Page_AbortTransaction",
51                                                  "Page_CommitTransaction" };
52
53                 const BindingFlags bflags = BindingFlags.Public |
54                                             BindingFlags.NonPublic |
55                                             BindingFlags.Instance;
56
57                 private string _templateSourceDir;
58                 private static string hashTableMutex = "lock"; //used to sync access ResourceHash property
59                 private byte[] GetResourceBytes(Type type) {
60                         Hashtable table = (Hashtable)AppDomain.CurrentDomain.GetData("TemplateControl.RES_BYTES");
61                         if (table == null) {
62                                 return null;
63                         }
64                         return (byte[])table[type];
65                 }
66                 private void SetResourceBytes(Type type, byte[] bytes) {
67                         Hashtable table = (Hashtable)AppDomain.CurrentDomain.GetData("TemplateControl.RES_BYTES");
68                         if (table == null) {
69                                 table = new Hashtable();
70                                 AppDomain.CurrentDomain.SetData("TemplateControl.RES_BYTES" , table);
71                         }
72                         table[type] = bytes;
73                         return;
74                 }
75
76                 private Hashtable ResourceHash {
77                         get {
78                                 Hashtable table = (Hashtable)AppDomain.CurrentDomain.GetData("TemplateControl.RES_STRING");
79                                 if (table == null) {
80                                         table = new Hashtable();
81                                         AppDomain.CurrentDomain.SetData("TemplateControl.RES_STRING" , table);
82                                 }
83                                 return table;
84                         }
85                 }
86
87                 private string CachedString(string filename , int offset, int size)
88                 {
89                         string key = filename + offset + size;
90                         lock (hashTableMutex)
91                         {
92                                 string strObj = (string)ResourceHash[key];
93                                 if (strObj == null) 
94                                 {
95                                         
96                                         char[] tmp = System.Text.Encoding.UTF8.GetChars(GetResourceBytes(this.GetType()) , offset , size);
97                                         strObj = new string(tmp);
98                                         ResourceHash.Add(key, strObj);
99                                 }
100                         
101                                 return strObj;
102                         }
103                         
104                 }
105                 public virtual string TemplateSourceDirectory_Private 
106                 {
107                         get { return null; }
108                 }
109
110                 [MonoTODO]
111                 // This shouldnt be there, Page.TemplateSourceDirectory must know to get 
112                 // the right directory of the control.
113                 public override string TemplateSourceDirectory 
114                 {
115                         get {
116 #if NET_2_0
117                                 if (this is MasterPage)
118                                         // because MasterPage also has implementation of this property,
119                                         // but not always gets the right directory, in case where master page
120                                         // is in the root of webapp and the page that uses it is in sub folder.
121                                         return base.TemplateSourceDirectory;
122 #endif
123                                 int location = 0;
124                                 if (_templateSourceDir == null)
125                                 {
126                                         string tempSrcDir = AppRelativeTemplateSourceDirectory;
127                                         if (tempSrcDir == null && Parent != null)
128                                                 tempSrcDir = Parent.TemplateSourceDirectory;
129                                         if (tempSrcDir != null && tempSrcDir.Length > 1)
130                                         {
131                                                 location = tempSrcDir.IndexOf('/',1);
132                                                 if (location!= -1)
133                                                         tempSrcDir = tempSrcDir.Substring(location+1);
134                                                 else
135                                                         tempSrcDir = string.Empty;
136                                         }
137                                         string answer =  HttpRuntime.AppDomainAppVirtualPath;
138                                         if(tempSrcDir == null)
139                                                 tempSrcDir = "";
140                                         
141                                         if (tempSrcDir.Length > 0 && tempSrcDir [tempSrcDir.Length - 1] == '/')
142                                                 tempSrcDir = tempSrcDir.Substring (0, tempSrcDir.Length - 1);
143
144                                         if (tempSrcDir.StartsWith("/") || tempSrcDir.Length == 0)
145                                                 _templateSourceDir =  answer + tempSrcDir;
146                                         else
147                                                 _templateSourceDir = answer + "/"+ tempSrcDir;
148                                 }
149                                 return _templateSourceDir;
150                         }
151                 }
152
153
154                 #region Constructor
155                 protected TemplateControl ()
156                 {
157                         Construct ();
158                 }
159
160                 #endregion
161
162                 #region Properties
163                 [EditorBrowsable (EditorBrowsableState.Never)]
164                 protected virtual int AutoHandlers {
165                         get { return 0; }
166                         set { }
167                 }
168
169                 [EditorBrowsable (EditorBrowsableState.Never)]
170                 protected virtual bool SupportAutoEvents {
171                         get { return true; }
172                 }
173
174                 #endregion
175
176                 #region Methods
177
178                 protected virtual void Construct ()
179                 {
180                 }
181
182                 [MonoTODO]
183                 protected LiteralControl CreateResourceBasedLiteralControl (int offset,
184                                                                                     int size,
185                                                                                     bool fAsciiOnly)
186                 {
187                         string str = CachedString(this.GetType().FullName, offset, size);
188                         return new LiteralControl(str);
189                 }
190
191                 internal void WireupAutomaticEvents ()
192                 {
193                         if (!SupportAutoEvents || !AutoEventWireup)
194                                 return;
195
196                         Type type = GetType ();
197                         foreach (string methodName in methodNames) {
198                                 MethodInfo method = type.GetMethod (methodName, bflags);
199                                 if (method == null)
200                                         continue;
201
202 #if ONLY_1_1
203                                 if (method.DeclaringType != type) {
204                                         if (!method.IsPublic && !method.IsFamilyOrAssembly &&
205                                             !method.IsFamilyAndAssembly && !method.IsFamily)
206                                                 continue;
207                                 }
208 #endif
209
210                                 if (method.ReturnType != typeof (void))
211                                         continue;
212
213                                 ParameterInfo [] parms = method.GetParameters ();
214                                 int length = parms.Length;
215                                 bool noParams = (length == 0);
216                                 if (!noParams && (length != 2 ||
217                                     parms [0].ParameterType != typeof (object) ||
218                                     parms [1].ParameterType != typeof (EventArgs)))
219                                         continue;
220
221                                 int pos = methodName.IndexOf ("_");
222                                 string eventName = methodName.Substring (pos + 1);
223                                 EventInfo evt = type.GetEvent (eventName);
224                                 if (evt == null) {
225                                         /* This should never happen */
226                                         continue;
227                                 }
228
229                                 if (noParams) {
230                                         NoParamsInvoker npi = new NoParamsInvoker (this, methodName);
231                                         evt.AddEventHandler (this, npi.FakeDelegate);
232                                 } else {
233                                         evt.AddEventHandler (this, Delegate.CreateDelegate (
234                                                         typeof (EventHandler), this, methodName));
235                                 }
236                         }
237                 }
238
239                 [EditorBrowsable (EditorBrowsableState.Never)]
240                 protected virtual void FrameworkInitialize ()
241                 {
242                 }
243
244                 Type GetTypeFromControlPath (string virtualPath)
245                 {
246                         if (virtualPath == null)
247                                 throw new ArgumentNullException ("virtualPath");
248
249                         string vpath = UrlUtils.Combine (TemplateSourceDirectory, virtualPath);
250                         return PageMapper.GetObjectType(vpath);
251                 }
252
253                 public Control LoadControl (string virtualPath)
254                 {
255                         object control = Activator.CreateInstance (GetTypeFromControlPath (virtualPath));
256                         if (control is UserControl)
257                                 ((UserControl) control).InitializeAsUserControl (Page);
258
259                         return (Control) control;
260                 }
261
262                 public ITemplate LoadTemplate (string virtualPath)
263                 {
264                         Type t = GetTypeFromControlPath (virtualPath);
265                         return new SimpleTemplate (t);
266                 }
267
268                 protected virtual void OnAbortTransaction (EventArgs e)
269                 {
270                         EventHandler eh = Events [abortTransaction] as EventHandler;
271                         if (eh != null)
272                                 eh (this, e);
273                 }
274
275                 protected virtual void OnCommitTransaction (EventArgs e)
276                 {
277                         EventHandler eh = Events [commitTransaction] as EventHandler;
278                         if (eh != null)
279                                 eh (this, e);
280                 }
281
282                 protected virtual void OnError (EventArgs e)
283                 {
284                         EventHandler eh = Events [error] as EventHandler;
285                         if (eh != null)
286                                 eh (this, e);
287                 }
288
289                 [MonoTODO]
290                 public Control ParseControl (string content)
291                 {
292                         return null;
293                 }
294
295                 [MonoTODO]
296                 [EditorBrowsable (EditorBrowsableState.Never)]
297                 public static object ReadStringResource (Type t)
298                 {
299                         return t;
300                 }
301 #if NET_2_0
302                 [MonoTODO ("is this correct?")]
303                 public Object ReadStringResource ()
304                 {
305                         return this.GetType();
306                 }
307 #endif
308                 [MonoTODO]
309                 [EditorBrowsable (EditorBrowsableState.Never)]
310                 protected void SetStringResourcePointer (object stringResourcePointer,
311                                                          int maxResourceOffset)
312                 {
313                         if ( GetResourceBytes(this.GetType()) != null)
314                                 return;
315
316                         java.lang.Class c = vmw.common.TypeUtils.ToClass(stringResourcePointer);
317                         java.lang.ClassLoader  contextClassLoader = c.getClassLoader();
318
319                         //TODO:move this code to page mapper
320                         string assemblyName = PageMapper.GetAssemblyResource(this.AppRelativeVirtualPath);
321                         
322                         java.io.InputStream inputStream = contextClassLoader.getResourceAsStream(assemblyName);
323
324                         System.IO.Stream strim = null;
325                         if (inputStream == null) {
326                                 string descPath = String.Join("/", new string[]{"assemblies", this.GetType().Assembly.GetName().Name, assemblyName});
327                                 try 
328                                 {
329                                         strim = new StreamReader(HttpContext.Current.Request.MapPath("/" + descPath)).BaseStream;
330                                 }
331                                 catch (Exception ex)
332                                 {
333                                         throw new System.IO.IOException("couldn't open resource file:" + assemblyName, ex);
334                                 }
335                                 if (strim == null)
336                                         throw new System.IO.IOException("couldn't open resource file:" + assemblyName);
337                         }
338
339                         try
340                         {
341                                 if (strim == null)
342                                         strim = (System.IO.Stream)vmw.common.IOUtils.getStream(inputStream);
343                                 int capacity = (int)strim.Length;
344                                 byte[] resourceBytes = new byte[capacity];
345                                 strim.Read(resourceBytes,0,capacity);
346                                 SetResourceBytes(this.GetType(), resourceBytes);
347                         }
348                         catch(Exception e)
349                         {
350                                 throw new HttpException("problem with dll.ghres file", e);
351                         }
352                         finally
353                         {
354                                 if(strim != null)
355                                         strim.Close();
356                                 if (inputStream != null )
357                                         inputStream.close();
358                         }
359                 }
360
361                 [MonoTODO]
362                 [EditorBrowsable (EditorBrowsableState.Never)]
363                 protected void WriteUTF8ResourceString (HtmlTextWriter output, int offset,
364                                                         int size, bool fAsciiOnly)
365                 {
366                         string str = CachedString(this.GetType().FullName, offset, size);
367                         output.Write(str);
368                 }
369
370                 #endregion
371
372                 #region Events
373
374                 [WebSysDescription ("Raised when the user aborts a transaction.")]
375                 public event EventHandler AbortTransaction {
376                         add { Events.AddHandler (abortTransaction, value); }
377                         remove { Events.RemoveHandler (abortTransaction, value); }
378                 }
379
380                 [WebSysDescription ("Raised when the user initiates a transaction.")]
381                 public event EventHandler CommitTransaction {
382                         add { Events.AddHandler (commitTransaction, value); }
383                         remove { Events.RemoveHandler (commitTransaction, value); }
384                 }
385
386                 [WebSysDescription ("Raised when an exception occurs that cannot be handled.")]
387                 public event EventHandler Error {
388                         add { Events.AddHandler (error, value); }
389                         remove { Events.RemoveHandler (error, value); }
390                 }
391
392                 #endregion
393
394                 class SimpleTemplate : ITemplate
395                 {
396                         Type type;
397
398                         public SimpleTemplate (Type type)
399                         {
400                                 this.type = type;
401                         }
402
403                         public void InstantiateIn (Control control)
404                         {
405                                 Control template = Activator.CreateInstance (type) as Control;
406                                 template.SetBindingContainer (false);
407                                 control.Controls.Add (template);
408                         }
409                 }
410
411 #if NET_2_0
412
413         string _appRelativeVirtualPath = null;
414
415         public string AppRelativeVirtualPath
416         {
417                 get { return _appRelativeVirtualPath; }
418                 set
419                 {
420                         if (value == null)
421                                 throw new ArgumentNullException ("value");
422                         if (!UrlUtils.IsRooted (value) && !(value.Length > 0 && value[0] == '~'))
423                                 throw new ArgumentException ("The path that is set is not rooted");
424                         _appRelativeVirtualPath = value;
425
426                         int lastSlash = _appRelativeVirtualPath.LastIndexOf ('/');
427                         AppRelativeTemplateSourceDirectory = (lastSlash > 0) ? _appRelativeVirtualPath.Substring (0, lastSlash + 1) : "~/";
428                 }
429         }
430
431         protected object Eval (string expression)
432         {
433                 return DataBinder.Eval (Page.GetDataItem (), expression);
434         }
435
436         protected string Eval (string expression, string format)
437         {
438                 return DataBinder.Eval (Page.GetDataItem (), expression, format);
439         }
440
441         protected object XPath (string xpathexpression)
442         {
443                 return XPathBinder.Eval (Page.GetDataItem (), xpathexpression);
444         }
445
446         protected string XPath (string xpathexpression, string format)
447         {
448                 return XPathBinder.Eval (Page.GetDataItem (), xpathexpression, format);
449         }
450
451         protected IEnumerable XPathSelect (string xpathexpression)
452         {
453                 return XPathBinder.Select (Page.GetDataItem (), xpathexpression);
454         }
455 #endif
456
457         }
458 }