2 // System.Web.Compilation.PageCompiler
5 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 // (C) 2002,2003 Ximian, Inc (http://www.ximian.com)
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System.Collections;
34 using System.Reflection;
36 using System.Web.Configuration;
38 using System.Web.SessionState;
39 using System.Web.Util;
41 using System.Web.Profile;
44 namespace System.Web.Compilation
46 class PageCompiler : TemplateControlCompiler
48 PageParser pageParser;
49 static CodeTypeReference intRef = new CodeTypeReference (typeof (int));
51 public PageCompiler (PageParser pageParser)
54 this.pageParser = pageParser;
57 protected override void CreateStaticFields ()
59 base.CreateStaticFields ();
61 CodeMemberField fld = new CodeMemberField (
67 "__fileDependencies");
68 fld.Attributes = MemberAttributes.Private | MemberAttributes.Static;
69 fld.InitExpression = new CodePrimitiveExpression (null);
70 mainClass.Members.Add (fld);
73 protected override void CreateConstructor (CodeStatementCollection localVars,
74 CodeStatementCollection trueStmt)
76 if (pageParser.ClientTarget != null) {
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));
85 ArrayList deps = pageParser.Dependencies;
86 int depsCount = deps != null ? deps.Count : 0;
89 if (localVars == null)
90 localVars = new CodeStatementCollection ();
92 trueStmt = new CodeStatementCollection ();
94 CodeAssignStatement assign;
97 new CodeVariableDeclarationStatement (
102 CodeVariableReferenceExpression dependencies = new CodeVariableReferenceExpression ("dependencies");
104 new CodeAssignStatement (dependencies, new CodeArrayCreateExpression (typeof (string), depsCount))
107 CodeArrayIndexerExpression arrayIndex;
110 for (int i = 0; i < depsCount; i++) {
112 arrayIndex = new CodeArrayIndexerExpression (dependencies, new CodeExpression[] {new CodePrimitiveExpression (i)});
113 assign = new CodeAssignStatement (arrayIndex, new CodePrimitiveExpression (o));
114 trueStmt.Add (assign);
117 CodeMethodInvokeExpression getDepsCall = new CodeMethodInvokeExpression (
119 "GetWrappedFileDependencies",
120 new CodeExpression[] {dependencies}
122 assign = new CodeAssignStatement (GetMainClassFieldReferenceExpression ("__fileDependencies"), getDepsCall);
124 localVars.Add (new CodeVariableDeclarationStatement (
129 CodeVariableReferenceExpression dependencies = new CodeVariableReferenceExpression ("dependencies");
131 new CodeAssignStatement (dependencies, new CodeObjectCreateExpression (typeof (ArrayList), new CodeExpression[] {new CodePrimitiveExpression (depsCount)}))
134 CodeMethodInvokeExpression invoke;
135 for (int i = 0; i < depsCount; i++) {
136 invoke = new CodeMethodInvokeExpression (dependencies, "Add", new CodeExpression[] {new CodePrimitiveExpression (deps [i])});
137 trueStmt.Add (invoke);
139 assign = new CodeAssignStatement (GetMainClassFieldReferenceExpression ("__fileDependencies"), dependencies);
142 trueStmt.Add (assign);
145 base.CreateConstructor (localVars, trueStmt);
148 protected override void AddInterfaces ()
150 base.AddInterfaces ();
151 CodeTypeReference cref;
153 if (pageParser.EnableSessionState) {
154 cref = new CodeTypeReference (typeof (IRequiresSessionState));
156 if (partialClass != null)
157 partialClass.BaseTypes.Add (cref);
160 mainClass.BaseTypes.Add (cref);
163 if (pageParser.ReadOnlySessionState) {
164 cref = new CodeTypeReference (typeof (IReadOnlySessionState));
166 if (partialClass != null)
167 partialClass.BaseTypes.Add (cref);
170 mainClass.BaseTypes.Add (cref);
174 if (pageParser.Async)
175 mainClass.BaseTypes.Add (new CodeTypeReference (typeof (System.Web.IHttpAsyncHandler)));
177 mainClass.BaseTypes.Add (new CodeTypeReference (typeof (System.Web.IHttpHandler)));
181 void CreateGetTypeHashCode ()
183 CodeMemberMethod method = new CodeMemberMethod ();
184 method.ReturnType = intRef;
185 method.Name = "GetTypeHashCode";
186 method.Attributes = MemberAttributes.Public | MemberAttributes.Override;
187 Random rnd = new Random (pageParser.InputFile.GetHashCode ());
188 method.Statements.Add (new CodeMethodReturnStatement (new CodePrimitiveExpression (rnd.Next ())));
189 mainClass.Members.Add (method);
192 static CodeAssignStatement CreatePropertyAssign (CodeExpression expr, string name, object value)
194 CodePropertyReferenceExpression prop;
195 prop = new CodePropertyReferenceExpression (expr, name);
196 CodePrimitiveExpression prim;
197 prim = new CodePrimitiveExpression (value);
198 return new CodeAssignStatement (prop, prim);
201 static CodeAssignStatement CreatePropertyAssign (string name, object value)
203 return CreatePropertyAssign (thisRef, name, value);
206 void AddStatementsFromDirective (CodeMemberMethod method)
208 string responseEncoding = pageParser.ResponseEncoding;
209 if (responseEncoding != null)
210 method.Statements.Add (CreatePropertyAssign ("ResponseEncoding", responseEncoding));
212 int codepage = pageParser.CodePage;
214 method.Statements.Add (CreatePropertyAssign ("CodePage", codepage));
216 string contentType = pageParser.ContentType;
217 if (contentType != null)
218 method.Statements.Add (CreatePropertyAssign ("ContentType", contentType));
220 if (pageParser.OutputCache) {
221 CodeMethodReferenceExpression init = new CodeMethodReferenceExpression (null,
223 CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression (init,
224 OutputCacheParams ());
225 method.Statements.Add (invoke);
228 int lcid = pageParser.LCID;
230 method.Statements.Add (CreatePropertyAssign ("LCID", lcid));
232 string culture = pageParser.Culture;
234 method.Statements.Add (CreatePropertyAssign ("Culture", culture));
236 culture = pageParser.UICulture;
238 method.Statements.Add (CreatePropertyAssign ("UICulture", culture));
240 string errorPage = pageParser.ErrorPage;
241 if (errorPage != null)
242 method.Statements.Add (CreatePropertyAssign ("ErrorPage", errorPage));
244 if (pageParser.HaveTrace) {
245 CodeAssignStatement stmt = new CodeAssignStatement ();
246 stmt.Left = new CodePropertyReferenceExpression (thisRef, "TraceEnabled");
247 stmt.Right = new CodePrimitiveExpression (pageParser.Trace);
248 method.Statements.Add (stmt);
251 if (pageParser.TraceMode != TraceMode.Default) {
252 CodeAssignStatement stmt = new CodeAssignStatement ();
253 CodeTypeReferenceExpression tm = new CodeTypeReferenceExpression ("System.Web.TraceMode");
254 stmt.Left = new CodePropertyReferenceExpression (thisRef, "TraceModeValue");
255 stmt.Right = new CodeFieldReferenceExpression (tm, pageParser.TraceMode.ToString ());
256 method.Statements.Add (stmt);
259 if (pageParser.NotBuffer) {
260 CodeAssignStatement stmt = new CodeAssignStatement ();
261 stmt.Left = new CodePropertyReferenceExpression (thisRef, "Buffer");
262 stmt.Right = new CodePrimitiveExpression (false);
263 method.Statements.Add (stmt);
267 if (!pageParser.EnableEventValidation) {
268 CodeAssignStatement stmt = new CodeAssignStatement ();
269 CodePropertyReferenceExpression prop;
270 prop = new CodePropertyReferenceExpression (thisRef, "EnableEventValidation");
272 stmt.Right = new CodePrimitiveExpression (pageParser.EnableEventValidation);
273 method.Statements.Add (stmt);
276 if (pageParser.MaintainScrollPositionOnPostBack) {
277 CodeAssignStatement stmt = new CodeAssignStatement ();
278 CodePropertyReferenceExpression prop;
279 prop = new CodePropertyReferenceExpression (thisRef, "MaintainScrollPositionOnPostBack");
281 stmt.Right = new CodePrimitiveExpression (pageParser.MaintainScrollPositionOnPostBack);
282 method.Statements.Add (stmt);
287 protected override void AddStatementsToInitMethod (CodeMemberMethod method)
290 AddStatementsFromDirective (method);
291 ILocation directiveLocation = pageParser.DirectiveLocation;
293 CodeArgumentReferenceExpression ctrlVar = new CodeArgumentReferenceExpression("__ctrl");
294 if (pageParser.Title != null)
295 method.Statements.Add (AddLinePragma (CreatePropertyAssign (ctrlVar, "Title", pageParser.Title), directiveLocation));
297 if (pageParser.MasterPageFile != null)
298 method.Statements.Add (AddLinePragma (CreatePropertyAssign (ctrlVar, "MasterPageFile", pageParser.MasterPageFile), directiveLocation));
300 if (pageParser.Theme != null)
301 method.Statements.Add (AddLinePragma (CreatePropertyAssign (ctrlVar, "Theme", pageParser.Theme), directiveLocation));
303 if (pageParser.StyleSheetTheme != null)
304 method.Statements.Add (AddLinePragma (CreatePropertyAssign (ctrlVar, "StyleSheetTheme", pageParser.StyleSheetTheme), directiveLocation));
306 if (pageParser.Async != false)
307 method.Statements.Add (AddLinePragma (CreatePropertyAssign (ctrlVar, "AsyncMode", pageParser.Async), directiveLocation));
309 if (pageParser.AsyncTimeout != -1)
310 method.Statements.Add (AddLinePragma (CreatePropertyAssign (ctrlVar, "AsyncTimeout",
311 TimeSpan.FromSeconds (pageParser.AsyncTimeout)), directiveLocation));
313 CodeMethodInvokeExpression expr = new CodeMethodInvokeExpression (thisRef, "InitializeCulture");
314 method.Statements.Add (AddLinePragma (new CodeExpressionStatement (expr), directiveLocation));
318 protected override void PrependStatementsToFrameworkInitialize (CodeMemberMethod method)
320 base.PrependStatementsToFrameworkInitialize (method);
322 if (pageParser.StyleSheetTheme != null)
323 method.Statements.Add (CreatePropertyAssign ("StyleSheetTheme", pageParser.StyleSheetTheme));
328 protected override void AppendStatementsToFrameworkInitialize (CodeMemberMethod method)
330 base.AppendStatementsToFrameworkInitialize (method);
332 ArrayList deps = pageParser.Dependencies;
333 int depsCount = deps != null ? deps.Count : 0;
336 CodeFieldReferenceExpression fileDependencies = GetMainClassFieldReferenceExpression ("__fileDependencies");
338 method.Statements.Add (
340 new CodeMethodInvokeExpression (
342 "AddWrappedFileDependencies",
343 new CodeExpression[] {fileDependencies})
345 new CodeAssignStatement (
346 new CodeFieldReferenceExpression (thisRef, "FileDependencies"),
355 AddStatementsFromDirective (method);
359 if (pageParser.ValidateRequest) {
360 CodeMethodInvokeExpression expr = new CodeMethodInvokeExpression ();
361 CodePropertyReferenceExpression prop;
362 prop = new CodePropertyReferenceExpression (thisRef, "Request");
363 expr.Method = new CodeMethodReferenceExpression (prop, "ValidateInput");
364 method.Statements.Add (expr);
369 CodeExpression[] OutputCacheParams ()
371 return new CodeExpression [] {
372 new CodePrimitiveExpression (pageParser.OutputCacheDuration),
374 new CodePrimitiveExpression (pageParser.OutputCacheVaryByContentEncodings),
376 new CodePrimitiveExpression (pageParser.OutputCacheVaryByHeader),
377 new CodePrimitiveExpression (pageParser.OutputCacheVaryByCustom),
378 new CodeSnippetExpression (typeof (OutputCacheLocation).ToString () +
379 "." + pageParser.OutputCacheLocation.ToString ()),
380 new CodePrimitiveExpression (pageParser.OutputCacheVaryByParam)
385 void CreateStronglyTypedProperty (Type type, string name)
390 CodeMemberProperty mprop = new CodeMemberProperty ();
392 mprop.Type = new CodeTypeReference (type);
393 mprop.Attributes = MemberAttributes.Public | MemberAttributes.New;
394 CodeExpression prop = new CodePropertyReferenceExpression (new CodeBaseReferenceExpression (), name);
395 prop = new CodeCastExpression (type, prop);
396 mprop.GetStatements.Add (new CodeMethodReturnStatement (prop));
397 if (partialClass != null)
398 partialClass.Members.Add (mprop);
400 mainClass.Members.Add (mprop);
404 protected internal override void CreateMethods ()
406 base.CreateMethods ();
409 CreateProfileProperty ();
410 CreateStronglyTypedProperty (pageParser.MasterType, "Master");
411 CreateStronglyTypedProperty (pageParser.PreviousPageType, "PreviousPage");
414 CreateGetTypeHashCode ();
417 if (pageParser.Async)
418 CreateAsyncMethods ();
423 void CreateAsyncMethods ()
425 CodeMemberMethod method = new CodeMemberMethod ();
426 CodeParameterDeclarationExpression arg;
427 CodeMethodInvokeExpression invoke;
429 // public virtual System.IAsyncResult BeginProcessRequest(System.Web.HttpContext context, System.AsyncCallback cb, object data);
430 method.ReturnType = new CodeTypeReference (typeof (IAsyncResult));
431 method.Name = "BeginProcessRequest";
432 method.Attributes = MemberAttributes.Public;
434 arg = new CodeParameterDeclarationExpression ();
435 arg.Type = new CodeTypeReference (typeof (HttpContext));
436 arg.Name = "context";
437 method.Parameters.Add (arg);
439 arg = new CodeParameterDeclarationExpression ();
440 arg.Type = new CodeTypeReference (typeof (AsyncCallback));
442 method.Parameters.Add (arg);
444 arg = new CodeParameterDeclarationExpression ();
445 arg.Type = new CodeTypeReference (typeof (object));
447 method.Parameters.Add (arg);
449 invoke = new CodeMethodInvokeExpression (thisRef, "AsyncPageBeginProcessRequest");
450 invoke.Parameters.Add (new CodeArgumentReferenceExpression ("context"));
451 invoke.Parameters.Add (new CodeArgumentReferenceExpression ("cb"));
452 invoke.Parameters.Add (new CodeArgumentReferenceExpression ("data"));
454 method.Statements.Add (new CodeMethodReturnStatement (invoke));
455 mainClass.Members.Add (method);
457 // public virtual void EndProcessRequest(System.IAsyncResult ar);
458 method = new CodeMemberMethod ();
459 method.ReturnType = new CodeTypeReference (typeof (void));
460 method.Name = "EndProcessRequest";
461 method.Attributes = MemberAttributes.Public;
463 arg = new CodeParameterDeclarationExpression ();
464 arg.Type = new CodeTypeReference (typeof (IAsyncResult));
466 method.Parameters.Add (arg);
468 invoke = new CodeMethodInvokeExpression (thisRef, "AsyncPageEndProcessRequest");
469 invoke.Parameters.Add (new CodeArgumentReferenceExpression ("ar"));
471 method.Statements.Add (invoke);
472 mainClass.Members.Add (method);
474 // public override void ProcessRequest(System.Web.HttpContext context);
475 method = new CodeMemberMethod ();
476 method.ReturnType = new CodeTypeReference (typeof (void));
477 method.Name = "ProcessRequest";
478 method.Attributes = MemberAttributes.Public | MemberAttributes.Override;
480 arg = new CodeParameterDeclarationExpression ();
481 arg.Type = new CodeTypeReference (typeof (HttpContext));
482 arg.Name = "context";
483 method.Parameters.Add (arg);
485 invoke = new CodeMethodInvokeExpression (new CodeBaseReferenceExpression (), "ProcessRequest");
486 invoke.Parameters.Add (new CodeArgumentReferenceExpression ("context"));
488 method.Statements.Add (invoke);
489 mainClass.Members.Add (method);
493 public static Type CompilePageType (PageParser pageParser)
495 PageCompiler compiler = new PageCompiler (pageParser);
496 return compiler.GetCompiledType ();