fixed tests
[mono.git] / mcs / class / System.Web / System.Web.UI / TemplateParser.cs
1 //
2 // System.Web.UI.TemplateParser
3 //
4 // Authors:
5 //      Duncan Mak (duncan@ximian.com)
6 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 //
8 // (C) 2002,2003 Ximian, Inc. (http://www.ximian.com)
9 // Copyright (C) 2005 Novell, Inc (http://www.novell.com)
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
31 using System.CodeDom.Compiler;
32 using System.Collections;
33 using System.Globalization;
34 using System.IO;
35 using System.Reflection;
36 using System.Security.Permissions;
37 using System.Web.Compilation;
38 using System.Web.Configuration;
39 using System.Web.Util;
40
41 namespace System.Web.UI {
42
43         // CAS
44         [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
45         [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
46         public abstract class TemplateParser : BaseParser
47         {
48                 string inputFile;
49                 string text;
50                 string privateBinPath;
51                 Hashtable mainAttributes;
52                 ArrayList dependencies;
53                 ArrayList assemblies;
54                 Hashtable anames;
55                 ArrayList imports;
56                 ArrayList interfaces;
57                 ArrayList scripts;
58                 Type baseType;
59                 bool baseTypeIsGlobal;
60                 string className;
61                 RootBuilder rootBuilder;
62                 bool debug;
63                 string compilerOptions;
64                 string language;
65                 bool strictOn = false;
66                 bool explicitOn = false;
67                 bool output_cache;
68                 int oc_duration;
69                 string oc_header, oc_custom, oc_param, oc_controls;
70                 bool oc_shared;
71                 OutputCacheLocation oc_location;
72                 CultureInfo invariantCulture = CultureInfo.InvariantCulture;
73 #if NET_2_0
74                 string src;
75                 string partialClassName;
76 #endif
77                 Assembly srcAssembly;
78                 int appAssemblyIndex = -1;
79
80                 internal TemplateParser ()
81                 {
82                         imports = new ArrayList ();
83 #if NET_2_0
84                         AddNamespaces (imports);
85 #else
86                         imports.Add ("System");
87                         imports.Add ("System.Collections");
88                         imports.Add ("System.Collections.Specialized");
89                         imports.Add ("System.Configuration");
90                         imports.Add ("System.Text");
91                         imports.Add ("System.Text.RegularExpressions");
92                         imports.Add ("System.Web");
93                         imports.Add ("System.Web.Caching");
94                         imports.Add ("System.Web.Security");
95                         imports.Add ("System.Web.SessionState");
96                         imports.Add ("System.Web.UI");
97                         imports.Add ("System.Web.UI.WebControls");
98                         imports.Add ("System.Web.UI.HtmlControls");
99 #endif
100
101                         assemblies = new ArrayList ();
102 #if NET_2_0
103                         bool addAssembliesInBin = false;
104                         foreach (AssemblyInfo info in CompilationConfig.Assemblies) {
105                                 if (info.Assembly == "*")
106                                         addAssembliesInBin = true;
107                                 else
108                                         AddAssemblyByName (info.Assembly);
109                         }
110                         if (addAssembliesInBin)
111                                 AddAssembliesInBin ();
112
113                         foreach (NamespaceInfo info in PagesConfig.Namespaces) {
114                                 imports.Add (info.Namespace);
115                         }
116 #else
117                         foreach (string a in CompilationConfig.Assemblies)
118                                 AddAssemblyByName (a);
119                         if (CompilationConfig.AssembliesInBin)
120                                 AddAssembliesInBin ();
121 #endif
122
123                         language = CompilationConfig.DefaultLanguage;
124                 }
125                 
126                 internal void AddApplicationAssembly ()
127                 {
128                         if (Context.ApplicationInstance == null)
129                                 return; // this may happen if we have Global.asax and have
130                                         // controls registered from Web.Config
131                         string location = Context.ApplicationInstance.AssemblyLocation;
132                         if (location != typeof (TemplateParser).Assembly.Location) {
133                                 appAssemblyIndex = assemblies.Add (location);
134                         }
135                 }
136
137                 protected abstract Type CompileIntoType ();
138
139 #if NET_2_0
140                 void AddNamespaces (ArrayList imports)
141                 {
142                         if (BuildManager.HaveResources)
143                                 imports.Add ("System.Resources");
144                         
145                         PagesSection pages = WebConfigurationManager.GetSection ("system.web/pages") as PagesSection;
146                         if (pages == null)
147                                 return;
148
149                         NamespaceCollection namespaces = pages.Namespaces;
150                         if (namespaces == null || namespaces.Count == 0)
151                                 return;
152
153                         foreach (NamespaceInfo nsi in namespaces)
154                                 imports.Add (nsi.Namespace);
155                 }
156 #endif
157                 
158                 internal void RegisterCustomControl (string tagPrefix, string tagName, string src)
159                 {
160                         string realpath = MapPath (src);
161                         if (String.Compare (realpath, inputFile, false, invariantCulture) == 0)
162                                 return;
163                         
164                         if (!File.Exists (realpath))
165                                 throw new ParseException (Location, "Could not find file \"" + realpath + "\".");
166                         string vpath = UrlUtils.Combine (BaseVirtualDir, src);
167                         Type type = null;
168                         AddDependency (realpath);
169                         try {
170                                 ArrayList other_deps = new ArrayList ();
171                                 type = UserControlParser.GetCompiledType (vpath, realpath, other_deps, Context);
172                                 foreach (string s in other_deps) {
173                                         AddDependency (s);
174                                 }
175                         } catch (ParseException pe) {
176                                 if (this is UserControlParser)
177                                         throw new ParseException (Location, pe.Message, pe);
178                                 throw;
179                         }
180
181                         AddAssembly (type.Assembly, true);
182                         RootBuilder.Foundry.RegisterFoundry (tagPrefix, tagName, type);
183                 }
184
185                 internal void RegisterNamespace (string tagPrefix, string ns, string assembly)
186                 {
187                         AddImport (ns);
188                         Assembly ass = AddAssemblyByName (assembly);
189                         AddDependency (ass.Location);
190                         RootBuilder.Foundry.RegisterFoundry (tagPrefix, ass, ns);
191                 }
192
193                 internal virtual void HandleOptions (object obj)
194                 {
195                 }
196
197                 internal static string GetOneKey (Hashtable tbl)
198                 {
199                         foreach (object key in tbl.Keys)
200                                 return key.ToString ();
201
202                         return null;
203                 }
204                 
205                 internal virtual void AddDirective (string directive, Hashtable atts)
206                 {
207                         if (String.Compare (directive, DefaultDirectiveName, true) == 0) {
208                                 if (mainAttributes != null)
209                                         ThrowParseException ("Only 1 " + DefaultDirectiveName + " is allowed");
210
211                                 mainAttributes = atts;
212                                 ProcessMainAttributes (mainAttributes);
213                                 return;
214                         }
215
216                         int cmp = String.Compare ("Assembly", directive, true);
217                         if (cmp == 0) {
218                                 string name = GetString (atts, "Name", null);
219                                 string src = GetString (atts, "Src", null);
220
221                                 if (atts.Count > 0)
222                                         ThrowParseException ("Attribute " + GetOneKey (atts) + " unknown.");
223
224                                 if (name == null && src == null)
225                                         ThrowParseException ("You gotta specify Src or Name");
226                                         
227                                 if (name != null && src != null)
228                                         ThrowParseException ("Src and Name cannot be used together");
229
230                                 if (name != null) {
231                                         AddAssemblyByName (name);
232                                 } else {
233                                         GetAssemblyFromSource (src);
234                                 }
235
236                                 return;
237                         }
238
239                         cmp = String.Compare ("Import", directive, true);
240                         if (cmp == 0) {
241                                 string namesp = GetString (atts, "Namespace", null);
242                                 if (atts.Count > 0)
243                                         ThrowParseException ("Attribute " + GetOneKey (atts) + " unknown.");
244                                 
245                                 if (namesp != null && namesp != "")
246                                         AddImport (namesp);
247                                 return;
248                         }
249
250                         cmp = String.Compare ("Implements", directive, true);
251                         if (cmp == 0) {
252                                 string ifacename = GetString (atts, "Interface", "");
253
254                                 if (atts.Count > 0)
255                                         ThrowParseException ("Attribute " + GetOneKey (atts) + " unknown.");
256                                 
257                                 Type iface = LoadType (ifacename);
258                                 if (iface == null)
259                                         ThrowParseException ("Cannot find type " + ifacename);
260
261                                 if (!iface.IsInterface)
262                                         ThrowParseException (iface + " is not an interface");
263
264                                 AddInterface (iface.FullName);
265                                 return;
266                         }
267
268                         cmp = String.Compare ("OutputCache", directive, true);
269                         if (cmp == 0) {
270                                 HttpResponse response = HttpContext.Current.Response;
271                                 if (response != null)
272                                         response.Cache.SetValidUntilExpires (true);
273                                 
274                                 output_cache = true;
275                                 
276                                 if (atts ["Duration"] == null)
277                                         ThrowParseException ("The directive is missing a 'duration' attribute.");
278                                 if (atts ["VaryByParam"] == null)
279                                         ThrowParseException ("This directive is missing a 'VaryByParam' " +
280                                                         "attribute, which should be set to \"none\", \"*\", " +
281                                                         "or a list of name/value pairs.");
282
283                                 foreach (DictionaryEntry entry in atts) {
284                                         string key = (string) entry.Key;
285                                         switch (key.ToLower ()) {
286                                         case "duration":
287                                                 oc_duration = Int32.Parse ((string) entry.Value);
288                                                 if (oc_duration < 1)
289                                                         ThrowParseException ("The 'duration' attribute must be set " +
290                                                                         "to a positive integer value");
291                                                 break;
292                                         case "varybyparam":
293                                                 oc_param = (string) entry.Value;
294                                                 if (String.Compare (oc_param, "none") == 0)
295                                                         oc_param = null;
296                                                 break;
297                                         case "varybyheader":
298                                                 oc_header = (string) entry.Value;
299                                                 break;
300                                         case "varybycustom":
301                                                 oc_custom = (string) entry.Value;
302                                                 break;
303                                         case "location":
304                                                 if (!(this is PageParser))
305                                                         goto default;
306
307                                                 try {
308                                                         oc_location = (OutputCacheLocation) Enum.Parse (
309                                                                 typeof (OutputCacheLocation), (string) entry.Value, true);
310                                                 } catch {
311                                                         ThrowParseException ("The 'location' attribute is case sensitive and " +
312                                                                         "must be one of the following values: Any, Client, " +
313                                                                         "Downstream, Server, None, ServerAndClient.");
314                                                 }
315                                                 break;
316                                         case "varybycontrol":
317                                                 if (this is PageParser)
318                                                         goto default;
319
320                                                 oc_controls = (string) entry.Value;
321                                                 break;
322                                         case "shared":
323                                                 if (this is PageParser)
324                                                         goto default;
325
326                                                 try {
327                                                         oc_shared = Boolean.Parse ((string) entry.Value);
328                                                 } catch {
329                                                         ThrowParseException ("The 'shared' attribute is case sensitive" +
330                                                                         " and must be set to 'true' or 'false'.");
331                                                 }
332                                                 break;
333                                         default:
334                                                 ThrowParseException ("The '" + key + "' attribute is not " +
335                                                                 "supported by the 'Outputcache' directive.");
336                                                 break;
337                                         }
338                                         
339                                 }
340                                 
341                                 return;
342                         }
343
344                         ThrowParseException ("Unknown directive: " + directive);
345                 }
346
347                 internal Type LoadType (string typeName)
348                 {
349                         // First try loaded assemblies, then try assemblies in Bin directory.
350                         Type type = null;
351                         bool seenBin = false;
352                         Assembly [] assemblies = AppDomain.CurrentDomain.GetAssemblies ();
353                         foreach (Assembly ass in assemblies) {
354                                 type = ass.GetType (typeName);
355                                 if (type == null)
356                                         continue;
357
358                                 if (Path.GetDirectoryName (ass.Location) != PrivateBinPath) {
359                                         AddAssembly (ass, true);
360                                 } else {
361                                         seenBin = true;
362                                 }
363
364                                 AddDependency (ass.Location);
365                                 return type;
366                         }
367
368                         if (seenBin)
369                                 return null;
370
371                         // Load from bin
372                         if (!Directory.Exists (PrivateBinPath))
373                                 return null;
374
375                         string [] binDlls = Directory.GetFiles (PrivateBinPath, "*.dll");
376                         foreach (string s in binDlls) {
377                                 Assembly binA = Assembly.LoadFrom (s);
378                                 type = binA.GetType (typeName);
379                                 if (type == null)
380                                         continue;
381
382                                 AddDependency (binA.Location);
383                                 return type;
384                         }
385
386                         return null;
387                 }
388
389                 void AddAssembliesInBin ()
390                 {
391                         if (!Directory.Exists (PrivateBinPath))
392                                 return;
393
394                         string [] binDlls = Directory.GetFiles (PrivateBinPath, "*.dll");
395                         foreach (string s in binDlls)
396                                 assemblies.Add (s);
397                 }
398
399                 internal virtual void AddInterface (string iface)
400                 {
401                         if (interfaces == null)
402                                 interfaces = new ArrayList ();
403
404                         if (!interfaces.Contains (iface))
405                                 interfaces.Add (iface);
406                 }
407                 
408                 internal virtual void AddImport (string namesp)
409                 {
410                         if (imports == null)
411                                 imports = new ArrayList ();
412
413                         if (!imports.Contains (namesp))
414                                 imports.Add (namesp);
415                 }
416
417                 internal virtual void AddSourceDependency (string filename)
418                 {
419                         if (dependencies != null && dependencies.Contains (filename)) {
420                                 ThrowParseException ("Circular file references are not allowed. File: " + filename);
421                         }
422
423                         AddDependency (filename);
424                 }
425
426                 internal virtual void AddDependency (string filename)
427                 {
428                         if (filename == "")
429                                 return;
430
431                         if (dependencies == null)
432                                 dependencies = new ArrayList ();
433
434                         if (!dependencies.Contains (filename))
435                                 dependencies.Add (filename);
436                 }
437                 
438                 internal virtual void AddAssembly (Assembly assembly, bool fullPath)
439                 {
440                         if (assembly.Location == "")
441                                 return;
442
443                         if (anames == null)
444                                 anames = new Hashtable ();
445
446                         string name = assembly.GetName ().Name;
447                         string loc = assembly.Location;
448                         if (fullPath) {
449                                 if (!assemblies.Contains (loc)) {
450                                         assemblies.Add (loc);
451                                 }
452
453                                 anames [name] = loc;
454                                 anames [loc] = assembly;
455                         } else {
456                                 if (!assemblies.Contains (name)) {
457                                         assemblies.Add (name);
458                                 }
459
460                                 anames [name] = assembly;
461                         }
462                 }
463
464                 internal virtual Assembly AddAssemblyByFileName (string filename)
465                 {
466                         Assembly assembly = null;
467                         Exception error = null;
468
469                         try {
470                                 assembly = Assembly.LoadFrom (filename);
471                         } catch (Exception e) { error = e; }
472
473                         if (assembly == null)
474                                 ThrowParseException ("Assembly " + filename + " not found", error);
475
476                         AddAssembly (assembly, true);
477                         return assembly;
478                 }
479
480                 internal virtual Assembly AddAssemblyByName (string name)
481                 {
482                         if (anames == null)
483                                 anames = new Hashtable ();
484
485                         if (anames.Contains (name)) {
486                                 object o = anames [name];
487                                 if (o is string)
488                                         o = anames [o];
489
490                                 return (Assembly) o;
491                         }
492
493                         Assembly assembly = null;
494                         Exception error = null;
495                         if (name.IndexOf (',') != -1) {
496                                 try {
497                                         assembly = Assembly.Load (name);
498                                 } catch (Exception e) { error = e; }
499                         }
500
501                         if (assembly == null) {
502                                 try {
503                                         assembly = Assembly.LoadWithPartialName (name);
504                                 } catch (Exception e) { error = e; }
505                         }
506                         
507                         if (assembly == null)
508                                 ThrowParseException ("Assembly " + name + " not found", error);
509
510                         AddAssembly (assembly, true);
511                         return assembly;
512                 }
513
514                 internal virtual void ProcessMainAttributes (Hashtable atts)
515                 {
516                         atts.Remove ("Description"); // ignored
517 #if NET_1_1
518                         atts.Remove ("CodeBehind");  // ignored
519 #endif
520                         atts.Remove ("AspCompat"); // ignored
521
522                         debug = GetBool (atts, "Debug", true);
523                         compilerOptions = GetString (atts, "CompilerOptions", "");
524                         language = GetString (atts, "Language", CompilationConfig.DefaultLanguage);
525                         strictOn = GetBool (atts, "Strict", CompilationConfig.Strict);
526                         explicitOn = GetBool (atts, "Explicit", CompilationConfig.Explicit);
527
528                         string inherits = GetString (atts, "Inherits", null);
529 #if NET_2_0
530                         // In ASP 2, the source file is actually integrated with
531                         // the generated file via the use of partial classes. This
532                         // means that the code file has to be confirmed, but not
533                         // used at this point.
534                         src = GetString (atts, "CodeFile", null);
535
536                         if (src != null && inherits != null) {
537                                 // Make sure the source exists
538                                 src = UrlUtils.Combine (BaseVirtualDir, src);
539                                 string realPath = MapPath (src, false);
540                                 if (!File.Exists (realPath))
541                                         ThrowParseException ("File " + src + " not found");
542
543                                 // We are going to create a partial class that shares
544                                 // the same name as the inherits tag, so reset the
545                                 // name. The base type is changed because it is the
546                                 // code file's responsibilty to extend the classes
547                                 // needed.
548                                 partialClassName = inherits;
549
550                                 // Add the code file as an option to the
551                                 // compiler. This lets both files be compiled at once.
552                                 compilerOptions += " \"" + realPath + "\"";
553                         } else if (inherits != null) {
554                                 // We just set the inherits directly because this is a
555                                 // Single-Page model.
556                                 SetBaseType (inherits);
557                         }
558 #else
559                         string src = GetString (atts, "Src", null);
560
561                         if (src != null)
562                                 srcAssembly = GetAssemblyFromSource (src);
563
564                         if (inherits != null)
565                                 SetBaseType (inherits);
566
567                         className = GetString (atts, "ClassName", null);
568                         if (className != null && !CodeGenerator.IsValidLanguageIndependentIdentifier (className))
569                                 ThrowParseException (String.Format ("'{0}' is not valid for 'className'", className));
570 #endif
571
572                         if (atts.Count > 0)
573                                 ThrowParseException ("Unknown attribute: " + GetOneKey (atts));
574                 }
575
576                 internal void SetBaseType (string type)
577                 {
578                         if (type == DefaultBaseTypeName)
579                                 return;
580
581                         Type parent = null;
582                         if (srcAssembly != null)
583                                 parent = srcAssembly.GetType (type);
584
585                         if (parent == null)
586                                 parent = LoadType (type);
587
588                         if (parent == null)
589                                 ThrowParseException ("Cannot find type " + type);
590
591                         if (!DefaultBaseType.IsAssignableFrom (parent))
592                                 ThrowParseException ("The parent type does not derive from " + DefaultBaseType);
593
594                         baseType = parent;
595                         if (parent.FullName.IndexOf ('.') == -1)
596                                 baseTypeIsGlobal = true;
597                 }
598
599                 Assembly GetAssemblyFromSource (string vpath)
600                 {
601                         vpath = UrlUtils.Combine (BaseVirtualDir, vpath);
602                         string realPath = MapPath (vpath, false);
603                         if (!File.Exists (realPath))
604                                 ThrowParseException ("File " + vpath + " not found");
605
606                         AddSourceDependency (realPath);
607
608                         CompilerResults result = CachingCompiler.Compile (language, realPath, realPath, assemblies);
609                         if (result.NativeCompilerReturnValue != 0) {
610                                 StreamReader reader = new StreamReader (realPath);
611                                 throw new CompilationException (realPath, result.Errors, reader.ReadToEnd ());
612                         }
613
614                         AddAssembly (result.CompiledAssembly, true);
615                         return result.CompiledAssembly;
616                 }
617                 
618                 internal abstract Type DefaultBaseType { get; }
619                 internal abstract string DefaultBaseTypeName { get; }
620                 internal abstract string DefaultDirectiveName { get; }
621
622                 internal string InputFile
623                 {
624                         get { return inputFile; }
625                         set { inputFile = value; }
626                 }
627
628 #if NET_2_0
629                 internal bool IsPartial
630                 {
631                         get { return src != null; }
632                 }
633
634                 internal string PartialClassName
635                 {
636                         get { return partialClassName; }
637                 }
638 #endif
639
640                 internal string Text
641                 {
642                         get { return text; }
643                         set { text = value; }
644                 }
645
646                 internal Type BaseType
647                 {
648                         get {
649                                 if (baseType == null)
650                                         baseType = DefaultBaseType;
651
652                                 return baseType;
653                         }
654                 }
655                 
656                 internal bool BaseTypeIsGlobal {
657                         get { return baseTypeIsGlobal; }
658                 }
659                 
660                 internal string ClassName {
661                         get {
662                                 if (className != null)
663                                         return className;
664
665                                 className = Path.GetFileName (inputFile).Replace ('.', '_');
666                                 className = className.Replace ('-', '_'); 
667                                 className = className.Replace (' ', '_');
668
669                                 if (Char.IsDigit(className[0])) {
670                                         className = "_" + className;
671                                 }
672
673                                 return className;
674                         }
675                 }
676
677                 internal string PrivateBinPath {
678                         get {
679                                 if (privateBinPath != null)
680                                         return privateBinPath;
681
682                                 AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
683                                 privateBinPath = Path.Combine (setup.ApplicationBase, setup.PrivateBinPath);
684
685                                 return privateBinPath;
686                         }
687                 }
688
689                 internal ArrayList Scripts {
690                         get {
691                                 if (scripts == null)
692                                         scripts = new ArrayList ();
693
694                                 return scripts;
695                         }
696                 }
697
698                 internal ArrayList Imports {
699                         get { return imports; }
700                 }
701
702                 internal ArrayList Assemblies {
703                         get {
704                                 if (appAssemblyIndex != -1) {
705                                         object o = assemblies [appAssemblyIndex];
706                                         assemblies.RemoveAt (appAssemblyIndex);
707                                         assemblies.Add (o);
708                                         appAssemblyIndex = -1;
709                                 }
710
711                                 return assemblies;
712                         }
713                 }
714
715                 internal ArrayList Interfaces {
716                         get { return interfaces; }
717                 }
718
719                 internal RootBuilder RootBuilder {
720                         get { return rootBuilder; }
721                         set { rootBuilder = value; }
722                 }
723
724                 internal ArrayList Dependencies {
725                         get { return dependencies; }
726                         set { dependencies = value; }
727                 }
728
729                 internal string CompilerOptions {
730                         get { return compilerOptions; }
731                 }
732
733                 internal string Language {
734                         get { return language; }
735                 }
736
737                 internal bool StrictOn {
738                         get { return strictOn; }
739                 }
740
741                 internal bool ExplicitOn {
742                         get { return explicitOn; }
743                 }
744                 
745                 internal bool Debug {
746                         get { return debug; }
747                 }
748
749                 internal bool OutputCache {
750                         get { return output_cache; }
751                 }
752
753                 internal int OutputCacheDuration {
754                         get { return oc_duration; }
755                 }
756
757                 internal string OutputCacheVaryByHeader {
758                         get { return oc_header; }
759                 }
760
761                 internal string OutputCacheVaryByCustom {
762                         get { return oc_custom; }
763                 }
764
765                 internal string OutputCacheVaryByControls {
766                         get { return oc_controls; }
767                 }
768                 
769                 internal bool OutputCacheShared {
770                         get { return oc_shared; }
771                 }
772                 
773                 internal OutputCacheLocation OutputCacheLocation {
774                         get { return oc_location; }
775                 }
776
777                 internal string OutputCacheVaryByParam {
778                         get { return oc_param; }
779                 }
780
781 #if NET_2_0
782                 internal PagesSection PagesConfig {
783                         get {
784                                 return WebConfigurationManager.GetSection ("system.web/pages") as PagesSection;
785                         }
786                 }
787 #else
788                 internal PagesConfiguration PagesConfig {
789                         get { return PagesConfiguration.GetInstance (Context); }
790                 }
791 #endif
792         }
793 }
794