undo
[mono.git] / mcs / class / System.Web / System.Web.UI / TemplateParser.cs
index 8309ffeabb4f85436075e908587f11ea9dd0d2a2..c3bb9afb900a712e4104c4ad1ef67fb1fa45f393 100644 (file)
@@ -4,9 +4,10 @@
 // Authors:
 //     Duncan Mak (duncan@ximian.com)
 //     Gonzalo Paniagua Javier (gonzalo@ximian.com)
+//      Marek Habersack (mhabersack@novell.com)
 //
 // (C) 2002,2003 Ximian, Inc. (http://www.ximian.com)
-// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2005-2008 Novell, Inc (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
 
 using System.CodeDom.Compiler;
 using System.Collections;
+using System.Collections.Generic;
 using System.ComponentModel;
 using System.Globalization;
 using System.IO;
 using System.Reflection;
 using System.Security.Permissions;
+using System.Text;
+using System.Threading;
 using System.Web.Compilation;
 using System.Web.Configuration;
 using System.Web.Hosting;
 using System.Web.Util;
 
-#if NET_2_0
-using System.Collections.Generic;
-#endif
-
 namespace System.Web.UI {
        internal class ServerSideScript
        {
@@ -62,16 +62,30 @@ namespace System.Web.UI {
        [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
        public abstract class TemplateParser : BaseParser
        {
+               [Flags]
+               internal enum OutputCacheParsedParams
+               {
+                       Location               = 0x0001,
+                       CacheProfile           = 0x0002,
+                       NoStore                = 0x0004,
+                       SqlDependency          = 0x0008,
+                       VaryByCustom           = 0x0010,
+                       VaryByHeader           = 0x0020,
+                       VaryByControl          = 0x0040,
+                       VaryByContentEncodings = 0x0080
+               }
+               
                string inputFile;
                string text;
-               string privateBinPath;
                Hashtable mainAttributes;
                ArrayList dependencies;
                ArrayList assemblies;
                Hashtable anames;
-               ArrayList imports;
-               ArrayList interfaces;
-               ArrayList scripts;
+               string[] binDirAssemblies;
+               Dictionary <string, bool> namespacesCache;
+               Dictionary <string, bool> imports;
+               List <string> interfaces;
+               List <ServerSideScript> scripts;
                Type baseType;
                bool baseTypeIsGlobal = true;
                string className;
@@ -80,19 +94,22 @@ namespace System.Web.UI {
                string compilerOptions;
                string language;
                bool implicitLanguage;
-               bool strictOn = false;
-               bool explicitOn = false;
-               bool linePragmasOn = false;
+               bool strictOn ;
+               bool explicitOn;
+               bool linePragmasOn = true;
                bool output_cache;
                int oc_duration;
                string oc_header, oc_custom, oc_param, oc_controls;
-#if NET_2_0
-               string oc_content_encodings;
-#endif
+               string oc_content_encodings, oc_cacheprofile, oc_sqldependency;
+               bool oc_nostore;
+               OutputCacheParsedParams oc_parsed_params = 0;
                bool oc_shared;
                OutputCacheLocation oc_location;
-               CultureInfo invariantCulture = CultureInfo.InvariantCulture;
-#if NET_2_0
+
+               // Kludge needed to support pre-parsing of the main directive (see
+               // AspNetGenerator.GetRootBuilderType)
+               internal int allowedMainDirectives = 0;
+               
                byte[] md5checksum;
                string src;
                bool srcIsLegacy;
@@ -100,64 +117,26 @@ namespace System.Web.UI {
                string codeFileBaseClass;
                string metaResourceKey;
                Type codeFileBaseClassType;
+               Type pageParserFilterType;
+               PageParserFilter pageParserFilter;
+               
                List <UnknownAttributeDescriptor> unknownMainAttributes;
                Stack <string> includeDirs;
-#else
-               Stack includeDirs;
-#endif
+               List <string> registeredTagNames;
                ILocation directiveLocation;
                
-               Assembly srcAssembly;
                int appAssemblyIndex = -1;
 
                internal TemplateParser ()
                {
+                       imports = new Dictionary <string, bool> (StringComparer.Ordinal);
                        LoadConfigDefaults ();
-                       
-                       imports = new ArrayList ();
-#if NET_2_0
-                       AddNamespaces (imports);
-#else
-                       imports.Add ("System");
-                       imports.Add ("System.Collections");
-                       imports.Add ("System.Collections.Specialized");
-                       imports.Add ("System.Configuration");
-                       imports.Add ("System.Text");
-                       imports.Add ("System.Text.RegularExpressions");
-                       imports.Add ("System.Web");
-                       imports.Add ("System.Web.Caching");
-                       imports.Add ("System.Web.Security");
-                       imports.Add ("System.Web.SessionState");
-                       imports.Add ("System.Web.UI");
-                       imports.Add ("System.Web.UI.WebControls");
-                       imports.Add ("System.Web.UI.HtmlControls");
-#endif
-
                        assemblies = new ArrayList ();
-#if NET_2_0
                        CompilationSection compConfig = CompilationConfig;
-                       
-                       bool addAssembliesInBin = false;
                        foreach (AssemblyInfo info in compConfig.Assemblies) {
-                               if (info.Assembly == "*")
-                                       addAssembliesInBin = true;
-                               else
+                               if (info.Assembly != "*")
                                        AddAssemblyByName (info.Assembly);
                        }
-                       if (addAssembliesInBin)
-                               AddAssembliesInBin ();
-
-                       foreach (NamespaceInfo info in PagesConfig.Namespaces) {
-                               imports.Add (info.Namespace);
-                       }
-#else
-                       CompilationConfiguration compConfig = CompilationConfig;
-                       
-                       foreach (string a in compConfig.Assemblies)
-                               AddAssemblyByName (a);
-                       if (compConfig.AssembliesInBin)
-                               AddAssembliesInBin ();
-#endif
 
                        language = compConfig.DefaultLanguage;
                        implicitLanguage = true;
@@ -165,6 +144,7 @@ namespace System.Web.UI {
 
                internal virtual void LoadConfigDefaults ()
                {
+                       AddNamespaces (imports);
                        debug = CompilationConfig.Debug;
                }
                
@@ -181,31 +161,40 @@ namespace System.Web.UI {
 
                protected abstract Type CompileIntoType ();
 
-#if NET_2_0
-               void AddNamespaces (ArrayList imports)
+               internal void AddControl (Type type, IDictionary attributes)
+               {
+                       AspGenerator generator = AspGenerator;
+                       if (generator == null)
+                               return;
+                       generator.AddControl (type, attributes);
+               }
+               
+               void AddNamespaces (Dictionary <string, bool> imports)
                {
                        if (BuildManager.HaveResources)
-                               imports.Add ("System.Resources");
+                               imports.Add ("System.Resources", true);
                        
-                       PagesSection pages = WebConfigurationManager.GetSection ("system.web/pages") as PagesSection;
+                       PagesSection pages = PagesConfig;
                        if (pages == null)
                                return;
 
                        NamespaceCollection namespaces = pages.Namespaces;
                        if (namespaces == null || namespaces.Count == 0)
                                return;
-
-                       foreach (NamespaceInfo nsi in namespaces)
-                               imports.Add (nsi.Namespace);
+                       
+                       foreach (NamespaceInfo nsi in namespaces) {
+                               string ns = nsi.Namespace;
+                               if (imports.ContainsKey (ns))
+                                       continue;
+                               
+                               imports.Add (ns, true);
+                       }
                }
-#endif
                
                internal void RegisterCustomControl (string tagPrefix, string tagName, string src)
                 {
                         string realpath = null;
                        bool fileExists = false;
-                       
-#if NET_2_0
                        VirtualFile vf = null;
                        VirtualPathProvider vpp = HostingEnvironment.VirtualPathProvider;
                        VirtualPath vp = new VirtualPath (src, BaseVirtualDir);
@@ -217,48 +206,24 @@ namespace System.Web.UI {
                                if (vf != null)
                                        realpath = MapPath (vf.VirtualPath);
                        }
-#else
-                       realpath = MapPath (src);
-                       fileExists = File.Exists (realpath);
-#endif
+
                        if (!fileExists)
-                               throw new ParseException (Location, "Could not find file \"" + src + "\".");
+                               ThrowParseFileNotFound (src);
 
-                       if (String.Compare (realpath, inputFile, false, invariantCulture) == 0)
+                       if (String.Compare (realpath, inputFile, false, Helpers.InvariantCulture) == 0)
                                 return;
                        
-#if NET_2_0
                        string vpath = vf.VirtualPath;
-#else
-                       string vpath = VirtualPathUtility.Combine (BaseVirtualDir, src);
-                       if (VirtualPathUtility.IsAbsolute (vpath))
-                               vpath = VirtualPathUtility.ToAppRelative (vpath);
-#endif
-                       
-                        Type type = null;
-                        AddDependency (vpath);
+                        
                         try {
-#if NET_2_0
-                               type = BuildManager.GetCompiledType (vpath);
-                               if (type == null)
-                                       throw new ParseException (Location, "Error compiling user control '" + vpath + "'.");
-
-                               if (!(typeof (UserControl).IsAssignableFrom (type)))
-                                       throw new ParseException (Location, "Type '" + type.ToString () + "' does not derive from 'System.Web.UI.UserControl'.");
-#else
-                               ArrayList other_deps = new ArrayList ();
-                                type = UserControlParser.GetCompiledType (vpath, realpath, other_deps, Context);
-                               foreach (string s in other_deps)
-                                        AddDependency (s);
-#endif
+                               RegisterTagName (tagPrefix + ":" + tagName);
+                               RootBuilder.Foundry.RegisterFoundry (tagPrefix, tagName, vpath);
+                               AddDependency (vpath);
                         } catch (ParseException pe) {
                                 if (this is UserControlParser)
                                         throw new ParseException (Location, pe.Message, pe);
                                 throw;
                         }
-
-                        AddAssembly (type.Assembly, true);
-                        RootBuilder.Foundry.RegisterFoundry (tagPrefix, tagName, type);
                 }
 
                 internal void RegisterNamespace (string tagPrefix, string ns, string assembly)
@@ -286,16 +251,27 @@ namespace System.Web.UI {
                
                internal virtual void AddDirective (string directive, Hashtable atts)
                {
-                       if (String.Compare (directive, DefaultDirectiveName, true) == 0) {
-                               if (mainAttributes != null)
+                       var pageParserFilter = PageParserFilter;
+                       if (String.Compare (directive, DefaultDirectiveName, true, Helpers.InvariantCulture) == 0) {
+                               bool allowMainDirective = allowedMainDirectives > 0;
+                               
+                               if (mainAttributes != null && !allowMainDirective)
                                        ThrowParseException ("Only 1 " + DefaultDirectiveName + " is allowed");
 
+                               allowedMainDirectives--;
+                               if (mainAttributes != null)
+                                       return;
+                               
+                               if (pageParserFilter != null)
+                                       pageParserFilter.PreprocessDirective (directive.ToLower (Helpers.InvariantCulture), atts);
+                               
                                mainAttributes = atts;
                                ProcessMainAttributes (mainAttributes);
                                return;
-                       }
-
-                       int cmp = String.Compare ("Assembly", directive, true);
+                       } else if (pageParserFilter != null)
+                               pageParserFilter.PreprocessDirective (directive.ToLower (Helpers.InvariantCulture), atts);
+                               
+                       int cmp = String.Compare ("Assembly", directive, true, Helpers.InvariantCulture);
                        if (cmp == 0) {
                                string name = GetString (atts, "Name", null);
                                string src = GetString (atts, "Src", null);
@@ -318,18 +294,17 @@ namespace System.Web.UI {
                                return;
                        }
 
-                       cmp = String.Compare ("Import", directive, true);
+                       cmp = String.Compare ("Import", directive, true, Helpers.InvariantCulture);
                        if (cmp == 0) {
                                string namesp = GetString (atts, "Namespace", null);
                                if (atts.Count > 0)
                                        ThrowParseException ("Attribute " + GetOneKey (atts) + " unknown.");
                                
-                               if (namesp != null && namesp != "")
-                                       AddImport (namesp);
+                               AddImport (namesp);
                                return;
                        }
 
-                       cmp = String.Compare ("Implements", directive, true);
+                       cmp = String.Compare ("Implements", directive, true, Helpers.InvariantCulture);
                        if (cmp == 0) {
                                string ifacename = GetString (atts, "Interface", "");
 
@@ -347,7 +322,7 @@ namespace System.Web.UI {
                                return;
                        }
 
-                       cmp = String.Compare ("OutputCache", directive, true);
+                       cmp = String.Compare ("OutputCache", directive, true, Helpers.InvariantCulture);
                        if (cmp == 0) {
                                HttpResponse response = HttpContext.Current.Response;
                                if (response != null)
@@ -364,28 +339,53 @@ namespace System.Web.UI {
 
                                foreach (DictionaryEntry entry in atts) {
                                        string key = (string) entry.Key;
-                                       switch (key.ToLower ()) {
+                                       if (key == null)
+                                               continue;
+                                       
+                                       switch (key.ToLower (Helpers.InvariantCulture)) {
                                                case "duration":
                                                        oc_duration = Int32.Parse ((string) entry.Value);
                                                        if (oc_duration < 1)
                                                                ThrowParseException ("The 'duration' attribute must be set " +
                                                                                     "to a positive integer value");
                                                        break;
-#if NET_2_0
+
+                                               case "sqldependency":
+                                                       oc_sqldependency = (string) entry.Value;
+                                                       break;
+                                                       
+                                               case "nostore":
+                                                       try {
+                                                               oc_nostore = Boolean.Parse ((string) entry.Value);
+                                                               oc_parsed_params |= OutputCacheParsedParams.NoStore;
+                                                       } catch {
+                                                               ThrowParseException ("The 'NoStore' attribute is case sensitive" +
+                                                                                    " and must be set to 'true' or 'false'.");
+                                                       }
+                                                       break;
+
+                                               case "cacheprofile":
+                                                       oc_cacheprofile = (string) entry.Value;
+                                                       oc_parsed_params |= OutputCacheParsedParams.CacheProfile;
+                                                       break;
+                                                       
                                                case "varybycontentencodings":
                                                        oc_content_encodings = (string) entry.Value;
+                                                       oc_parsed_params |= OutputCacheParsedParams.VaryByContentEncodings;
                                                        break;
-#endif
+
                                                case "varybyparam":
                                                        oc_param = (string) entry.Value;
-                                                       if (String.Compare (oc_param, "none") == 0)
+                                                       if (String.Compare (oc_param, "none", true, Helpers.InvariantCulture) == 0)
                                                                oc_param = null;
                                                        break;
                                                case "varybyheader":
                                                        oc_header = (string) entry.Value;
+                                                       oc_parsed_params |= OutputCacheParsedParams.VaryByHeader;
                                                        break;
                                                case "varybycustom":
                                                        oc_custom = (string) entry.Value;
+                                                       oc_parsed_params |= OutputCacheParsedParams.VaryByCustom;
                                                        break;
                                                case "location":
                                                        if (!(this is PageParser))
@@ -394,6 +394,7 @@ namespace System.Web.UI {
                                                        try {
                                                                oc_location = (OutputCacheLocation) Enum.Parse (
                                                                        typeof (OutputCacheLocation), (string) entry.Value, true);
+                                                               oc_parsed_params |= OutputCacheParsedParams.Location;
                                                        } catch {
                                                                ThrowParseException ("The 'location' attribute is case sensitive and " +
                                                                                     "must be one of the following values: Any, Client, " +
@@ -401,11 +402,8 @@ namespace System.Web.UI {
                                                        }
                                                        break;
                                                case "varybycontrol":
-#if ONLY_1_1
-                                                       if (this is PageParser)
-                                                               goto default;
-#endif
                                                        oc_controls = (string) entry.Value;
+                                                       oc_parsed_params |= OutputCacheParsedParams.VaryByControl;
                                                        break;
                                                case "shared":
                                                        if (this is PageParser)
@@ -451,16 +449,10 @@ namespace System.Web.UI {
                        return type;
                }
 
-               void AddAssembliesInBin ()
-               {
-                       foreach (string s in HttpApplication.BinDirectoryAssemblies)
-                               assemblies.Add (s);
-               }
-               
                internal virtual void AddInterface (string iface)
                {
                        if (interfaces == null)
-                               interfaces = new ArrayList ();
+                               interfaces = new List <string> ();
 
                        if (!interfaces.Contains (iface))
                                interfaces.Add (iface);
@@ -468,13 +460,73 @@ namespace System.Web.UI {
                
                internal virtual void AddImport (string namesp)
                {
+                       if (namesp == null || namesp.Length == 0)
+                               return;
+                       
                        if (imports == null)
-                               imports = new ArrayList ();
+                               imports = new Dictionary <string, bool> (StringComparer.Ordinal);
+                       
+                       if (imports.ContainsKey (namesp))
+                               return;
+                       
+                       imports.Add (namesp, true);
+                       AddAssemblyForNamespace (namesp);
+               }
 
-                       if (!imports.Contains (namesp))
-                               imports.Add (namesp);
+               void AddAssemblyForNamespace (string namesp)
+               {
+                       if (binDirAssemblies == null)
+                               binDirAssemblies = HttpApplication.BinDirectoryAssemblies;
+                       if (binDirAssemblies.Length == 0)
+                               return;
+
+                       if (namespacesCache == null)
+                               namespacesCache = new Dictionary <string, bool> ();
+                       else if (namespacesCache.ContainsKey (namesp))
+                               return;
+                       
+                       foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies ())
+                               if (FindNamespaceInAssembly (asm, namesp))
+                                       return;
+                       
+                       IList tla = BuildManager.TopLevelAssemblies;
+                       if (tla != null && tla.Count > 0) {
+                               foreach (Assembly asm in tla) {
+                                       if (FindNamespaceInAssembly (asm, namesp))
+                                               return;
+                               }
+                       }
+
+                       Assembly a;
+                       foreach (string s in binDirAssemblies) {
+                               a = Assembly.LoadFrom (s);
+                               if (FindNamespaceInAssembly (a, namesp))
+                                       return;
+                       }
                }
 
+               bool FindNamespaceInAssembly (Assembly asm, string namesp)
+               {
+                       Type[] asmTypes;
+
+                       try {
+                               asmTypes = asm.GetTypes ();
+                       } catch (ReflectionTypeLoadException) {
+                               // ignore
+                               return false;
+                       }
+                       
+                       foreach (Type type in asmTypes) {
+                               if (String.Compare (type.Namespace, namesp, StringComparison.Ordinal) == 0) {
+                                       namespacesCache.Add (namesp, true);
+                                       AddAssembly (asm, true);
+                                       return true;
+                               }
+                       }
+
+                       return false;
+               }
+               
                internal virtual void AddSourceDependency (string filename)
                {
                        if (dependencies != null && dependencies.Contains (filename))
@@ -485,7 +537,7 @@ namespace System.Web.UI {
 
                internal virtual void AddDependency (string filename)
                {
-                       if (filename == "")
+                       if (filename == null || filename == String.Empty)
                                return;
 
                        if (dependencies == null)
@@ -497,7 +549,7 @@ namespace System.Web.UI {
                
                internal virtual void AddAssembly (Assembly assembly, bool fullPath)
                {
-                       if (assembly.Location == "")
+                       if (assembly == null || assembly.Location == String.Empty)
                                return;
 
                        if (anames == null)
@@ -572,19 +624,12 @@ namespace System.Web.UI {
                internal virtual void ProcessMainAttributes (Hashtable atts)
                {
                        directiveLocation = new System.Web.Compilation.Location (Location);
-                       
-#if NET_2_0
                        CompilationSection compConfig;
-#else
-                       CompilationConfiguration compConfig;
-#endif
 
                        compConfig = CompilationConfig;
                        
                        atts.Remove ("Description"); // ignored
-#if NET_1_1
                        atts.Remove ("CodeBehind");  // ignored
-#endif
                        atts.Remove ("AspCompat"); // ignored
                        
                        debug = GetBool (atts, "Debug", compConfig.Debug);
@@ -597,12 +642,12 @@ namespace System.Web.UI {
                        
                        strictOn = GetBool (atts, "Strict", compConfig.Strict);
                        explicitOn = GetBool (atts, "Explicit", compConfig.Explicit);
-                       linePragmasOn = GetBool (atts, "LinePragmas", false);
-                       
+                       if (atts.ContainsKey ("LinePragmas"))
+                               linePragmasOn = GetBool (atts, "LinePragmas", true);
+
                        string inherits = GetString (atts, "Inherits", null);
                        string srcRealPath = null;
                        
-#if NET_2_0
                        // In ASP 2, the source file is actually integrated with
                        // the generated file via the use of partial classes. This
                        // means that the code file has to be confirmed, but not
@@ -665,17 +710,7 @@ namespace System.Web.UI {
                                // Single-Page model.
                                SetBaseType (inherits);
                        }
-#else
-                       string src = GetString (atts, "Src", null);
 
-                       if (src != null) {
-                               srcRealPath = MapPath (src, false);
-                               srcAssembly = GetAssemblyFromSource (src);
-                       }
-                       
-                       if (inherits != null)
-                               SetBaseType (inherits);
-#endif
                        if (src != null) {
                                if (VirtualPathUtility.IsAbsolute (src))
                                        src = VirtualPathUtility.ToAppRelative (src);
@@ -684,20 +719,13 @@ namespace System.Web.UI {
                        
                        className = GetString (atts, "ClassName", null);
                        if (className != null) {
-#if NET_2_0
                                string [] identifiers = className.Split ('.');
                                for (int i = 0; i < identifiers.Length; i++)
                                        if (!CodeGenerator.IsValidLanguageIndependentIdentifier (identifiers [i]))
                                                ThrowParseException (String.Format ("'{0}' is not a valid "
                                                        + "value for attribute 'classname'.", className));
-#else
-                               if (!CodeGenerator.IsValidLanguageIndependentIdentifier (className))
-                                       ThrowParseException (String.Format ("'{0}' is not a valid "
-                                               + "value for attribute 'classname'.", className));
-#endif
                        }
 
-#if NET_2_0
                        if (this is TemplateControlParser)
                                metaResourceKey = GetString (atts, "meta:resourcekey", null);
                        
@@ -716,17 +744,27 @@ namespace System.Web.UI {
                                }
                                return;
                        }
-#endif
+
                        if (atts.Count > 0)
                                ThrowParseException ("Unknown attribute: " + GetOneKey (atts));
                }
 
-#if NET_2_0
+               void RegisterTagName (string tagName)
+               {
+                       if (registeredTagNames == null)
+                               registeredTagNames = new List <string> ();
+
+                       if (registeredTagNames.Contains (tagName))
+                               return;
+
+                       registeredTagNames.Add (tagName);
+               }
+               
                void CheckUnknownAttribute (string name, string val, string inherits)
                {
                        MemberInfo mi = null;
                        bool missing = false;
-                       string memberName = name.Trim ().ToLower (CultureInfo.InvariantCulture);
+                       string memberName = name.Trim ().ToLower (Helpers.InvariantCulture);
                        Type parent = codeFileBaseClassType;
 
                        if (parent == null)
@@ -793,28 +831,29 @@ namespace System.Web.UI {
                        UnknownAttributeDescriptor desc = new UnknownAttributeDescriptor (mi, value);
                        unknownMainAttributes.Add (desc);
                }
-#endif
                
                internal void SetBaseType (string type)
                {
-                       if (type == null || type == DefaultBaseTypeName) {
-                               baseType = DefaultBaseType;
-                               return;
-                       }
-                       
-                       Type parent = null;
-                       if (srcAssembly != null)
-                               parent = srcAssembly.GetType (type);
+                       Type parent;                    
+                       if (type == null || type == DefaultBaseTypeName)
+                               parent = DefaultBaseType;
+                       else
+                               parent = null;
 
-                       if (parent == null)
+                       if (parent == null) {
                                parent = LoadType (type);
 
-                       if (parent == null)
-                               ThrowParseException ("Cannot find type " + type);
+                               if (parent == null)
+                                       ThrowParseException ("Cannot find type " + type);
 
-                       if (!DefaultBaseType.IsAssignableFrom (parent))
-                               ThrowParseException ("The parent type '" + type + "' does not derive from " + DefaultBaseType);
+                               if (!DefaultBaseType.IsAssignableFrom (parent))
+                                       ThrowParseException ("The parent type '" + type + "' does not derive from " + DefaultBaseType);
+                       }
 
+                       var pageParserFilter = PageParserFilter;
+                       if (pageParserFilter != null && !pageParserFilter.AllowBaseType (parent))
+                               throw new HttpException ("Base type '" + parent + "' is not allowed.");
+                       
                        baseType = parent;
                }
 
@@ -826,13 +865,8 @@ namespace System.Web.UI {
 
                internal void PushIncludeDir (string dir)
                {
-                       if (includeDirs == null) {
-#if NET_2_0
+                       if (includeDirs == null)
                                includeDirs = new Stack <string> (1);
-#else
-                               includeDirs = new Stack (1);
-#endif
-                       }
 
                        includeDirs.Push (dir);
                }
@@ -855,8 +889,6 @@ namespace System.Web.UI {
                        AddSourceDependency (vpath);
                        
                        CompilerResults result;
-
-#if NET_2_0
                        string tmp;
                        CompilerParameters parameters;
                        CodeDomProvider provider = BaseCompiler.CreateProvider (HttpContext.Current, language, out parameters, out tmp);
@@ -868,9 +900,7 @@ namespace System.Web.UI {
                        abuilder.AddAssemblyReference (BuildManager.GetReferencedAssemblies () as List <Assembly>);
                        abuilder.AddCodeFile (realPath);
                        result = abuilder.BuildAssembly (new VirtualPath (vpath));
-#else
-                       result = CachingCompiler.Compile (language, realPath, realPath, assemblies, Debug);
-#endif
+
                        if (result.NativeCompilerReturnValue != 0) {
                                using (StreamReader reader = new StreamReader (realPath)) {
                                        throw new CompilationException (realPath, result.Errors, reader.ReadToEnd ());
@@ -884,12 +914,44 @@ namespace System.Web.UI {
                internal abstract string DefaultBaseTypeName { get; }
                internal abstract string DefaultDirectiveName { get; }
 
-#if NET_2_0
+               internal bool LinePragmasOn {
+                       get { return linePragmasOn; }
+               }
+               
                internal byte[] MD5Checksum {
                        get { return md5checksum; }
                        set { md5checksum = value; }
                }
-#endif
+
+               internal PageParserFilter PageParserFilter {
+                       get {
+                               if (pageParserFilter != null)
+                                       return pageParserFilter;
+
+                               Type t = PageParserFilterType;
+                               if (t == null)
+                                       return null;
+                               
+                               pageParserFilter = Activator.CreateInstance (t) as PageParserFilter;
+                               pageParserFilter.Initialize (this);
+
+                               return pageParserFilter;
+                       }
+               }
+               
+               internal Type PageParserFilterType {
+                       get {
+                               if (pageParserFilterType == null) {
+                                       string typeName = PagesConfig.PageParserFilterType;
+                                       if (String.IsNullOrEmpty (typeName))
+                                               return null;
+                                       
+                                       pageParserFilterType = HttpApplication.LoadType (typeName, true);
+                               }
+                               
+                               return pageParserFilterType;
+                       }
+               }
                
                internal Type DefaultBaseType {
                        get {
@@ -902,14 +964,7 @@ namespace System.Web.UI {
                internal ILocation DirectiveLocation {
                        get { return directiveLocation; }
                }
-
-#if NET_2_0
-               internal VirtualPath VirtualPath {
-                       get;
-                       set;
-               }
-#endif
-
+               
                internal string ParserDir {
                        get {
                                if (includeDirs == null || includeDirs.Count == 0)
@@ -925,7 +980,6 @@ namespace System.Web.UI {
                        set { inputFile = value; }
                }
 
-#if NET_2_0
                internal bool IsPartial {
                        get { return (!srcIsLegacy && src != null); }
                }
@@ -960,7 +1014,6 @@ namespace System.Web.UI {
                {
                        get { return unknownMainAttributes; }
                }
-#endif
 
                internal string Text {
                        get { return text; }
@@ -982,14 +1035,67 @@ namespace System.Web.UI {
                }
 
                static long autoClassCounter = 0;
-               static object autoClassCounterLock = new object ();
+
+               internal string EncodeIdentifier (string value)
+               {
+                       if (value == null || value.Length == 0 || CodeGenerator.IsValidLanguageIndependentIdentifier (value))
+                               return value;
+
+                       StringBuilder ret = new StringBuilder ();
+
+                       char ch = value [0];
+                       switch (Char.GetUnicodeCategory (ch)) {
+                               case UnicodeCategory.LetterNumber:
+                               case UnicodeCategory.LowercaseLetter:
+                               case UnicodeCategory.TitlecaseLetter:
+                               case UnicodeCategory.UppercaseLetter:
+                               case UnicodeCategory.OtherLetter:
+                               case UnicodeCategory.ModifierLetter:
+                               case UnicodeCategory.ConnectorPunctuation:
+                                       ret.Append (ch);
+                                       break;
+
+                               case UnicodeCategory.DecimalDigitNumber:
+                                       ret.Append ('_');
+                                       ret.Append (ch);
+                                       break;
+                                       
+                               default:
+                                       ret.Append ('_');
+                                       break;
+                       }
+
+                       for (int i = 1; i < value.Length; i++) {
+                               ch = value [i];
+                               switch (Char.GetUnicodeCategory (ch)) {
+                                       case UnicodeCategory.LetterNumber:
+                                       case UnicodeCategory.LowercaseLetter:
+                                       case UnicodeCategory.TitlecaseLetter:
+                                       case UnicodeCategory.UppercaseLetter:
+                                       case UnicodeCategory.OtherLetter:
+                                       case UnicodeCategory.ModifierLetter:
+                                       case UnicodeCategory.ConnectorPunctuation:
+                                       case UnicodeCategory.DecimalDigitNumber:
+                                       case UnicodeCategory.NonSpacingMark:
+                                       case UnicodeCategory.SpacingCombiningMark:
+                                       case UnicodeCategory.Format:
+                                               ret.Append (ch);
+                                               break;
+                                               
+                                       default:
+                                               ret.Append ('_');
+                                               break;
+                               }
+                       }
+
+                       return ret.ToString ();
+               }
                
                internal string ClassName {
                        get {
                                if (className != null)
                                        return className;
 
-#if NET_2_0
                                string physPath = HttpContext.Current.Request.PhysicalApplicationPath;
                                string inFile;
                                
@@ -1008,45 +1114,37 @@ namespace System.Web.UI {
                                if (String.IsNullOrEmpty (inFile)) {
                                        // generate a unique class name
                                        long suffix;
-                                       lock (autoClassCounterLock) {
-                                               suffix = autoClassCounter++;
-                                       }
-
+                                       suffix = Interlocked.Increment (ref autoClassCounter);
                                        className = String.Format ("autoclass_nosource_{0:x}", suffix);
                                        return className;
                                }
                                
-                               if (StrUtils.StartsWith (inFile, physPath)) {
-                                       className = inputFile.Substring (physPath.Length).ToLower (CultureInfo.InvariantCulture);
-                                       className = className.Replace ('.', '_');
-                                       className = className.Replace ('/', '_').Replace ('\\', '_');
-                               } else
-#endif
-                               className = Path.GetFileName (inputFile).Replace ('.', '_');
-                               className = className.Replace ('-', '_'); 
-                               className = className.Replace (' ', '_');
-
-                               if (Char.IsDigit(className[0])) {
-                                       className = "_" + className;
-                               }
-
+                               if (StrUtils.StartsWith (inFile, physPath))
+                                       className = inputFile.Substring (physPath.Length).ToLower (Helpers.InvariantCulture);
+                               else
+                                       className = Path.GetFileName (inputFile);
+                               className = EncodeIdentifier (className);
                                return className;
                        }
                }
 
-               internal ArrayList Scripts {
+               internal List <ServerSideScript> Scripts {
                        get {
                                if (scripts == null)
-                                       scripts = new ArrayList ();
+                                       scripts = new List <ServerSideScript> ();
 
                                return scripts;
                        }
                }
 
-               internal ArrayList Imports {
+               internal Dictionary <string, bool> Imports {
                        get { return imports; }
                }
 
+               internal List <string> Interfaces {
+                       get { return interfaces; }
+               }
+               
                internal ArrayList Assemblies {
                        get {
                                if (appAssemblyIndex != -1) {
@@ -1060,12 +1158,16 @@ namespace System.Web.UI {
                        }
                }
 
-               internal ArrayList Interfaces {
-                       get { return interfaces; }
-               }
-
                internal RootBuilder RootBuilder {
-                       get { return rootBuilder; }
+                       get {
+                               if (rootBuilder != null)
+                                       return rootBuilder;
+                               AspGenerator generator = AspGenerator;
+                               if (generator != null)
+                                       rootBuilder = generator.RootBuilder;
+
+                               return rootBuilder;
+                       }
                        set { rootBuilder = value; }
                }
 
@@ -1106,16 +1208,30 @@ namespace System.Web.UI {
                        get { return oc_duration; }
                }
 
-#if NET_2_0
+               internal OutputCacheParsedParams OutputCacheParsedParameters {
+                       get { return oc_parsed_params; }
+               }
+
+               internal string OutputCacheSqlDependency {
+                       get { return oc_sqldependency; }
+               }
+               
+               internal string OutputCacheCacheProfile {
+                       get { return oc_cacheprofile; }
+               }
+               
                internal string OutputCacheVaryByContentEncodings {
                        get { return oc_content_encodings; }
                }
 
+               internal bool OutputCacheNoStore {
+                       get { return oc_nostore; }
+               }
+               
                internal virtual TextReader Reader {
                        get { return null; }
                        set { /* no-op */ }
                }
-#endif
                
                internal string OutputCacheVaryByHeader {
                        get { return oc_header; }
@@ -1141,17 +1257,17 @@ namespace System.Web.UI {
                        get { return oc_param; }
                }
 
-#if NET_2_0
+               internal List <string> RegisteredTagNames {
+                       get { return registeredTagNames; }
+               }
+               
                internal PagesSection PagesConfig {
-                       get {
-                               return WebConfigurationManager.GetSection ("system.web/pages") as PagesSection;
-                       }
+                       get { return GetConfigSection <PagesSection> ("system.web/pages") as PagesSection; }
                }
-#else
-               internal PagesConfiguration PagesConfig {
-                       get { return PagesConfiguration.GetInstance (Context); }
+
+               internal AspGenerator AspGenerator {
+                       get;
+                       set;
                }
-#endif
        }
-}
-
+}
\ No newline at end of file