2007-12-13 Marek Habersack <mhabersack@novell.com>
[mono.git] / mcs / class / System.Web / System.Web.Compilation / AppResourcesCompiler.cs
index daeba2effa598a285055e6e362f38fb37789eb43..690050c9e4fb777bf3b5833444468a9a7fe14dcd 100644 (file)
@@ -47,12 +47,14 @@ namespace System.Web.Compilation
        internal class AppResourcesCompiler
        {
                const string cachePrefix = "@@LocalResourcesAssemblies";
+               public const string DefaultCultureKey = ".:!DefaultCulture!:.";
                
                bool isGlobal;
                HttpContext context;
                AppResourceFilesCollection files;
                string tempDirectory;
                string virtualPath;
+               Dictionary <string, List <string>> cultureFiles;
                
                string TempDirectory {
                        get {
@@ -61,12 +63,17 @@ namespace System.Web.Compilation
                                return (tempDirectory = AppDomain.CurrentDomain.SetupInformation.DynamicBase);
                        }
                }
+
+               public Dictionary <string, List <string>> CultureFiles {
+                       get { return cultureFiles; }
+               }
                
                public AppResourcesCompiler (HttpContext context)
                {
                        this.context = context;
                        this.isGlobal = true;
                        this.files = new AppResourceFilesCollection (context);
+                       this.cultureFiles = new Dictionary <string, List <string>> ();
                }
 
                public AppResourcesCompiler (string virtualPath)
@@ -75,6 +82,7 @@ namespace System.Web.Compilation
                        this.virtualPath = virtualPath;
                        this.isGlobal = false;
                        this.files = new AppResourceFilesCollection (HttpContext.Current.Request.MapPath (virtualPath));
+                       this.cultureFiles = new Dictionary <string, List <string>> ();
                }
                
                public Assembly Compile ()
@@ -98,23 +106,10 @@ namespace System.Web.Compilation
                        if (assemblyPath == null)
                                throw new ApplicationException ("Failed to create global resources assembly");
                        
-                       CompilationSection config = WebConfigurationManager.GetSection ("system.web/compilation") as CompilationSection;
-                       if (config == null || !CodeDomProvider.IsDefinedLanguage (config.DefaultLanguage))
-                               throw new ApplicationException ("Could not get the default compiler.");
-                       CompilerInfo ci = CodeDomProvider.GetCompilerInfo (config.DefaultLanguage);
-                       if (ci == null || !ci.IsCodeDomProviderTypeValid)
-                               throw new ApplicationException ("Failed to obtain the default compiler information.");
-
-                       CompilerParameters cp = ci.CreateDefaultCompilerParameters ();
-                       cp.OutputAssembly = assemblyPath;
-                       cp.GenerateExecutable = false;
-                       cp.TreatWarningsAsErrors = true;
-                       cp.IncludeDebugInformation = config.Debug;
-                       
-                       List <string>[] fileGroups = GroupGlobalFiles (cp);
+                       List <string>[] fileGroups = GroupGlobalFiles ();
                        if (fileGroups == null || fileGroups.Length == 0)
                                return null;
-
+                       
                        CodeCompileUnit unit = new CodeCompileUnit ();
                        CodeNamespace ns = new CodeNamespace (null);
                        ns.Imports.Add (new CodeNamespaceImport ("System"));
@@ -123,36 +118,21 @@ namespace System.Web.Compilation
                        ns.Imports.Add (new CodeNamespaceImport ("System.Resources"));
                        unit.Namespaces.Add (ns);
 
-                       CodeDomProvider provider;
-                       provider = ci.CreateProvider ();
-                       if (provider == null)
-                               throw new ApplicationException ("Failed to instantiate the default compiler.");
+                       AppResourcesAssemblyBuilder builder = new AppResourcesAssemblyBuilder ("App_GlobalResources", assemblyPath,
+                                                                                              this);
+                       CodeDomProvider provider = builder.Provider;
                        
                        Dictionary <string,bool> assemblies = new Dictionary<string,bool> ();
                        foreach (List<string> ls in fileGroups)
                                DomFromResource (ls [0], unit, assemblies, provider);
+                       
                        foreach (KeyValuePair<string,bool> de in assemblies)
                                unit.ReferencedAssemblies.Add (de.Key);
                        
-                       AssemblyBuilder abuilder = new AssemblyBuilder (provider);
-                       abuilder.AddCodeCompileUnit (unit);
-
-                       CompilerResults results = abuilder.BuildAssembly (cp);
-                       Assembly ret = null;
+                       builder.Build (unit);
+                       HttpContext.AppGlobalResourcesAssembly = builder.MainAssembly;
                        
-                       if (results.Errors.Count == 0) {
-                               ret = results.CompiledAssembly;
-                               BuildManager.TopLevelAssemblies.Add (ret);
-                               HttpContext.AppGlobalResourcesAssembly = ret;
-                       } else {
-                               if (context.IsCustomErrorEnabled)
-                                       throw new ApplicationException ("An error occurred while compiling global resources.");
-                               throw new CompilationException (null, results.Errors, null);
-                       }
-                       HttpRuntime.WritePreservationFile (ret, "App_GlobalResources");
-                       HttpRuntime.EnableAssemblyMapping (true);
-
-                       return ret;
+                       return builder.MainAssembly;
                }
 
                Assembly CompileLocal ()
@@ -175,42 +155,19 @@ namespace System.Web.Compilation
                                                                             "dll",
                                                                             OnCreateRandomFile) as string;
                        if (assemblyPath == null)
-                               throw new ApplicationException ("Failed to create global resources assembly");
-                       
-                       CompilationSection config = WebConfigurationManager.GetSection ("system.web/compilation") as CompilationSection;
-                       if (config == null || !CodeDomProvider.IsDefinedLanguage (config.DefaultLanguage))
-                               throw new ApplicationException ("Could not get the default compiler.");
-                       CompilerInfo ci = CodeDomProvider.GetCompilerInfo (config.DefaultLanguage);
-                       if (ci == null || !ci.IsCodeDomProviderTypeValid)
-                               throw new ApplicationException ("Failed to obtain the default compiler information.");
-
-                       CompilerParameters cp = ci.CreateDefaultCompilerParameters ();
-                       cp.OutputAssembly = assemblyPath;
-                       cp.GenerateExecutable = false;
-                       cp.TreatWarningsAsErrors = true;
-                       cp.IncludeDebugInformation = config.Debug;
+                               throw new ApplicationException ("Failed to create local resources assembly");
 
                        List<AppResourceFileInfo> files = this.files.Files;
                        foreach (AppResourceFileInfo arfi in files)
-                               GetResourceFile (arfi, cp, true);
+                               GetResourceFile (arfi, true);
 
-                       CodeDomProvider provider;
-                       provider = ci.CreateProvider ();
-                       if (provider == null)
-                               throw new ApplicationException ("Failed to instantiate the default compiler.");
-                       
-                       AssemblyBuilder abuilder = new AssemblyBuilder (provider);
-                       CompilerResults results = abuilder.BuildAssembly (cp);
-                       Assembly ret = null;
+                       AppResourcesAssemblyBuilder builder = new AppResourcesAssemblyBuilder ("App_LocalResources", assemblyPath,
+                                                                                              this);
+                       builder.Build ();
+                       Assembly ret = builder.MainAssembly;
                        
-                       if (results.Errors.Count == 0) {
-                               ret = results.CompiledAssembly;
+                       if (ret != null)
                                AddAssemblyToCache (virtualPath, ret);
-                       } else {
-                               if (context.IsCustomErrorEnabled)
-                                       throw new ApplicationException ("An error occurred while compiling global resources.");
-                               throw new CompilationException (null, results.Errors, null);
-                       }
 
                        return ret;
                }
@@ -219,7 +176,7 @@ namespace System.Web.Compilation
                {
                        Dictionary <string, Assembly> cache;
 
-                       cache = HttpRuntime.Cache[cachePrefix] as Dictionary <string, Assembly>;
+                       cache = HttpRuntime.InternalCache[cachePrefix] as Dictionary <string, Assembly>;
                        if (cache == null || !cache.ContainsKey (path))
                                return null;
                        return cache [path];
@@ -227,7 +184,7 @@ namespace System.Web.Compilation
                
                void AddAssemblyToCache (string path, Assembly asm)
                {
-                       Cache runtimeCache = HttpRuntime.Cache;
+                       Cache runtimeCache = HttpRuntime.InternalCache;
                        Dictionary <string, Assembly> cache;
                        
                        cache = runtimeCache[cachePrefix] as Dictionary <string, Assembly>;
@@ -247,7 +204,7 @@ namespace System.Web.Compilation
                        return ret;
                }
 
-               bool IsFileCultureValid (string fileName)
+               string IsFileCultureValid (string fileName)
                 {
                     string tmp = Path.GetFileNameWithoutExtension (fileName);
                     tmp = Path.GetExtension (tmp);
@@ -255,27 +212,40 @@ namespace System.Web.Compilation
                               tmp = tmp.Substring (1);
                             try {
                                 CultureInfo.GetCultureInfo (tmp);
-                                return true;
+                                return tmp;
                             } catch {
-                                return false;
+                                return null;
                             }
                     } 
-                    return false;
+                    return null;
                 }
-
-               string GetResourceFile (AppResourceFileInfo arfi, CompilerParameters cp, bool local)
+               
+               string GetResourceFile (AppResourceFileInfo arfi, bool local)
                {
                        string resfile;
                        if (arfi.Kind == AppResourceFileKind.ResX)
                                resfile = CompileResource (arfi, local);
                        else
                                resfile = arfi.Info.FullName;
-                       if (!String.IsNullOrEmpty (resfile))
-                               cp.EmbeddedResources.Add (resfile);
+                       if (!String.IsNullOrEmpty (resfile)) {
+                               string culture = IsFileCultureValid (resfile);
+                               if (culture == null)
+                                       culture = DefaultCultureKey;
+                               
+                               List <string> cfiles;
+                               if (cultureFiles.ContainsKey (culture))
+                                       cfiles = cultureFiles [culture];
+                               else {
+                                       cfiles = new List <string> (1);
+                                       cultureFiles [culture] = cfiles;
+                               }
+                               cfiles.Add (resfile);
+                       }
+                               
                        return resfile;
                }
                
-               List <string>[] GroupGlobalFiles (CompilerParameters cp)
+               List <string>[] GroupGlobalFiles ()
                {
                        List<AppResourceFileInfo> files = this.files.Files;
                        List<List<string>> groups = new List<List<string>> ();
@@ -306,7 +276,7 @@ namespace System.Web.Compilation
                                        filedots = CountChars ('.', tmp);
 
                                        if (filedots == basedots + 1 && tmp.StartsWith (basename)) {
-                                               if (IsFileCultureValid (s2)) {
+                                               if (IsFileCultureValid (s2) != null) {
                                                        // A valid translated file for this name
                                                        defaultFile = arfi;
                                                        break;
@@ -321,7 +291,7 @@ namespace System.Web.Compilation
                                }
                                if (defaultFile != null) {
                                        List<string> al = new List<string> ();
-                                       al.Add (GetResourceFile (arfi, cp, false));
+                                       al.Add (GetResourceFile (arfi, false));
                                        arfi.Seen = true;
                                        groups.Add (al);
                                        
@@ -344,7 +314,7 @@ namespace System.Web.Compilation
                                                continue;
                                        tmp2 = arfi.Info.Name;
                                        if (tmp2.StartsWith (tmp)) {
-                                               al.Add (GetResourceFile (arfi, cp, false));
+                                               al.Add (GetResourceFile (arfi, false));
                                                arfi.Seen = true;
                                        }
                                }
@@ -360,12 +330,12 @@ namespace System.Web.Compilation
                                if (arfi.Seen)
                                        continue;
 
-                               if (IsFileCultureValid (arfi.Info.FullName))
+                               if (IsFileCultureValid (arfi.Info.FullName) != null)
                                        continue; // Culture found, we reject the file
 
                                // A single default file, create a group
                                List<string> al = new List<string> ();
-                               al.Add (GetResourceFile (arfi, cp, false));
+                               al.Add (GetResourceFile (arfi, false));
                                groups.Add (al);
                        }
                        groups.Sort (lcList);
@@ -389,7 +359,7 @@ namespace System.Web.Compilation
                                nsname = "Resources";
                        } else {
                                if (!nsname.StartsWith ("Resources", StringComparison.InvariantCulture))
-                                       nsname = String.Format ("Resources.{0}", nsname);
+                                       nsname = String.Concat ("Resources.", nsname);
                                classname = classname.Substring(1);
                        }
 
@@ -414,12 +384,12 @@ namespace System.Web.Compilation
                        cls.IsClass = true;
                        cls.TypeAttributes = TypeAttributes.Public | TypeAttributes.Sealed;
 
-                       CodeMemberField cmf = new CodeMemberField (typeof(CultureInfo), "culture");
+                       CodeMemberField cmf = new CodeMemberField (typeof(CultureInfo), "_culture");
                        cmf.InitExpression = new CodePrimitiveExpression (null);
                        cmf.Attributes = MemberAttributes.Private | MemberAttributes.Final | MemberAttributes.Static;
                        cls.Members.Add (cmf);
 
-                       cmf = new CodeMemberField (typeof(ResourceManager), "resourceManager");
+                       cmf = new CodeMemberField (typeof(ResourceManager), "_resourceManager");
                        cmf.InitExpression = new CodePrimitiveExpression (null);
                        cmf.Attributes = MemberAttributes.Private | MemberAttributes.Final | MemberAttributes.Static;
                        cls.Members.Add (cmf);
@@ -441,8 +411,8 @@ namespace System.Web.Compilation
                        cmp.HasGet = true;
                        cmp.HasSet = true;
                        cmp.Type = new CodeTypeReference (typeof(CultureInfo));
-                       CodePropertyGenericGet (cmp.GetStatements, "culture", classname);
-                       CodePropertyGenericSet (cmp.SetStatements, "culture", classname);
+                       CodePropertyGenericGet (cmp.GetStatements, "_culture", classname);
+                       CodePropertyGenericSet (cmp.SetStatements, "_culture", classname);
                        cls.Members.Add (cmp);
 
                        // Add the resource properties
@@ -498,7 +468,7 @@ namespace System.Web.Compilation
                        CodeStatement st;
                        CodeExpression exp;
 
-                       exp = new CodeFieldReferenceExpression (new CodeTypeReferenceExpression (typename), "resourceManager");
+                       exp = new CodeFieldReferenceExpression (new CodeTypeReferenceExpression (typename), "_resourceManager");
                        st = new CodeConditionStatement (
                                new CodeBinaryOperatorExpression (
                                        exp,
@@ -535,7 +505,7 @@ namespace System.Web.Compilation
                                gotstr ? "GetString" : "GetObject",
                                new CodeExpression [] { new CodePrimitiveExpression (resname),
                                                        new CodeFieldReferenceExpression (
-                                                               new CodeTypeReferenceExpression (typename), "culture") });
+                                                               new CodeTypeReferenceExpression (typename), "_culture") });
                        st = new CodeVariableDeclarationStatement (
                                restype,
                                "obj",