AspGenerator.cs 60 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012
  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 = Type.GetType (typeName);
  491. if (type != null)
  492. return type;
  493. string [] binDlls = Directory.GetFiles (privateBinPath, "*.dll");
  494. Assembly assembly;
  495. foreach (string dll in binDlls) {
  496. string dllPath = Path.Combine (privateBinPath, dll);
  497. assembly = null;
  498. try {
  499. assembly = Assembly.LoadFrom (dllPath);
  500. type = assembly.GetType (typeName);
  501. } catch (Exception e) {
  502. if (assembly != null) {
  503. Console.WriteLine ("ASP.NET Warning: assembly {0} loaded", dllPath);
  504. Console.WriteLine ("ASP.NET Warning: but type {0} not found", typeName);
  505. } else {
  506. Console.WriteLine ("ASP.NET Warning: unable to load type {0} from {1}",
  507. typeName, dllPath);
  508. }
  509. Console.WriteLine ("ASP.NET Warning: error was: {0}", e.Message);
  510. }
  511. if (type != null)
  512. return type;
  513. }
  514. return null;
  515. }
  516. private void PageDirective (TagAttributes att)
  517. {
  518. if (att ["ClassName"] != null){
  519. this.className = (string) att ["ClassName"];
  520. Options ["ClassName"] = className;
  521. }
  522. if (att ["EnableSessionState"] != null){
  523. if (!IsPage)
  524. throw new ApplicationException ("EnableSessionState not allowed here.");
  525. string est = (string) att ["EnableSessionState"];
  526. if (0 == String.Compare (est, "false", true))
  527. sessionState = SessionState.Disabled;
  528. else if (0 == String.Compare (est, "true", true))
  529. sessionState = SessionState.Enabled;
  530. else if (0 == String.Compare (est, "readonly", true))
  531. sessionState = SessionState.ReadOnly;
  532. else
  533. throw new ApplicationException ("EnableSessionState in Page directive not set to " +
  534. "a correct value: " + est);
  535. }
  536. if (att ["Inherits"] != null) {
  537. parent = (string) att ["Inherits"];
  538. parentType = LoadParentType (parent);
  539. if (parentType == null)
  540. throw new ApplicationException ("The class " + parent + " cannot be found.");
  541. }
  542. if (att ["CompilerOptions"] != null)
  543. Options ["CompilerOptions"] = (string) att ["CompilerOptions"];
  544. if (att ["AutoEventWireup"] != null) {
  545. if (options ["AutoEventWireup"] != null)
  546. throw new ApplicationException ("Already have an AutoEventWireup attribute");
  547. bool autoevent = true;
  548. string v = att ["AutoEventWireup"] as string;
  549. try {
  550. autoevent = Convert.ToBoolean (v);
  551. } catch (Exception) {
  552. throw new ApplicationException ("'" + v + "' is not a valid value for AutoEventWireup");
  553. }
  554. options ["AutoEventWireup"] = autoevent;
  555. }
  556. //FIXME: add support for more attributes.
  557. }
  558. void AddReference (string dll)
  559. {
  560. string references = Options ["References"] as string;
  561. if (references == null)
  562. references = dll;
  563. else
  564. references = references + " " + dll;
  565. Options ["References"] = references;
  566. }
  567. private void RegisterDirective (TagAttributes att)
  568. {
  569. string tag_prefix = (string) (att ["tagprefix"] == null ? "" : att ["tagprefix"]);
  570. string name_space = (string) (att ["namespace"] == null ? "" : att ["namespace"]);
  571. string assembly_name = (string) (att ["assembly"] == null ? "" : att ["assembly"]);
  572. string tag_name = (string) (att ["tagname"] == null ? "" : att ["tagname"]);
  573. string src = (string) (att ["src"] == null ? "" : att ["src"]);
  574. if (tag_prefix != "" && name_space != "" && assembly_name != ""){
  575. if (tag_name != "" || src != "")
  576. throw new ApplicationException ("Invalid attributes for @ Register: " +
  577. att.ToString ());
  578. AddUsing (name_space);
  579. string dll = privateBinPath + Path.DirectorySeparatorChar + assembly_name + ".dll";
  580. // Hack: it should use assembly.load semantics...
  581. // may be when we don't run mcs as a external program...
  582. if (!File.Exists (dll))
  583. dll = assembly_name;
  584. Foundry.RegisterFoundry (tag_prefix, dll, name_space);
  585. AddReference (dll);
  586. return;
  587. }
  588. if (tag_prefix != "" && tag_name != "" && src != ""){
  589. if (name_space != "" && assembly_name != "")
  590. throw new ApplicationException ("Invalid attributes for @ Register: " +
  591. att.ToString ());
  592. if (!src.EndsWith (".ascx"))
  593. throw new ApplicationException ("Source file extension for controls " +
  594. "must be .ascx");
  595. UserControlData data = GenerateUserControl (src, Context);
  596. switch (data.result) {
  597. case UserControlResult.OK:
  598. AddUsing ("ASP");
  599. string dll = "output" + Path.DirectorySeparatorChar + data.assemblyName + ".dll";
  600. Foundry.RegisterFoundry (tag_prefix, tag_name, data.assemblyName, "ASP", data.className);
  601. AddReference (data.assemblyName);
  602. break;
  603. case UserControlResult.FileNotFound:
  604. throw new ApplicationException ("File '" + src + "' not found.");
  605. case UserControlResult.CompilationFailed:
  606. //TODO: should say where the generated .cs file is for the server to
  607. //show the source and the compiler error
  608. throw new NotImplementedException ();
  609. }
  610. return;
  611. }
  612. throw new ApplicationException ("Invalid combination of attributes in " +
  613. "@ Register: " + att.ToString ());
  614. }
  615. private void ProcessDirective ()
  616. {
  617. Directive directive = (Directive) elements.Current;
  618. TagAttributes att = directive.Attributes;
  619. if (att == null)
  620. return;
  621. string value;
  622. string id = directive.TagID.ToUpper ();
  623. switch (id){
  624. case "APPLICATION":
  625. if (main_directive != null)
  626. throw new ApplicationException (id + " not allowed after " + main_directive);
  627. if (!IsApplication)
  628. throw new ApplicationException ("@Application not allowed.");
  629. string inherits = att ["inherits"] as string;
  630. if (inherits != null)
  631. Options ["Inherits"] = inherits;
  632. main_directive = directive.TagID;
  633. break;
  634. case "PAGE":
  635. case "CONTROL":
  636. if (main_directive != null)
  637. throw new ApplicationException (id + " not allowed after " + main_directive);
  638. if (IsUserControl && id != "CONTROL")
  639. throw new ApplicationException ("@Page not allowed for user controls.");
  640. else if (IsPage && id != "PAGE")
  641. throw new ApplicationException ("@Control not allowed here. This is a page!");
  642. PageDirective (att);
  643. main_directive = directive.TagID;
  644. break;
  645. case "IMPORT":
  646. value = att ["namespace"] as string;
  647. if (value == null || att.Count > 1)
  648. throw new ApplicationException ("Wrong syntax in Import directive.");
  649. string _using = "using " + value + ";";
  650. if (AddUsing (value) == true) {
  651. string imports = Options ["Import"] as string;
  652. if (imports == null) {
  653. imports = value;
  654. } else {
  655. imports += "," + value;
  656. }
  657. Options ["Import"] = imports;
  658. }
  659. break;
  660. case "IMPLEMENTS":
  661. if (IsApplication)
  662. throw new ApplicationException ("@ Implements not allowed in an application file.");
  663. string iface = (string) att ["interface"];
  664. AddInterface (iface);
  665. break;
  666. case "REGISTER":
  667. if (IsApplication)
  668. throw new ApplicationException ("@ Register not allowed in an application file.");
  669. RegisterDirective (att);
  670. break;
  671. case "ASSEMBLY":
  672. if (att.Count > 1)
  673. throw new ApplicationException ("Wrong syntax in Assembly directive.");
  674. string name = att ["name"] as string;
  675. string src = att ["src"] as string;
  676. if (name == null && src == null)
  677. throw new ApplicationException ("Wrong syntax in Assembly directive.");
  678. if (IsApplication && src != null)
  679. throw new ApplicationException ("'name' attribute expected.");
  680. value = (name == null) ? src : name;
  681. string assemblies = Options ["Assembly"] as string;
  682. if (assemblies == null) {
  683. assemblies = value;
  684. } else {
  685. assemblies += "," + value;
  686. }
  687. Options ["Assembly"] = assemblies;
  688. break;
  689. }
  690. }
  691. private void ProcessPlainText ()
  692. {
  693. PlainText asis = (PlainText) elements.Current;
  694. string trimmed = asis.Text.Trim ();
  695. if (trimmed == String.Empty && controls.SpaceBetweenTags == true)
  696. return;
  697. if (IsApplication) {
  698. if (trimmed != String.Empty)
  699. throw new ApplicationException (app_file_wrong);
  700. return;
  701. }
  702. if (trimmed != String.Empty && controls.PeekChildKind () != ChildrenKind.CONTROLS){
  703. string tag_id = controls.PeekTagID ();
  704. throw new ApplicationException ("Literal content not allowed for " + tag_id);
  705. }
  706. string escaped_text = Escape (asis.Text);
  707. current_function.AppendFormat ("\t\t\t__parser.AddParsedSubObject (" +
  708. "new System.Web.UI.LiteralControl (\"{0}\"));\n",
  709. escaped_text);
  710. StringBuilder codeRenderFunction = controls.CodeRenderFunction;
  711. codeRenderFunction.AppendFormat ("\t\t\t__output.Write (\"{0}\");\n", escaped_text);
  712. }
  713. private string EnumValueNameToString (Type enum_type, string value_name)
  714. {
  715. if (value_name.EndsWith ("*"))
  716. throw new ApplicationException ("Invalid property value: '" + value_name +
  717. ". It must be a valid " + enum_type.ToString () + " value.");
  718. MemberInfo [] nested_types = enum_type.FindMembers (MemberTypes.Field,
  719. BindingFlags.Public | BindingFlags.Static,
  720. Type.FilterNameIgnoreCase,
  721. value_name);
  722. if (nested_types.Length == 0)
  723. throw new ApplicationException ("Value " + value_name + " not found in enumeration " +
  724. enum_type.ToString ());
  725. if (nested_types.Length > 1)
  726. throw new ApplicationException ("Value " + value_name + " found " +
  727. nested_types.Length + " in enumeration " +
  728. enum_type.ToString ());
  729. return enum_type.ToString () + "." + nested_types [0].Name;
  730. }
  731. private void NewControlFunction (string tag_id,
  732. string control_id,
  733. Type control_type,
  734. ChildrenKind children_kind,
  735. string defaultPropertyName)
  736. {
  737. ChildrenKind prev_children_kind = controls.PeekChildKind ();
  738. if (prev_children_kind == ChildrenKind.NONE ||
  739. prev_children_kind == ChildrenKind.PROPERTIES){
  740. string prev_tag_id = controls.PeekTagID ();
  741. throw new ApplicationException ("Child controls not allowed for " + prev_tag_id);
  742. }
  743. if (prev_children_kind == ChildrenKind.DBCOLUMNS &&
  744. control_type != typeof (System.Web.UI.WebControls.DataGridColumn) &&
  745. !control_type.IsSubclassOf (typeof (System.Web.UI.WebControls.DataGridColumn)))
  746. throw new ApplicationException ("Inside " + controls.PeekTagID () + " only " +
  747. "System.Web.UI.WebControls.DataGridColum " +
  748. "objects are allowed");
  749. else if (prev_children_kind == ChildrenKind.LISTITEM &&
  750. control_type != typeof (System.Web.UI.WebControls.ListItem))
  751. throw new ApplicationException ("Inside " + controls.PeekTagID () + " only " +
  752. "System.Web.UI.WebControls.ListItem " +
  753. "objects are allowed");
  754. else if (prev_children_kind == ChildrenKind.HTMLROW &&
  755. control_type != typeof (System.Web.UI.HtmlControls.HtmlTableRow))
  756. throw new ApplicationException ("Inside " + controls.PeekTagID () + " only " +
  757. "System.Web.UI.HtmlControls.HtmlTableRow " +
  758. "objects are allowed");
  759. else if (prev_children_kind == ChildrenKind.HTMLCELL &&
  760. control_type != typeof (System.Web.UI.HtmlControls.HtmlTableCell))
  761. throw new ApplicationException ("Inside " + controls.PeekTagID () + " only " +
  762. "System.Web.UI.HtmlControls.HtmlTableCell " +
  763. "objects are allowed");
  764. StringBuilder func_code = new StringBuilder ();
  765. current_function = func_code;
  766. if (0 == String.Compare (tag_id, "form", true)){
  767. if (has_form_tag)
  768. throw new ApplicationException ("Only one form server tag allowed.");
  769. has_form_tag = true;
  770. }
  771. controls.Push (control_type, control_id, tag_id, children_kind, defaultPropertyName);
  772. bool is_generic = control_type == typeof (System.Web.UI.HtmlControls.HtmlGenericControl);
  773. functions.Push (current_function);
  774. if (control_type != typeof (System.Web.UI.WebControls.ListItem))
  775. current_function.AppendFormat ("\t\tprivate System.Web.UI.Control __BuildControl_" +
  776. "{0} ()\n\t\t{{\n\t\t\t{1} __ctrl;\n\n\t\t\t__ctrl" +
  777. " = new {1} ({2});\n\t\t\tthis.{0} = __ctrl;\n",
  778. control_id, control_type,
  779. (is_generic? "\"" + tag_id + "\"" : ""));
  780. else
  781. current_function.AppendFormat ("\t\tprivate void __BuildControl_{0} ()\n\t\t{{" +
  782. "\n\t\t\t{1} __ctrl;\n\t\t\t__ctrl = new {1} ();" +
  783. "\n\t\t\tthis.{0} = __ctrl;\n",
  784. control_id, control_type);
  785. if (children_kind == ChildrenKind.CONTROLS || children_kind == ChildrenKind.OPTION)
  786. current_function.Append ("\t\t\tSystem.Web.UI.IParserAccessor __parser = " +
  787. "(System.Web.UI.IParserAccessor) __ctrl;\n");
  788. }
  789. private void DataBoundProperty (Type target, string varName, string value)
  790. {
  791. if (value == "")
  792. throw new ApplicationException ("Empty data binding tag.");
  793. string control_id = controls.PeekControlID ();
  794. string control_type_string = controls.PeekType ().ToString ();
  795. StringBuilder db_function = controls.DataBindFunction;
  796. string container;
  797. if (controls.Container == null)
  798. container = "System.Web.UI.Control";
  799. else
  800. container = controls.Container.ToString ();
  801. if (db_function.Length == 0)
  802. db_function.AppendFormat ("\t\tpublic void __DataBind_{0} (object sender, " +
  803. "System.EventArgs e) {{\n" +
  804. "\t\t\t{1} Container;\n" +
  805. "\t\t\t{2} target;\n" +
  806. "\t\t\ttarget = ({2}) sender;\n" +
  807. "\t\t\tContainer = ({1}) target.BindingContainer;\n",
  808. control_id, container, control_type_string);
  809. /* Removes '<%#' and '%>' */
  810. string real_value = value.Remove (0,3);
  811. real_value = real_value.Remove (real_value.Length - 2, 2);
  812. real_value = real_value.Trim ();
  813. if (target == typeof (string))
  814. db_function.AppendFormat ("\t\t\ttarget.{0} = System.Convert.ToString ({1});\n",
  815. varName, real_value);
  816. else
  817. db_function.AppendFormat ("\t\t\ttarget.{0} = ({1}) ({2});\n",
  818. varName, target, real_value);
  819. }
  820. /*
  821. * Returns true if it generates some code for the specified property
  822. */
  823. private void AddCodeForPropertyOrField (Type type, string var_name, string att, bool isDataBound)
  824. {
  825. /* FIXME: should i check for this or let the compiler fail?
  826. * if (!prop.CanWrite)
  827. * ....
  828. */
  829. if (isDataBound) {
  830. DataBoundProperty (type, var_name, att);
  831. }
  832. else if (type == typeof (string)){
  833. if (att == null)
  834. throw new ApplicationException ("null value for attribute " + var_name );
  835. current_function.AppendFormat ("\t\t\t__ctrl.{0} = \"{1}\";\n", var_name,
  836. Escape (att)); // FIXME: really Escape this?
  837. }
  838. else if (type.IsEnum){
  839. if (att == null)
  840. throw new ApplicationException ("null value for attribute " + var_name );
  841. string enum_value = EnumValueNameToString (type, att);
  842. current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, enum_value);
  843. }
  844. else if (type == typeof (bool)){
  845. string value;
  846. if (att == null)
  847. value = "true"; //FIXME: is this ok for non Style properties?
  848. else if (0 == String.Compare (att, "true", true))
  849. value = "true";
  850. else if (0 == String.Compare (att, "false", true))
  851. value = "false";
  852. else
  853. throw new ApplicationException ("Value '" + att + "' is not a valid boolean.");
  854. current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, value);
  855. }
  856. else if (type == typeof (System.Web.UI.WebControls.Unit)){
  857. //FIXME: should use the culture specified in Page
  858. try {
  859. Unit value = Unit.Parse (att, System.Globalization.CultureInfo.InvariantCulture);
  860. } catch (Exception) {
  861. throw new ApplicationException ("'" + att + "' cannot be parsed as a unit.");
  862. }
  863. current_function.AppendFormat ("\t\t\t__ctrl.{0} = " +
  864. "System.Web.UI.WebControls.Unit.Parse (\"{1}\", " +
  865. "System.Globalization.CultureInfo.InvariantCulture);\n",
  866. var_name, att);
  867. }
  868. else if (type == typeof (System.Web.UI.WebControls.FontUnit)){
  869. //FIXME: should use the culture specified in Page
  870. try {
  871. FontUnit value = FontUnit.Parse (att, System.Globalization.CultureInfo.InvariantCulture);
  872. } catch (Exception) {
  873. throw new ApplicationException ("'" + att + "' cannot be parsed as a unit.");
  874. }
  875. current_function.AppendFormat ("\t\t\t__ctrl.{0} = " +
  876. "System.Web.UI.WebControls.FontUnit.Parse (\"{1}\", " +
  877. "System.Globalization.CultureInfo.InvariantCulture);\n",
  878. var_name, att);
  879. }
  880. else if (type == typeof (Int16) || type == typeof (Int32) || type == typeof (Int64)) {
  881. long value;
  882. try {
  883. value = Int64.Parse (att); //FIXME: should use the culture specified in Page
  884. } catch (Exception){
  885. throw new ApplicationException (att + " is not a valid signed number " +
  886. "or is out of range.");
  887. }
  888. current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, value);
  889. }
  890. else if (type == typeof (UInt16) || type == typeof (UInt32) || type == typeof (UInt64)) {
  891. ulong value;
  892. try {
  893. value = UInt64.Parse (att); //FIXME: should use the culture specified in Page
  894. } catch (Exception){
  895. throw new ApplicationException (att + " is not a valid unsigned number " +
  896. "or is out of range.");
  897. }
  898. current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, value);
  899. }
  900. else if (type == typeof (float)) {
  901. float value;
  902. try {
  903. value = Single.Parse (att);
  904. } catch (Exception){
  905. throw new ApplicationException (att + " is not avalid float number or " +
  906. "is out of range.");
  907. }
  908. current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, value);
  909. }
  910. else if (type == typeof (double)){
  911. double value;
  912. try {
  913. value = Double.Parse (att);
  914. } catch (Exception){
  915. throw new ApplicationException (att + " is not avalid double number or " +
  916. "is out of range.");
  917. }
  918. current_function.AppendFormat ("\t\t\t__ctrl.{0} = {1};\n", var_name, value);
  919. }
  920. else if (type == typeof (System.Drawing.Color)){
  921. Color c;
  922. try {
  923. c = (Color) TypeDescriptor.GetConverter (typeof (Color)).ConvertFromString (att);
  924. } catch (Exception e){
  925. throw new ApplicationException ("Color " + att + " is not a valid color.", e);
  926. }
  927. // Should i also test for IsSystemColor?
  928. // Are KnownColor members in System.Drawing.Color?
  929. if (c.IsKnownColor){
  930. current_function.AppendFormat ("\t\t\t__ctrl.{0} = System.Drawing.Color." +
  931. "{1};\n", var_name, c.Name);
  932. }
  933. else {
  934. current_function.AppendFormat ("\t\t\t__ctrl.{0} = System.Drawing.Color." +
  935. "FromArgb ({1}, {2}, {3}, {4});\n",
  936. var_name, c.A, c.R, c.G, c.B);
  937. }
  938. }
  939. else {
  940. throw new ApplicationException ("Unsupported type in property: " +
  941. type.ToString ());
  942. }
  943. }
  944. private bool ProcessPropertiesAndFields (MemberInfo member, string id, TagAttributes att)
  945. {
  946. int hyphen = id.IndexOf ('-');
  947. bool isPropertyInfo = (member is PropertyInfo);
  948. bool is_processed = false;
  949. bool isDataBound = att.IsDataBound ((string) att [id]);
  950. Type type;
  951. if (isPropertyInfo) {
  952. type = ((PropertyInfo) member).PropertyType;
  953. if (hyphen == -1 && ((PropertyInfo) member).CanWrite == false)
  954. return false;
  955. } else {
  956. type = ((FieldInfo) member).FieldType;
  957. }
  958. if (0 == String.Compare (member.Name, id, true)){
  959. AddCodeForPropertyOrField (type, member.Name, (string) att [id], isDataBound);
  960. is_processed = true;
  961. } else if (hyphen != -1 && (type == fontinfoType || type == styleType || type.IsSubclassOf (styleType))){
  962. string prop_field = id.Replace ("-", ".");
  963. string [] parts = prop_field.Split (new char [] {'.'});
  964. if (parts.Length != 2 || 0 != String.Compare (member.Name, parts [0], true))
  965. return false;
  966. PropertyInfo [] subprops = type.GetProperties ();
  967. foreach (PropertyInfo subprop in subprops){
  968. if (0 != String.Compare (subprop.Name, parts [1], true))
  969. continue;
  970. if (subprop.CanWrite == false)
  971. return false;
  972. bool is_bool = subprop.PropertyType == typeof (bool);
  973. if (!is_bool && att [id] == null){
  974. att [id] = ""; // Font-Size -> Font-Size="" as html
  975. return false;
  976. }
  977. string value;
  978. if (att [id] == null && is_bool)
  979. value = "true"; // Font-Bold <=> Font-Bold="true"
  980. else
  981. value = (string) att [id];
  982. AddCodeForPropertyOrField (subprop.PropertyType,
  983. member.Name + "." + subprop.Name,
  984. value, isDataBound);
  985. is_processed = true;
  986. }
  987. }
  988. return is_processed;
  989. }
  990. private void AddCodeForAttributes (Type type, TagAttributes att)
  991. {
  992. EventInfo [] ev_info = type.GetEvents ();
  993. PropertyInfo [] prop_info = type.GetProperties ();
  994. FieldInfo [] field_info = type.GetFields ();
  995. bool is_processed = false;
  996. ArrayList processed = new ArrayList ();
  997. foreach (string id in att.Keys){
  998. if (0 == String.Compare (id, "runat", true) || 0 == String.Compare (id, "id", true))
  999. continue;
  1000. if (id.Length > 2 && id.Substring (0, 2).ToUpper () == "ON"){
  1001. string id_as_event = id.Substring (2);
  1002. foreach (EventInfo ev in ev_info){
  1003. if (0 == String.Compare (ev.Name, id_as_event, true)){
  1004. current_function.AppendFormat (
  1005. "\t\t\t__ctrl.{0} += " +
  1006. "new {1} (this.{2});\n",
  1007. ev.Name, ev.EventHandlerType, att [id]);
  1008. is_processed = true;
  1009. break;
  1010. }
  1011. }
  1012. if (is_processed){
  1013. is_processed = false;
  1014. continue;
  1015. }
  1016. }
  1017. foreach (PropertyInfo prop in prop_info){
  1018. is_processed = ProcessPropertiesAndFields (prop, id, att);
  1019. if (is_processed)
  1020. break;
  1021. }
  1022. if (!is_processed) {
  1023. foreach (FieldInfo field in field_info){
  1024. is_processed = ProcessPropertiesAndFields (field, id, att);
  1025. if (is_processed)
  1026. break;
  1027. }
  1028. }
  1029. if (is_processed){
  1030. is_processed = false;
  1031. continue;
  1032. }
  1033. current_function.AppendFormat ("\t\t\t((System.Web.UI.IAttributeAccessor) __ctrl)." +
  1034. "SetAttribute (\"{0}\", \"{1}\");\n",
  1035. id, Escape ((string) att [id]));
  1036. }
  1037. }
  1038. private void AddCodeRenderControl (StringBuilder function)
  1039. {
  1040. AddCodeRenderControl (function, controls.CodeRenderIndex);
  1041. }
  1042. private void AddCodeRenderControl (StringBuilder function, int index)
  1043. {
  1044. function.AppendFormat ("\t\t\tparameterContainer.Controls [{0}]." +
  1045. "RenderControl (__output);\n", index);
  1046. }
  1047. private void AddRenderMethodDelegate (StringBuilder function, string control_id)
  1048. {
  1049. function.AppendFormat ("\t\t\t__ctrl.SetRenderMethodDelegate (new System.Web." +
  1050. "UI.RenderMethod (this.__Render_{0}));\n", control_id);
  1051. }
  1052. private void AddCodeRenderFunction (string codeRender, string control_id)
  1053. {
  1054. StringBuilder codeRenderFunction = new StringBuilder ();
  1055. codeRenderFunction.AppendFormat ("\t\tprivate void __Render_{0} " +
  1056. "(System.Web.UI.HtmlTextWriter __output, " +
  1057. "System.Web.UI.Control parameterContainer)\n" +
  1058. "\t\t{{\n", control_id);
  1059. codeRenderFunction.Append (codeRender);
  1060. codeRenderFunction.Append ("\t\t}\n\n");
  1061. init_funcs.Append (codeRenderFunction);
  1062. }
  1063. private void RemoveLiterals (StringBuilder function)
  1064. {
  1065. string no_literals = Regex.Replace (function.ToString (),
  1066. @"\t\t\t__parser.AddParsedSubObject \(" +
  1067. @"new System.Web.UI.LiteralControl \(.+\);\n", "");
  1068. function.Length = 0;
  1069. function.Append (no_literals);
  1070. }
  1071. private bool FinishControlFunction (string tag_id)
  1072. {
  1073. if (functions.Count == 0)
  1074. throw new ApplicationException ("Unbalanced open/close tags");
  1075. if (controls.Count == 0)
  1076. return false;
  1077. string saved_id = controls.PeekTagID ();
  1078. if (0 != String.Compare (saved_id, tag_id, true))
  1079. return false;
  1080. StringBuilder old_function = (StringBuilder) functions.Pop ();
  1081. current_function = (StringBuilder) functions.Peek ();
  1082. string control_id = controls.PeekControlID ();
  1083. Type control_type = controls.PeekType ();
  1084. ChildrenKind child_kind = controls.PeekChildKind ();
  1085. bool hasDataBindFunction = controls.HasDataBindFunction ();
  1086. if (hasDataBindFunction)
  1087. old_function.AppendFormat ("\t\t\t__ctrl.DataBinding += new System.EventHandler " +
  1088. "(this.__DataBind_{0});\n", control_id);
  1089. bool useCodeRender = controls.UseCodeRender;
  1090. if (useCodeRender)
  1091. AddRenderMethodDelegate (old_function, control_id);
  1092. if (control_type == typeof (System.Web.UI.ITemplate)){
  1093. old_function.Append ("\n\t\t}\n\n");
  1094. current_function.AppendFormat ("\t\t\t__ctrl.{0} = new System.Web.UI." +
  1095. "CompiledTemplateBuilder (new System.Web.UI." +
  1096. "BuildTemplateMethod (this.__BuildControl_{1}));\n",
  1097. saved_id, control_id);
  1098. }
  1099. else if (control_type == typeof (System.Web.UI.WebControls.DataGridColumnCollection)){
  1100. old_function.Append ("\n\t\t}\n\n");
  1101. current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} (__ctrl.{1});\n",
  1102. control_id, saved_id);
  1103. }
  1104. else if (control_type == typeof (System.Web.UI.WebControls.DataGridColumn) ||
  1105. control_type.IsSubclassOf (typeof (System.Web.UI.WebControls.DataGridColumn)) ||
  1106. control_type == typeof (System.Web.UI.WebControls.ListItem)){
  1107. old_function.Append ("\n\t\t}\n\n");
  1108. string parsed = "";
  1109. string ctrl_name = "ctrl";
  1110. Type cont = controls.Container;
  1111. if (cont == null || cont == typeof (System.Web.UI.HtmlControls.HtmlSelect)){
  1112. parsed = "ParsedSubObject";
  1113. ctrl_name = "parser";
  1114. }
  1115. current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} ();\n" +
  1116. "\t\t\t__{1}.Add{2} (this.{0});\n\n",
  1117. control_id, ctrl_name, parsed);
  1118. }
  1119. else if (child_kind == ChildrenKind.LISTITEM){
  1120. old_function.Append ("\n\t\t}\n\n");
  1121. init_funcs.Append (old_function); // Closes the BuildList function
  1122. old_function = (StringBuilder) functions.Pop ();
  1123. current_function = (StringBuilder) functions.Peek ();
  1124. old_function.AppendFormat ("\n\t\t\tthis.__BuildControl_{0} (__ctrl.{1});\n\t\t\t" +
  1125. "return __ctrl;\n\t\t}}\n\n",
  1126. control_id, controls.PeekDefaultPropertyName ());
  1127. controls.Pop ();
  1128. control_id = controls.PeekControlID ();
  1129. current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} ();\n\t\t\t__parser." +
  1130. "AddParsedSubObject (this.{0});\n\n", control_id);
  1131. } else if (control_type == typeof (HtmlTableCell)) {
  1132. old_function.Append ("\n\t\t\treturn __ctrl;\n\t\t}\n\n");
  1133. object top = controls.Pop ();
  1134. Type t = controls.PeekType ();
  1135. controls.Push (top);
  1136. string parsed = "";
  1137. string ctrl_name = "ctrl";
  1138. if (t != typeof (HtmlTableRow)) {
  1139. parsed = "ParsedSubObject";
  1140. ctrl_name = "parser";
  1141. }
  1142. current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} ();\n" +
  1143. "\t\t\t__{1}.Add{2} (this.{0});\n\n",
  1144. control_id, ctrl_name, parsed);
  1145. } else if (child_kind == ChildrenKind.HTMLROW || child_kind == ChildrenKind.HTMLCELL) {
  1146. old_function.Append ("\n\t\t}\n\n");
  1147. init_funcs.Append (old_function);
  1148. old_function = (StringBuilder) functions.Pop ();
  1149. current_function = (StringBuilder) functions.Peek ();
  1150. old_function.AppendFormat ("\n\t\t\tthis.__BuildControl_{0} (__ctrl.{1});\n\t\t\t" +
  1151. "return __ctrl;\n\t\t}}\n\n",
  1152. control_id, controls.PeekDefaultPropertyName ());
  1153. controls.Pop ();
  1154. control_id = controls.PeekControlID ();
  1155. current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} ();\n", control_id);
  1156. if (child_kind == ChildrenKind.HTMLROW) {
  1157. current_function.AppendFormat ("\t\t\t__parser.AddParsedSubObject ({0});\n",
  1158. control_id);
  1159. } else {
  1160. current_function.AppendFormat ("\t\t\t__ctrl.Add (this.{0});\n", control_id);
  1161. }
  1162. } else {
  1163. old_function.Append ("\n\t\t\treturn __ctrl;\n\t\t}\n\n");
  1164. current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} ();\n\t\t\t__parser." +
  1165. "AddParsedSubObject (this.{0});\n\n", control_id);
  1166. }
  1167. if (useCodeRender)
  1168. RemoveLiterals (old_function);
  1169. init_funcs.Append (old_function);
  1170. if (useCodeRender)
  1171. AddCodeRenderFunction (controls.CodeRenderFunction.ToString (), control_id);
  1172. if (hasDataBindFunction){
  1173. StringBuilder db_function = controls.DataBindFunction;
  1174. db_function.Append ("\t\t}\n\n");
  1175. init_funcs.Append (db_function);
  1176. }
  1177. // Avoid getting empty stacks for unbalanced open/close tags
  1178. if (controls.Count > 1){
  1179. controls.Pop ();
  1180. AddCodeRenderControl (controls.CodeRenderFunction, controls.ChildIndex);
  1181. }
  1182. return true;
  1183. }
  1184. private void NewTableElementFunction (HtmlControlTag ctrl)
  1185. {
  1186. string control_id = Tag.GetDefaultID ();
  1187. ChildrenKind child_kind;
  1188. Type t;
  1189. if (ctrl.ControlType == typeof (HtmlTable)) {
  1190. t = typeof (HtmlTableRowCollection);
  1191. child_kind = ChildrenKind.HTMLROW;
  1192. } else {
  1193. t = typeof (HtmlTableCellCollection);
  1194. child_kind = ChildrenKind.HTMLCELL;
  1195. }
  1196. controls.Push (ctrl.ControlType,
  1197. control_id,
  1198. ctrl.TagID,
  1199. child_kind,
  1200. ctrl.ParseChildren);
  1201. current_function = new StringBuilder ();
  1202. functions.Push (current_function);
  1203. current_function.AppendFormat ("\t\tprivate void __BuildControl_{0} ({1} __ctrl)\n" +
  1204. "\t\t{{\n", control_id, t);
  1205. }
  1206. private void ProcessHtmlControlTag ()
  1207. {
  1208. HtmlControlTag html_ctrl = (HtmlControlTag) elements.Current;
  1209. if (html_ctrl.TagID.ToUpper () == "SCRIPT"){
  1210. //FIXME: if the is script is to be read from disk, do it!
  1211. if (html_ctrl.SelfClosing)
  1212. throw new ApplicationException ("Read script from file not supported yet.");
  1213. if (elements.MoveNext () == false)
  1214. throw new ApplicationException ("Error after " + html_ctrl.ToString ());
  1215. if (elements.Current is PlainText){
  1216. script.Append (((PlainText) elements.Current).Text);
  1217. if (!elements.MoveNext ())
  1218. throw new ApplicationException ("Error after " +
  1219. elements.Current.ToString ());
  1220. }
  1221. if (elements.Current is CloseTag)
  1222. elements.MoveNext ();
  1223. return;
  1224. } else if (IsApplication) {
  1225. throw new ApplicationException (app_file_wrong);
  1226. }
  1227. Type controlType = html_ctrl.ControlType;
  1228. AddProtectedField (controlType, html_ctrl.ControlID);
  1229. ChildrenKind children_kind;
  1230. if (0 == String.Compare (html_ctrl.TagID, "table", true))
  1231. children_kind = ChildrenKind.HTMLROW;
  1232. else if (0 == String.Compare (html_ctrl.TagID, "tr", true))
  1233. children_kind = ChildrenKind.HTMLCELL;
  1234. else if (0 != String.Compare (html_ctrl.TagID, "select", true))
  1235. children_kind = html_ctrl.IsContainer ? ChildrenKind.CONTROLS :
  1236. ChildrenKind.NONE;
  1237. else
  1238. children_kind = ChildrenKind.OPTION;
  1239. NewControlFunction (html_ctrl.TagID, html_ctrl.ControlID, controlType, children_kind, html_ctrl.ParseChildren);
  1240. current_function.AppendFormat ("\t\t\t__ctrl.ID = \"{0}\";\n", html_ctrl.ControlID);
  1241. AddCodeForAttributes (html_ctrl.ControlType, html_ctrl.Attributes);
  1242. if (children_kind == ChildrenKind.HTMLROW || children_kind == ChildrenKind.HTMLCELL)
  1243. NewTableElementFunction (html_ctrl);
  1244. if (!html_ctrl.SelfClosing)
  1245. JustDoIt ();
  1246. else
  1247. FinishControlFunction (html_ctrl.TagID);
  1248. }
  1249. // Closing is performed in FinishControlFunction ()
  1250. private void NewBuildListFunction (AspComponent component)
  1251. {
  1252. string control_id = Tag.GetDefaultID ();
  1253. controls.Push (component.ComponentType,
  1254. control_id,
  1255. component.TagID,
  1256. ChildrenKind.LISTITEM,
  1257. component.DefaultPropertyName);
  1258. current_function = new StringBuilder ();
  1259. functions.Push (current_function);
  1260. current_function.AppendFormat ("\t\tprivate void __BuildControl_{0} " +
  1261. "(System.Web.UI.WebControls.ListItemCollection __ctrl)\n" +
  1262. "\t\t{{\n", control_id);
  1263. }
  1264. private void ProcessComponent ()
  1265. {
  1266. AspComponent component = (AspComponent) elements.Current;
  1267. Type component_type = component.ComponentType;
  1268. AddProtectedField (component_type, component.ControlID);
  1269. NewControlFunction (component.TagID, component.ControlID, component_type,
  1270. component.ChildrenKind, component.DefaultPropertyName);
  1271. if (component_type.IsSubclassOf (typeof (System.Web.UI.UserControl)))
  1272. current_function.Append ("\t\t\t__ctrl.InitializeAsUserControl (Page);\n");
  1273. if (component_type.IsSubclassOf (typeof (System.Web.UI.Control)))
  1274. current_function.AppendFormat ("\t\t\t__ctrl.ID = \"{0}\";\n", component.ControlID);
  1275. AddCodeForAttributes (component.ComponentType, component.Attributes);
  1276. if (component.ChildrenKind == ChildrenKind.LISTITEM)
  1277. NewBuildListFunction (component);
  1278. if (!component.SelfClosing)
  1279. JustDoIt ();
  1280. else
  1281. FinishControlFunction (component.TagID);
  1282. }
  1283. private void ProcessServerObjectTag ()
  1284. {
  1285. ServerObjectTag obj = (ServerObjectTag) elements.Current;
  1286. declarations.AppendFormat ("\t\tprivate {0} cached{1};\n", obj.ObjectClass, obj.ObjectID);
  1287. constructor.AppendFormat ("\n\t\tprivate {0} {1}\n\t\t{{\n\t\t\tget {{\n\t\t\t\t" +
  1288. "if (this.cached{1} == null)\n\t\t\t\t\tthis.cached{1} = " +
  1289. "new {0} ();\n\t\t\t\treturn cached{1};\n\t\t\t}}\n\t\t}}\n\n",
  1290. obj.ObjectClass, obj.ObjectID);
  1291. }
  1292. // Creates a new function that sets the values of subproperties.
  1293. private void NewStyleFunction (PropertyTag tag)
  1294. {
  1295. current_function = new StringBuilder ();
  1296. string prop_id = tag.PropertyID;
  1297. Type prop_type = tag.PropertyType;
  1298. // begin function
  1299. current_function.AppendFormat ("\t\tprivate void __BuildControl_{0} ({1} __ctrl)\n" +
  1300. "\t\t{{\n", prop_id, prop_type);
  1301. // Add property initialization code
  1302. PropertyInfo [] subprop_info = prop_type.GetProperties ();
  1303. TagAttributes att = tag.Attributes;
  1304. string subprop_name = null;
  1305. foreach (string id in att.Keys){
  1306. if (0 == String.Compare (id, "runat", true) || 0 == String.Compare (id, "id", true))
  1307. continue;
  1308. bool is_processed = false;
  1309. foreach (PropertyInfo subprop in subprop_info){
  1310. is_processed = ProcessPropertiesAndFields (subprop, id, att);
  1311. if (is_processed){
  1312. subprop_name = subprop.Name;
  1313. break;
  1314. }
  1315. }
  1316. if (subprop_name == null)
  1317. throw new ApplicationException ("Property " + tag.TagID + " does not have " +
  1318. "a " + id + " subproperty.");
  1319. }
  1320. // Finish function
  1321. current_function.Append ("\n\t\t}\n\n");
  1322. init_funcs.Append (current_function);
  1323. current_function = (StringBuilder) functions.Peek ();
  1324. current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} (__ctrl.{1});\n",
  1325. prop_id, tag.PropertyName);
  1326. if (!tag.SelfClosing){
  1327. // Next tag should be the closing tag
  1328. controls.Push (null, null, null, ChildrenKind.NONE, null);
  1329. bool closing_tag_found = false;
  1330. Element elem;
  1331. while (!closing_tag_found && elements.MoveNext ()){
  1332. elem = (Element) elements.Current;
  1333. if (elem is PlainText)
  1334. ProcessPlainText ();
  1335. else if (!(elem is CloseTag))
  1336. throw new ApplicationException ("Tag " + tag.TagID +
  1337. " not properly closed.");
  1338. else
  1339. closing_tag_found = true;
  1340. }
  1341. if (!closing_tag_found)
  1342. throw new ApplicationException ("Tag " + tag.TagID + " not properly closed.");
  1343. controls.Pop ();
  1344. }
  1345. }
  1346. // This one just opens the function. Closing is performed in FinishControlFunction ()
  1347. private void NewTemplateFunction (PropertyTag tag)
  1348. {
  1349. /*
  1350. * FIXME
  1351. * This function does almost the same as NewControlFunction.
  1352. * Consider merging.
  1353. */
  1354. string prop_id = tag.PropertyID;
  1355. Type prop_type = tag.PropertyType;
  1356. string tag_id = tag.PropertyName; // Real property name used in FinishControlFunction
  1357. controls.Push (prop_type, prop_id, tag_id, ChildrenKind.CONTROLS, null);
  1358. current_function = new StringBuilder ();
  1359. functions.Push (current_function);
  1360. current_function.AppendFormat ("\t\tprivate void __BuildControl_{0} " +
  1361. "(System.Web.UI.Control __ctrl)\n" +
  1362. "\t\t{{\n" +
  1363. "\t\t\tSystem.Web.UI.IParserAccessor __parser " +
  1364. "= (System.Web.UI.IParserAccessor) __ctrl;\n" , prop_id);
  1365. }
  1366. // Closing is performed in FinishControlFunction ()
  1367. private void NewDBColumnFunction (PropertyTag tag)
  1368. {
  1369. /*
  1370. * FIXME
  1371. * This function also does almost the same as NewControlFunction.
  1372. * Consider merging.
  1373. */
  1374. string prop_id = tag.PropertyID;
  1375. Type prop_type = tag.PropertyType;
  1376. string tag_id = tag.PropertyName; // Real property name used in FinishControlFunction
  1377. controls.Push (prop_type, prop_id, tag_id, ChildrenKind.DBCOLUMNS, null);
  1378. current_function = new StringBuilder ();
  1379. functions.Push (current_function);
  1380. current_function.AppendFormat ("\t\tprivate void __BuildControl_{0} " +
  1381. "(System.Web.UI.WebControl.DataGridColumnCollection __ctrl)\n" +
  1382. "\t\t{{\n", prop_id);
  1383. }
  1384. private void NewPropertyFunction (PropertyTag tag)
  1385. {
  1386. if (tag.PropertyType == typeof (System.Web.UI.WebControls.Style) ||
  1387. tag.PropertyType.IsSubclassOf (typeof (System.Web.UI.WebControls.Style)))
  1388. NewStyleFunction (tag);
  1389. else if (tag.PropertyType == typeof (System.Web.UI.ITemplate))
  1390. NewTemplateFunction (tag);
  1391. else if (tag.PropertyType == typeof (System.Web.UI.WebControls.DataGridColumnCollection))
  1392. NewDBColumnFunction (tag);
  1393. else
  1394. throw new ApplicationException ("Other than Style and ITemplate not supported yet. " +
  1395. tag.PropertyType);
  1396. }
  1397. private void ProcessHtmlTag ()
  1398. {
  1399. Tag tag = (Tag) elements.Current;
  1400. ChildrenKind child_kind = controls.PeekChildKind ();
  1401. if (child_kind == ChildrenKind.NONE){
  1402. string tag_id = controls.PeekTagID ();
  1403. throw new ApplicationException (tag + " not allowed inside " + tag_id);
  1404. }
  1405. if (child_kind == ChildrenKind.OPTION){
  1406. if (0 != String.Compare (tag.TagID, "option", true))
  1407. throw new ApplicationException ("Only <option> tags allowed inside <select>.");
  1408. string default_id = Tag.GetDefaultID ();
  1409. Type type = typeof (System.Web.UI.WebControls.ListItem);
  1410. AddProtectedField (type, default_id);
  1411. NewControlFunction (tag.TagID, default_id, type, ChildrenKind.CONTROLS, null);
  1412. return;
  1413. }
  1414. if (child_kind == ChildrenKind.CONTROLS) {
  1415. ArrayList tag_elements = tag.GetElements ();
  1416. foreach (Element e in tag_elements) {
  1417. if (e is PlainText) {
  1418. elements.Current = e;
  1419. ProcessPlainText ();
  1420. } else if (e is CodeRenderTag) {
  1421. elements.Current = e;
  1422. ProcessCodeRenderTag ();
  1423. } else if (e is DataBindingTag) {
  1424. elements.Current = e;
  1425. ProcessDataBindingLiteral ();
  1426. } else {
  1427. throw new ApplicationException (fullPath + ": unexpected tag type " + e.GetType ());
  1428. }
  1429. }
  1430. return;
  1431. }
  1432. if (child_kind == ChildrenKind.HTMLROW) {
  1433. if (0 == String.Compare (tag.TagID, "tr", true)) {
  1434. elements.Current = new HtmlControlTag (tag);
  1435. ProcessHtmlControlTag ();
  1436. return;
  1437. }
  1438. }
  1439. if (child_kind == ChildrenKind.HTMLCELL) {
  1440. if (0 == String.Compare (tag.TagID, "td", true)) {
  1441. elements.Current = new HtmlControlTag (tag);
  1442. ProcessHtmlControlTag ();
  1443. return;
  1444. }
  1445. }
  1446. // Now child_kind should be PROPERTIES, so only allow tag_id == property
  1447. Type control_type = controls.PeekType ();
  1448. PropertyInfo [] prop_info = control_type.GetProperties ();
  1449. bool is_processed = false;
  1450. foreach (PropertyInfo prop in prop_info){
  1451. if (0 == String.Compare (prop.Name, tag.TagID, true)){
  1452. PropertyTag prop_tag = new PropertyTag (tag, prop.PropertyType, prop.Name);
  1453. NewPropertyFunction (prop_tag);
  1454. is_processed = true;
  1455. break;
  1456. }
  1457. }
  1458. if (!is_processed){
  1459. string tag_id = controls.PeekTagID ();
  1460. throw new ApplicationException (tag.TagID + " is not a property of " + control_type);
  1461. }
  1462. }
  1463. private Tag Map (Tag tag)
  1464. {
  1465. int pos = tag.TagID.IndexOf (":");
  1466. if (pos == -1) {
  1467. ChildrenKind child_kind = controls.PeekChildKind ();
  1468. if (child_kind == ChildrenKind.HTMLROW && 0 == String.Compare (tag.TagID, "tr", true)) {
  1469. tag.Attributes.Add ("runat", "server");
  1470. return new HtmlControlTag (tag);
  1471. } else if (child_kind == ChildrenKind.HTMLROW && 0 == String.Compare (tag.TagID, "tr", true)) {
  1472. tag.Attributes.Add ("runat", "server");
  1473. return new HtmlControlTag (tag);
  1474. }
  1475. }
  1476. if (tag is CloseTag ||
  1477. ((tag.Attributes == null ||
  1478. !tag.Attributes.IsRunAtServer ()) && pos == -1))
  1479. return tag;
  1480. if (pos == -1){
  1481. if (0 == String.Compare (tag.TagID, "object", true))
  1482. return new ServerObjectTag (tag);
  1483. return new HtmlControlTag (tag);
  1484. }
  1485. string foundry_name = tag.TagID.Substring (0, pos);
  1486. string component_name = tag.TagID.Substring (pos + 1);
  1487. if (Foundry.LookupFoundry (foundry_name) == false)
  1488. throw new ApplicationException ("Cannot find foundry for alias'" + foundry_name + "'");
  1489. AspComponent component = Foundry.MakeAspComponent (foundry_name, component_name, tag);
  1490. if (component == null)
  1491. throw new ApplicationException ("Cannot find component '" + component_name +
  1492. "' for alias '" + foundry_name + "'");
  1493. return component;
  1494. }
  1495. private void ProcessCloseTag ()
  1496. {
  1497. CloseTag close_tag = (CloseTag) elements.Current;
  1498. if (FinishControlFunction (close_tag.TagID))
  1499. return;
  1500. elements.Current = new PlainText (close_tag.PlainHtml);
  1501. ProcessPlainText ();
  1502. }
  1503. private void ProcessDataBindingLiteral ()
  1504. {
  1505. DataBindingTag dataBinding = (DataBindingTag) elements.Current;
  1506. string actual_value = dataBinding.Data;
  1507. if (actual_value == "")
  1508. throw new ApplicationException ("Empty data binding tag.");
  1509. if (controls.PeekChildKind () != ChildrenKind.CONTROLS)
  1510. throw new ApplicationException ("Data bound content not allowed for " +
  1511. controls.PeekTagID ());
  1512. StringBuilder db_function = new StringBuilder ();
  1513. string control_id = Tag.GetDefaultID ();
  1514. string control_type_string = "System.Web.UI.DataBoundLiteralControl";
  1515. AddProtectedField (typeof (System.Web.UI.DataBoundLiteralControl), control_id);
  1516. // Build the control
  1517. db_function.AppendFormat ("\t\tprivate System.Web.UI.Control __BuildControl_{0} ()\n" +
  1518. "\t\t{{\n\t\t\t{1} __ctrl;\n\n" +
  1519. "\t\t\t__ctrl = new {1} (0, 1);\n" +
  1520. "\t\t\tthis.{0} = __ctrl;\n" +
  1521. "\t\t\t__ctrl.DataBinding += new System.EventHandler " +
  1522. "(this.__DataBind_{0});\n" +
  1523. "\t\t\treturn __ctrl;\n"+
  1524. "\t\t}}\n\n",
  1525. control_id, control_type_string);
  1526. // DataBinding handler
  1527. db_function.AppendFormat ("\t\tpublic void __DataBind_{0} (object sender, " +
  1528. "System.EventArgs e) {{\n" +
  1529. "\t\t\t{1} Container;\n" +
  1530. "\t\t\t{2} target;\n" +
  1531. "\t\t\ttarget = ({2}) sender;\n" +
  1532. "\t\t\tContainer = ({1}) target.BindingContainer;\n" +
  1533. "\t\t\ttarget.SetDataBoundString (0, System.Convert." +
  1534. "ToString ({3}));\n" +
  1535. "\t\t}}\n\n",
  1536. control_id, controls.Container, control_type_string,
  1537. actual_value);
  1538. init_funcs.Append (db_function);
  1539. current_function.AppendFormat ("\t\t\tthis.__BuildControl_{0} ();\n\t\t\t__parser." +
  1540. "AddParsedSubObject (this.{0});\n\n", control_id);
  1541. AddCodeRenderControl (controls.CodeRenderFunction);
  1542. }
  1543. private void ProcessCodeRenderTag ()
  1544. {
  1545. CodeRenderTag code_tag = (CodeRenderTag) elements.Current;
  1546. controls.UseCodeRender = true;
  1547. if (code_tag.IsVarName)
  1548. controls.CodeRenderFunction.AppendFormat ("\t\t\t__output.Write ({0});\n",
  1549. code_tag.Code);
  1550. else
  1551. controls.CodeRenderFunction.AppendFormat ("\t\t\t{0}\n", code_tag.Code);
  1552. }
  1553. public void ProcessElements ()
  1554. {
  1555. JustDoIt ();
  1556. End ();
  1557. parse_ok = true;
  1558. }
  1559. private void JustDoIt ()
  1560. {
  1561. Element element;
  1562. while (elements.MoveNext ()){
  1563. element = (Element) elements.Current;
  1564. if (element is Directive){
  1565. ProcessDirective ();
  1566. } else if (element is PlainText){
  1567. ProcessPlainText ();
  1568. } else if (element is DataBindingTag){
  1569. if (IsApplication)
  1570. throw new ApplicationException (app_file_wrong);
  1571. ProcessDataBindingLiteral ();
  1572. } else if (element is CodeRenderTag){
  1573. if (IsApplication)
  1574. throw new ApplicationException (app_file_wrong);
  1575. ProcessCodeRenderTag ();
  1576. } else {
  1577. elements.Current = Map ((Tag) element);
  1578. if (elements.Current is ServerObjectTag) {
  1579. ProcessServerObjectTag ();
  1580. continue;
  1581. }
  1582. if (elements.Current is HtmlControlTag) {
  1583. ProcessHtmlControlTag ();
  1584. continue;
  1585. }
  1586. if (IsApplication)
  1587. throw new ApplicationException (app_file_wrong);
  1588. else if (elements.Current is AspComponent)
  1589. ProcessComponent ();
  1590. else if (elements.Current is CloseTag)
  1591. ProcessCloseTag ();
  1592. else if (elements.Current is Tag)
  1593. ProcessHtmlTag ();
  1594. else
  1595. throw new ApplicationException ("This place should not be reached.");
  1596. }
  1597. }
  1598. }
  1599. private string GetTemplateDirectory ()
  1600. {
  1601. string templatePath = Path.GetDirectoryName (fullPath);
  1602. string appPath = Path.GetDirectoryName (HttpRuntime.AppDomainAppPath);
  1603. if (templatePath == appPath)
  1604. return "/";
  1605. templatePath = templatePath.Substring (appPath.Length);
  1606. if (Path.DirectorySeparatorChar != '/')
  1607. templatePath = templatePath.Replace (Path.DirectorySeparatorChar, '/');
  1608. return templatePath;
  1609. }
  1610. private void End ()
  1611. {
  1612. if (isPage) {
  1613. if (sessionState == SessionState.Enabled || sessionState == SessionState.ReadOnly)
  1614. AddInterface (typeof (System.Web.SessionState.IRequiresSessionState));
  1615. if (sessionState == SessionState.ReadOnly)
  1616. AddInterface (typeof (System.Web.SessionState.IReadOnlySessionState));
  1617. }
  1618. classDecl = "\tpublic class " + className + " : " + parent + interfaces + " {\n";
  1619. prolog.Append ("\n" + classDecl);
  1620. declarations.Append ("\t\tprivate static bool __intialized = false;\n\n");
  1621. if (IsPage)
  1622. declarations.Append ("\t\tprivate static ArrayList __fileDependencies;\n\n");
  1623. // adds the constructor
  1624. constructor.AppendFormat ("\t\tpublic {0} ()\n\t\t{{\n", className);
  1625. if (!IsApplication)
  1626. constructor.Append ("\t\t\tSystem.Collections.ArrayList dependencies;\n\n");
  1627. constructor.AppendFormat ("\t\t\tif (ASP.{0}.__intialized == false){{\n", className);
  1628. if (IsPage) {
  1629. constructor.AppendFormat ("\t\t\t\tdependencies = new System.Collections.ArrayList ();\n" +
  1630. "\t\t\t\tdependencies.Add (@\"{1}\");\n" +
  1631. "\t\t\t\tASP.{0}.__fileDependencies = dependencies;\n",
  1632. className, fullPath);
  1633. }
  1634. constructor.AppendFormat ("\t\t\t\tASP.{0}.__intialized = true;\n\t\t\t}}\n\t\t}}\n\n",
  1635. className);
  1636. if (!IsApplication) {
  1637. //FIXME: add AutoHandlers: don't know what for...yet!
  1638. constructor.AppendFormat (
  1639. "\t\tprotected override int AutoHandlers\n\t\t{{\n" +
  1640. "\t\t\tget {{ return ASP.{0}.__autoHandlers; }}\n" +
  1641. "\t\t\tset {{ ASP.{0}.__autoHandlers = value; }}\n" +
  1642. "\t\t}}\n\n", className);
  1643. constructor.Append (
  1644. "\t\tprotected System.Web.HttpApplication ApplicationInstance\n\t\t{\n" +
  1645. "\t\t\tget { return (System.Web.HttpApplication) this.Context.ApplicationInstance; }\n" +
  1646. "\t\t}\n\n");
  1647. constructor.AppendFormat (
  1648. "\t\tpublic override string TemplateSourceDirectory\n\t\t{{\n" +
  1649. "\t\t\tget {{ return \"{0}\"; }}\n" +
  1650. "\t\t}}\n\n", GetTemplateDirectory ());
  1651. epilog.Append ("\n\t\tprotected override void FrameworkInitialize ()\n\t\t{\n" +
  1652. "\t\t\tthis.__BuildControlTree (this);\n");
  1653. if (IsPage) {
  1654. epilog.AppendFormat ("\t\t\tthis.FileDependencies = ASP.{0}.__fileDependencies;\n" +
  1655. "\t\t\tthis.EnableViewStateMac = true;\n", className);
  1656. }
  1657. epilog.Append ("\t\t}\n\n");
  1658. }
  1659. if (IsPage) {
  1660. Random rnd = new Random ();
  1661. epilog.AppendFormat ("\t\tpublic override int GetTypeHashCode ()\n\t\t{{\n" +
  1662. "\t\t\treturn {0};\n" +
  1663. "\t\t}}\n", rnd.Next ());
  1664. }
  1665. epilog.Append ("\t}\n}\n");
  1666. // Closes the currently opened tags
  1667. StringBuilder old_function = current_function;
  1668. string control_id;
  1669. while (functions.Count > 1){
  1670. old_function.Append ("\n\t\t\treturn __ctrl;\n\t\t}\n\n");
  1671. init_funcs.Append (old_function);
  1672. control_id = controls.PeekControlID ();
  1673. FinishControlFunction (control_id);
  1674. controls.AddChild ();
  1675. old_function = (StringBuilder) functions.Pop ();
  1676. current_function = (StringBuilder) functions.Peek ();
  1677. controls.Pop ();
  1678. }
  1679. bool useCodeRender = controls.UseCodeRender;
  1680. if (useCodeRender){
  1681. RemoveLiterals (current_function);
  1682. AddRenderMethodDelegate (current_function, controls.PeekControlID ());
  1683. }
  1684. current_function.Append ("\t\t}\n\n");
  1685. init_funcs.Append (current_function);
  1686. if (useCodeRender)
  1687. AddCodeRenderFunction (controls.CodeRenderFunction.ToString (), controls.PeekControlID ());
  1688. functions.Pop ();
  1689. }
  1690. //
  1691. // Functions related to compilation of user controls
  1692. //
  1693. private static char dirSeparator = Path.DirectorySeparatorChar;
  1694. struct UserControlData
  1695. {
  1696. public UserControlResult result;
  1697. public string className;
  1698. public string assemblyName;
  1699. }
  1700. private static UserControlData GenerateUserControl (string src, HttpContext context)
  1701. {
  1702. UserControlData data = new UserControlData ();
  1703. data.result = UserControlResult.OK;
  1704. UserControlCompiler compiler = new UserControlCompiler (new UserControlParser (src, context));
  1705. Type t = compiler.GetCompiledType ();
  1706. if (t == null) {
  1707. data.result = UserControlResult.CompilationFailed;
  1708. return data;
  1709. }
  1710. data.className = t.Name;
  1711. data.assemblyName = compiler.TargetFile;
  1712. return data;
  1713. }
  1714. }
  1715. }