2 // (C) 2005 Mainsoft Corporation (http://www.mainsoft.com)
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:
14 // The above copyright notice and this permission notice shall be
15 // included in all copies or substantial portions of the Software.
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.
27 using System.Collections;
28 using System.ComponentModel;
29 using System.Reflection;
32 using System.Web.J2EE;
35 using System.Web.Util;
37 namespace System.Web.UI {
39 public abstract class TemplateControl : Control, INamingContainer
41 static object abortTransaction = new object ();
42 static object commitTransaction = new object ();
43 static object error = new object ();
44 static string [] methodNames = { "Page_Init",
49 "Page_PreRenderComplete",
50 "Page_SaveStateComplete",
59 "Page_AbortTransaction",
60 "Page_CommitTransaction" };
62 const BindingFlags bflags = BindingFlags.Public |
63 BindingFlags.NonPublic |
64 BindingFlags.Instance;
65 static readonly Type [] NoParams = new Type [0];
67 private static string hashTableMutex = "lock"; //used to sync access ResourceHash property
68 private byte [] GetResourceBytes (Type type)
70 Hashtable table = (Hashtable) AppDomain.CurrentDomain.GetData ("TemplateControl.RES_BYTES");
74 return (byte []) table [type];
76 private void SetResourceBytes (Type type, byte [] bytes)
78 Hashtable table = (Hashtable) AppDomain.CurrentDomain.GetData ("TemplateControl.RES_BYTES");
80 table = new Hashtable ();
81 AppDomain.CurrentDomain.SetData ("TemplateControl.RES_BYTES", table);
87 private Hashtable ResourceHash
91 Hashtable table = (Hashtable) AppDomain.CurrentDomain.GetData ("TemplateControl.RES_STRING");
93 table = new Hashtable ();
94 AppDomain.CurrentDomain.SetData ("TemplateControl.RES_STRING", table);
100 private string CachedString (string filename, int offset, int size)
102 string key = filename + offset + size;
103 lock (hashTableMutex) {
104 string strObj = (string) ResourceHash [key];
105 if (strObj == null) {
107 char [] tmp = System.Text.Encoding.UTF8.GetChars (GetResourceBytes (this.GetType ()), offset, size);
108 strObj = new string (tmp);
109 ResourceHash.Add (key, strObj);
116 public virtual string TemplateSourceDirectory_Private
122 protected TemplateControl ()
130 [EditorBrowsable (EditorBrowsableState.Never)]
131 protected virtual int AutoHandlers
137 [EditorBrowsable (EditorBrowsableState.Never)]
138 protected virtual bool SupportAutoEvents
147 protected virtual void Construct ()
152 protected LiteralControl CreateResourceBasedLiteralControl (int offset,
156 string str = CachedString (this.GetType ().FullName, offset, size);
157 return new LiteralControl (str);
160 sealed class EventMethodMap
162 public EventMethodMap (EventInfo Event, MethodInfo Method, bool NoParameters)
165 this.Method = Method;
166 this.NoParameters = NoParameters;
169 public readonly EventInfo Event;
170 public readonly MethodInfo Method;
171 public readonly bool NoParameters;
174 // This hashtable cashes methods and events found in user code
175 const string eventMethodCacheKey = "eventMethodCacheKey";
176 static Hashtable EventMethodCache
178 get { return (Hashtable) AppDomain.CurrentDomain.GetData (eventMethodCacheKey); }
179 set { AppDomain.CurrentDomain.SetData (eventMethodCacheKey, value); }
182 internal void WireupAutomaticEvents ()
184 Type cacheKey = this.GetType ();
185 Hashtable eventMethodCache = EventMethodCache;
186 ArrayList eventMethodList = eventMethodCache == null ? null : (ArrayList) eventMethodCache [cacheKey];
188 if (eventMethodList == null) {
189 eventMethodList = new ArrayList ();
191 if (!SupportAutoEvents || !AutoEventWireup)
194 Type thisType = typeof (TemplateControl);
195 Type voidType = typeof (void);
196 Type [] DefaultParams = new Type [] {
198 typeof (EventArgs) };
200 foreach (string methodName in methodNames) {
202 bool noParams = false;
203 Type type = GetType ();
205 method = type.GetMethod (methodName, bflags, null, DefaultParams, null);
206 if (method != null) {
210 type = type.BaseType;
212 while (type != thisType);
214 if (method == null) {
217 method = type.GetMethod (methodName, bflags, null, NoParams, null);
218 if (method != null) {
223 type = type.BaseType;
225 while (type != thisType);
230 if (method.ReturnType != voidType)
233 int pos = methodName.IndexOf ("_");
234 string eventName = methodName.Substring (pos + 1);
235 EventInfo evt = GetType ().GetEvent (eventName);
237 /* This should never happen */
241 eventMethodList.Add (new EventMethodMap (evt, method, noParams));
243 if (method.DeclaringType != type) {
244 if (!method.IsPublic && !method.IsFamilyOrAssembly &&
245 !method.IsFamilyAndAssembly && !method.IsFamily)
250 // We copy to not lock
252 Hashtable newEventMethodCache = eventMethodCache == null ? new Hashtable () : (Hashtable) eventMethodCache.Clone ();
253 newEventMethodCache [cacheKey] = eventMethodList;
254 EventMethodCache = newEventMethodCache;
257 foreach (EventMethodMap eventMethod in eventMethodList) {
258 if (eventMethod.NoParameters) {
259 NoParamsInvoker npi = new NoParamsInvoker (this, eventMethod.Method);
260 eventMethod.Event.AddEventHandler (this, npi.FakeDelegate);
263 eventMethod.Event.AddEventHandler (this, Delegate.CreateDelegate (typeof (EventHandler), this, eventMethod.Method));
268 [EditorBrowsable (EditorBrowsableState.Never)]
269 protected virtual void FrameworkInitialize ()
273 Type GetTypeFromControlPath (string virtualPath)
275 if (virtualPath == null)
276 throw new ArgumentNullException ("virtualPath");
278 string vpath = UrlUtils.Combine (TemplateSourceDirectory, virtualPath);
279 return PageMapper.GetObjectType (Context, vpath);
282 public Control LoadControl (string virtualPath)
284 object control = Activator.CreateInstance (GetTypeFromControlPath (virtualPath));
285 if (control is UserControl)
286 ((UserControl) control).InitializeAsUserControl (Page);
288 return (Control) control;
291 public ITemplate LoadTemplate (string virtualPath)
293 Type t = GetTypeFromControlPath (virtualPath);
294 return new SimpleTemplate (t);
297 protected virtual void OnAbortTransaction (EventArgs e)
299 EventHandler eh = Events [abortTransaction] as EventHandler;
304 protected virtual void OnCommitTransaction (EventArgs e)
306 EventHandler eh = Events [commitTransaction] as EventHandler;
311 protected virtual void OnError (EventArgs e)
313 EventHandler eh = Events [error] as EventHandler;
318 [MonoNotSupported ("Not supported")]
319 public Control ParseControl (string content)
321 throw new NotSupportedException ();
324 [MonoLimitation ("Always returns false")]
325 public virtual bool TestDeviceFilter (string filterName)
331 [EditorBrowsable (EditorBrowsableState.Never)]
332 public static object ReadStringResource (Type t)
337 [MonoTODO ("is this correct?")]
338 public Object ReadStringResource ()
340 return this.GetType ();
344 [EditorBrowsable (EditorBrowsableState.Never)]
345 protected void SetStringResourcePointer (object stringResourcePointer,
346 int maxResourceOffset)
348 if (GetResourceBytes (this.GetType ()) != null)
351 java.lang.Class c = vmw.common.TypeUtils.ToClass (stringResourcePointer);
352 java.lang.ClassLoader contextClassLoader = c.getClassLoader ();
354 //TODO:move this code to page mapper
355 string assemblyName = PageMapper.GetAssemblyResource (HttpContext.Current, this.AppRelativeVirtualPath);
356 if (assemblyName == null)
357 throw new HttpException (404, "The requested resource (" + this.AppRelativeVirtualPath + ") is not available.");
359 java.io.InputStream inputStream = contextClassLoader.getResourceAsStream (assemblyName);
361 System.IO.Stream strim = null;
362 if (inputStream == null) {
363 string descPath = String.Join ("/", new string [] { "assemblies", this.GetType ().Assembly.GetName ().Name, assemblyName });
365 strim = new StreamReader (HttpContext.Current.Request.MapPath ("/" + descPath)).BaseStream;
367 catch (Exception ex) {
368 throw new System.IO.IOException ("couldn't open resource file:" + assemblyName, ex);
371 throw new System.IO.IOException ("couldn't open resource file:" + assemblyName);
376 strim = (System.IO.Stream) vmw.common.IOUtils.getStream (inputStream);
377 int capacity = (int) strim.Length;
378 byte [] resourceBytes = new byte [capacity];
379 strim.Read (resourceBytes, 0, capacity);
380 SetResourceBytes (this.GetType (), resourceBytes);
382 catch (Exception e) {
383 throw new HttpException ("problem with dll.ghres file", e);
388 if (inputStream != null)
389 inputStream.close ();
394 [EditorBrowsable (EditorBrowsableState.Never)]
395 protected void WriteUTF8ResourceString (HtmlTextWriter output, int offset,
396 int size, bool fAsciiOnly)
398 string str = CachedString (this.GetType ().FullName, offset, size);
406 [WebSysDescription ("Raised when the user aborts a transaction.")]
407 public event EventHandler AbortTransaction
409 add { Events.AddHandler (abortTransaction, value); }
410 remove { Events.RemoveHandler (abortTransaction, value); }
413 [WebSysDescription ("Raised when the user initiates a transaction.")]
414 public event EventHandler CommitTransaction
416 add { Events.AddHandler (commitTransaction, value); }
417 remove { Events.RemoveHandler (commitTransaction, value); }
420 [WebSysDescription ("Raised when an exception occurs that cannot be handled.")]
421 public event EventHandler Error
423 add { Events.AddHandler (error, value); }
424 remove { Events.RemoveHandler (error, value); }
429 class SimpleTemplate : ITemplate
433 public SimpleTemplate (Type type)
438 public void InstantiateIn (Control control)
440 Control template = Activator.CreateInstance (type) as Control;
441 template.SetBindingContainer (false);
442 control.Controls.Add (template);
448 string _appRelativeVirtualPath = null;
450 public string AppRelativeVirtualPath
452 get { return _appRelativeVirtualPath; }
456 throw new ArgumentNullException ("value");
457 if (!UrlUtils.IsRooted (value) && !(value.Length > 0 && value [0] == '~'))
458 throw new ArgumentException ("The path that is set is not rooted");
459 _appRelativeVirtualPath = value;
461 int lastSlash = _appRelativeVirtualPath.LastIndexOf ('/');
462 AppRelativeTemplateSourceDirectory = (lastSlash > 0) ? _appRelativeVirtualPath.Substring (0, lastSlash + 1) : "~/";
466 protected internal object Eval (string expression)
468 return DataBinder.Eval (Page.GetDataItem (), expression);
471 protected internal string Eval (string expression, string format)
473 return DataBinder.Eval (Page.GetDataItem (), expression, format);
476 protected internal object XPath (string xpathexpression)
478 return XPathBinder.Eval (Page.GetDataItem (), xpathexpression);
481 protected internal object XPath (string xpathexpression, IXmlNamespaceResolver resolver)
483 return XPathBinder.Eval (Page.GetDataItem (), xpathexpression, null, resolver);
486 protected internal string XPath (string xpathexpression, string format)
488 return XPathBinder.Eval (Page.GetDataItem (), xpathexpression, format);
491 protected internal string XPath (string xpathexpression, string format, IXmlNamespaceResolver resolver)
493 return XPathBinder.Eval (Page.GetDataItem (), xpathexpression, format, resolver);
496 protected internal IEnumerable XPathSelect (string xpathexpression)
498 return XPathBinder.Select (Page.GetDataItem (), xpathexpression);
501 protected internal IEnumerable XPathSelect (string xpathexpression, IXmlNamespaceResolver resolver)
503 return XPathBinder.Select (Page.GetDataItem (), xpathexpression, resolver);
506 protected object GetGlobalResourceObject (string className, string resourceKey)
508 return HttpContext.GetGlobalResourceObject (className, resourceKey);
511 [MonoTODO ("Not implemented")]
512 protected object GetGlobalResourceObject (string className, string resourceKey, Type objType, string propName)
514 // FIXME: not sure how to implement that one yet
515 throw new NotSupportedException ();
518 protected Object GetLocalResourceObject (string resourceKey)
520 return HttpContext.GetLocalResourceObject (Context.Request.Path, resourceKey);
523 [MonoTODO ("Not implemented")]
524 protected Object GetLocalResourceObject (string resourceKey, Type objType, string propName)
526 // FIXME: not sure how to implement that one yet
527 throw new NotSupportedException ();