Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mcs / class / System.Web / System.Web.Compilation / ClientBuildManager.cs
1 //
2 // System.Web.Compilation.ClientBuildManager
3 //
4 // Authors:
5 //      Chris Toshok (toshok@ximian.com)
6 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 //
8 // (C) 2006-2009 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 using System;
33 using System.CodeDom;
34 using System.CodeDom.Compiler;
35 using System.ComponentModel;
36 using System.Collections;
37 using System.Globalization;
38 using System.IO;
39 using System.Web;
40 using System.Web.Hosting;
41 using System.Web.Util;
42
43 namespace System.Web.Compilation
44 {
45         public sealed class ClientBuildManager : MarshalByRefObject, IDisposable
46         {
47                 static readonly object appDomainShutdownEvent = new object ();
48                 static readonly object appDomainStartedEvent = new object ();
49                 static readonly object appDomainUnloadedEvent = new object ();
50                 
51                 string virt_dir;
52                 string phys_src_dir;
53                 //string phys_target_dir;
54                 //ClientBuildManagerParameter build_params;
55                 BareApplicationHost host;
56                 ApplicationManager manager;
57                 string app_id;
58                 string cache_path;
59
60                 EventHandlerList events = new EventHandlerList ();
61                 
62                 public event BuildManagerHostUnloadEventHandler AppDomainShutdown {
63                         add { events.AddHandler (appDomainShutdownEvent, value); }
64                         remove { events.RemoveHandler (appDomainShutdownEvent, value); }
65                 }
66                 
67                 public event EventHandler AppDomainStarted {
68                         add { events.AddHandler (appDomainStartedEvent, value); }
69                         remove { events.RemoveHandler (appDomainStartedEvent, value); }
70                 }
71                 
72                 public event BuildManagerHostUnloadEventHandler AppDomainUnloaded {
73                         add { events.AddHandler (appDomainUnloadedEvent, value); }
74                         remove { events.RemoveHandler (appDomainUnloadedEvent, value); }
75                 }
76
77                 public ClientBuildManager (string appVirtualDir, string appPhysicalSourceDir)
78                 {
79                         if (appVirtualDir == null || appVirtualDir == "")
80                                 throw new ArgumentNullException ("appVirtualDir");
81                         if (appPhysicalSourceDir == null || appPhysicalSourceDir == "")
82                                 throw new ArgumentNullException ("appPhysicalSourceDir");
83
84                         virt_dir = appVirtualDir; // TODO: adjust vpath (it allows 'blah' that turns into '/blah', '////blah', '\\blah'...
85                         phys_src_dir = appPhysicalSourceDir;
86                         manager = ApplicationManager.GetApplicationManager ();
87                 }
88
89                 public ClientBuildManager (string appVirtualDir, string appPhysicalSourceDir,
90                                            string appPhysicalTargetDir)
91                         : this (appVirtualDir, appPhysicalSourceDir)
92                 {
93                         if (appPhysicalTargetDir == null || appPhysicalTargetDir == "")
94                                 throw new ArgumentNullException ("appPhysicalTargetDir");
95
96                         //phys_target_dir = appPhysicalTargetDir;
97                 }
98
99                 public ClientBuildManager (string appVirtualDir, string appPhysicalSourceDir,
100                                         string appPhysicalTargetDir, ClientBuildManagerParameter parameter)
101                         : this (appVirtualDir, appPhysicalSourceDir, appPhysicalTargetDir)
102                 {
103                         //build_params = parameter;
104                 }
105
106                 BareApplicationHost Host {
107                         get {
108                                 if (host != null)
109                                         return host;
110
111                                 int hashcode = virt_dir.GetHashCode ();
112                                 if (app_id != null)
113                                         hashcode ^= Int32.Parse (app_id);
114
115                                 app_id = hashcode.ToString (Helpers.InvariantCulture);
116                                 host = manager.CreateHostWithCheck (app_id, virt_dir, phys_src_dir);
117                                 cache_path = "";
118                                 //cache_path = Path.Combine (Path.GetTempPath (),
119                                         //String.Format ("{0}-temp-aspnet-{1:x}", Environment.UserName, i));
120
121                                 int hash = virt_dir.GetHashCode () << 5 + phys_src_dir.GetHashCode ();
122                                 cache_path = Path.Combine (cache_path, hash.ToString (Helpers.InvariantCulture));
123                                 Directory.CreateDirectory (cache_path);
124                                 OnAppDomainStarted ();
125                                 return host;
126                         }
127                 }
128
129                 void OnAppDomainStarted ()
130                 {
131                         EventHandler eh = events [appDomainStartedEvent] as EventHandler;
132                         if (eh != null)
133                                 eh (this, EventArgs.Empty);
134                 }
135
136                 void OnAppDomainShutdown (ApplicationShutdownReason reason)
137                 {
138                         BuildManagerHostUnloadEventHandler eh = events [appDomainShutdownEvent] as BuildManagerHostUnloadEventHandler;
139                         if (eh != null) {
140                                 BuildManagerHostUnloadEventArgs args = new BuildManagerHostUnloadEventArgs (reason);
141                                 eh (this, args);
142                         }
143                 }
144
145 //              void OnDomainUnload (object sender, EventArgs args)
146 //              {
147 //                      OnAppDomainUnloaded (0); // FIXME: set a reason?
148 //              }
149 //
150 //              void OnAppDomainUnloaded (ApplicationShutdownReason reason)
151 //              {
152 //                      if (AppDomainUnloaded != null) {
153 //                              BuildManagerHostUnloadEventArgs args = new BuildManagerHostUnloadEventArgs (reason);
154 //                              AppDomainUnloaded (this, args);
155 //                      }
156 //              }
157
158                 [MonoTODO ("Not implemented")]
159                 public void CompileApplicationDependencies ()
160                 {
161                         throw new NotImplementedException ();
162                 }
163
164                 public void CompileFile (string virtualPath)
165                 {
166                         CompileFile (virtualPath, null);
167                 }
168
169                 [MonoTODO ("Not implemented")]
170                 public void CompileFile (string virtualPath, ClientBuildManagerCallback callback)
171                 {
172                         // 1. Creates the Host
173                         // This creates a .compiled file + an assembly
174                         // App_Code reported to be built *before* anything else (with progress callback)
175                         throw new NotImplementedException ();
176                 }
177
178                 public IRegisteredObject CreateObject (Type type, bool failIfExists)
179                 {
180                         return manager.CreateObject (app_id, type, virt_dir, phys_src_dir, failIfExists);
181                 }
182
183                 [MonoTODO("Currently does not return the GeneratedCode")]
184                 public string GenerateCode (string virtualPath, string virtualFileString, out IDictionary linePragmasTable)
185                 {
186                         // This thing generates a .ccu (CodeCompileUnit?) file (reported as TrueType font data by 'file'!)
187                         // resultType=7 vs. resultType=3 for assemblies reported in the .compiled file
188                         // The virtual path is just added to the dependencies list, but is checked to be an absolute path.
189                         // IsHostCreated returns true after calling this method.
190                         //
191                         // A null file string causes virtualPath to be mapped and read to generate the code
192                         //
193
194                         if (String.IsNullOrEmpty (virtualPath))
195                                 throw new ArgumentNullException ("virtualPath");
196
197                         Type cprovider_type;
198                         CompilerParameters parameters;
199                         GenerateCodeCompileUnit (virtualPath, virtualFileString, out cprovider_type,
200                                                  out parameters, out linePragmasTable);
201                         return null;
202                 }
203
204                 [MonoTODO ("Not implemented")]
205                 public CodeCompileUnit GenerateCodeCompileUnit (string virtualPath,
206                                                                 string virtualFileString,
207                                                                 out Type codeDomProviderType,
208                                                                 out CompilerParameters compilerParameters,
209                                                                 out IDictionary linePragmasTable)
210                 {
211                         throw new NotImplementedException ();
212                 }
213
214                 public CodeCompileUnit GenerateCodeCompileUnit (string virtualPath,
215                                                                 out Type codeDomProviderType,
216                                                                 out CompilerParameters compilerParameters,
217                                                                 out IDictionary linePragmasTable)
218                 {
219                         return GenerateCodeCompileUnit (virtualPath, out codeDomProviderType,
220                                                         out compilerParameters, out linePragmasTable);
221                 }
222
223                 static string [] shutdown_directories = new string [] {
224                                                 "bin", "App_GlobalResources", "App_Code",
225                                                 "App_WebReferences", "App_Browsers" };
226
227                 public string [] GetAppDomainShutdownDirectories ()
228                 {
229                         return shutdown_directories;
230                 }
231
232                 [MonoTODO ("Not implemented")]
233                 public IDictionary GetBrowserDefinitions ()
234                 {
235                         throw new NotImplementedException ();
236                 }
237
238                 [MonoTODO ("Not implemented")]
239                 public void GetCodeDirectoryInformation (string virtualCodeDir,
240                                                         out Type codeDomProviderType,
241                                                         out CompilerParameters compilerParameters,
242                                                         out string generatedFilesDir)
243                 {
244                         throw new NotImplementedException ();
245                 }
246
247                 [MonoTODO ("Not implemented")]
248                 public Type GetCompiledType (string virtualPath)
249                 {
250                         // CompileFile + get the type based on .compiled file information
251                         // Throws if virtualPath is a special virtual directory (App_Code et al)
252                         throw new NotImplementedException ();
253                 }
254
255                 [MonoTODO ("Not implemented")]
256                 public void GetCompilerParameters (string virtualPath,
257                                                 out Type codeDomProviderType,
258                                                 out CompilerParameters compilerParameters)
259                 {
260                         throw new NotImplementedException ();
261                 }
262
263                 [MonoTODO ("Not implemented")]
264                 public string GetGeneratedFileVirtualPath (string filePath)
265                 {
266                         // returns empty string for any vpath. Test with real paths.
267                         throw new NotImplementedException ();
268                 }
269
270                 [MonoTODO ("Not implemented")]
271                 public string GetGeneratedSourceFile (string virtualPath)
272                 {
273                         // This one takes a directory name /xxx and /xxx/App_Code throw either
274                         // a KeyNotFoundException or an InvalidOperationException
275                         throw new NotImplementedException ();
276                 }
277
278                 [MonoTODO ("Not implemented")]
279                 public string [] GetTopLevelAssemblyReferences (string virtualPath)
280                 {
281                         throw new NotImplementedException ();
282                 }
283
284                 public string [] GetVirtualCodeDirectories ()
285                 {
286                         // Host is created here when needed. (Unload()+GetVirtualCodeDirectories()+IsHostCreated -> true)
287                         //return Host.
288                         throw new NotImplementedException ();
289                 }
290
291                 public override object InitializeLifetimeService ()
292                 {
293                         return null;
294                 }
295
296                 [MonoTODO ("Not implemented")]
297                 public bool IsCodeAssembly (string assemblyName)
298                 {
299                         // Trying all the assemblies loaded by FullName and GetName().Name yield false here :-?
300                         throw new NotImplementedException ();
301                 }
302
303                 [MonoTODO ("Not implemented")]
304                 public void PrecompileApplication ()
305                 {
306                         throw new NotImplementedException ();
307                 }
308
309                 [MonoTODO ("Not implemented")]
310                 public void PrecompileApplication (ClientBuildManagerCallback callback)
311                 {
312                         throw new NotImplementedException ();
313                 }
314
315                 [MonoTODO ("Not implemented")]
316                 public void PrecompileApplication (ClientBuildManagerCallback callback, bool forceCleanBuild)
317                 {
318                         throw new NotImplementedException ();
319                 }
320
321                 public bool Unload ()
322                 {
323                         if (host != null) {
324                                 host.Shutdown ();
325                                 OnAppDomainShutdown (0);
326                                 host = null;
327                         }
328
329                         return true; // FIXME: may be we should do this synch. + timeout? Test!
330                 }
331
332                 public string CodeGenDir {
333                         get { return Host.GetCodeGenDir (); }
334                 }
335
336                 public bool IsHostCreated {
337                         get { return host != null; }
338                 }
339
340                 void IDisposable.Dispose ()
341                 {
342                         Unload ();
343                 }
344         }
345
346 }
347
348