AspGenerator.cs 61 KB

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