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