AspGenerator.cs 61 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021
  1. //
  2. // System.Web.Compilation.AspGenerator
  3. //
  4. // Authors:
  5. // Gonzalo Paniagua Javier ([email protected])
  6. //
  7. // (C) 2002 Ximian, Inc (http://www.ximian.com)
  8. //
  9. using System;
  10. using System.Collections;
  11. using System.ComponentModel;
  12. using System.Drawing;
  13. using System.Diagnostics;
  14. using System.IO;
  15. using System.Reflection;
  16. using System.Text;
  17. using System.Text.RegularExpressions;
  18. using System.Web.UI;
  19. using System.Web.UI.HtmlControls;
  20. using System.Web.UI.WebControls;
  21. using System.Web.Util;
  22. namespace System.Web.Compilation
  23. {
  24. class ControlStack
  25. {
  26. private Stack controls;
  27. private ControlStackData top;
  28. private bool space_between_tags;
  29. private bool sbt_valid;
  30. class ControlStackData
  31. {
  32. public Type controlType;
  33. public string controlID;
  34. public string tagID;
  35. public ChildrenKind childKind;
  36. public string defaultPropertyName;
  37. public int childrenNumber;
  38. public Type container;
  39. public StringBuilder dataBindFunction;
  40. public StringBuilder codeRenderFunction;
  41. public bool useCodeRender;
  42. public int codeRenderIndex;
  43. public ControlStackData (Type controlType,
  44. string controlID,
  45. string tagID,
  46. ChildrenKind childKind,
  47. string defaultPropertyName,
  48. Type container)
  49. {
  50. this.controlType = controlType;
  51. this.controlID = controlID;
  52. this.tagID = tagID;
  53. this.childKind = childKind;
  54. this.defaultPropertyName = defaultPropertyName;
  55. this.container = container;
  56. childrenNumber = 0;
  57. }
  58. public override string ToString ()
  59. {
  60. return controlType + " " + controlID + " " + tagID + " " + childKind + " " + childrenNumber;
  61. }
  62. }
  63. public ControlStack ()
  64. {
  65. controls = new Stack ();
  66. }
  67. private Type GetContainerType (Type type)
  68. {
  69. if (type != typeof (System.Web.UI.Control) &&
  70. !type.IsSubclassOf (typeof (System.Web.UI.Control)))
  71. return null;
  72. Type container_type;
  73. if (type == typeof (System.Web.UI.WebControls.DataList))
  74. container_type = typeof (System.Web.UI.WebControls.DataListItem);
  75. else if (type == typeof (System.Web.UI.WebControls.DataGrid))
  76. container_type = typeof (System.Web.UI.WebControls.DataGridItem);
  77. else if (type == typeof (System.Web.UI.WebControls.Repeater))
  78. container_type = typeof (System.Web.UI.WebControls.RepeaterItem);
  79. else if (type == typeof (ListControl) || type.IsSubclassOf (typeof (ListControl)))
  80. container_type = type;
  81. else
  82. container_type = Container;
  83. return container_type;
  84. }
  85. public void Push (object o)
  86. {
  87. if (!(o is ControlStackData))
  88. return;
  89. controls.Push (o);
  90. top = (ControlStackData) o;
  91. sbt_valid = false;
  92. }
  93. public void Push (Type controlType,
  94. string controlID,
  95. string tagID,
  96. ChildrenKind childKind,
  97. string defaultPropertyName)
  98. {
  99. Type container_type = null;
  100. if (controlType != null){
  101. AddChild ();
  102. container_type = GetContainerType (controlType);
  103. if (container_type == null)
  104. container_type = this.Container;
  105. }
  106. top = new ControlStackData (controlType,
  107. controlID,
  108. tagID,
  109. childKind,
  110. defaultPropertyName,
  111. container_type);
  112. sbt_valid = false;
  113. controls.Push (top);
  114. }
  115. public object Pop ()
  116. {
  117. object item = controls.Pop ();
  118. if (controls.Count != 0)
  119. top = (ControlStackData) controls.Peek ();
  120. sbt_valid = false;
  121. return item;
  122. }
  123. public Type PeekType ()
  124. {
  125. return top.controlType;
  126. }
  127. public string PeekControlID ()
  128. {
  129. return top.controlID;
  130. }
  131. public string PeekTagID ()
  132. {
  133. return top.tagID;
  134. }
  135. public ChildrenKind PeekChildKind ()
  136. {
  137. return top.childKind;
  138. }
  139. public string PeekDefaultPropertyName ()
  140. {
  141. return top.defaultPropertyName;
  142. }
  143. public void AddChild ()
  144. {
  145. if (top != null)
  146. top.childrenNumber++;
  147. }
  148. public bool HasDataBindFunction ()
  149. {
  150. if (top.dataBindFunction == null || top.dataBindFunction.Length == 0)
  151. return false;
  152. return true;
  153. }
  154. public bool UseCodeRender
  155. {
  156. get {
  157. if (top.codeRenderFunction == null || top.codeRenderFunction.Length == 0)
  158. return false;
  159. return top.useCodeRender;
  160. }
  161. set { top.useCodeRender= value; }
  162. }
  163. public bool SpaceBetweenTags
  164. {
  165. get {
  166. if (!sbt_valid){
  167. sbt_valid = true;
  168. Type type = top.controlType;
  169. if (type.Namespace == "System.Web.UI.WebControls")
  170. space_between_tags = true;
  171. else if (type.IsSubclassOf (typeof (System.Web.UI.WebControls.WebControl)))
  172. space_between_tags = true;
  173. else if (type == typeof (System.Web.UI.HtmlControls.HtmlSelect))
  174. space_between_tags = true;
  175. else if (type == typeof (System.Web.UI.HtmlControls.HtmlTable))
  176. space_between_tags = true;
  177. else if (type == typeof (System.Web.UI.HtmlControls.HtmlTableRow))
  178. space_between_tags = true;
  179. else if (type == typeof (System.Web.UI.HtmlControls.HtmlTableCell))
  180. space_between_tags = true;
  181. else
  182. space_between_tags = false;
  183. }
  184. return space_between_tags;
  185. }
  186. }
  187. public Type Container {
  188. get {
  189. if (top == null)
  190. return null;
  191. return top.container;
  192. }
  193. }
  194. public StringBuilder DataBindFunction
  195. {
  196. get {
  197. if (top.dataBindFunction == null)
  198. top.dataBindFunction = new StringBuilder ();
  199. return top.dataBindFunction;
  200. }
  201. }
  202. public int CodeRenderIndex {
  203. get {
  204. return top.codeRenderIndex++;
  205. }
  206. }
  207. public StringBuilder CodeRenderFunction
  208. {
  209. get {
  210. if (top.codeRenderFunction == null)
  211. top.codeRenderFunction = new StringBuilder ();
  212. return top.codeRenderFunction;
  213. }
  214. }
  215. public int ChildIndex
  216. {
  217. get { return top.childrenNumber - 1; }
  218. }
  219. public int Count
  220. {
  221. get { return controls.Count; }
  222. }
  223. public override string ToString ()
  224. {
  225. return top.ToString () + " " + top.useCodeRender;
  226. }
  227. }
  228. class ArrayListWrapper
  229. {
  230. private ArrayList list;
  231. private int index;
  232. public ArrayListWrapper (ArrayList list)
  233. {
  234. this.list = list;
  235. index = -1;
  236. }
  237. private void CheckIndex ()
  238. {
  239. if (index == -1 || index == list.Count)
  240. throw new InvalidOperationException ();
  241. }
  242. public object Current
  243. {
  244. get {
  245. CheckIndex ();
  246. return list [index];
  247. }
  248. set {
  249. CheckIndex ();
  250. list [index] = value;
  251. }
  252. }
  253. public bool MoveNext ()
  254. {
  255. if (index < list.Count)
  256. index++;
  257. return index < list.Count;
  258. }
  259. }
  260. class AspGenerator
  261. {
  262. private object [] parts;
  263. private ArrayListWrapper elements;
  264. private StringBuilder prolog;
  265. private StringBuilder declarations;
  266. private StringBuilder script;
  267. private StringBuilder constructor;
  268. private StringBuilder init_funcs;
  269. private StringBuilder epilog;
  270. private StringBuilder current_function;
  271. private Stack functions;
  272. private ControlStack controls;
  273. private bool parse_ok;
  274. private bool has_form_tag;
  275. private AspComponentFoundry aspFoundry;
  276. private string classDecl;
  277. private string className;
  278. private string interfaces;
  279. private string basetype;
  280. private string parent;
  281. private Type parentType;
  282. private string fullPath;
  283. Hashtable options;
  284. string privateBinPath;
  285. string main_directive;
  286. static string app_file_wrong = "The content in the application file is not valid.";
  287. bool isPage;
  288. bool isUserControl;
  289. bool isApplication;
  290. HttpContext context;
  291. SessionState sessionState = SessionState.Enabled;
  292. static Type styleType = typeof (System.Web.UI.WebControls.Style);
  293. static Type fontinfoType = typeof (System.Web.UI.WebControls.FontInfo);
  294. enum UserControlResult
  295. {
  296. OK = 0,
  297. FileNotFound = 1,
  298. CompilationFailed = 2
  299. }
  300. enum SessionState
  301. {
  302. Enabled,
  303. ReadOnly,
  304. Disabled
  305. }
  306. public AspGenerator (string pathToFile, ArrayList elements)
  307. {
  308. if (elements == null)
  309. throw new ArgumentNullException ();
  310. this.elements = new ArrayListWrapper (elements);
  311. string filename = Path.GetFileName (pathToFile);
  312. this.className = filename.Replace ('.', '_'); // Overridden by @ Page classname
  313. this.className = className.Replace ('-', '_');
  314. this.className = className.Replace (' ', '_');
  315. Options ["ClassName"] = this.className;
  316. this.fullPath = Path.GetFullPath (pathToFile);
  317. this.has_form_tag = false;
  318. AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
  319. privateBinPath = setup.PrivateBinPath;
  320. // This is a hack until we can run stuff in different domains
  321. if (privateBinPath == null || privateBinPath.Length == 0)
  322. privateBinPath = "bin";
  323. if (!Path.IsPathRooted (privateBinPath))
  324. privateBinPath = Path.Combine (setup.ApplicationBase, privateBinPath);
  325. Init ();
  326. }
  327. public string BaseType {
  328. get { return basetype; }
  329. set {
  330. if (parent == null)
  331. parent = value;
  332. basetype = value;
  333. isUserControl = (basetype == "System.Web.UI.UserControl");
  334. isPage = (basetype == "System.Web.UI.Page");
  335. isApplication = (basetype == "System.Web.HttpApplication");
  336. }
  337. }
  338. public bool IsUserControl {
  339. get { return isUserControl; }
  340. }
  341. public bool IsPage {
  342. get { return isPage; }
  343. }
  344. public bool IsApplication {
  345. get { return isApplication; }
  346. }
  347. public string Interfaces {
  348. get { return interfaces; }
  349. }
  350. public Hashtable Options {
  351. get {
  352. if (options == null)
  353. options = new Hashtable ();
  354. return options;
  355. }
  356. }
  357. internal HttpContext Context {
  358. get { return context; }
  359. set { context = value; }
  360. }
  361. bool AddUsing (string nspace)
  362. {
  363. string _using = "using " + nspace + ";";
  364. if (prolog.ToString ().IndexOf (_using) == -1) {
  365. prolog.AppendFormat ("\t{0}\n", _using);
  366. return true;
  367. }
  368. return false;
  369. }
  370. void AddInterface (Type type)
  371. {
  372. AddInterface (type.ToString ());
  373. }
  374. public void AddInterface (string iface)
  375. {
  376. if (interfaces == null) {
  377. interfaces = ", " + iface;
  378. } else {
  379. string s = ", " + iface;
  380. if (interfaces.IndexOf (s) == -1)
  381. interfaces += s;
  382. }
  383. }
  384. private AspComponentFoundry Foundry
  385. {
  386. get {
  387. if (aspFoundry == null)
  388. aspFoundry = new AspComponentFoundry ();
  389. return aspFoundry;
  390. }
  391. }
  392. private void Init ()
  393. {
  394. controls = new ControlStack ();
  395. controls.Push (typeof (System.Web.UI.Control), "Root", null, ChildrenKind.CONTROLS, null);
  396. prolog = new StringBuilder ();
  397. declarations = new StringBuilder ();
  398. script = new StringBuilder ();
  399. constructor = new StringBuilder ();
  400. init_funcs = new StringBuilder ();
  401. epilog = new StringBuilder ();
  402. current_function = new StringBuilder ();
  403. functions = new Stack ();
  404. functions.Push (current_function);
  405. parts = new Object [6];
  406. parts [0] = prolog;
  407. parts [1] = declarations;
  408. parts [2] = script;
  409. parts [3] = constructor;
  410. parts [4] = init_funcs;
  411. parts [5] = epilog;
  412. prolog.Append ("namespace ASP {\n" +
  413. "\tusing System;\n" +
  414. "\tusing System.Collections;\n" +
  415. "\tusing System.Collections.Specialized;\n" +
  416. "\tusing System.Configuration;\n" +
  417. "\tusing System.IO;\n" +
  418. "\tusing System.Text;\n" +
  419. "\tusing System.Text.RegularExpressions;\n" +
  420. "\tusing System.Web;\n" +
  421. "\tusing System.Web.Caching;\n" +
  422. "\tusing System.Web.Security;\n" +
  423. "\tusing System.Web.SessionState;\n" +
  424. "\tusing System.Web.UI;\n" +
  425. "\tusing System.Web.UI.WebControls;\n" +
  426. "\tusing System.Web.UI.HtmlControls;\n");
  427. declarations.Append ("\t\tprivate static int __autoHandlers;\n");
  428. current_function.Append ("\t\tprivate void __BuildControlTree (System.Web.UI.Control __ctrl)\n\t\t{\n");
  429. if (!IsUserControl)
  430. current_function.Append ("\t\t\tSystem.Web.UI.IParserAccessor __parser = " +
  431. "(System.Web.UI.IParserAccessor) __ctrl;\n\n");
  432. else
  433. controls.UseCodeRender = true;
  434. }
  435. public StringReader GetCode ()
  436. {
  437. if (!parse_ok)
  438. throw new ApplicationException ("You gotta call ProcessElements () first!");
  439. StringBuilder code = new StringBuilder ();
  440. for (int i = 0; i < parts.Length; i++)
  441. code.Append ((StringBuilder) parts [i]);
  442. return new StringReader (code.ToString ());
  443. }
  444. public void Print ()
  445. {
  446. if (!parse_ok){
  447. Console.WriteLine ("//Warning!!!: Elements not correctly parsed.");
  448. }
  449. Console.Write (GetCode ().ReadToEnd ());
  450. }
  451. // Regex.Escape () make some illegal escape sequences for a C# source.
  452. private string Escape (string input)
  453. {
  454. if (input == null)
  455. return String.Empty;
  456. string output = input.Replace ("\\", "\\\\");
  457. output = output.Replace ("\"", "\\\"");
  458. output = output.Replace ("\t", "\\t");
  459. output = output.Replace ("\r", "\\r");
  460. output = output.Replace ("\n", "\\n");
  461. output = output.Replace ("\n", "\\n");
  462. return output;
  463. }
  464. bool AddProtectedField (Type type, string fieldName)
  465. {
  466. if (parentType == null) {
  467. declarations.AppendFormat ("\t\tprotected {0} {1};\n", type.ToString (), fieldName);
  468. return true;
  469. }
  470. FieldInfo field = parentType.GetField (fieldName, BindingFlags.Public |
  471. BindingFlags.NonPublic |
  472. BindingFlags.Instance |
  473. BindingFlags.Static);
  474. if (field == null || (!field.IsPublic && !field.IsFamily)) {
  475. declarations.AppendFormat ("\t\tprotected {0} {1};\n", type.ToString (), fieldName);
  476. return true;
  477. }
  478. if (!field.FieldType.IsAssignableFrom (type)) {
  479. string message = String.Format ("The base class includes the field '{0}', but its " +
  480. "type '{1}' is not compatible with {2}",
  481. fieldName, field.FieldType, type);
  482. throw new ApplicationException (message);
  483. }
  484. return false;
  485. }
  486. private Type LoadParentType (string typeName)
  487. {
  488. // First try loaded assemblies, then try assemblies in Bin directory.
  489. // By now i do this 'by hand' but may be this is a runtime/gac task.
  490. Type type = null;
  491. Assembly [] assemblies = AppDomain.CurrentDomain.GetAssemblies ();
  492. foreach (Assembly ass in assemblies) {
  493. type = ass.GetType (typeName);
  494. if (type != null)
  495. return type;
  496. }
  497. Assembly assembly;
  498. string [] binDlls = Directory.GetFiles (privateBinPath, "*.dll");
  499. foreach (string dll in binDlls) {
  500. string dllPath = Path.Combine (privateBinPath, dll);
  501. assembly = null;
  502. try {
  503. assembly = Assembly.LoadFrom (dllPath);
  504. type = assembly.GetType (typeName);
  505. } catch (Exception e) {
  506. if (assembly != null) {
  507. Console.WriteLine ("ASP.NET Warning: assembly {0} loaded", dllPath);
  508. Console.WriteLine ("ASP.NET Warning: but type {0} not found", typeName);
  509. } else {
  510. Console.WriteLine ("ASP.NET Warning: unable to load type {0} from {1}",
  511. typeName, dllPath);
  512. }
  513. Console.WriteLine ("ASP.NET Warning: error was: {0}", e.Message);
  514. }
  515. if (type != null)
  516. return type;
  517. }
  518. return null;
  519. }
  520. private void PageDirective (TagAttributes att)
  521. {
  522. if (att ["ClassName"] != null){
  523. this.className = (string) att ["ClassName"];
  524. Options ["ClassName"] = className;
  525. }
  526. if (att ["EnableSessionState"] != null){
  527. if (!IsPage)
  528. throw new ApplicationException ("EnableSessionState not allowed here.");
  529. string est = (string) att ["EnableSessionState"];
  530. if (0 == String.Compare (est, "false", true))
  531. sessionState = SessionState.Disabled;
  532. else if (0 == String.Compare (est, "true", true))
  533. sessionState = SessionState.Enabled;
  534. else if (0 == String.Compare (est, "readonly", true))
  535. sessionState = SessionState.ReadOnly;
  536. else
  537. throw new ApplicationException ("EnableSessionState in Page directive not set to " +
  538. "a correct value: " + est);
  539. }
  540. if (att ["Inherits"] != null) {
  541. parent = (string) att ["Inherits"];
  542. parentType = LoadParentType (parent);
  543. if (parentType == null)
  544. throw new ApplicationException ("The class " + parent + " cannot be found.");
  545. }
  546. if (att ["CompilerOptions"] != null)
  547. Options ["CompilerOptions"] = (string) att ["CompilerOptions"];
  548. if (att ["AutoEventWireup"] != null) {
  549. if (options ["AutoEventWireup"] != null)
  550. throw new ApplicationException ("Already have an AutoEventWireup attribute");
  551. bool autoevent = true;
  552. string v = att ["AutoEventWireup"] as string;
  553. try {
  554. autoevent = Convert.ToBoolean (v);
  555. } catch (Exception) {
  556. throw new ApplicationException ("'" + v + "' is not a valid value for AutoEventWireup");
  557. }
  558. options ["AutoEventWireup"] = autoevent;
  559. }
  560. //FIXME: add support for more attributes.
  561. }
  562. void AddReference (string dll)
  563. {
  564. string references = Options ["References"] as string;
  565. if (references == null)
  566. references = dll;
  567. else
  568. references = references + " " + dll;
  569. Options ["References"] = references;
  570. }
  571. private void RegisterDirective (TagAttributes att)
  572. {
  573. string tag_prefix = (string) (att ["tagprefix"] == null ? "" : att ["tagprefix"]);
  574. string name_space = (string) (att ["namespace"] == null ? "" : att ["namespace"]);
  575. string assembly_name = (string) (att ["assembly"] == null ? "" : att ["assembly"]);
  576. string tag_name = (string) (att ["tagname"] == null ? "" : att ["tagname"]);
  577. string src = (string) (att ["src"] == null ? "" : att ["src"]);
  578. if (tag_prefix != "" && name_space != "" && assembly_name != ""){
  579. if (tag_name != "" || src != "")
  580. throw new ApplicationException ("Invalid attributes for @ Register: " +
  581. att.ToString ());
  582. AddUsing (name_space);
  583. string dll = privateBinPath + Path.DirectorySeparatorChar + assembly_name + ".dll";
  584. // Hack: it should use assembly.load semantics...
  585. // may be when we don't run mcs as a external program...
  586. if (!File.Exists (dll))
  587. dll = assembly_name;
  588. Foundry.RegisterFoundry (tag_prefix, dll, name_space);
  589. AddReference (dll);
  590. return;
  591. }
  592. if (tag_prefix != "" && tag_name != "" && src != ""){
  593. if (name_space != "" && assembly_name != "")
  594. throw new ApplicationException ("Invalid attributes for @ Register: " +
  595. att.ToString ());
  596. if (!src.EndsWith (".ascx"))
  597. throw new ApplicationException ("Source file extension for controls " +
  598. "must be .ascx");
  599. UserControlData data = GenerateUserControl (src, Context);
  600. switch (data.result) {
  601. case UserControlResult.OK:
  602. AddUsing ("ASP");
  603. string dll = "output" + Path.DirectorySeparatorChar + data.assemblyName + ".dll";
  604. Foundry.RegisterFoundry (tag_prefix, tag_name, data.assemblyName, "ASP", data.className);
  605. AddReference (data.assemblyName);
  606. break;
  607. case UserControlResult.FileNotFound:
  608. throw new ApplicationException ("File '" + src + "' not found.");
  609. case UserControlResult.CompilationFailed:
  610. //TODO: should say where the generated .cs file is for the server to
  611. //show the source and the compiler error
  612. throw new NotImplementedException ();
  613. }
  614. return;
  615. }
  616. throw new ApplicationException ("Invalid combination of attributes in " +
  617. "@ Register: " + att.ToString ());
  618. }
  619. private void ProcessDirective ()
  620. {
  621. Directive directive = (Directive) elements.Current;
  622. TagAttributes att = directive.Attributes;
  623. if (att == null)
  624. return;
  625. string value;
  626. string id = directive.TagID.ToUpper ();
  627. switch (id){
  628. case "APPLICATION":
  629. if (main_directive != null)
  630. throw new ApplicationException (id + " not allowed after " + main_directive);
  631. if (!IsApplication)
  632. throw new ApplicationException ("@Application not allowed.");
  633. string inherits = att ["inherits"] as string;
  634. if (inherits != null)
  635. Options ["Inherits"] = inherits;
  636. main_directive = directive.TagID;
  637. break;
  638. case "PAGE":
  639. case "CONTROL":
  640. if (main_directive != null)
  641. throw new ApplicationException (id + " not allowed after " + main_directive);
  642. if (IsUserControl && id != "CONTROL")
  643. throw new ApplicationException ("@Page not allowed for user controls.");
  644. else if (IsPage && id != "PAGE")
  645. throw new ApplicationException ("@Control not allowed here. This is a page!");
  646. PageDirective (att);
  647. main_directive = directive.TagID;
  648. break;
  649. case "IMPORT":
  650. value = att ["namespace"] as string;
  651. if (value == null || att.Count > 1)
  652. throw new ApplicationException ("Wrong syntax in Import directive.");
  653. string _using = "using " + value + ";";
  654. if (AddUsing (value) == true) {
  655. string imports = Options ["Import"] as string;
  656. if (imports == null) {
  657. imports = value;
  658. } else {
  659. imports += "," + value;
  660. }
  661. Options ["Import"] = imports;
  662. }
  663. break;
  664. case "IMPLEMENTS":
  665. if (IsApplication)
  666. throw new ApplicationException ("@ Implements not allowed in an application file.");
  667. string iface = (string) att ["interface"];
  668. AddInterface (iface);
  669. break;
  670. case "REGISTER":
  671. if (IsApplication)
  672. throw new ApplicationException ("@ Register not allowed in an application file.");
  673. RegisterDirective (att);
  674. break;
  675. case "ASSEMBLY":
  676. if (att.Count > 1)
  677. throw new ApplicationException ("Wrong syntax in Assembly directive.");
  678. string name = att ["name"] as string;
  679. string src = att ["src"] as string;
  680. if (name == null && src == null)
  681. throw new ApplicationException ("Wrong syntax in Assembly directive.");
  682. if (IsApplication && src != null)
  683. throw new ApplicationException ("'name' attribute expected.");
  684. value = (name == null) ? src : name;
  685. string assemblies = Options ["Assembly"] as string;
  686. if (assemblies == null) {
  687. assemblies = value;
  688. } else {
  689. assemblies += "," + value;
  690. }
  691. Options ["Assembly"] = assemblies;
  692. break;
  693. }
  694. }
  695. private void ProcessPlainText ()
  696. {
  697. PlainText asis = (PlainText) elements.Current;
  698. string trimmed = asis.Text.Trim ();
  699. if (trimmed == String.Empty && controls.SpaceBetweenTags == true)
  700. return;
  701. if (IsApplication) {
  702. if (trimmed != String.Empty)
  703. throw new ApplicationException (app_file_wrong);
  704. return;
  705. }
  706. if (trimmed != String.Empty && controls.PeekChildKind () != ChildrenKind.CONTROLS){
  707. string tag_id = controls.PeekTagID ();
  708. throw new ApplicationException ("Literal content not allowed for " + tag_id);
  709. }
  710. string escaped_text = Escape (asis.Text);
  711. current_function.AppendFormat ("\t\t\t__parser.AddParsedSubObject (" +
  712. "new System.Web.UI.LiteralControl (\"{0}\"));\n",
  713. escaped_text);
  714. StringBuilder codeRenderFunction = controls.CodeRenderFunction;
  715. codeRenderFunction.AppendFormat ("\t\t\t__output.Write (\"{0}\");\n", escaped_text);
  716. }
  717. private string EnumValueNameToString (Type enum_type, string value_name)
  718. {
  719. if (value_name.EndsWith ("*"))
  720. throw new ApplicationException ("Invalid property value: '" + value_name +
  721. ". It must be a valid " + enum_type.ToString () + " value.");
  722. MemberInfo [] nested_types = enum_type.FindMembers (MemberTypes.Field,
  723. BindingFlags.Public | BindingFlags.Static,
  724. Type.FilterNameIgnoreCase,
  725. value_name);
  726. if (nested_types.Length == 0)
  727. throw new ApplicationException ("Value " + value_name + " not found in enumeration " +
  728. enum_type.ToString ());
  729. if (nested_types.Length > 1)
  730. throw new ApplicationException ("Value " + value_name + " found " +
  731. nested_types.Length + " in enumeration " +
  732. enum_type.ToString ());
  733. return enum_type.ToString () + "." + nested_types [0].Name;
  734. }
  735. private void NewControlFunction (string tag_id,
  736. string control_id,
  737. Type control_type,
  738. ChildrenKind children_kind,
  739. string defaultPropertyName)
  740. {
  741. ChildrenKind prev_children_kind = controls.PeekChildKind ();
  742. if (prev_children_kind == ChildrenKind.NONE ||
  743. prev_children_kind == ChildrenKind.PROPERTIES){
  744. string prev_tag_id = controls.PeekTagID ();
  745. throw new ApplicationException ("Child controls not allowed for " + prev_tag_id);
  746. }
  747. if (prev_children_kind == ChildrenKind.DBCOLUMNS &&
  748. control_type != typeof (System.Web.UI.WebControls.DataGridColumn) &&
  749. !control_type.IsSubclassOf (typeof (System.Web.UI.WebControls.DataGridColumn)))
  750. throw new ApplicationException ("Inside " + controls.PeekTagID () + " only " +
  751. "System.Web.UI.WebControls.DataGridColum " +
  752. "objects are allowed");
  753. else if (prev_children_kind == ChildrenKind.LISTITEM &&
  754. control_type != typeof (System.Web.UI.WebControls.ListItem))
  755. throw new ApplicationException ("Inside " + controls.PeekTagID () + " only " +
  756. "System.Web.UI.WebControls.ListItem " +
  757. "objects are allowed");
  758. else if (prev_children_kind == ChildrenKind.HTMLROW &&
  759. control_type != typeof (System.Web.UI.HtmlControls.HtmlTableRow))
  760. throw new ApplicationException ("Inside " + controls.PeekTagID () + " only " +
  761. "System.Web.UI.HtmlControls.HtmlTableRow " +
  762. "objects are allowed");
  763. else if (prev_children_kind == ChildrenKind.HTMLCELL &&
  764. control_type != typeof (System.Web.UI.HtmlControls.HtmlTableCell))
  765. throw new ApplicationException ("Inside " + controls.PeekTagID () + " only " +
  766. "System.Web.UI.HtmlControls.HtmlTableCell " +
  767. "objects are allowed");
  768. StringBuilder func_code = new StringBuilder ();
  769. current_function = func_code;
  770. if (0 == String.Compare (tag_id, "form", true)){
  771. if (has_form_tag)
  772. throw new ApplicationException ("Only one form server tag allowed.");
  773. has_form_tag = true;
  774. }
  775. controls.Push (control_type, control_id, tag_id, children_kind, defaultPropertyName);
  776. bool is_generic = control_type == typeof (System.Web.UI.HtmlControls.HtmlGenericControl);
  777. functions.Push (current_function);
  778. if (control_type != typeof (System.Web.UI.WebControls.ListItem) &&
  779. prev_children_kind != ChildrenKind.DBCOLUMNS) {
  780. current_function.AppendFormat ("\t\tprivate System.Web.UI.Control __BuildControl_" +
  781. "{0} ()\n\t\t{{\n\t\t\t{1} __ctrl;\n\n\t\t\t__ctrl" +
  782. " = new {1} ({2});\n\t\t\tthis.{0} = __ctrl;\n",
  783. control_id, control_type,
  784. (is_generic? "\"" + tag_id + "\"" : ""));
  785. } else {
  786. current_function.AppendFormat ("\t\tprivate void __BuildControl_{0} ()\n\t\t{{" +
  787. "\n\t\t\t{1} __ctrl;\n\t\t\t__ctrl = new {1} ();" +
  788. "\n\t\t\tthis.{0} = __ctrl;\n",
  789. control_id, control_type);
  790. }
  791. if (children_kind == ChildrenKind.CONTROLS || children_kind == ChildrenKind.OPTION)
  792. current_function.Append ("\t\t\tSystem.Web.UI.IParserAccessor __parser = " +
  793. "(System.Web.UI.IParserAccessor) __ctrl;\n");
  794. }
  795. private void DataBoundProperty (Type target, string varName, string value)
  796. {
  797. if (value == "")
  798. throw new ApplicationException ("Empty data binding tag.");
  799. string control_id = controls.PeekControlID ();
  800. string control_type_string = controls.PeekType ().ToString ();
  801. StringBuilder db_function = controls.DataBindFunction;
  802. string container;
  803. if (controls.Container == null || !typeof (INamingContainer).IsAssignableFrom (controls.Container))
  804. container = "System.Web.UI.Control";
  805. else {
  806. container = controls.Container.ToString ();
  807. }
  808. if (db_function.Length == 0)
  809. db_function.AppendFormat ("\t\tpublic void __DataBind_{0} (object sender, " +
  810. "System.EventArgs e) {{\n" +
  811. "\t\t\t{1} Container;\n" +
  812. "\t\t\t{2} target;\n" +
  813. "\t\t\ttarget = ({2}) sender;\n" +
  814. "\t\t\tContainer = ({1}) target.BindingContainer;\n",
  815. control_id, container, control_type_string);
  816. /* Removes '<%#' and '%>' */
  817. string real_value = value.Remove (0,3);
  818. real_value = real_value.Remove (real_value.Length - 2, 2);
  819. real_value = real_value.Trim ();
  820. if (target == typeof (string))
  821. db_function.AppendFormat ("\t\t\ttarget.{0} = System.Convert.ToString ({1});\n",
  822. varName, real_value);
  823. else
  824. db_function.AppendFormat ("\t\t\ttarget.{0} = ({1}) ({2});\n",
  825. varName, target, real_value);
  826. }
  827. /*
  828. * Returns true if it generates some code for the specified property
  829. */
  830. private void AddCodeForPropertyOrField (Type type, string var_name, string att, bool isDataBound)
  831. {
  832. /* FIXME: should i check for this or let the compiler fail?
  833. * if (!prop.CanWrite)
  834. * ....
  835. */
  836. if (isDataBound) {
  837. DataBoundProperty (type, var_name, att);
  838. }
  839. else if (type == typeof (string)){
  840. if (att == null)
  841. throw new ApplicationException ("null value for attribute " + var_name );
  842. current_function.AppendFormat ("\t\t\t__ctrl.{0} = \"{1}\";\n", var_name,
  843. Escape (att)); // FIXME: really Escape this?
  844. }
  845. else if (type.IsEnum){
  846. if (att == null)
  847. throw new ApplicationException ("null value for attribute " + var_name );
  848. string enum_value = EnumValueNameToString (type, att);
  849. current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, enum_value);
  850. }
  851. else if (type == typeof (bool)){
  852. string value;
  853. if (att == null)
  854. value = "true"; //FIXME: is this ok for non Style properties?
  855. else if (0 == String.Compare (att, "true", true))
  856. value = "true";
  857. else if (0 == String.Compare (att, "false", true))
  858. value = "false";
  859. else
  860. throw new ApplicationException ("Value '" + att + "' is not a valid boolean.");
  861. current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, value);
  862. }
  863. else if (type == typeof (System.Web.UI.WebControls.Unit)){
  864. //FIXME: should use the culture specified in Page
  865. try {
  866. Unit value = Unit.Parse (att, System.Globalization.CultureInfo.InvariantCulture);
  867. } catch (Exception) {
  868. throw new ApplicationException ("'" + att + "' cannot be parsed as a unit.");
  869. }
  870. current_function.AppendFormat ("\t\t\t__ctrl.{0} = " +
  871. "System.Web.UI.WebControls.Unit.Parse (\"{1}\", " +
  872. "System.Globalization.CultureInfo.InvariantCulture);\n",
  873. var_name, att);
  874. }
  875. else if (type == typeof (System.Web.UI.WebControls.FontUnit)){
  876. //FIXME: should use the culture specified in Page
  877. try {
  878. FontUnit value = FontUnit.Parse (att, System.Globalization.CultureInfo.InvariantCulture);
  879. } catch (Exception) {
  880. throw new ApplicationException ("'" + att + "' cannot be parsed as a unit.");
  881. }
  882. current_function.AppendFormat ("\t\t\t__ctrl.{0} = " +
  883. "System.Web.UI.WebControls.FontUnit.Parse (\"{1}\", " +
  884. "System.Globalization.CultureInfo.InvariantCulture);\n",
  885. var_name, att);
  886. }
  887. else if (type == typeof (Int16) || type == typeof (Int32) || type == typeof (Int64)) {
  888. long value;
  889. try {
  890. value = Int64.Parse (att); //FIXME: should use the culture specified in Page
  891. } catch (Exception){
  892. throw new ApplicationException (att + " is not a valid signed number " +
  893. "or is out of range.");
  894. }
  895. current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, value);
  896. }
  897. else if (type == typeof (UInt16) || type == typeof (UInt32) || type == typeof (UInt64)) {
  898. ulong value;
  899. try {
  900. value = UInt64.Parse (att); //FIXME: should use the culture specified in Page
  901. } catch (Exception){
  902. throw new ApplicationException (att + " is not a valid unsigned number " +
  903. "or is out of range.");
  904. }
  905. current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, value);
  906. }
  907. else if (type == typeof (float)) {
  908. float value;
  909. try {
  910. value = Single.Parse (att);
  911. } catch (Exception){
  912. throw new ApplicationException (att + " is not avalid float number or " +
  913. "is out of range.");
  914. }
  915. current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, value);
  916. }
  917. else if (type == typeof (double)){
  918. double value;
  919. try {
  920. value = Double.Parse (att);
  921. } catch (Exception){
  922. throw new ApplicationException (att + " is not avalid double number or " +
  923. "is out of range.");
  924. }
  925. current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, value);
  926. }
  927. else if (type == typeof (System.Drawing.Color)){
  928. Color c;
  929. try {
  930. c = (Color) TypeDescriptor.GetConverter (typeof (Color)).ConvertFromString (att);
  931. } catch (Exception e){
  932. throw new ApplicationException ("Color " + att + " is not a valid color.", e);
  933. }
  934. // Should i also test for IsSystemColor?
  935. // Are KnownColor members in System.Drawing.Color?
  936. if (c.IsKnownColor){
  937. current_function.AppendFormat ("\t\t\t__ctrl.{0} = System.Drawing.Color." +
  938. "{1};\n", var_name, c.Name);
  939. }
  940. else {
  941. current_function.AppendFormat ("\t\t\t__ctrl.{0} = System.Drawing.Color." +
  942. "FromArgb ({1}, {2}, {3}, {4});\n",
  943. var_name, c.A, c.R, c.G, c.B);
  944. }
  945. }
  946. else {
  947. throw new ApplicationException ("Unsupported type in property: " +
  948. type.ToString ());
  949. }
  950. }
  951. private bool ProcessPropertiesAndFields (MemberInfo member, string id, TagAttributes att)
  952. {
  953. int hyphen = id.IndexOf ('-');
  954. bool isPropertyInfo = (member is PropertyInfo);
  955. bool is_processed = false;
  956. bool isDataBound = att.IsDataBound ((string) att [id]);
  957. Type type;
  958. if (isPropertyInfo) {
  959. type = ((PropertyInfo) member).PropertyType;
  960. if (hyphen == -1 && ((PropertyInfo) member).CanWrite == false)
  961. return false;
  962. } else {
  963. type = ((FieldInfo) member).FieldType;
  964. }
  965. if (0 == String.Compare (member.Name, id, true)){
  966. AddCodeForPropertyOrField (type, member.Name, (string) att [id], isDataBound);
  967. is_processed = true;
  968. } else if (hyphen != -1 && (type == fontinfoType || type == styleType || type.IsSubclassOf (styleType))){
  969. string prop_field = id.Replace ("-", ".");
  970. string [] parts = prop_field.Split (new char [] {'.'});
  971. if (parts.Length != 2 || 0 != String.Compare (member.Name, parts [0], true))
  972. return false;
  973. PropertyInfo [] subprops = type.GetProperties ();
  974. foreach (PropertyInfo subprop in subprops){
  975. if (0 != String.Compare (subprop.Name, parts [1], true))
  976. continue;
  977. if (subprop.CanWrite == false)
  978. return false;
  979. bool is_bool = subprop.PropertyType == typeof (bool);
  980. if (!is_bool && att [id] == null){
  981. att [id] = ""; // Font-Size -> Font-Size="" as html
  982. return false;
  983. }
  984. string value;
  985. if (att [id] == null && is_bool)
  986. value = "true"; // Font-Bold <=> Font-Bold="true"
  987. else
  988. value = (string) att [id];
  989. AddCodeForPropertyOrField (subprop.PropertyType,
  990. member.Name + "." + subprop.Name,
  991. value, isDataBound);
  992. is_processed = true;
  993. }
  994. }
  995. return is_processed;
  996. }
  997. private void AddCodeForAttributes (Type type, TagAttributes att)
  998. {
  999. EventInfo [] ev_info = type.GetEvents ();
  1000. PropertyInfo [] prop_info = type.GetProperties ();
  1001. FieldInfo [] field_info = type.GetFields ();
  1002. bool is_processed = false;
  1003. ArrayList processed = new ArrayList ();
  1004. foreach (string id in att.Keys){
  1005. if (0 == String.Compare (id, "runat", true) || 0 == String.Compare (id, "id", true))
  1006. continue;
  1007. if (id.Length > 2 && id.Substring (0, 2).ToUpper () == "ON"){
  1008. string id_as_event = id.Substring (2);
  1009. foreach (EventInfo ev in ev_info){
  1010. if (0 == String.Compare (ev.Name, id_as_event, true)){
  1011. current_function.AppendFormat (
  1012. "\t\t\t__ctrl.{0} += " +
  1013. "new {1} (this.{2});\n",
  1014. ev.Name, ev.EventHandlerType, att [id]);
  1015. is_processed = true;
  1016. break;
  1017. }
  1018. }
  1019. if (is_processed){
  1020. is_processed = false;
  1021. continue;
  1022. }
  1023. }
  1024. foreach (PropertyInfo prop in prop_info){
  1025. is_processed = ProcessPropertiesAndFields (prop, id, att);
  1026. if (is_processed)
  1027. break;
  1028. }
  1029. if (!is_processed) {
  1030. foreach (FieldInfo field in field_info){
  1031. is_processed = ProcessPropertiesAndFields (field, id, att);
  1032. if (is_processed)
  1033. break;
  1034. }
  1035. }
  1036. if (is_processed){
  1037. is_processed = false;
  1038. continue;
  1039. }
  1040. current_function.AppendFormat ("\t\t\t((System.Web.UI.IAttributeAccessor) __ctrl)." +
  1041. "SetAttribute (\"{0}\", \"{1}\");\n",
  1042. id, Escape ((string) att [id]));
  1043. }
  1044. }
  1045. private void AddCodeRenderControl (StringBuilder function)
  1046. {
  1047. AddCodeRenderControl (function, controls.CodeRenderIndex);
  1048. }
  1049. private void AddCodeRenderControl (StringBuilder function, int index)
  1050. {
  1051. function.AppendFormat ("\t\t\tparameterContainer.Controls [{0}]." +
  1052. "RenderControl (__output);\n", index);
  1053. }
  1054. private void AddRenderMethodDelegate (StringBuilder function, string control_id)
  1055. {
  1056. function.AppendFormat ("\t\t\t__ctrl.SetRenderMethodDelegate (new System.Web." +
  1057. "UI.RenderMethod (this.__Render_{0}));\n", control_id);
  1058. }
  1059. private void AddCodeRenderFunction (string codeRender, string control_id)
  1060. {
  1061. StringBuilder codeRenderFunction = new StringBuilder ();
  1062. codeRenderFunction.AppendFormat ("\t\tprivate void __Render_{0} " +
  1063. "(System.Web.UI.HtmlTextWriter __output, " +
  1064. "System.Web.UI.Control parameterContainer)\n" +
  1065. "\t\t{{\n", control_id);
  1066. codeRenderFunction.Append (codeRender);
  1067. codeRenderFunction.Append ("\t\t}\n\n");
  1068. init_funcs.Append (codeRenderFunction);
  1069. }
  1070. private void RemoveLiterals (StringBuilder function)
  1071. {
  1072. string no_literals = Regex.Replace (function.ToString (),
  1073. @"\t\t\t__parser.AddParsedSubObject \(" +
  1074. @"new System.Web.UI.LiteralControl \(.+\);\n", "");
  1075. function.Length = 0;
  1076. function.Append (no_literals);
  1077. }
  1078. private bool FinishControlFunction (string tag_id)
  1079. {
  1080. if (functions.Count == 0)
  1081. throw new ApplicationException ("Unbalanced open/close tags");
  1082. if (controls.Count == 0)
  1083. return false;
  1084. string saved_id = controls.PeekTagID ();
  1085. if (0 != String.Compare (saved_id, tag_id, true))
  1086. return false;
  1087. StringBuilder old_function = (StringBuilder) functions.Pop ();
  1088. current_function = (StringBuilder) functions.Peek ();
  1089. string control_id = controls.PeekControlID ();
  1090. Type control_type = controls.PeekType ();
  1091. ChildrenKind child_kind = controls.PeekChildKind ();
  1092. bool hasDataBindFunction = controls.HasDataBindFunction ();
  1093. if (hasDataBindFunction)
  1094. old_function.AppendFormat ("\t\t\t__ctrl.DataBinding += new System.EventHandler " +
  1095. "(this.__DataBind_{0});\n", control_id);
  1096. bool useCodeRender = controls.UseCodeRender;
  1097. if (useCodeRender)
  1098. AddRenderMethodDelegate (old_function, control_id);
  1099. if (control_type == typeof (System.Web.UI.ITemplate)){
  1100. old_function.Append ("\n\t\t}\n\n");
  1101. current_function.AppendFormat ("\t\t\t__ctrl.{0} = new System.Web.UI." +
  1102. "CompiledTemplateBuilder (new System.Web.UI." +
  1103. "BuildTemplateMethod (this.__BuildControl_{1}));\n",
  1104. saved_id, control_id);
  1105. }
  1106. else if (control_type == typeof (System.Web.UI.WebControls.DataGridColumnCollection)){
  1107. old_function.Append ("\n\t\t}\n\n");
  1108. current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} (__ctrl.{1});\n",
  1109. control_id, saved_id);
  1110. }
  1111. else if (control_type == typeof (System.Web.UI.WebControls.DataGridColumn) ||
  1112. control_type.IsSubclassOf (typeof (System.Web.UI.WebControls.DataGridColumn)) ||
  1113. control_type == typeof (System.Web.UI.WebControls.ListItem)){
  1114. old_function.Append ("\n\t\t}\n\n");
  1115. string parsed = "";
  1116. string ctrl_name = "ctrl";
  1117. Type cont = controls.Container;
  1118. if (cont == null || cont == typeof (System.Web.UI.HtmlControls.HtmlSelect)){
  1119. parsed = "ParsedSubObject";
  1120. ctrl_name = "parser";
  1121. }
  1122. current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} ();\n" +
  1123. "\t\t\t__{1}.Add{2} (this.{0});\n\n",
  1124. control_id, ctrl_name, parsed);
  1125. }
  1126. else if (child_kind == ChildrenKind.LISTITEM){
  1127. old_function.Append ("\n\t\t}\n\n");
  1128. init_funcs.Append (old_function); // Closes the BuildList function
  1129. old_function = (StringBuilder) functions.Pop ();
  1130. current_function = (StringBuilder) functions.Peek ();
  1131. old_function.AppendFormat ("\n\t\t\tthis.__BuildControl_{0} (__ctrl.{1});\n\t\t\t" +
  1132. "return __ctrl;\n\t\t}}\n\n",
  1133. control_id, controls.PeekDefaultPropertyName ());
  1134. controls.Pop ();
  1135. control_id = controls.PeekControlID ();
  1136. current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} ();\n\t\t\t__parser." +
  1137. "AddParsedSubObject (this.{0});\n\n", control_id);
  1138. } else if (control_type == typeof (HtmlTableCell)) {
  1139. old_function.Append ("\n\t\t\treturn __ctrl;\n\t\t}\n\n");
  1140. object top = controls.Pop ();
  1141. Type t = controls.PeekType ();
  1142. controls.Push (top);
  1143. string parsed = "";
  1144. string ctrl_name = "ctrl";
  1145. if (t != typeof (HtmlTableRow)) {
  1146. parsed = "ParsedSubObject";
  1147. ctrl_name = "parser";
  1148. }
  1149. current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} ();\n" +
  1150. "\t\t\t__{1}.Add{2} (this.{0});\n\n",
  1151. control_id, ctrl_name, parsed);
  1152. } else if (child_kind == ChildrenKind.HTMLROW || child_kind == ChildrenKind.HTMLCELL) {
  1153. old_function.Append ("\n\t\t}\n\n");
  1154. init_funcs.Append (old_function);
  1155. old_function = (StringBuilder) functions.Pop ();
  1156. current_function = (StringBuilder) functions.Peek ();
  1157. old_function.AppendFormat ("\n\t\t\tthis.__BuildControl_{0} (__ctrl.{1});\n\t\t\t" +
  1158. "return __ctrl;\n\t\t}}\n\n",
  1159. control_id, controls.PeekDefaultPropertyName ());
  1160. controls.Pop ();
  1161. control_id = controls.PeekControlID ();
  1162. current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} ();\n", control_id);
  1163. if (child_kind == ChildrenKind.HTMLROW) {
  1164. current_function.AppendFormat ("\t\t\t__parser.AddParsedSubObject ({0});\n",
  1165. control_id);
  1166. } else {
  1167. current_function.AppendFormat ("\t\t\t__ctrl.Add (this.{0});\n", control_id);
  1168. }
  1169. } else {
  1170. old_function.Append ("\n\t\t\treturn __ctrl;\n\t\t}\n\n");
  1171. current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} ();\n\t\t\t__parser." +
  1172. "AddParsedSubObject (this.{0});\n\n", control_id);
  1173. }
  1174. if (useCodeRender)
  1175. RemoveLiterals (old_function);
  1176. init_funcs.Append (old_function);
  1177. if (useCodeRender)
  1178. AddCodeRenderFunction (controls.CodeRenderFunction.ToString (), control_id);
  1179. if (hasDataBindFunction){
  1180. StringBuilder db_function = controls.DataBindFunction;
  1181. db_function.Append ("\t\t}\n\n");
  1182. init_funcs.Append (db_function);
  1183. }
  1184. // Avoid getting empty stacks for unbalanced open/close tags
  1185. if (controls.Count > 1){
  1186. controls.Pop ();
  1187. AddCodeRenderControl (controls.CodeRenderFunction, controls.ChildIndex);
  1188. }
  1189. return true;
  1190. }
  1191. private void NewTableElementFunction (HtmlControlTag ctrl)
  1192. {
  1193. string control_id = Tag.GetDefaultID ();
  1194. ChildrenKind child_kind;
  1195. Type t;
  1196. if (ctrl.ControlType == typeof (HtmlTable)) {
  1197. t = typeof (HtmlTableRowCollection);
  1198. child_kind = ChildrenKind.HTMLROW;
  1199. } else {
  1200. t = typeof (HtmlTableCellCollection);
  1201. child_kind = ChildrenKind.HTMLCELL;
  1202. }
  1203. controls.Push (ctrl.ControlType,
  1204. control_id,
  1205. ctrl.TagID,
  1206. child_kind,
  1207. ctrl.ParseChildren);
  1208. current_function = new StringBuilder ();
  1209. functions.Push (current_function);
  1210. current_function.AppendFormat ("\t\tprivate void __BuildControl_{0} ({1} __ctrl)\n" +
  1211. "\t\t{{\n", control_id, t);
  1212. }
  1213. private void ProcessHtmlControlTag ()
  1214. {
  1215. HtmlControlTag html_ctrl = (HtmlControlTag) elements.Current;
  1216. if (html_ctrl.TagID.ToUpper () == "SCRIPT"){
  1217. //FIXME: if the is script is to be read from disk, do it!
  1218. if (html_ctrl.SelfClosing)
  1219. throw new ApplicationException ("Read script from file not supported yet.");
  1220. if (elements.MoveNext () == false)
  1221. throw new ApplicationException ("Error after " + html_ctrl.ToString ());
  1222. if (elements.Current is PlainText){
  1223. script.Append (((PlainText) elements.Current).Text);
  1224. if (!elements.MoveNext ())
  1225. throw new ApplicationException ("Error after " +
  1226. elements.Current.ToString ());
  1227. }
  1228. if (elements.Current is CloseTag)
  1229. elements.MoveNext ();
  1230. return;
  1231. } else if (IsApplication) {
  1232. throw new ApplicationException (app_file_wrong);
  1233. }
  1234. Type controlType = html_ctrl.ControlType;
  1235. AddProtectedField (controlType, html_ctrl.ControlID);
  1236. ChildrenKind children_kind;
  1237. if (0 == String.Compare (html_ctrl.TagID, "table", true))
  1238. children_kind = ChildrenKind.HTMLROW;
  1239. else if (0 == String.Compare (html_ctrl.TagID, "tr", true))
  1240. children_kind = ChildrenKind.HTMLCELL;
  1241. else if (0 != String.Compare (html_ctrl.TagID, "select", true))
  1242. children_kind = html_ctrl.IsContainer ? ChildrenKind.CONTROLS :
  1243. ChildrenKind.NONE;
  1244. else
  1245. children_kind = ChildrenKind.OPTION;
  1246. NewControlFunction (html_ctrl.TagID, html_ctrl.ControlID, controlType, children_kind, html_ctrl.ParseChildren);
  1247. current_function.AppendFormat ("\t\t\t__ctrl.ID = \"{0}\";\n", html_ctrl.ControlID);
  1248. AddCodeForAttributes (html_ctrl.ControlType, html_ctrl.Attributes);
  1249. if (children_kind == ChildrenKind.HTMLROW || children_kind == ChildrenKind.HTMLCELL)
  1250. NewTableElementFunction (html_ctrl);
  1251. if (!html_ctrl.SelfClosing)
  1252. JustDoIt ();
  1253. else
  1254. FinishControlFunction (html_ctrl.TagID);
  1255. }
  1256. // Closing is performed in FinishControlFunction ()
  1257. private void NewBuildListFunction (AspComponent component)
  1258. {
  1259. string control_id = Tag.GetDefaultID ();
  1260. controls.Push (component.ComponentType,
  1261. control_id,
  1262. component.TagID,
  1263. ChildrenKind.LISTITEM,
  1264. component.DefaultPropertyName);
  1265. current_function = new StringBuilder ();
  1266. functions.Push (current_function);
  1267. current_function.AppendFormat ("\t\tprivate void __BuildControl_{0} " +
  1268. "(System.Web.UI.WebControls.ListItemCollection __ctrl)\n" +
  1269. "\t\t{{\n", control_id);
  1270. }
  1271. private void ProcessComponent ()
  1272. {
  1273. AspComponent component = (AspComponent) elements.Current;
  1274. Type component_type = component.ComponentType;
  1275. AddProtectedField (component_type, component.ControlID);
  1276. NewControlFunction (component.TagID, component.ControlID, component_type,
  1277. component.ChildrenKind, component.DefaultPropertyName);
  1278. if (component_type == typeof (UserControl) ||
  1279. component_type.IsSubclassOf (typeof (System.Web.UI.UserControl)))
  1280. current_function.Append ("\t\t\t__ctrl.InitializeAsUserControl (Page);\n");
  1281. if (component_type == typeof (Control) ||
  1282. component_type.IsSubclassOf (typeof (System.Web.UI.Control)))
  1283. current_function.AppendFormat ("\t\t\t__ctrl.ID = \"{0}\";\n", component.ControlID);
  1284. AddCodeForAttributes (component.ComponentType, component.Attributes);
  1285. if (component.ChildrenKind == ChildrenKind.LISTITEM)
  1286. NewBuildListFunction (component);
  1287. if (!component.SelfClosing)
  1288. JustDoIt ();
  1289. else
  1290. FinishControlFunction (component.TagID);
  1291. }
  1292. private void ProcessServerObjectTag ()
  1293. {
  1294. ServerObjectTag obj = (ServerObjectTag) elements.Current;
  1295. declarations.AppendFormat ("\t\tprivate {0} cached{1};\n", obj.ObjectClass, obj.ObjectID);
  1296. constructor.AppendFormat ("\n\t\tprivate {0} {1}\n\t\t{{\n\t\t\tget {{\n\t\t\t\t" +
  1297. "if (this.cached{1} == null)\n\t\t\t\t\tthis.cached{1} = " +
  1298. "new {0} ();\n\t\t\t\treturn cached{1};\n\t\t\t}}\n\t\t}}\n\n",
  1299. obj.ObjectClass, obj.ObjectID);
  1300. }
  1301. // Creates a new function that sets the values of subproperties.
  1302. private void NewStyleFunction (PropertyTag tag)
  1303. {
  1304. current_function = new StringBuilder ();
  1305. string prop_id = tag.PropertyID;
  1306. Type prop_type = tag.PropertyType;
  1307. // begin function
  1308. current_function.AppendFormat ("\t\tprivate void __BuildControl_{0} ({1} __ctrl)\n" +
  1309. "\t\t{{\n", prop_id, prop_type);
  1310. // Add property initialization code
  1311. PropertyInfo [] subprop_info = prop_type.GetProperties ();
  1312. TagAttributes att = tag.Attributes;
  1313. string subprop_name = null;
  1314. foreach (string id in att.Keys){
  1315. if (0 == String.Compare (id, "runat", true) || 0 == String.Compare (id, "id", true))
  1316. continue;
  1317. bool is_processed = false;
  1318. foreach (PropertyInfo subprop in subprop_info){
  1319. is_processed = ProcessPropertiesAndFields (subprop, id, att);
  1320. if (is_processed){
  1321. subprop_name = subprop.Name;
  1322. break;
  1323. }
  1324. }
  1325. if (subprop_name == null)
  1326. throw new ApplicationException ("Property " + tag.TagID + " does not have " +
  1327. "a " + id + " subproperty.");
  1328. }
  1329. // Finish function
  1330. current_function.Append ("\n\t\t}\n\n");
  1331. init_funcs.Append (current_function);
  1332. current_function = (StringBuilder) functions.Peek ();
  1333. current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} (__ctrl.{1});\n",
  1334. prop_id, tag.PropertyName);
  1335. if (!tag.SelfClosing){
  1336. // Next tag should be the closing tag
  1337. controls.Push (null, null, null, ChildrenKind.NONE, null);
  1338. bool closing_tag_found = false;
  1339. Element elem;
  1340. while (!closing_tag_found && elements.MoveNext ()){
  1341. elem = (Element) elements.Current;
  1342. if (elem is PlainText)
  1343. ProcessPlainText ();
  1344. else if (!(elem is CloseTag))
  1345. throw new ApplicationException ("Tag " + tag.TagID +
  1346. " not properly closed.");
  1347. else
  1348. closing_tag_found = true;
  1349. }
  1350. if (!closing_tag_found)
  1351. throw new ApplicationException ("Tag " + tag.TagID + " not properly closed.");
  1352. controls.Pop ();
  1353. }
  1354. }
  1355. // This one just opens the function. Closing is performed in FinishControlFunction ()
  1356. private void NewTemplateFunction (PropertyTag tag)
  1357. {
  1358. /*
  1359. * FIXME
  1360. * This function does almost the same as NewControlFunction.
  1361. * Consider merging.
  1362. */
  1363. string prop_id = tag.PropertyID;
  1364. Type prop_type = tag.PropertyType;
  1365. string tag_id = tag.PropertyName; // Real property name used in FinishControlFunction
  1366. controls.Push (prop_type, prop_id, tag_id, ChildrenKind.CONTROLS, null);
  1367. current_function = new StringBuilder ();
  1368. functions.Push (current_function);
  1369. current_function.AppendFormat ("\t\tprivate void __BuildControl_{0} " +
  1370. "(System.Web.UI.Control __ctrl)\n" +
  1371. "\t\t{{\n" +
  1372. "\t\t\tSystem.Web.UI.IParserAccessor __parser " +
  1373. "= (System.Web.UI.IParserAccessor) __ctrl;\n" , prop_id);
  1374. }
  1375. // Closing is performed in FinishControlFunction ()
  1376. private void NewDBColumnFunction (PropertyTag tag)
  1377. {
  1378. /*
  1379. * FIXME
  1380. * This function also does almost the same as NewControlFunction.
  1381. * Consider merging.
  1382. */
  1383. string prop_id = tag.PropertyID;
  1384. Type prop_type = tag.PropertyType;
  1385. string tag_id = tag.PropertyName; // Real property name used in FinishControlFunction
  1386. controls.Push (prop_type, prop_id, tag_id, ChildrenKind.DBCOLUMNS, null);
  1387. current_function = new StringBuilder ();
  1388. functions.Push (current_function);
  1389. current_function.AppendFormat ("\t\tprivate void __BuildControl_{0} " +
  1390. "(System.Web.UI.WebControls.DataGridColumnCollection __ctrl)\n" +
  1391. "\t\t{{\n", prop_id);
  1392. }
  1393. private void NewPropertyFunction (PropertyTag tag)
  1394. {
  1395. if (tag.PropertyType == typeof (System.Web.UI.WebControls.Style) ||
  1396. tag.PropertyType.IsSubclassOf (typeof (System.Web.UI.WebControls.Style)))
  1397. NewStyleFunction (tag);
  1398. else if (tag.PropertyType == typeof (System.Web.UI.ITemplate))
  1399. NewTemplateFunction (tag);
  1400. else if (tag.PropertyType == typeof (System.Web.UI.WebControls.DataGridColumnCollection))
  1401. NewDBColumnFunction (tag);
  1402. else
  1403. throw new ApplicationException ("Other than Style and ITemplate not supported yet. " +
  1404. tag.PropertyType);
  1405. }
  1406. private void ProcessHtmlTag ()
  1407. {
  1408. Tag tag = (Tag) elements.Current;
  1409. ChildrenKind child_kind = controls.PeekChildKind ();
  1410. if (child_kind == ChildrenKind.NONE){
  1411. string tag_id = controls.PeekTagID ();
  1412. throw new ApplicationException (tag + " not allowed inside " + tag_id);
  1413. }
  1414. if (child_kind == ChildrenKind.OPTION){
  1415. if (0 != String.Compare (tag.TagID, "option", true))
  1416. throw new ApplicationException ("Only <option> tags allowed inside <select>.");
  1417. string default_id = Tag.GetDefaultID ();
  1418. Type type = typeof (System.Web.UI.WebControls.ListItem);
  1419. AddProtectedField (type, default_id);
  1420. NewControlFunction (tag.TagID, default_id, type, ChildrenKind.CONTROLS, null);
  1421. return;
  1422. }
  1423. if (child_kind == ChildrenKind.CONTROLS) {
  1424. ArrayList tag_elements = tag.GetElements ();
  1425. foreach (Element e in tag_elements) {
  1426. if (e is PlainText) {
  1427. elements.Current = e;
  1428. ProcessPlainText ();
  1429. } else if (e is CodeRenderTag) {
  1430. elements.Current = e;
  1431. ProcessCodeRenderTag ();
  1432. } else if (e is DataBindingTag) {
  1433. elements.Current = e;
  1434. ProcessDataBindingLiteral ();
  1435. } else {
  1436. throw new ApplicationException (fullPath + ": unexpected tag type " + e.GetType ());
  1437. }
  1438. }
  1439. return;
  1440. }
  1441. if (child_kind == ChildrenKind.HTMLROW) {
  1442. if (0 == String.Compare (tag.TagID, "tr", true)) {
  1443. elements.Current = new HtmlControlTag (tag);
  1444. ProcessHtmlControlTag ();
  1445. return;
  1446. }
  1447. }
  1448. if (child_kind == ChildrenKind.HTMLCELL) {
  1449. if (0 == String.Compare (tag.TagID, "td", true)) {
  1450. elements.Current = new HtmlControlTag (tag);
  1451. ProcessHtmlControlTag ();
  1452. return;
  1453. }
  1454. }
  1455. // Now child_kind should be PROPERTIES, so only allow tag_id == property
  1456. Type control_type = controls.PeekType ();
  1457. PropertyInfo [] prop_info = control_type.GetProperties ();
  1458. bool is_processed = false;
  1459. foreach (PropertyInfo prop in prop_info){
  1460. if (0 == String.Compare (prop.Name, tag.TagID, true)){
  1461. PropertyTag prop_tag = new PropertyTag (tag, prop.PropertyType, prop.Name);
  1462. NewPropertyFunction (prop_tag);
  1463. is_processed = true;
  1464. break;
  1465. }
  1466. }
  1467. if (!is_processed){
  1468. string tag_id = controls.PeekTagID ();
  1469. throw new ApplicationException (tag.TagID + " is not a property of " + control_type);
  1470. }
  1471. }
  1472. private Tag Map (Tag tag)
  1473. {
  1474. int pos = tag.TagID.IndexOf (":");
  1475. if (pos == -1) {
  1476. ChildrenKind child_kind = controls.PeekChildKind ();
  1477. if (child_kind == ChildrenKind.HTMLROW && 0 == String.Compare (tag.TagID, "tr", true)) {
  1478. tag.Attributes.Add ("runat", "server");
  1479. return new HtmlControlTag (tag);
  1480. } else if (child_kind == ChildrenKind.HTMLROW && 0 == String.Compare (tag.TagID, "tr", true)) {
  1481. tag.Attributes.Add ("runat", "server");
  1482. return new HtmlControlTag (tag);
  1483. }
  1484. }
  1485. if (tag is CloseTag ||
  1486. ((tag.Attributes == null ||
  1487. !tag.Attributes.IsRunAtServer ()) && pos == -1))
  1488. return tag;
  1489. if (pos == -1){
  1490. if (0 == String.Compare (tag.TagID, "object", true))
  1491. return new ServerObjectTag (tag);
  1492. return new HtmlControlTag (tag);
  1493. }
  1494. string foundry_name = tag.TagID.Substring (0, pos);
  1495. string component_name = tag.TagID.Substring (pos + 1);
  1496. if (Foundry.LookupFoundry (foundry_name) == false)
  1497. throw new ApplicationException ("Cannot find foundry for alias'" + foundry_name + "'");
  1498. AspComponent component = Foundry.MakeAspComponent (foundry_name, component_name, tag);
  1499. if (component == null)
  1500. throw new ApplicationException ("Cannot find component '" + component_name +
  1501. "' for alias '" + foundry_name + "'");
  1502. return component;
  1503. }
  1504. private void ProcessCloseTag ()
  1505. {
  1506. CloseTag close_tag = (CloseTag) elements.Current;
  1507. if (FinishControlFunction (close_tag.TagID))
  1508. return;
  1509. elements.Current = new PlainText (close_tag.PlainHtml);
  1510. ProcessPlainText ();
  1511. }
  1512. private void ProcessDataBindingLiteral ()
  1513. {
  1514. DataBindingTag dataBinding = (DataBindingTag) elements.Current;
  1515. string actual_value = dataBinding.Data;
  1516. if (actual_value == "")
  1517. throw new ApplicationException ("Empty data binding tag.");
  1518. if (controls.PeekChildKind () != ChildrenKind.CONTROLS)
  1519. throw new ApplicationException ("Data bound content not allowed for " +
  1520. controls.PeekTagID ());
  1521. StringBuilder db_function = new StringBuilder ();
  1522. string control_id = Tag.GetDefaultID ();
  1523. string control_type_string = "System.Web.UI.DataBoundLiteralControl";
  1524. AddProtectedField (typeof (System.Web.UI.DataBoundLiteralControl), control_id);
  1525. // Build the control
  1526. db_function.AppendFormat ("\t\tprivate System.Web.UI.Control __BuildControl_{0} ()\n" +
  1527. "\t\t{{\n\t\t\t{1} __ctrl;\n\n" +
  1528. "\t\t\t__ctrl = new {1} (0, 1);\n" +
  1529. "\t\t\tthis.{0} = __ctrl;\n" +
  1530. "\t\t\t__ctrl.DataBinding += new System.EventHandler " +
  1531. "(this.__DataBind_{0});\n" +
  1532. "\t\t\treturn __ctrl;\n"+
  1533. "\t\t}}\n\n",
  1534. control_id, control_type_string);
  1535. // DataBinding handler
  1536. db_function.AppendFormat ("\t\tpublic void __DataBind_{0} (object sender, " +
  1537. "System.EventArgs e) {{\n" +
  1538. "\t\t\t{1} Container;\n" +
  1539. "\t\t\t{2} target;\n" +
  1540. "\t\t\ttarget = ({2}) sender;\n" +
  1541. "\t\t\tContainer = ({1}) target.BindingContainer;\n" +
  1542. "\t\t\ttarget.SetDataBoundString (0, System.Convert." +
  1543. "ToString ({3}));\n" +
  1544. "\t\t}}\n\n",
  1545. control_id, controls.Container, control_type_string,
  1546. actual_value);
  1547. init_funcs.Append (db_function);
  1548. current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} ();\n\t\t\t__parser." +
  1549. "AddParsedSubObject (this.{0});\n\n", control_id);
  1550. AddCodeRenderControl (controls.CodeRenderFunction);
  1551. }
  1552. private void ProcessCodeRenderTag ()
  1553. {
  1554. CodeRenderTag code_tag = (CodeRenderTag) elements.Current;
  1555. controls.UseCodeRender = true;
  1556. if (code_tag.IsVarName)
  1557. controls.CodeRenderFunction.AppendFormat ("\t\t\t__output.Write ({0});\n",
  1558. code_tag.Code);
  1559. else
  1560. controls.CodeRenderFunction.AppendFormat ("\t\t\t{0}\n", code_tag.Code);
  1561. }
  1562. public void ProcessElements ()
  1563. {
  1564. JustDoIt ();
  1565. End ();
  1566. parse_ok = true;
  1567. }
  1568. private void JustDoIt ()
  1569. {
  1570. Element element;
  1571. while (elements.MoveNext ()){
  1572. element = (Element) elements.Current;
  1573. if (element is Directive){
  1574. ProcessDirective ();
  1575. } else if (element is PlainText){
  1576. ProcessPlainText ();
  1577. } else if (element is DataBindingTag){
  1578. if (IsApplication)
  1579. throw new ApplicationException (app_file_wrong);
  1580. ProcessDataBindingLiteral ();
  1581. } else if (element is CodeRenderTag){
  1582. if (IsApplication)
  1583. throw new ApplicationException (app_file_wrong);
  1584. ProcessCodeRenderTag ();
  1585. } else {
  1586. elements.Current = Map ((Tag) element);
  1587. if (elements.Current is ServerObjectTag) {
  1588. ProcessServerObjectTag ();
  1589. continue;
  1590. }
  1591. if (elements.Current is HtmlControlTag) {
  1592. ProcessHtmlControlTag ();
  1593. continue;
  1594. }
  1595. if (IsApplication)
  1596. throw new ApplicationException (app_file_wrong);
  1597. else if (elements.Current is AspComponent)
  1598. ProcessComponent ();
  1599. else if (elements.Current is CloseTag)
  1600. ProcessCloseTag ();
  1601. else if (elements.Current is Tag)
  1602. ProcessHtmlTag ();
  1603. else
  1604. throw new ApplicationException ("This place should not be reached.");
  1605. }
  1606. }
  1607. }
  1608. private string GetTemplateDirectory ()
  1609. {
  1610. string templatePath = Path.GetDirectoryName (fullPath);
  1611. string appPath = Path.GetDirectoryName (HttpRuntime.AppDomainAppPath);
  1612. if (templatePath == appPath)
  1613. return "/";
  1614. templatePath = templatePath.Substring (appPath.Length);
  1615. if (Path.DirectorySeparatorChar != '/')
  1616. templatePath = templatePath.Replace (Path.DirectorySeparatorChar, '/');
  1617. return templatePath;
  1618. }
  1619. private void End ()
  1620. {
  1621. if (isPage) {
  1622. if (sessionState == SessionState.Enabled || sessionState == SessionState.ReadOnly)
  1623. AddInterface (typeof (System.Web.SessionState.IRequiresSessionState));
  1624. if (sessionState == SessionState.ReadOnly)
  1625. AddInterface (typeof (System.Web.SessionState.IReadOnlySessionState));
  1626. }
  1627. classDecl = "\tpublic class " + className + " : " + parent + interfaces + " {\n";
  1628. prolog.Append ("\n" + classDecl);
  1629. declarations.Append ("\t\tprivate static bool __intialized = false;\n\n");
  1630. if (IsPage)
  1631. declarations.Append ("\t\tprivate static ArrayList __fileDependencies;\n\n");
  1632. // adds the constructor
  1633. constructor.AppendFormat ("\t\tpublic {0} ()\n\t\t{{\n", className);
  1634. if (!IsApplication)
  1635. constructor.Append ("\t\t\tSystem.Collections.ArrayList dependencies;\n\n");
  1636. constructor.AppendFormat ("\t\t\tif (ASP.{0}.__intialized == false){{\n", className);
  1637. if (IsPage) {
  1638. constructor.AppendFormat ("\t\t\t\tdependencies = new System.Collections.ArrayList ();\n" +
  1639. "\t\t\t\tdependencies.Add (@\"{1}\");\n" +
  1640. "\t\t\t\tASP.{0}.__fileDependencies = dependencies;\n",
  1641. className, fullPath);
  1642. }
  1643. constructor.AppendFormat ("\t\t\t\tASP.{0}.__intialized = true;\n\t\t\t}}\n\t\t}}\n\n",
  1644. className);
  1645. if (!IsApplication) {
  1646. //FIXME: add AutoHandlers: don't know what for...yet!
  1647. constructor.AppendFormat (
  1648. "\t\tprotected override int AutoHandlers\n\t\t{{\n" +
  1649. "\t\t\tget {{ return ASP.{0}.__autoHandlers; }}\n" +
  1650. "\t\t\tset {{ ASP.{0}.__autoHandlers = value; }}\n" +
  1651. "\t\t}}\n\n", className);
  1652. constructor.Append (
  1653. "\t\tprotected System.Web.HttpApplication ApplicationInstance\n\t\t{\n" +
  1654. "\t\t\tget { return (System.Web.HttpApplication) this.Context.ApplicationInstance; }\n" +
  1655. "\t\t}\n\n");
  1656. constructor.AppendFormat (
  1657. "\t\tpublic override string TemplateSourceDirectory\n\t\t{{\n" +
  1658. "\t\t\tget {{ return \"{0}\"; }}\n" +
  1659. "\t\t}}\n\n", GetTemplateDirectory ());
  1660. epilog.Append ("\n\t\tprotected override void FrameworkInitialize ()\n\t\t{\n" +
  1661. "\t\t\tthis.__BuildControlTree (this);\n");
  1662. if (IsPage) {
  1663. epilog.AppendFormat ("\t\t\tthis.FileDependencies = ASP.{0}.__fileDependencies;\n" +
  1664. "\t\t\tthis.EnableViewStateMac = true;\n", className);
  1665. }
  1666. epilog.Append ("\t\t}\n\n");
  1667. }
  1668. if (IsPage) {
  1669. Random rnd = new Random ();
  1670. epilog.AppendFormat ("\t\tpublic override int GetTypeHashCode ()\n\t\t{{\n" +
  1671. "\t\t\treturn {0};\n" +
  1672. "\t\t}}\n", rnd.Next ());
  1673. }
  1674. epilog.Append ("\t}\n}\n");
  1675. // Closes the currently opened tags
  1676. StringBuilder old_function = current_function;
  1677. string control_id;
  1678. while (functions.Count > 1){
  1679. old_function.Append ("\n\t\t\treturn __ctrl;\n\t\t}\n\n");
  1680. init_funcs.Append (old_function);
  1681. control_id = controls.PeekControlID ();
  1682. FinishControlFunction (control_id);
  1683. controls.AddChild ();
  1684. old_function = (StringBuilder) functions.Pop ();
  1685. current_function = (StringBuilder) functions.Peek ();
  1686. controls.Pop ();
  1687. }
  1688. bool useCodeRender = controls.UseCodeRender;
  1689. if (useCodeRender){
  1690. RemoveLiterals (current_function);
  1691. AddRenderMethodDelegate (current_function, controls.PeekControlID ());
  1692. }
  1693. current_function.Append ("\t\t}\n\n");
  1694. init_funcs.Append (current_function);
  1695. if (useCodeRender)
  1696. AddCodeRenderFunction (controls.CodeRenderFunction.ToString (), controls.PeekControlID ());
  1697. functions.Pop ();
  1698. }
  1699. //
  1700. // Functions related to compilation of user controls
  1701. //
  1702. private static char dirSeparator = Path.DirectorySeparatorChar;
  1703. struct UserControlData
  1704. {
  1705. public UserControlResult result;
  1706. public string className;
  1707. public string assemblyName;
  1708. }
  1709. private static UserControlData GenerateUserControl (string src, HttpContext context)
  1710. {
  1711. UserControlData data = new UserControlData ();
  1712. data.result = UserControlResult.OK;
  1713. UserControlCompiler compiler = new UserControlCompiler (new UserControlParser (src, context));
  1714. Type t = compiler.GetCompiledType ();
  1715. if (t == null) {
  1716. data.result = UserControlResult.CompilationFailed;
  1717. return data;
  1718. }
  1719. data.className = t.Name;
  1720. data.assemblyName = compiler.TargetFile;
  1721. return data;
  1722. }
  1723. }
  1724. }