AspGenerator.cs 57 KB

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