2007-11-06 Marek Habersack <mhabersack@novell.com>
[mono.git] / mcs / class / System.Web / System.Web.Compilation / BuildManager.cs
1 //
2 // System.Web.Compilation.BuildManager
3 //
4 // Authors:
5 //      Chris Toshok (toshok@ximian.com)
6 //      Gonzalo Paniagua Javier (gonzalo@novell.com)
7 //
8 // (C) 2006 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
32 #if NET_2_0
33
34 using System;
35 using System.CodeDom;
36 using System.CodeDom.Compiler;
37 using System.Collections;
38 using System.Collections.Generic;
39 using System.IO;
40 using System.Reflection;
41 using System.Web;
42 using System.Web.Configuration;
43 using System.Web.Hosting;
44
45 namespace System.Web.Compilation {
46         public sealed class BuildManager {
47                 private static List<Assembly> AppCode_Assemblies = new List<Assembly>();
48                 private static List<Assembly> TopLevel_Assemblies = new List<Assembly>();
49                 private static bool haveResources;
50                 
51                 internal BuildManager ()
52                 {
53                 }
54
55                 internal static void ThrowNoProviderException (string extension)
56                 {
57                         string msg = "No registered provider for extension '{0}'.";
58                         throw new HttpException (String.Format (msg, extension));
59                 }
60
61                 public static object CreateInstanceFromVirtualPath (string virtualPath, Type requiredBaseType)
62                 {
63                         // virtualPath + Exists done in GetCompiledType()
64                         if (requiredBaseType == null)
65                                 throw new NullReferenceException (); // This is what MS does, but from somewhere else.
66
67                         // Get the Type.
68                         Type type = GetCompiledType (virtualPath);
69                         if (!requiredBaseType.IsAssignableFrom (type)) {
70                                 string msg = String.Format ("Type '{0}' does not inherit from '{1}'.",
71                                                                 type.FullName, requiredBaseType.FullName);
72                                 throw new HttpException (500, msg);
73                         }
74
75                         return Activator.CreateInstance (type, null);
76                 }
77
78                 [MonoTODO ("Not implemented, always returns null")]
79                 public static BuildDependencySet GetCachedBuildDependencySet (HttpContext context, string virtualPath)
80                 {
81                         return null; // null is ok here until we store the dependency set in the Cache.
82                 }
83
84                 internal static BuildProvider GetBuildProviderForPath (string virtualPath, bool throwOnMissing)
85                 {
86                         string extension = VirtualPathUtility.GetExtension (virtualPath);
87                         CompilationSection c = WebConfigurationManager.GetSection ("system.web/compilation", virtualPath) as CompilationSection;
88                         if (c == null)
89                                 ThrowNoProviderException (extension);
90                         
91                         BuildProviderCollection coll = c.BuildProviders;
92                         if (coll == null || coll.Count == 0)
93                                 ThrowNoProviderException (extension);
94                         
95                         BuildProvider provider = coll.GetProviderForExtension (extension);
96                         if (provider == null && throwOnMissing)
97                                 ThrowNoProviderException (extension);
98
99                         return provider;
100                 }
101                 
102                 public static Assembly GetCompiledAssembly (string virtualPath)
103                 {
104                         BuildProvider provider;
105                         CompilerParameters parameters;
106
107                         AssemblyBuilder abuilder = GetAssemblyBuilder (virtualPath, out provider);
108                         CompilerType ctype = provider.CodeCompilerType;
109                         parameters = PrepareParameters (abuilder.TempFiles, virtualPath, ctype.CompilerParameters);
110                         CompilerResults results = abuilder.BuildAssembly (virtualPath, parameters);
111                         return results.CompiledAssembly;
112                 }
113
114                 static AssemblyBuilder GetAssemblyBuilder (string virtualPath, out BuildProvider provider)
115                 {
116                         if (virtualPath == null || virtualPath == "")
117                                 throw new ArgumentNullException ("virtualPath");
118
119                         if (virtualPath [0] != '/')
120                                 throw new ArgumentException ("The virtual path is not rooted", "virtualPath");
121
122                         if (!HostingEnvironment.VirtualPathProvider.FileExists (virtualPath))
123                                 throw new HttpException (String.Format ("The file '{0}' does not exist.", virtualPath));
124                         provider = GetBuildProviderForPath (virtualPath, true);
125                         CompilerType compiler_type = provider.CodeCompilerType;
126                         Type ctype = compiler_type.CodeDomProviderType;
127                         CodeDomProvider dom_provider = (CodeDomProvider) Activator.CreateInstance (ctype, null);
128
129                         AssemblyBuilder abuilder = new AssemblyBuilder (virtualPath, dom_provider);
130                         provider.SetVirtualPath (virtualPath);
131                         provider.GenerateCode (abuilder);
132                         return abuilder;
133                 }
134
135                 public static string GetCompiledCustomString (string virtualPath)
136                 {
137                         BuildProvider provider = GetBuildProviderForPath (virtualPath, false);
138                         if (provider == null)
139                                 return null;
140                         // FIXME: where to get the CompilerResults from?
141                         return provider.GetCustomString (null);
142                 }
143
144                 static CompilerParameters PrepareParameters (TempFileCollection temp_files,
145                                                                 string virtualPath,
146                                                                 CompilerParameters base_params)
147                 {
148                         CompilerParameters res = new CompilerParameters ();
149                         res.TempFiles = temp_files;
150                         res.CompilerOptions = base_params.CompilerOptions;
151                         res.IncludeDebugInformation = base_params.IncludeDebugInformation;
152                         res.TreatWarningsAsErrors = base_params.TreatWarningsAsErrors;
153                         res.WarningLevel = base_params.WarningLevel;
154                         string dllfilename = Path.GetFileName (temp_files.AddExtension ("dll", true));
155                         res.OutputAssembly = Path.Combine (temp_files.TempDir, dllfilename);
156                         return res;
157                 }
158
159                 public static Type GetCompiledType (string virtualPath)
160                 {
161                         BuildProvider provider;
162                         CompilerParameters parameters;
163
164                         AssemblyBuilder abuilder = GetAssemblyBuilder (virtualPath, out provider);
165                         CompilerType ctype = provider.CodeCompilerType;
166                         parameters = PrepareParameters (abuilder.TempFiles, virtualPath, ctype.CompilerParameters);
167                         CompilerResults results = abuilder.BuildAssembly (virtualPath, parameters);
168                         return provider.GetGeneratedType (results);
169                 }
170
171                 // The 2 GetType() overloads work on the global.asax, App_GlobalResources, App_WebReferences or App_Browsers
172                 public static Type GetType (string typeName, bool throwOnError)
173                 {
174                         return GetType (typeName, throwOnError, false);
175                 }
176
177                 public static Type GetType (string typeName, bool throwOnError, bool ignoreCase)
178                 {
179                         Type ret = null;
180                         try {
181                                 foreach (Assembly asm in TopLevel_Assemblies) {
182                                         ret = asm.GetType (typeName, throwOnError, ignoreCase);
183                                         if (ret != null)
184                                                 break;
185                                 }
186                         } catch (Exception ex) {
187                                 throw new HttpException ("Failed to find the specified type.", ex);
188                         }
189                         return ret;
190                 }
191
192                 internal static ICollection GetVirtualPathDependencies (string virtualPath, BuildProvider bprovider)
193                 {
194                         BuildProvider provider = bprovider;
195                         if (provider == null)
196                                 provider = GetBuildProviderForPath (virtualPath, false);
197                         if (provider == null)
198                                 return null;
199                         return provider.VirtualPathDependencies;
200                 }
201                 
202                 public static ICollection GetVirtualPathDependencies (string virtualPath)
203                 {
204                         return GetVirtualPathDependencies (virtualPath, null);
205                 }
206
207                 // Assemblies built from the App_Code directory
208                 public static IList CodeAssemblies {
209                         get { return AppCode_Assemblies; }
210                 }
211
212                 internal static IList TopLevelAssemblies {
213                         get { return TopLevel_Assemblies; }
214                 }
215
216                 internal static bool HaveResources {
217                         get { return haveResources; }
218                         set { haveResources = value; }
219                 }
220         }
221 }
222
223 #endif
224