AspGenerator.cs 60 KB

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