merge -r 98047:98048
[mono.git] / mcs / class / System.Web / System.Web.Compilation / PageCompiler.cs
1 //
2 // System.Web.Compilation.PageCompiler
3 //
4 // Authors:
5 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
6 //
7 // (C) 2002,2003 Ximian, Inc (http://www.ximian.com)
8 //
9
10 //
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:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
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.
29 //
30 using System;
31 using System.CodeDom;
32 using System.Collections;
33 using System.IO;
34 using System.Reflection;
35 using System.Text;
36 using System.Web.Configuration;
37 using System.Web.UI;
38 using System.Web.SessionState;
39 using System.Web.Util;
40 #if NET_2_0
41 using System.Web.Profile;
42 #endif
43
44 namespace System.Web.Compilation
45 {
46         class PageCompiler : TemplateControlCompiler
47         {
48                 PageParser pageParser;
49                 static CodeTypeReference intRef = new CodeTypeReference (typeof (int));
50
51                 public PageCompiler (PageParser pageParser)
52                         : base (pageParser)
53                 {
54                         this.pageParser = pageParser;
55                 }
56
57 #if NET_2_0
58                 protected override void CreateStaticFields ()
59                 {
60                         base.CreateStaticFields ();
61                         
62                         CodeMemberField fld = new CodeMemberField (typeof (object), "__fileDependencies");
63                         fld.Attributes = MemberAttributes.Private | MemberAttributes.Static;
64                         fld.InitExpression = new CodePrimitiveExpression (null);
65                         mainClass.Members.Add (fld);
66                 }
67 #endif
68                 
69                 protected override void CreateConstructor (CodeStatementCollection localVars,
70                                                            CodeStatementCollection trueStmt)
71                 {
72                         if (pageParser.ClientTarget != null) {
73                                 CodeExpression prop;
74                                 prop = new CodePropertyReferenceExpression (thisRef, "ClientTarget");
75                                 CodeExpression ct = new CodePrimitiveExpression (pageParser.ClientTarget);
76                                 if (localVars == null)
77                                         localVars = new CodeStatementCollection ();
78                                 localVars.Add (new CodeAssignStatement (prop, ct));
79                         }
80
81 #if NET_2_0
82                         ArrayList deps = pageParser.Dependencies;
83                         int depsCount = deps != null ? deps.Count : 0;
84                         
85                         if (depsCount > 0) {
86                                 if (localVars == null)
87                                         localVars = new CodeStatementCollection ();
88                                 if (trueStmt == null)
89                                         trueStmt = new CodeStatementCollection ();
90
91                                 localVars.Add (
92                                         new CodeVariableDeclarationStatement (
93                                                 typeof (string[]),
94                                                 "dependencies")
95                                 );
96
97                                 CodeVariableReferenceExpression dependencies = new CodeVariableReferenceExpression ("dependencies");
98                                 trueStmt.Add (
99                                         new CodeAssignStatement (dependencies, new CodeArrayCreateExpression (typeof (string), depsCount))
100                                 );
101                                 
102                                 CodeArrayIndexerExpression arrayIndex;
103                                 CodeAssignStatement assign;
104                                 object o;
105                                 
106                                 for (int i = 0; i < depsCount; i++) {
107                                         o = deps [i];
108                                         arrayIndex = new CodeArrayIndexerExpression (dependencies, new CodeExpression[] {new CodePrimitiveExpression (i)});
109                                         assign = new CodeAssignStatement (arrayIndex, new CodePrimitiveExpression (o));
110                                         trueStmt.Add (assign);
111                                 }
112                                 
113                                 CodeMethodInvokeExpression getDepsCall = new CodeMethodInvokeExpression (
114                                         thisRef,
115                                         "GetWrappedFileDependencies",
116                                         new CodeExpression[] {dependencies}
117                                 );
118
119                                 assign = new CodeAssignStatement (GetMainClassFieldReferenceExpression ("__fileDependencies"), getDepsCall);
120                                 trueStmt.Add (assign);
121                         }
122 #endif
123                         base.CreateConstructor (localVars, trueStmt);
124                 }
125                 
126                 protected override void AddInterfaces () 
127                 {
128                         base.AddInterfaces ();
129                         CodeTypeReference cref;
130                         
131                         if (pageParser.EnableSessionState) {
132                                 cref = new CodeTypeReference (typeof (IRequiresSessionState));
133 #if NET_2_0
134                                 if (partialClass != null)
135                                         partialClass.BaseTypes.Add (cref);
136                                 else
137 #endif
138                                         mainClass.BaseTypes.Add (cref);
139                         }
140                         
141                         if (pageParser.ReadOnlySessionState) {
142                                 cref = new CodeTypeReference (typeof (IReadOnlySessionState));
143 #if NET_2_0
144                                 if (partialClass != null)
145                                         partialClass.BaseTypes.Add (cref);                                      
146                                 else
147 #endif
148                                         mainClass.BaseTypes.Add (cref);
149                         }
150
151 #if NET_2_0
152                         if (pageParser.Async)
153                                 mainClass.BaseTypes.Add (new CodeTypeReference (typeof (System.Web.IHttpAsyncHandler)));
154                         
155                         mainClass.BaseTypes.Add (new CodeTypeReference (typeof (System.Web.IHttpHandler)));
156 #endif
157                 }
158
159                 void CreateGetTypeHashCode () 
160                 {
161                         CodeMemberMethod method = new CodeMemberMethod ();
162                         method.ReturnType = intRef;
163                         method.Name = "GetTypeHashCode";
164                         method.Attributes = MemberAttributes.Public | MemberAttributes.Override;
165                         Random rnd = new Random (pageParser.InputFile.GetHashCode ());
166                         method.Statements.Add (new CodeMethodReturnStatement (new CodePrimitiveExpression (rnd.Next ())));
167                         mainClass.Members.Add (method);
168                 }
169
170                 static CodeAssignStatement CreatePropertyAssign (CodeExpression expr, string name, object value)
171                 {
172                         CodePropertyReferenceExpression prop;
173                         prop = new CodePropertyReferenceExpression (expr, name);
174                         CodePrimitiveExpression prim;
175                         prim = new CodePrimitiveExpression (value);
176                         return new CodeAssignStatement (prop, prim);
177                 }
178
179                 static CodeAssignStatement CreatePropertyAssign (string name, object value)
180                 {
181                         return CreatePropertyAssign (thisRef, name, value);
182                 }
183
184                 protected override void AddStatementsToInitMethod (CodeMemberMethod method)
185                 {
186 #if NET_2_0
187                         ILocation directiveLocation = pageParser.DirectiveLocation;
188                         
189                         CodeArgumentReferenceExpression ctrlVar = new CodeArgumentReferenceExpression("__ctrl");
190                         if (pageParser.Title != null)
191                                 method.Statements.Add (AddLinePragma (CreatePropertyAssign (ctrlVar, "Title", pageParser.Title), directiveLocation));
192
193                         if (pageParser.MasterPageFile != null)
194                                 method.Statements.Add (AddLinePragma (CreatePropertyAssign (ctrlVar, "MasterPageFile", pageParser.MasterPageFile), directiveLocation));
195
196                         if (pageParser.Theme != null)
197                                 method.Statements.Add (AddLinePragma (CreatePropertyAssign (ctrlVar, "Theme", pageParser.Theme), directiveLocation));
198
199                         if (pageParser.StyleSheetTheme != null)
200                                 method.Statements.Add (AddLinePragma (CreatePropertyAssign (ctrlVar, "StyleSheetTheme", pageParser.StyleSheetTheme), directiveLocation));
201
202                         if (pageParser.Async != false)
203                                 method.Statements.Add (AddLinePragma (CreatePropertyAssign (ctrlVar, "AsyncMode", pageParser.Async), directiveLocation));
204
205                         if (pageParser.AsyncTimeout != -1)
206                                 method.Statements.Add (AddLinePragma (CreatePropertyAssign (ctrlVar, "AsyncTimeout",
207                                                                                             TimeSpan.FromSeconds (pageParser.AsyncTimeout)), directiveLocation));
208
209                         CodeMethodInvokeExpression expr = new CodeMethodInvokeExpression (thisRef, "InitializeCulture");
210                         method.Statements.Add (AddLinePragma (new CodeExpressionStatement (expr), directiveLocation));
211 #endif
212                 }
213
214                 protected override void PrependStatementsToFrameworkInitialize (CodeMemberMethod method)
215                 {
216                         base.PrependStatementsToFrameworkInitialize (method);
217 #if NET_2_0
218                         if (pageParser.StyleSheetTheme != null)
219                                 method.Statements.Add (CreatePropertyAssign ("StyleSheetTheme", pageParser.StyleSheetTheme));
220 #endif
221                 }
222
223                 protected override void AppendStatementsToFrameworkInitialize (CodeMemberMethod method)
224                 {
225                         base.AppendStatementsToFrameworkInitialize (method);
226                         
227 #if NET_2_0
228                         ArrayList deps = pageParser.Dependencies;
229                         int depsCount = deps != null ? deps.Count : 0;
230                         
231                         if (depsCount > 0) {
232                                 CodeFieldReferenceExpression fileDependencies = GetMainClassFieldReferenceExpression ("__fileDependencies");
233
234                                 method.Statements.Add (
235                                         new CodeMethodInvokeExpression (
236                                                 thisRef,
237                                                 "AddWrappedFileDependencies",
238                                                 new CodeExpression[] {fileDependencies})
239                                 );
240                         }
241 #endif
242                         
243                         string responseEncoding = pageParser.ResponseEncoding;
244                         if (responseEncoding != null)
245                                 method.Statements.Add (CreatePropertyAssign ("ResponseEncoding", responseEncoding));
246                         
247                         int codepage = pageParser.CodePage;
248                         if (codepage != -1)
249                                 method.Statements.Add (CreatePropertyAssign ("CodePage", codepage));
250
251                         string contentType = pageParser.ContentType;
252                         if (contentType != null)
253                                 method.Statements.Add (CreatePropertyAssign ("ContentType", contentType));
254
255                         if (pageParser.OutputCache) {
256                                 CodeMethodReferenceExpression init = new CodeMethodReferenceExpression (null,
257                                                 "InitOutputCache");
258                                 CodeMethodInvokeExpression invoke = new CodeMethodInvokeExpression (init,
259                                                 OutputCacheParams ());
260                                 method.Statements.Add (invoke);
261                         }
262                         
263                         int lcid = pageParser.LCID;
264                         if (lcid != -1)
265                                 method.Statements.Add (CreatePropertyAssign ("LCID", lcid));
266
267                         string culture = pageParser.Culture;
268                         if (culture != null)
269                                 method.Statements.Add (CreatePropertyAssign ("Culture", culture));
270
271                         culture = pageParser.UICulture;
272                         if (culture != null)
273                                 method.Statements.Add (CreatePropertyAssign ("UICulture", culture));
274
275                         string errorPage = pageParser.ErrorPage;
276                         if (errorPage != null)
277                                 method.Statements.Add (CreatePropertyAssign ("ErrorPage", errorPage));
278
279                         if (pageParser.HaveTrace) {
280                                 CodeAssignStatement stmt = new CodeAssignStatement ();
281                                 stmt.Left = new CodePropertyReferenceExpression (thisRef, "TraceEnabled");
282                                 stmt.Right = new CodePrimitiveExpression (pageParser.Trace);
283                                 method.Statements.Add (stmt);
284                         }
285
286                         if (pageParser.TraceMode != TraceMode.Default) {
287                                 CodeAssignStatement stmt = new CodeAssignStatement ();
288                                 CodeTypeReferenceExpression tm = new CodeTypeReferenceExpression ("System.Web.TraceMode");
289                                 stmt.Left = new CodePropertyReferenceExpression (thisRef, "TraceModeValue");
290                                 stmt.Right = new CodeFieldReferenceExpression (tm, pageParser.TraceMode.ToString ());
291                                 method.Statements.Add (stmt);
292                         }
293
294                         if (pageParser.NotBuffer) {
295                                 CodeAssignStatement stmt = new CodeAssignStatement ();
296                                 stmt.Left = new CodePropertyReferenceExpression (thisRef, "Buffer");
297                                 stmt.Right = new CodePrimitiveExpression (false);
298                                 method.Statements.Add (stmt);
299                         }
300
301 #if NET_1_1
302                         if (pageParser.ValidateRequest) {
303                                 CodeMethodInvokeExpression expr = new CodeMethodInvokeExpression ();
304                                 CodePropertyReferenceExpression prop;
305                                 prop = new CodePropertyReferenceExpression (thisRef, "Request");
306                                 expr.Method = new CodeMethodReferenceExpression (prop, "ValidateInput");
307                                 method.Statements.Add (expr);
308                         }
309 #endif
310 #if NET_2_0
311                         if (!pageParser.EnableEventValidation) {
312                                 CodeAssignStatement stmt = new CodeAssignStatement ();
313                                 CodePropertyReferenceExpression prop;
314                                 prop = new CodePropertyReferenceExpression (thisRef, "EnableEventValidation");
315                                 stmt.Left = prop;
316                                 stmt.Right = new CodePrimitiveExpression (pageParser.EnableEventValidation);
317                                 method.Statements.Add (stmt);
318                         }
319
320                         if (pageParser.MaintainScrollPositionOnPostBack) {
321                                 CodeAssignStatement stmt = new CodeAssignStatement ();
322                                 CodePropertyReferenceExpression prop;
323                                 prop = new CodePropertyReferenceExpression (thisRef, "MaintainScrollPositionOnPostBack");
324                                 stmt.Left = prop;
325                                 stmt.Right = new CodePrimitiveExpression (pageParser.MaintainScrollPositionOnPostBack);
326                                 method.Statements.Add (stmt);
327                         }
328 #endif
329                 }
330
331                 private CodeExpression[] OutputCacheParams ()
332                 {
333                         return new CodeExpression [] {
334                                 new CodePrimitiveExpression (pageParser.OutputCacheDuration),
335 #if NET_2_0
336                                 new CodePrimitiveExpression (pageParser.OutputCacheVaryByContentEncodings),
337 #endif
338                                 new CodePrimitiveExpression (pageParser.OutputCacheVaryByHeader),
339                                 new CodePrimitiveExpression (pageParser.OutputCacheVaryByCustom),
340                                 new CodeSnippetExpression (typeof (OutputCacheLocation).ToString () +
341                                                 "." + pageParser.OutputCacheLocation.ToString ()),
342                                 new CodePrimitiveExpression (pageParser.OutputCacheVaryByParam)
343                                 };
344                 }
345
346 #if NET_2_0
347                 void CreateStronglyTypedProperty (Type type, string name)
348                 {
349                         if (type == null)
350                                 return;
351                         
352                         CodeMemberProperty mprop = new CodeMemberProperty ();
353                         mprop.Name = name;
354                         mprop.Type = new CodeTypeReference (type);
355                         mprop.Attributes = MemberAttributes.Public | MemberAttributes.New;
356                         CodeExpression prop = new CodePropertyReferenceExpression (new CodeBaseReferenceExpression (), name);
357                         prop = new CodeCastExpression (type, prop);
358                         mprop.GetStatements.Add (new CodeMethodReturnStatement (prop));
359                         if (partialClass != null)
360                                 partialClass.Members.Add (mprop);
361                         else
362                                 mainClass.Members.Add (mprop);
363                 }
364 #endif
365                 
366                 protected internal override void CreateMethods ()
367                 {
368                         base.CreateMethods ();
369
370 #if NET_2_0
371                         CreateProfileProperty ();
372                         CreateStronglyTypedProperty (pageParser.MasterType, "Master");
373                         CreateStronglyTypedProperty (pageParser.PreviousPageType, "PreviousPage");
374 #endif
375                         
376                         CreateGetTypeHashCode ();
377
378 #if NET_2_0
379                         if (pageParser.Async)
380                                 CreateAsyncMethods ();
381 #endif
382                 }
383
384 #if NET_2_0
385                 void CreateAsyncMethods ()
386                 {
387                         CodeMemberMethod method = new CodeMemberMethod ();
388                         CodeParameterDeclarationExpression arg;
389                         CodeMethodInvokeExpression invoke;
390
391                         // public virtual System.IAsyncResult BeginProcessRequest(System.Web.HttpContext context, System.AsyncCallback cb, object data);
392                         method.ReturnType = new CodeTypeReference (typeof (IAsyncResult));
393                         method.Name = "BeginProcessRequest";
394                         method.Attributes = MemberAttributes.Public;
395                         
396                         arg = new CodeParameterDeclarationExpression ();
397                         arg.Type = new CodeTypeReference (typeof (HttpContext));
398                         arg.Name = "context";
399                         method.Parameters.Add (arg);
400
401                         arg = new CodeParameterDeclarationExpression ();
402                         arg.Type = new CodeTypeReference (typeof (AsyncCallback));
403                         arg.Name = "cb";
404                         method.Parameters.Add (arg);
405
406                         arg = new CodeParameterDeclarationExpression ();
407                         arg.Type = new CodeTypeReference (typeof (object));
408                         arg.Name = "data";
409                         method.Parameters.Add (arg);
410
411                         invoke = new CodeMethodInvokeExpression (thisRef, "AsyncPageBeginProcessRequest");
412                         invoke.Parameters.Add (new CodeArgumentReferenceExpression ("context"));
413                         invoke.Parameters.Add (new CodeArgumentReferenceExpression ("cb"));
414                         invoke.Parameters.Add (new CodeArgumentReferenceExpression ("data"));
415
416                         method.Statements.Add (new CodeMethodReturnStatement (invoke));
417                         mainClass.Members.Add (method);
418
419                         // public virtual void EndProcessRequest(System.IAsyncResult ar);
420                         method = new CodeMemberMethod ();
421                         method.ReturnType = new CodeTypeReference (typeof (void));
422                         method.Name = "EndProcessRequest";
423                         method.Attributes = MemberAttributes.Public;
424
425                         arg = new CodeParameterDeclarationExpression ();
426                         arg.Type = new CodeTypeReference (typeof (IAsyncResult));
427                         arg.Name = "ar";
428                         method.Parameters.Add (arg);
429
430                         invoke = new CodeMethodInvokeExpression (thisRef, "AsyncPageEndProcessRequest");
431                         invoke.Parameters.Add (new CodeArgumentReferenceExpression ("ar"));
432
433                         method.Statements.Add (invoke);
434                         mainClass.Members.Add (method);
435
436                         // public override void ProcessRequest(System.Web.HttpContext context);
437                         method = new CodeMemberMethod ();
438                         method.ReturnType = new CodeTypeReference (typeof (void));
439                         method.Name = "ProcessRequest";
440                         method.Attributes = MemberAttributes.Public | MemberAttributes.Override;
441
442                         arg = new CodeParameterDeclarationExpression ();
443                         arg.Type = new CodeTypeReference (typeof (HttpContext));
444                         arg.Name = "context";
445                         method.Parameters.Add (arg);
446                         
447                         invoke = new CodeMethodInvokeExpression (new CodeBaseReferenceExpression (), "ProcessRequest");
448                         invoke.Parameters.Add (new CodeArgumentReferenceExpression ("context"));
449
450                         method.Statements.Add (invoke);
451                         mainClass.Members.Add (method);
452                 }
453 #endif
454                 
455                 public static Type CompilePageType (PageParser pageParser)
456                 {
457                         PageCompiler compiler = new PageCompiler (pageParser);
458                         return compiler.GetCompiledType ();
459                 }
460         }
461 }
462
463