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