PageCompiler.cs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. //
  2. // System.Web.Compilation.PageCompiler
  3. //
  4. // Authors:
  5. // Gonzalo Paniagua Javier ([email protected])
  6. //
  7. // (C) 2002,2003 Ximian, Inc (http://www.ximian.com)
  8. //
  9. //
  10. // Permission is hereby granted, free of charge, to any person obtaining
  11. // a copy of this software and associated documentation files (the
  12. // "Software"), to deal in the Software without restriction, including
  13. // without limitation the rights to use, copy, modify, merge, publish,
  14. // distribute, sublicense, and/or sell copies of the Software, and to
  15. // permit persons to whom the Software is furnished to do so, subject to
  16. // the following conditions:
  17. //
  18. // The above copyright notice and this permission notice shall be
  19. // included in all copies or substantial portions of the Software.
  20. //
  21. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  22. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  23. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  24. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  25. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  26. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  27. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  28. //
  29. using System;
  30. using System.CodeDom;
  31. using System.Collections;
  32. using System.IO;
  33. using System.Reflection;
  34. using System.Text;
  35. using System.Web.Configuration;
  36. using System.Web.UI;
  37. using System.Web.SessionState;
  38. using System.Web.Util;
  39. #if NET_2_0
  40. using System.Web.Profile;
  41. #endif
  42. namespace System.Web.Compilation
  43. {
  44. class PageCompiler : TemplateControlCompiler
  45. {
  46. PageParser pageParser;
  47. static CodeTypeReference intRef = new CodeTypeReference (typeof (int));
  48. public PageCompiler (PageParser pageParser)
  49. : base (pageParser)
  50. {
  51. this.pageParser = pageParser;
  52. }
  53. protected override void CreateStaticFields ()
  54. {
  55. base.CreateStaticFields ();
  56. CodeMemberField fld = new CodeMemberField (
  57. #if NET_2_0
  58. typeof (object),
  59. #else
  60. typeof (ArrayList),
  61. #endif
  62. "__fileDependencies");
  63. fld.Attributes = MemberAttributes.Private | MemberAttributes.Static;
  64. fld.InitExpression = new CodePrimitiveExpression (null);
  65. mainClass.Members.Add (fld);
  66. }
  67. protected override void CreateConstructor (CodeStatementCollection localVars,
  68. CodeStatementCollection trueStmt)
  69. {
  70. #if NET_2_0
  71. if (!String.IsNullOrEmpty (pageParser.MasterPageFile))
  72. // This is here just to trigger master page build, so that its type
  73. // is available when compiling the page itself.
  74. Type master = BuildManager.GetCompiledType (pageParser.MasterPageFile);
  75. #endif
  76. if (pageParser.ClientTarget != null) {
  77. CodeExpression prop;
  78. prop = new CodePropertyReferenceExpression (thisRef, "ClientTarget");
  79. CodeExpression ct = new CodePrimitiveExpression (pageParser.ClientTarget);
  80. if (localVars == null)
  81. localVars = new CodeStatementCollection ();
  82. localVars.Add (new CodeAssignStatement (prop, ct));
  83. }
  84. ArrayList deps = pageParser.Dependencies;
  85. int depsCount = deps != null ? deps.Count : 0;
  86. if (depsCount > 0) {
  87. if (localVars == null)
  88. localVars = new CodeStatementCollection ();
  89. if (trueStmt == null)
  90. trueStmt = new CodeStatementCollection ();
  91. CodeAssignStatement assign;
  92. #if NET_2_0
  93. localVars.Add (
  94. new CodeVariableDeclarationStatement (
  95. typeof (string[]),
  96. "dependencies")
  97. );
  98. CodeVariableReferenceExpression dependencies = new CodeVariableReferenceExpression ("dependencies");
  99. trueStmt.Add (
  100. new CodeAssignStatement (dependencies, new CodeArrayCreateExpression (typeof (string), depsCount))
  101. );
  102. CodeArrayIndexerExpression arrayIndex;
  103. object o;
  104. for (int i = 0; i < depsCount; i++) {
  105. o = deps [i];
  106. arrayIndex = new CodeArrayIndexerExpression (dependencies, new CodeExpression[] {new CodePrimitiveExpression (i)});
  107. assign = new CodeAssignStatement (arrayIndex, new CodePrimitiveExpression (o));
  108. trueStmt.Add (assign);
  109. }
  110. CodeMethodInvokeExpression getDepsCall = new CodeMethodInvokeExpression (
  111. thisRef,
  112. "GetWrappedFileDependencies",
  113. new CodeExpression[] {dependencies}
  114. );
  115. assign = new CodeAssignStatement (GetMainClassFieldReferenceExpression ("__fileDependencies"), getDepsCall);
  116. #else
  117. localVars.Add (new CodeVariableDeclarationStatement (
  118. typeof (ArrayList),
  119. "dependencies")
  120. );
  121. CodeVariableReferenceExpression dependencies = new CodeVariableReferenceExpression ("dependencies");
  122. trueStmt.Add (
  123. new CodeAssignStatement (dependencies, new CodeObjectCreateExpression (typeof (ArrayList), new CodeExpression[] {new CodePrimitiveExpression (depsCount)}))
  124. );
  125. CodeMethodInvokeExpression invoke;
  126. for (int i = 0; i < depsCount; i++) {
  127. invoke = new CodeMethodInvokeExpression (dependencies, "Add", new CodeExpression[] {new CodePrimitiveExpression (deps [i])});
  128. trueStmt.Add (invoke);
  129. }
  130. assign = new CodeAssignStatement (GetMainClassFieldReferenceExpression ("__fileDependencies"), dependencies);
  131. #endif
  132. trueStmt.Add (assign);
  133. }
  134. base.CreateConstructor (localVars, trueStmt);
  135. }
  136. protected override void AddInterfaces ()
  137. {
  138. base.AddInterfaces ();
  139. CodeTypeReference cref;
  140. if (pageParser.EnableSessionState) {
  141. cref = new CodeTypeReference (typeof (IRequiresSessionState));
  142. #if NET_2_0
  143. if (partialClass != null)
  144. partialClass.BaseTypes.Add (cref);
  145. else
  146. #endif
  147. mainClass.BaseTypes.Add (cref);
  148. }
  149. if (pageParser.ReadOnlySessionState) {
  150. cref = new CodeTypeReference (typeof (IReadOnlySessionState));
  151. #if NET_2_0
  152. if (partialClass != null)
  153. partialClass.BaseTypes.Add (cref);
  154. else
  155. #endif
  156. mainClass.BaseTypes.Add (cref);
  157. }
  158. #if NET_2_0
  159. if (pageParser.Async)
  160. mainClass.BaseTypes.Add (new CodeTypeReference (typeof (System.Web.IHttpAsyncHandler)));
  161. mainClass.BaseTypes.Add (new CodeTypeReference (typeof (System.Web.IHttpHandler)));
  162. #endif
  163. }
  164. void CreateGetTypeHashCode ()
  165. {
  166. CodeMemberMethod method = new CodeMemberMethod ();
  167. method.ReturnType = intRef;
  168. method.Name = "GetTypeHashCode";
  169. method.Attributes = MemberAttributes.Public | MemberAttributes.Override;
  170. Random rnd = new Random (pageParser.InputFile.GetHashCode ());
  171. method.Statements.Add (new CodeMethodReturnStatement (new CodePrimitiveExpression (rnd.Next ())));
  172. mainClass.Members.Add (method);
  173. }
  174. static CodeAssignStatement CreatePropertyAssign (CodeExpression expr, string name, object value)
  175. {
  176. CodePropertyReferenceExpression prop;
  177. prop = new CodePropertyReferenceExpression (expr, name);
  178. CodePrimitiveExpression prim;
  179. prim = new CodePrimitiveExpression (value);
  180. return new CodeAssignStatement (prop, prim);
  181. }
  182. static CodeAssignStatement CreatePropertyAssign (string name, object value)
  183. {
  184. return CreatePropertyAssign (thisRef, name, value);
  185. }
  186. void AddStatementsFromDirective (CodeMemberMethod method)
  187. {
  188. string responseEncoding = pageParser.ResponseEncoding;
  189. if (responseEncoding != null)
  190. method.Statements.Add (CreatePropertyAssign ("ResponseEncoding", responseEncoding));
  191. int codepage = pageParser.CodePage;
  192. if (codepage != -1)
  193. method.Statements.Add (CreatePropertyAssign ("CodePage", codepage));
  194. string contentType = pageParser.ContentType;
  195. if (contentType != null)
  196. method.Statements.Add (CreatePropertyAssign ("ContentType", contentType));
  197. if (pageParser.OutputCache) {
  198. CodeMethodReferenceExpression init = new CodeMethodReferenceExpression (null,
  199. "InitOutputCache");
  200. CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression (init,
  201. OutputCacheParams ());
  202. method.Statements.Add (invoke);
  203. }
  204. int lcid = pageParser.LCID;
  205. if (lcid != -1)
  206. method.Statements.Add (CreatePropertyAssign ("LCID", lcid));
  207. string culture = pageParser.Culture;
  208. if (culture != null)
  209. method.Statements.Add (CreatePropertyAssign ("Culture", culture));
  210. culture = pageParser.UICulture;
  211. if (culture != null)
  212. method.Statements.Add (CreatePropertyAssign ("UICulture", culture));
  213. string errorPage = pageParser.ErrorPage;
  214. if (errorPage != null)
  215. method.Statements.Add (CreatePropertyAssign ("ErrorPage", errorPage));
  216. if (pageParser.HaveTrace) {
  217. CodeAssignStatement stmt = new CodeAssignStatement ();
  218. stmt.Left = new CodePropertyReferenceExpression (thisRef, "TraceEnabled");
  219. stmt.Right = new CodePrimitiveExpression (pageParser.Trace);
  220. method.Statements.Add (stmt);
  221. }
  222. if (pageParser.TraceMode != TraceMode.Default) {
  223. CodeAssignStatement stmt = new CodeAssignStatement ();
  224. CodeTypeReferenceExpression tm = new CodeTypeReferenceExpression ("System.Web.TraceMode");
  225. stmt.Left = new CodePropertyReferenceExpression (thisRef, "TraceModeValue");
  226. stmt.Right = new CodeFieldReferenceExpression (tm, pageParser.TraceMode.ToString ());
  227. method.Statements.Add (stmt);
  228. }
  229. if (pageParser.NotBuffer) {
  230. CodeAssignStatement stmt = new CodeAssignStatement ();
  231. stmt.Left = new CodePropertyReferenceExpression (thisRef, "Buffer");
  232. stmt.Right = new CodePrimitiveExpression (false);
  233. method.Statements.Add (stmt);
  234. }
  235. #if NET_2_0
  236. if (!pageParser.EnableEventValidation) {
  237. CodeAssignStatement stmt = new CodeAssignStatement ();
  238. CodePropertyReferenceExpression prop;
  239. prop = new CodePropertyReferenceExpression (thisRef, "EnableEventValidation");
  240. stmt.Left = prop;
  241. stmt.Right = new CodePrimitiveExpression (pageParser.EnableEventValidation);
  242. method.Statements.Add (stmt);
  243. }
  244. if (pageParser.MaintainScrollPositionOnPostBack) {
  245. CodeAssignStatement stmt = new CodeAssignStatement ();
  246. CodePropertyReferenceExpression prop;
  247. prop = new CodePropertyReferenceExpression (thisRef, "MaintainScrollPositionOnPostBack");
  248. stmt.Left = prop;
  249. stmt.Right = new CodePrimitiveExpression (pageParser.MaintainScrollPositionOnPostBack);
  250. method.Statements.Add (stmt);
  251. }
  252. #endif
  253. }
  254. protected override void AddStatementsToInitMethod (CodeMemberMethod method)
  255. {
  256. #if NET_2_0
  257. AddStatementsFromDirective (method);
  258. ILocation directiveLocation = pageParser.DirectiveLocation;
  259. CodeArgumentReferenceExpression ctrlVar = new CodeArgumentReferenceExpression("__ctrl");
  260. if (pageParser.Title != null)
  261. method.Statements.Add (AddLinePragma (CreatePropertyAssign (ctrlVar, "Title", pageParser.Title), directiveLocation));
  262. if (pageParser.MasterPageFile != null)
  263. method.Statements.Add (AddLinePragma (CreatePropertyAssign (ctrlVar, "MasterPageFile", pageParser.MasterPageFile), directiveLocation));
  264. if (pageParser.Theme != null)
  265. method.Statements.Add (AddLinePragma (CreatePropertyAssign (ctrlVar, "Theme", pageParser.Theme), directiveLocation));
  266. if (pageParser.StyleSheetTheme != null)
  267. method.Statements.Add (AddLinePragma (CreatePropertyAssign (ctrlVar, "StyleSheetTheme", pageParser.StyleSheetTheme), directiveLocation));
  268. if (pageParser.Async != false)
  269. method.Statements.Add (AddLinePragma (CreatePropertyAssign (ctrlVar, "AsyncMode", pageParser.Async), directiveLocation));
  270. if (pageParser.AsyncTimeout != -1)
  271. method.Statements.Add (AddLinePragma (CreatePropertyAssign (ctrlVar, "AsyncTimeout",
  272. TimeSpan.FromSeconds (pageParser.AsyncTimeout)), directiveLocation));
  273. CodeMethodInvokeExpression expr = new CodeMethodInvokeExpression (thisRef, "InitializeCulture");
  274. method.Statements.Add (AddLinePragma (new CodeExpressionStatement (expr), directiveLocation));
  275. #endif
  276. }
  277. protected override void PrependStatementsToFrameworkInitialize (CodeMemberMethod method)
  278. {
  279. base.PrependStatementsToFrameworkInitialize (method);
  280. #if NET_2_0
  281. if (pageParser.StyleSheetTheme != null)
  282. method.Statements.Add (CreatePropertyAssign ("StyleSheetTheme", pageParser.StyleSheetTheme));
  283. #endif
  284. }
  285. protected override void AppendStatementsToFrameworkInitialize (CodeMemberMethod method)
  286. {
  287. base.AppendStatementsToFrameworkInitialize (method);
  288. ArrayList deps = pageParser.Dependencies;
  289. int depsCount = deps != null ? deps.Count : 0;
  290. if (depsCount > 0) {
  291. CodeFieldReferenceExpression fileDependencies = GetMainClassFieldReferenceExpression ("__fileDependencies");
  292. method.Statements.Add (
  293. #if NET_2_0
  294. new CodeMethodInvokeExpression (
  295. thisRef,
  296. "AddWrappedFileDependencies",
  297. new CodeExpression[] {fileDependencies})
  298. #else
  299. new CodeAssignStatement (
  300. new CodeFieldReferenceExpression (thisRef, "FileDependencies"),
  301. fileDependencies
  302. )
  303. #endif
  304. );
  305. }
  306. #if ONLY_1_1
  307. AddStatementsFromDirective (method);
  308. #endif
  309. #if NET_1_1
  310. if (pageParser.ValidateRequest) {
  311. CodeMethodInvokeExpression expr = new CodeMethodInvokeExpression ();
  312. CodePropertyReferenceExpression prop;
  313. prop = new CodePropertyReferenceExpression (thisRef, "Request");
  314. expr.Method = new CodeMethodReferenceExpression (prop, "ValidateInput");
  315. method.Statements.Add (expr);
  316. }
  317. #endif
  318. }
  319. CodeExpression[] OutputCacheParams ()
  320. {
  321. return new CodeExpression [] {
  322. new CodePrimitiveExpression (pageParser.OutputCacheDuration),
  323. #if NET_2_0
  324. new CodePrimitiveExpression (pageParser.OutputCacheVaryByContentEncodings),
  325. #endif
  326. new CodePrimitiveExpression (pageParser.OutputCacheVaryByHeader),
  327. new CodePrimitiveExpression (pageParser.OutputCacheVaryByCustom),
  328. new CodeSnippetExpression (typeof (OutputCacheLocation).ToString () +
  329. "." + pageParser.OutputCacheLocation.ToString ()),
  330. new CodePrimitiveExpression (pageParser.OutputCacheVaryByParam)
  331. };
  332. }
  333. #if NET_2_0
  334. void CreateStronglyTypedProperty (Type type, string name)
  335. {
  336. if (type == null)
  337. return;
  338. CodeMemberProperty mprop = new CodeMemberProperty ();
  339. mprop.Name = name;
  340. mprop.Type = new CodeTypeReference (type);
  341. mprop.Attributes = MemberAttributes.Public | MemberAttributes.New;
  342. CodeExpression prop = new CodePropertyReferenceExpression (new CodeBaseReferenceExpression (), name);
  343. prop = new CodeCastExpression (type, prop);
  344. mprop.GetStatements.Add (new CodeMethodReturnStatement (prop));
  345. if (partialClass != null)
  346. partialClass.Members.Add (mprop);
  347. else
  348. mainClass.Members.Add (mprop);
  349. AddReferencedAssembly (type.Assembly);
  350. }
  351. #endif
  352. protected internal override void CreateMethods ()
  353. {
  354. base.CreateMethods ();
  355. #if NET_2_0
  356. CreateProfileProperty ();
  357. CreateStronglyTypedProperty (pageParser.MasterType, "Master");
  358. CreateStronglyTypedProperty (pageParser.PreviousPageType, "PreviousPage");
  359. #endif
  360. CreateGetTypeHashCode ();
  361. #if NET_2_0
  362. if (pageParser.Async)
  363. CreateAsyncMethods ();
  364. #endif
  365. }
  366. #if NET_2_0
  367. void CreateAsyncMethods ()
  368. {
  369. CodeMemberMethod method = new CodeMemberMethod ();
  370. CodeParameterDeclarationExpression arg;
  371. CodeMethodInvokeExpression invoke;
  372. // public virtual System.IAsyncResult BeginProcessRequest(System.Web.HttpContext context, System.AsyncCallback cb, object data);
  373. method.ReturnType = new CodeTypeReference (typeof (IAsyncResult));
  374. method.Name = "BeginProcessRequest";
  375. method.Attributes = MemberAttributes.Public;
  376. arg = new CodeParameterDeclarationExpression ();
  377. arg.Type = new CodeTypeReference (typeof (HttpContext));
  378. arg.Name = "context";
  379. method.Parameters.Add (arg);
  380. arg = new CodeParameterDeclarationExpression ();
  381. arg.Type = new CodeTypeReference (typeof (AsyncCallback));
  382. arg.Name = "cb";
  383. method.Parameters.Add (arg);
  384. arg = new CodeParameterDeclarationExpression ();
  385. arg.Type = new CodeTypeReference (typeof (object));
  386. arg.Name = "data";
  387. method.Parameters.Add (arg);
  388. invoke = new CodeMethodInvokeExpression (thisRef, "AsyncPageBeginProcessRequest");
  389. invoke.Parameters.Add (new CodeArgumentReferenceExpression ("context"));
  390. invoke.Parameters.Add (new CodeArgumentReferenceExpression ("cb"));
  391. invoke.Parameters.Add (new CodeArgumentReferenceExpression ("data"));
  392. method.Statements.Add (new CodeMethodReturnStatement (invoke));
  393. mainClass.Members.Add (method);
  394. // public virtual void EndProcessRequest(System.IAsyncResult ar);
  395. method = new CodeMemberMethod ();
  396. method.ReturnType = new CodeTypeReference (typeof (void));
  397. method.Name = "EndProcessRequest";
  398. method.Attributes = MemberAttributes.Public;
  399. arg = new CodeParameterDeclarationExpression ();
  400. arg.Type = new CodeTypeReference (typeof (IAsyncResult));
  401. arg.Name = "ar";
  402. method.Parameters.Add (arg);
  403. invoke = new CodeMethodInvokeExpression (thisRef, "AsyncPageEndProcessRequest");
  404. invoke.Parameters.Add (new CodeArgumentReferenceExpression ("ar"));
  405. method.Statements.Add (invoke);
  406. mainClass.Members.Add (method);
  407. // public override void ProcessRequest(System.Web.HttpContext context);
  408. method = new CodeMemberMethod ();
  409. method.ReturnType = new CodeTypeReference (typeof (void));
  410. method.Name = "ProcessRequest";
  411. method.Attributes = MemberAttributes.Public | MemberAttributes.Override;
  412. arg = new CodeParameterDeclarationExpression ();
  413. arg.Type = new CodeTypeReference (typeof (HttpContext));
  414. arg.Name = "context";
  415. method.Parameters.Add (arg);
  416. invoke = new CodeMethodInvokeExpression (new CodeBaseReferenceExpression (), "ProcessRequest");
  417. invoke.Parameters.Add (new CodeArgumentReferenceExpression ("context"));
  418. method.Statements.Add (invoke);
  419. mainClass.Members.Add (method);
  420. }
  421. #endif
  422. public static Type CompilePageType (PageParser pageParser)
  423. {
  424. PageCompiler compiler = new PageCompiler (pageParser);
  425. return compiler.GetCompiledType ();
  426. }
  427. }
  428. }