2003-10-14 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono.git] / mcs / class / System.Web / System.Web.Compilation / CachingCompiler.cs
1 //
2 // System.Web.Compilation.CachingCompiler
3 //
4 // Authors:
5 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
6 //
7 // (C) 2002 Ximian, Inc (http://www.ximian.com)
8 //
9 using System;
10 using System.CodeDom;
11 using System.CodeDom.Compiler;
12 using System.Collections;
13 using System.Collections.Specialized;
14 using System.IO;
15 using System.Web.UI;
16
17 namespace System.Web.Compilation
18 {
19         //TODO: caching should be done using System.Web.Caching, but that namespace still need some work.
20         internal class CompilationCacheItem
21         {
22                 CompilerResults result;
23                 ArrayList dependencies;
24                 DateTime reference;
25
26                 public CompilationCacheItem (CompilerResults result, ArrayList dependencies)
27                 {
28                         this.result = result;
29                         this.dependencies = dependencies;
30                         this.reference = DateTime.Now;
31                 }
32
33                 public CompilationCacheItem (CompilerResults result, string file)
34                 {
35                         this.result = result;
36                         this.dependencies = new ArrayList (1);
37                         dependencies.Add (file);
38                         this.reference = DateTime.Now;
39                 }
40
41                 public bool CheckDependencies (string key)
42                 {
43                         if (dependencies == null)
44                                 return true; // Forever young
45
46                         foreach (string s in dependencies) {
47                                 if (!File.Exists (s) || File.GetLastWriteTime (s) > reference)
48                                         return false;
49                         }
50                         
51                         return true;
52                 }
53
54                 public CompilerResults Result {
55                         get { return result; }
56                 }
57         }
58
59         internal class CompilationCache
60         {
61                 static Hashtable cache;
62                 static CompilationCache instance = new CompilationCache ();
63                 
64                 private CompilationCache ()
65                 {
66                 }
67
68                 static CompilationCache ()
69                 {
70                         cache = new Hashtable ();
71                 }
72
73                 public static CompilationCache GetInstance ()
74                 {
75                         return instance;
76                 }
77
78                 public bool CheckDependencies (CompilationCacheItem item, string key)
79                 {
80                         bool result = item.CheckDependencies (key);
81                         if (result == false)
82                                 cache.Remove (key);
83
84                         return result;
85                 }
86
87                 public CompilationCacheItem this [string key] {
88                         get { return cache [key] as CompilationCacheItem; }
89                         set { cache [key] = value; }
90                 }
91         }
92         
93         internal class CachingCompiler
94         {
95                 static CompilationCache cache = CompilationCache.GetInstance ();
96
97                 private CachingCompiler () {}
98
99                 public static CompilationCacheItem GetCached (string key)
100                 {
101                         if (key == null)
102                                 throw new ArgumentNullException ("key");
103
104                         CompilationCacheItem item = cache [key];
105                         if (item != null && cache.CheckDependencies (item, key))
106                                 return item;
107
108                         return null;
109                 }
110
111                 static object compilationLock = new object ();
112                 public static CompilerResults Compile (BaseCompiler compiler)
113                 {
114                         string key = compiler.Parser.InputFile;
115                         CompilationCacheItem item = GetCached (key);
116                         if (item != null)
117                                 return item.Result;
118                         
119                         CompilerResults results = null;
120                         lock (compilationLock) {
121                                 item = GetCached (key);
122                                 if (item != null)
123                                         return item.Result;
124
125                                 results = compiler.Compiler.CompileAssemblyFromDom (compiler.CompilerParameters, compiler.Unit);
126                                 cache [key] = new CompilationCacheItem (results, compiler.Parser.Dependencies);
127                         }
128
129                         return results;
130                 }
131
132                 public static CompilerResults Compile (string key, string file, WebServiceCompiler compiler)
133                 {
134                         CompilationCacheItem item = GetCached (key);
135                         if (item != null)
136                                 return item.Result;
137                         
138                         CompilerResults results = null;
139                         lock (compilationLock) {
140                                 item = GetCached (key);
141                                 if (item != null)
142                                         return item.Result;
143
144                                 SimpleWebHandlerParser parser = compiler.Parser;
145                                 CompilerParameters options = GetOptions (parser.Assemblies);
146                                 options.IncludeDebugInformation = parser.Debug;
147                                 results = compiler.Compiler.CompileAssemblyFromFile (options, file);
148                                 cache [key] = new CompilationCacheItem (results, parser.Dependencies);
149                         }
150
151                         return results;
152                 }
153
154                 static CompilerParameters GetOptions (ICollection assemblies)
155                 {
156                         CompilerParameters options = new CompilerParameters ();
157                         if (assemblies != null) {
158                                 StringCollection coll = options.ReferencedAssemblies;
159                                 foreach (string str in assemblies)
160                                         coll.Add (str);
161                         }
162
163                         return options;
164                 }
165
166                 public static CompilerResults Compile (string key, string file, ArrayList assemblies)
167                 {
168                         CompilationCacheItem item = GetCached (key);
169                         if (item != null)
170                                 return item.Result;
171                         
172                         CompilerResults results = null;
173                         lock (compilationLock) {
174                                 item = GetCached (file);
175                                 if (item != null)
176                                         return item.Result;
177
178                                 CompilerParameters options = GetOptions (assemblies);
179                                 //TODO: support for other languages
180                                 results = CSCompiler.Compiler.CompileAssemblyFromFile (options, file);
181                                 cache [key] = new CompilationCacheItem (results, file);
182                         }
183
184                         return results;
185                 }
186         }
187 }
188