merge -r 53370:58178
[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 // (c) Copyright Novell, Inc. (http://www.novell.com)
9 //
10
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31 using System;
32 using System.CodeDom.Compiler;
33 using System.Collections;
34 using System.Collections.Specialized;
35 using System.IO;
36 using System.Reflection;
37 using System.Web.UI;
38 using System.Web.Caching;
39 using System.Web.Configuration;
40
41 namespace System.Web.Compilation
42 {
43         class CachingCompiler
44         {
45                 static string dynamicBase = AppDomain.CurrentDomain.SetupInformation.DynamicBase;
46                 static object compilationLock = new object ();
47                 const string cachePrefix = "@@Assembly";
48                 const string cacheTypePrefix = "@@@Type";
49
50                 public static void InsertTypeFileDep (Type type, string filename)
51                 {
52                         CacheDependency dep = new CacheDependency (filename);
53                         HttpRuntime.Cache.InsertPrivate (cacheTypePrefix + filename, type, dep);
54                 }
55
56                 public static void InsertType (Type type, string filename)
57                 {
58                         string [] cacheKeys = new string [] { cachePrefix + filename };
59                         CacheDependency dep = new CacheDependency (null, cacheKeys);
60                         HttpRuntime.Cache.InsertPrivate (cacheTypePrefix + filename, type, dep);
61                 }
62
63                 public static Type GetTypeFromCache (string filename)
64                 {
65                         return (Type) HttpRuntime.Cache [cacheTypePrefix + filename];
66                 }
67
68                 public static CompilerResults Compile (BaseCompiler compiler)
69                 {
70                         Cache cache = HttpRuntime.Cache;
71                         string key = cachePrefix + compiler.Parser.InputFile;
72                         CompilerResults results = (CompilerResults) cache [key];
73                         if (results != null)
74                                 return results;
75
76                         lock (compilationLock) {
77                                 results = (CompilerResults) cache [key];
78                                 if (results != null)
79                                         return results;
80
81                                 ICodeCompiler comp = compiler.Compiler;
82                                 results = comp.CompileAssemblyFromDom (compiler.CompilerParameters, compiler.Unit);
83                                 string [] deps = (string []) compiler.Parser.Dependencies.ToArray (typeof (string));
84                                 cache.InsertPrivate (key, results, new CacheDependency (deps));
85                         }
86
87                         return results;
88                 }
89
90                 public static CompilerResults Compile (WebServiceCompiler compiler)
91                 {
92                         string key = cachePrefix + compiler.Parser.PhysicalPath;
93                         Cache cache = HttpRuntime.Cache;
94                         CompilerResults results = (CompilerResults) cache [key];
95                         if (results != null)
96                                 return results;
97
98                         lock (compilationLock) {
99                                 results = (CompilerResults) cache [key];
100                                 if (results != null)
101                                         return results;
102
103                                 SimpleWebHandlerParser parser = compiler.Parser;
104                                 CompilerParameters options = compiler.CompilerOptions;
105                                 options.IncludeDebugInformation = parser.Debug;
106                                 results = compiler.Compiler.CompileAssemblyFromFile (options, compiler.InputFile);
107                                 string [] deps = (string []) parser.Dependencies.ToArray (typeof (string));
108                                 cache.InsertPrivate (key, results, new CacheDependency (deps));
109                         }
110
111                         return results;
112                 }
113
114                 internal static CompilerParameters GetOptions (ICollection assemblies)
115                 {
116                         CompilerParameters options = new CompilerParameters ();
117                         if (assemblies != null) {
118                                 StringCollection coll = options.ReferencedAssemblies;
119                                 foreach (string str in assemblies)
120                                         coll.Add (str);
121                         }
122
123                         return options;
124                 }
125
126                 public static CompilerResults Compile (string language, string key, string file,
127                                                         ArrayList assemblies)
128                 {
129                         Cache cache = HttpRuntime.Cache;
130                         CompilerResults results = (CompilerResults) cache [cachePrefix + key];
131                         if (results != null)
132                                 return results;
133
134                         if (!Directory.Exists (dynamicBase))
135                                 Directory.CreateDirectory (dynamicBase);
136
137                         lock (compilationLock) {
138                                 results = (CompilerResults) cache [cachePrefix + key];
139                                 if (results != null)
140                                         return results;
141  
142                                 CompilationConfiguration config;
143                                 config = CompilationConfiguration.GetInstance (HttpContext.Current);
144                                 CodeDomProvider provider = config.GetProvider (language);
145                                 if (provider == null)
146                                         throw new HttpException ("Configuration error. Language not supported: " +
147                                                                   language, 500);
148
149                                 ICodeCompiler compiler = provider.CreateCompiler ();
150                                 CompilerParameters options = GetOptions (assemblies);
151                                 TempFileCollection tempcoll = new TempFileCollection (config.TempDirectory, true);
152                                 string dllfilename = Path.GetFileName (tempcoll.AddExtension ("dll", true));
153                                 options.OutputAssembly = Path.Combine (dynamicBase, dllfilename);
154                                 results = compiler.CompileAssemblyFromFile (options, file);
155                                 ArrayList realdeps = new ArrayList (assemblies.Count + 1);
156                                 realdeps.Add (file);
157                                 for (int i = assemblies.Count - 1; i >= 0; i--) {
158                                         string current = (string) assemblies [i];
159                                         if (Path.IsPathRooted (current))
160                                                 realdeps.Add (current);
161                                 }
162
163                                 string [] deps = (string []) realdeps.ToArray (typeof (string));
164                                 cache.InsertPrivate (cachePrefix + key, results, new CacheDependency (deps));
165                         }
166
167                         return results;
168                 }
169
170                 public static Type CompileAndGetType (string typename, string language, string key,
171                                                 string file, ArrayList assemblies)
172                 {
173                         CompilerResults result = CachingCompiler.Compile (language, key, file, assemblies);
174                         if (result.NativeCompilerReturnValue != 0) {
175                                 StreamReader reader = new StreamReader (file);
176                                 throw new CompilationException (file, result.Errors, reader.ReadToEnd ());
177                         }
178
179                         Assembly assembly = result.CompiledAssembly;
180                         if (assembly == null) {
181                                 StreamReader reader = new StreamReader (file);
182                                 throw new CompilationException (file, result.Errors, reader.ReadToEnd ());
183                         }
184                 
185                         Type type = assembly.GetType (typename, true);
186                         InsertType (type, file);
187                         return type;
188                 }
189         }
190 }
191