* System.Web20.csproj: added ObjectInputStream.cs and ObjectOutputStream.cs
[mono.git] / mcs / class / System.Web / System.Web.UI / TemplateParser.cs
index 97a817dc88aef2bfe9180aff4a4facc39eeae460..4e8f30e54dd822a1d18cfa7917858d5048f99a7f 100644 (file)
@@ -44,7 +44,18 @@ using System.Collections.Generic;
 #endif
 
 namespace System.Web.UI {
-
+       internal class ServerSideScript
+       {
+               public readonly string Script;
+               public readonly ILocation Location;
+               
+               public ServerSideScript (string script, ILocation location)
+               {
+                       Script = script;
+                       Location = location;
+               }
+       }
+       
        // CAS
        [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
        [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
@@ -61,7 +72,7 @@ namespace System.Web.UI {
                ArrayList interfaces;
                ArrayList scripts;
                Type baseType;
-               bool baseTypeIsGlobal;
+               bool baseTypeIsGlobal = true;
                string className;
                RootBuilder rootBuilder;
                bool debug;
@@ -74,22 +85,30 @@ namespace System.Web.UI {
                bool output_cache;
                int oc_duration;
                string oc_header, oc_custom, oc_param, oc_controls;
+#if NET_2_0
+               string oc_content_encodings;
+#endif
                bool oc_shared;
                OutputCacheLocation oc_location;
                CultureInfo invariantCulture = CultureInfo.InvariantCulture;
 #if NET_2_0
                string src;
+               bool srcIsLegacy;
                string partialClassName;
                string codeFileBaseClass;
                string metaResourceKey;
                Type codeFileBaseClassType;
                List <UnknownAttributeDescriptor> unknownMainAttributes;
 #endif
+               ILocation directiveLocation;
+               
                Assembly srcAssembly;
                int appAssemblyIndex = -1;
 
                internal TemplateParser ()
                {
+                       LoadConfigDefaults ();
+                       
                        imports = new ArrayList ();
 #if NET_2_0
                        AddNamespaces (imports);
@@ -111,8 +130,10 @@ namespace System.Web.UI {
 
                        assemblies = new ArrayList ();
 #if NET_2_0
+                       CompilationSection compConfig = CompilationConfig;
+                       
                        bool addAssembliesInBin = false;
-                       foreach (AssemblyInfo info in CompilationConfig.Assemblies) {
+                       foreach (AssemblyInfo info in compConfig.Assemblies) {
                                if (info.Assembly == "*")
                                        addAssembliesInBin = true;
                                else
@@ -125,15 +146,22 @@ namespace System.Web.UI {
                                imports.Add (info.Namespace);
                        }
 #else
-                       foreach (string a in CompilationConfig.Assemblies)
+                       CompilationConfiguration compConfig = CompilationConfig;
+                       
+                       foreach (string a in compConfig.Assemblies)
                                AddAssemblyByName (a);
-                       if (CompilationConfig.AssembliesInBin)
+                       if (compConfig.AssembliesInBin)
                                AddAssembliesInBin ();
 #endif
 
-                       language = CompilationConfig.DefaultLanguage;
+                       language = compConfig.DefaultLanguage;
                        implicitLanguage = true;
                }
+
+               internal virtual void LoadConfigDefaults ()
+               {
+                       debug = CompilationConfig.Debug;
+               }
                
                internal void AddApplicationAssembly ()
                {
@@ -176,14 +204,20 @@ namespace System.Web.UI {
                         if (!File.Exists (realpath))
                                 throw new ParseException (Location, "Could not find file \"" + realpath + "\".");
                        string vpath = VirtualPathUtility.Combine (BaseVirtualDir, src);
+                       if (VirtualPathUtility.IsAbsolute (vpath))
+                               vpath = VirtualPathUtility.ToAppRelative (vpath);
+                       
                         Type type = null;
-                        AddDependency (realpath);
+                        AddDependency (vpath);
                         try {
-                                ArrayList other_deps = new ArrayList ();
+#if NET_2_0
+                               type = BuildManager.GetCompiledType (vpath);
+#else
+                               ArrayList other_deps = new ArrayList ();
                                 type = UserControlParser.GetCompiledType (vpath, realpath, other_deps, Context);
-                                foreach (string s in other_deps) {
+                               foreach (string s in other_deps)
                                         AddDependency (s);
-                                }
+#endif
                         } catch (ParseException pe) {
                                 if (this is UserControlParser)
                                         throw new ParseException (Location, pe.Message, pe);
@@ -199,10 +233,8 @@ namespace System.Web.UI {
                         AddImport (ns);
                         Assembly ass = null;
                        
-                       if (assembly != null && assembly.Length > 0) {
+                       if (assembly != null && assembly.Length > 0)
                                ass = AddAssemblyByName (assembly);
-                               AddDependency (ass.Location);
-                       }
                        
                         RootBuilder.Foundry.RegisterFoundry (tagPrefix, ass, ns);
                 }
@@ -300,58 +332,63 @@ namespace System.Web.UI {
                                foreach (DictionaryEntry entry in atts) {
                                        string key = (string) entry.Key;
                                        switch (key.ToLower ()) {
-                                       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;
-                                       case "varybyparam":
-                                               oc_param = (string) entry.Value;
-                                               if (String.Compare (oc_param, "none") == 0)
-                                                       oc_param = null;
-                                               break;
-                                       case "varybyheader":
-                                               oc_header = (string) entry.Value;
-                                               break;
-                                       case "varybycustom":
-                                               oc_custom = (string) entry.Value;
-                                               break;
-                                       case "location":
-                                               if (!(this is PageParser))
-                                                       goto default;
+                                               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 "varybycontentencodings":
+                                                       oc_content_encodings = (string) entry.Value;
+                                                       break;
+#endif
+                                               case "varybyparam":
+                                                       oc_param = (string) entry.Value;
+                                                       if (String.Compare (oc_param, "none") == 0)
+                                                               oc_param = null;
+                                                       break;
+                                               case "varybyheader":
+                                                       oc_header = (string) entry.Value;
+                                                       break;
+                                               case "varybycustom":
+                                                       oc_custom = (string) entry.Value;
+                                                       break;
+                                               case "location":
+                                                       if (!(this is PageParser))
+                                                               goto default;
                                                
-                                               try {
-                                                       oc_location = (OutputCacheLocation) Enum.Parse (
-                                                               typeof (OutputCacheLocation), (string) entry.Value, true);
-                                               } catch {
-                                                       ThrowParseException ("The 'location' attribute is case sensitive and " +
-                                                                       "must be one of the following values: Any, Client, " +
-                                                                       "Downstream, Server, None, ServerAndClient.");
-                                               }
-                                               break;
-                                       case "varybycontrol":
+                                                       try {
+                                                               oc_location = (OutputCacheLocation) Enum.Parse (
+                                                                       typeof (OutputCacheLocation), (string) entry.Value, true);
+                                                       } catch {
+                                                               ThrowParseException ("The 'location' attribute is case sensitive and " +
+                                                                                    "must be one of the following values: Any, Client, " +
+                                                                                    "Downstream, Server, None, ServerAndClient.");
+                                                       }
+                                                       break;
+                                               case "varybycontrol":
 #if ONLY_1_1
-                                               if (this is PageParser)
-                                                       goto default;
+                                                       if (this is PageParser)
+                                                               goto default;
 #endif
-                                                oc_controls = (string) entry.Value;
-                                               break;
-                                       case "shared":
-                                               if (this is PageParser)
-                                                       goto default;
-
-                                               try {
-                                                       oc_shared = Boolean.Parse ((string) entry.Value);
-                                               } catch {
-                                                       ThrowParseException ("The 'shared' attribute is case sensitive" +
-                                                                       " and must be set to 'true' or 'false'.");
-                                               }
-                                               break;
-                                       default:
-                                               ThrowParseException ("The '" + key + "' attribute is not " +
-                                                               "supported by the 'Outputcache' directive.");
-                                               break;
+                                                       oc_controls = (string) entry.Value;
+                                                       break;
+                                               case "shared":
+                                                       if (this is PageParser)
+                                                               goto default;
+
+                                                       try {
+                                                               oc_shared = Boolean.Parse ((string) entry.Value);
+                                                       } catch {
+                                                               ThrowParseException ("The 'shared' attribute is case sensitive" +
+                                                                                    " and must be set to 'true' or 'false'.");
+                                                       }
+                                                       break;
+                                               default:
+                                                       ThrowParseException ("The '" + key + "' attribute is not " +
+                                                                            "supported by the 'Outputcache' directive.");
+                                                       break;
                                        }
                                        
                                }
@@ -370,7 +407,6 @@ namespace System.Web.UI {
                        Assembly asm = type.Assembly;
                        string location = asm.Location;
                        
-                       AddDependency (location);
                        string dirname = Path.GetDirectoryName (location);
                        bool doAddAssembly = true;
                        foreach (string dir in HttpApplication.BinDirectories) {
@@ -412,9 +448,8 @@ namespace System.Web.UI {
 
                internal virtual void AddSourceDependency (string filename)
                {
-                       if (dependencies != null && dependencies.Contains (filename)) {
+                       if (dependencies != null && dependencies.Contains (filename))
                                ThrowParseException ("Circular file references are not allowed. File: " + filename);
-                       }
 
                        AddDependency (filename);
                }
@@ -507,30 +542,37 @@ 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
-#if NET_2_0
-                       // these two are ignored for the moment
-                       atts.Remove ("Async");
-                       atts.Remove ("AsyncTimeOut");
-#endif
                        
-                       debug = GetBool (atts, "Debug", true);
+                       debug = GetBool (atts, "Debug", compConfig.Debug);
                        compilerOptions = GetString (atts, "CompilerOptions", "");
                        language = GetString (atts, "Language", "");
                        if (language.Length != 0)
                                implicitLanguage = false;
                        else
-                               language = CompilationConfig.DefaultLanguage;
+                               language = compConfig.DefaultLanguage;
                        
-                       strictOn = GetBool (atts, "Strict", CompilationConfig.Strict);
-                       explicitOn = GetBool (atts, "Explicit", CompilationConfig.Explicit);
+                       strictOn = GetBool (atts, "Strict", compConfig.Strict);
+                       explicitOn = GetBool (atts, "Explicit", compConfig.Explicit);
                        linePragmasOn = GetBool (atts, "LinePragmas", false);
                        
                        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
@@ -541,12 +583,31 @@ namespace System.Web.UI {
 
                        if (src == null && codeFileBaseClass != null)
                                ThrowParseException ("The 'CodeFileBaseClass' attribute cannot be used without a 'CodeFile' attribute");
+
+                       string legacySrc = GetString (atts, "Src", null);
+                       if (legacySrc != null) {
+                               legacySrc = UrlUtils.Combine (BaseVirtualDir, legacySrc);
+                               if (src == null) {
+                                       src = legacySrc;
+                                       legacySrc = MapPath (legacySrc, false);
+                                       srcRealPath = legacySrc;
+                                       if (!File.Exists (srcRealPath))
+                                               ThrowParseException ("File " + src + " not found");
+                                       
+                                       srcIsLegacy = true;
+                               } else 
+                                       legacySrc = MapPath (legacySrc, false);
+                               
+                               GetAssemblyFromSource (legacySrc);
+                               AddDependency (legacySrc);
+                       }
                        
-                       if (src != null && inherits != null) {
+                       if (!srcIsLegacy && src != null && inherits != null) {
                                // Make sure the source exists
                                src = UrlUtils.Combine (BaseVirtualDir, src);
-                               string realPath = MapPath (src, false);
-                               if (!File.Exists (realPath))
+                               srcRealPath = MapPath (src, false);
+                               
+                               if (!File.Exists (srcRealPath))
                                        ThrowParseException ("File " + src + " not found");
 
                                // We are going to create a partial class that shares
@@ -558,7 +619,7 @@ namespace System.Web.UI {
 
                                // Add the code file as an option to the
                                // compiler. This lets both files be compiled at once.
-                               compilerOptions += " \"" + realPath + "\"";
+                               compilerOptions += " \"" + srcRealPath + "\"";
 
                                if (codeFileBaseClass != null) {
                                        try {
@@ -577,12 +638,20 @@ namespace System.Web.UI {
 #else
                        string src = GetString (atts, "Src", null);
 
-                       if (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);
+                               AddDependency (src);
+                       }
+                       
                        className = GetString (atts, "ClassName", null);
                        if (className != null) {
 #if NET_2_0
@@ -698,9 +767,11 @@ namespace System.Web.UI {
                
                internal void SetBaseType (string type)
                {
-                       if (type == DefaultBaseTypeName)
+                       if (type == null || type == DefaultBaseTypeName) {
+                               baseType = DefaultBaseType;
                                return;
-
+                       }
+                       
                        Type parent = null;
                        if (srcAssembly != null)
                                parent = srcAssembly.GetType (type);
@@ -715,8 +786,6 @@ namespace System.Web.UI {
                                ThrowParseException ("The parent type does not derive from " + DefaultBaseType);
 
                        baseType = parent;
-                       if (parent.FullName.IndexOf ('.') == -1)
-                               baseTypeIsGlobal = true;
                }
 
                internal void SetLanguage (string language)
@@ -732,9 +801,9 @@ namespace System.Web.UI {
                        if (!File.Exists (realPath))
                                ThrowParseException ("File " + vpath + " not found");
 
-                       AddSourceDependency (realPath);
+                       AddSourceDependency (vpath);
 
-                       CompilerResults result = CachingCompiler.Compile (language, realPath, realPath, assemblies);
+                       CompilerResults result = CachingCompiler.Compile (language, realPath, realPath, assemblies, Debug);
                        if (result.NativeCompilerReturnValue != 0) {
                                StreamReader reader = new StreamReader (realPath);
                                throw new CompilationException (realPath, result.Errors, reader.ReadToEnd ());
@@ -742,12 +811,23 @@ namespace System.Web.UI {
 
                        AddAssembly (result.CompiledAssembly, true);
                        return result.CompiledAssembly;
-               }
-               
-               internal abstract Type DefaultBaseType { get; }
+               }               
+
                internal abstract string DefaultBaseTypeName { get; }
                internal abstract string DefaultDirectiveName { get; }
 
+               internal Type DefaultBaseType {
+                       get {
+                               Type type = Type.GetType (DefaultBaseTypeName, true);
+
+                               return type;
+                       }
+               }
+               
+               internal ILocation DirectiveLocation {
+                       get { return directiveLocation; }
+               }
+               
                internal string InputFile
                {
                        get { return inputFile; }
@@ -756,9 +836,13 @@ namespace System.Web.UI {
 
 #if NET_2_0
                internal bool IsPartial {
-                       get { return src != null; }
+                       get { return (!srcIsLegacy && src != null); }
                }
 
+               internal string CodeBehindSource {
+                       get { return src; }
+               }
+                       
                internal string PartialClassName {
                        get { return partialClassName; }
                }
@@ -782,24 +866,23 @@ namespace System.Web.UI {
                }
 #endif
 
-               internal string Text
-               {
+               internal string Text {
                        get { return text; }
                        set { text = value; }
                }
 
-               internal Type BaseType
-               {
+               internal Type BaseType {
                        get {
                                if (baseType == null)
-                                       baseType = DefaultBaseType;
-
+                                       SetBaseType (DefaultBaseTypeName);
+                               
                                return baseType;
                        }
                }
                
                internal bool BaseTypeIsGlobal {
                        get { return baseTypeIsGlobal; }
+                       set { baseTypeIsGlobal = value; }
                }
                
                internal string ClassName {
@@ -809,8 +892,24 @@ namespace System.Web.UI {
 
 #if NET_2_0
                                string physPath = HttpContext.Current.Request.PhysicalApplicationPath;
+                               string inFile;
                                
-                               if (StrUtils.StartsWith (inputFile, physPath)) {
+                               if (String.IsNullOrEmpty (inputFile)) {
+                                       inFile = null;
+                                       StreamReader sr = Reader as StreamReader;
+
+                                       if (sr != null) {
+                                               FileStream fr = sr.BaseStream as FileStream;
+                                               if (fr != null)
+                                                       inFile = fr.Name;
+                                       }
+                               } else
+                                       inFile = inputFile;
+
+                               if (String.IsNullOrEmpty (inFile))
+                                       throw new HttpException ("Unable to determine class name - no input file found.");
+                               
+                               if (StrUtils.StartsWith (inFile, physPath)) {
                                        className = inputFile.Substring (physPath.Length).ToLower (CultureInfo.InvariantCulture);
                                        className = className.Replace ('.', '_');
                                        className = className.Replace ('/', '_').Replace ('\\', '_');
@@ -900,6 +999,17 @@ namespace System.Web.UI {
                        get { return oc_duration; }
                }
 
+#if NET_2_0
+               internal string OutputCacheVaryByContentEncodings {
+                       get { return oc_content_encodings; }
+               }
+
+               internal virtual TextReader Reader {
+                       get { return null; }
+                       set { /* no-op */ }
+               }
+#endif
+               
                internal string OutputCacheVaryByHeader {
                        get { return oc_header; }
                }