a575963da9
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
349 lines
11 KiB
C#
349 lines
11 KiB
C#
//
|
|
// System.Web.Compilation.ClientBuildManager
|
|
//
|
|
// Authors:
|
|
// Chris Toshok (toshok@ximian.com)
|
|
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
|
|
//
|
|
// (C) 2006-2009 Novell, Inc (http://www.novell.com)
|
|
//
|
|
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining
|
|
// a copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
|
// permit persons to whom the Software is furnished to do so, subject to
|
|
// the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be
|
|
// included in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
//
|
|
|
|
using System;
|
|
using System.CodeDom;
|
|
using System.CodeDom.Compiler;
|
|
using System.ComponentModel;
|
|
using System.Collections;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Web;
|
|
using System.Web.Hosting;
|
|
using System.Web.Util;
|
|
|
|
namespace System.Web.Compilation
|
|
{
|
|
public sealed class ClientBuildManager : MarshalByRefObject, IDisposable
|
|
{
|
|
static readonly object appDomainShutdownEvent = new object ();
|
|
static readonly object appDomainStartedEvent = new object ();
|
|
static readonly object appDomainUnloadedEvent = new object ();
|
|
|
|
string virt_dir;
|
|
string phys_src_dir;
|
|
//string phys_target_dir;
|
|
//ClientBuildManagerParameter build_params;
|
|
BareApplicationHost host;
|
|
ApplicationManager manager;
|
|
string app_id;
|
|
string cache_path;
|
|
|
|
EventHandlerList events = new EventHandlerList ();
|
|
|
|
public event BuildManagerHostUnloadEventHandler AppDomainShutdown {
|
|
add { events.AddHandler (appDomainShutdownEvent, value); }
|
|
remove { events.RemoveHandler (appDomainShutdownEvent, value); }
|
|
}
|
|
|
|
public event EventHandler AppDomainStarted {
|
|
add { events.AddHandler (appDomainStartedEvent, value); }
|
|
remove { events.RemoveHandler (appDomainStartedEvent, value); }
|
|
}
|
|
|
|
public event BuildManagerHostUnloadEventHandler AppDomainUnloaded {
|
|
add { events.AddHandler (appDomainUnloadedEvent, value); }
|
|
remove { events.RemoveHandler (appDomainUnloadedEvent, value); }
|
|
}
|
|
|
|
public ClientBuildManager (string appVirtualDir, string appPhysicalSourceDir)
|
|
{
|
|
if (appVirtualDir == null || appVirtualDir == "")
|
|
throw new ArgumentNullException ("appVirtualDir");
|
|
if (appPhysicalSourceDir == null || appPhysicalSourceDir == "")
|
|
throw new ArgumentNullException ("appPhysicalSourceDir");
|
|
|
|
virt_dir = appVirtualDir; // TODO: adjust vpath (it allows 'blah' that turns into '/blah', '////blah', '\\blah'...
|
|
phys_src_dir = appPhysicalSourceDir;
|
|
manager = ApplicationManager.GetApplicationManager ();
|
|
}
|
|
|
|
public ClientBuildManager (string appVirtualDir, string appPhysicalSourceDir,
|
|
string appPhysicalTargetDir)
|
|
: this (appVirtualDir, appPhysicalSourceDir)
|
|
{
|
|
if (appPhysicalTargetDir == null || appPhysicalTargetDir == "")
|
|
throw new ArgumentNullException ("appPhysicalTargetDir");
|
|
|
|
//phys_target_dir = appPhysicalTargetDir;
|
|
}
|
|
|
|
public ClientBuildManager (string appVirtualDir, string appPhysicalSourceDir,
|
|
string appPhysicalTargetDir, ClientBuildManagerParameter parameter)
|
|
: this (appVirtualDir, appPhysicalSourceDir, appPhysicalTargetDir)
|
|
{
|
|
//build_params = parameter;
|
|
}
|
|
|
|
BareApplicationHost Host {
|
|
get {
|
|
if (host != null)
|
|
return host;
|
|
|
|
int hashcode = virt_dir.GetHashCode ();
|
|
if (app_id != null)
|
|
hashcode ^= Int32.Parse (app_id);
|
|
|
|
app_id = hashcode.ToString (Helpers.InvariantCulture);
|
|
host = manager.CreateHostWithCheck (app_id, virt_dir, phys_src_dir);
|
|
cache_path = "";
|
|
//cache_path = Path.Combine (Path.GetTempPath (),
|
|
//String.Format ("{0}-temp-aspnet-{1:x}", Environment.UserName, i));
|
|
|
|
int hash = virt_dir.GetHashCode () << 5 + phys_src_dir.GetHashCode ();
|
|
cache_path = Path.Combine (cache_path, hash.ToString (Helpers.InvariantCulture));
|
|
Directory.CreateDirectory (cache_path);
|
|
OnAppDomainStarted ();
|
|
return host;
|
|
}
|
|
}
|
|
|
|
void OnAppDomainStarted ()
|
|
{
|
|
EventHandler eh = events [appDomainStartedEvent] as EventHandler;
|
|
if (eh != null)
|
|
eh (this, EventArgs.Empty);
|
|
}
|
|
|
|
void OnAppDomainShutdown (ApplicationShutdownReason reason)
|
|
{
|
|
BuildManagerHostUnloadEventHandler eh = events [appDomainShutdownEvent] as BuildManagerHostUnloadEventHandler;
|
|
if (eh != null) {
|
|
BuildManagerHostUnloadEventArgs args = new BuildManagerHostUnloadEventArgs (reason);
|
|
eh (this, args);
|
|
}
|
|
}
|
|
|
|
// void OnDomainUnload (object sender, EventArgs args)
|
|
// {
|
|
// OnAppDomainUnloaded (0); // FIXME: set a reason?
|
|
// }
|
|
//
|
|
// void OnAppDomainUnloaded (ApplicationShutdownReason reason)
|
|
// {
|
|
// if (AppDomainUnloaded != null) {
|
|
// BuildManagerHostUnloadEventArgs args = new BuildManagerHostUnloadEventArgs (reason);
|
|
// AppDomainUnloaded (this, args);
|
|
// }
|
|
// }
|
|
|
|
[MonoTODO ("Not implemented")]
|
|
public void CompileApplicationDependencies ()
|
|
{
|
|
throw new NotImplementedException ();
|
|
}
|
|
|
|
public void CompileFile (string virtualPath)
|
|
{
|
|
CompileFile (virtualPath, null);
|
|
}
|
|
|
|
[MonoTODO ("Not implemented")]
|
|
public void CompileFile (string virtualPath, ClientBuildManagerCallback callback)
|
|
{
|
|
// 1. Creates the Host
|
|
// This creates a .compiled file + an assembly
|
|
// App_Code reported to be built *before* anything else (with progress callback)
|
|
throw new NotImplementedException ();
|
|
}
|
|
|
|
public IRegisteredObject CreateObject (Type type, bool failIfExists)
|
|
{
|
|
return manager.CreateObject (app_id, type, virt_dir, phys_src_dir, failIfExists);
|
|
}
|
|
|
|
[MonoTODO("Currently does not return the GeneratedCode")]
|
|
public string GenerateCode (string virtualPath, string virtualFileString, out IDictionary linePragmasTable)
|
|
{
|
|
// This thing generates a .ccu (CodeCompileUnit?) file (reported as TrueType font data by 'file'!)
|
|
// resultType=7 vs. resultType=3 for assemblies reported in the .compiled file
|
|
// The virtual path is just added to the dependencies list, but is checked to be an absolute path.
|
|
// IsHostCreated returns true after calling this method.
|
|
//
|
|
// A null file string causes virtualPath to be mapped and read to generate the code
|
|
//
|
|
|
|
if (String.IsNullOrEmpty (virtualPath))
|
|
throw new ArgumentNullException ("virtualPath");
|
|
|
|
Type cprovider_type;
|
|
CompilerParameters parameters;
|
|
GenerateCodeCompileUnit (virtualPath, virtualFileString, out cprovider_type,
|
|
out parameters, out linePragmasTable);
|
|
return null;
|
|
}
|
|
|
|
[MonoTODO ("Not implemented")]
|
|
public CodeCompileUnit GenerateCodeCompileUnit (string virtualPath,
|
|
string virtualFileString,
|
|
out Type codeDomProviderType,
|
|
out CompilerParameters compilerParameters,
|
|
out IDictionary linePragmasTable)
|
|
{
|
|
throw new NotImplementedException ();
|
|
}
|
|
|
|
public CodeCompileUnit GenerateCodeCompileUnit (string virtualPath,
|
|
out Type codeDomProviderType,
|
|
out CompilerParameters compilerParameters,
|
|
out IDictionary linePragmasTable)
|
|
{
|
|
return GenerateCodeCompileUnit (virtualPath, out codeDomProviderType,
|
|
out compilerParameters, out linePragmasTable);
|
|
}
|
|
|
|
static string [] shutdown_directories = new string [] {
|
|
"bin", "App_GlobalResources", "App_Code",
|
|
"App_WebReferences", "App_Browsers" };
|
|
|
|
public string [] GetAppDomainShutdownDirectories ()
|
|
{
|
|
return shutdown_directories;
|
|
}
|
|
|
|
[MonoTODO ("Not implemented")]
|
|
public IDictionary GetBrowserDefinitions ()
|
|
{
|
|
throw new NotImplementedException ();
|
|
}
|
|
|
|
[MonoTODO ("Not implemented")]
|
|
public void GetCodeDirectoryInformation (string virtualCodeDir,
|
|
out Type codeDomProviderType,
|
|
out CompilerParameters compilerParameters,
|
|
out string generatedFilesDir)
|
|
{
|
|
throw new NotImplementedException ();
|
|
}
|
|
|
|
[MonoTODO ("Not implemented")]
|
|
public Type GetCompiledType (string virtualPath)
|
|
{
|
|
// CompileFile + get the type based on .compiled file information
|
|
// Throws if virtualPath is a special virtual directory (App_Code et al)
|
|
throw new NotImplementedException ();
|
|
}
|
|
|
|
[MonoTODO ("Not implemented")]
|
|
public void GetCompilerParameters (string virtualPath,
|
|
out Type codeDomProviderType,
|
|
out CompilerParameters compilerParameters)
|
|
{
|
|
throw new NotImplementedException ();
|
|
}
|
|
|
|
[MonoTODO ("Not implemented")]
|
|
public string GetGeneratedFileVirtualPath (string filePath)
|
|
{
|
|
// returns empty string for any vpath. Test with real paths.
|
|
throw new NotImplementedException ();
|
|
}
|
|
|
|
[MonoTODO ("Not implemented")]
|
|
public string GetGeneratedSourceFile (string virtualPath)
|
|
{
|
|
// This one takes a directory name /xxx and /xxx/App_Code throw either
|
|
// a KeyNotFoundException or an InvalidOperationException
|
|
throw new NotImplementedException ();
|
|
}
|
|
|
|
[MonoTODO ("Not implemented")]
|
|
public string [] GetTopLevelAssemblyReferences (string virtualPath)
|
|
{
|
|
throw new NotImplementedException ();
|
|
}
|
|
|
|
public string [] GetVirtualCodeDirectories ()
|
|
{
|
|
// Host is created here when needed. (Unload()+GetVirtualCodeDirectories()+IsHostCreated -> true)
|
|
//return Host.
|
|
throw new NotImplementedException ();
|
|
}
|
|
|
|
public override object InitializeLifetimeService ()
|
|
{
|
|
return null;
|
|
}
|
|
|
|
[MonoTODO ("Not implemented")]
|
|
public bool IsCodeAssembly (string assemblyName)
|
|
{
|
|
// Trying all the assemblies loaded by FullName and GetName().Name yield false here :-?
|
|
throw new NotImplementedException ();
|
|
}
|
|
|
|
[MonoTODO ("Not implemented")]
|
|
public void PrecompileApplication ()
|
|
{
|
|
throw new NotImplementedException ();
|
|
}
|
|
|
|
[MonoTODO ("Not implemented")]
|
|
public void PrecompileApplication (ClientBuildManagerCallback callback)
|
|
{
|
|
throw new NotImplementedException ();
|
|
}
|
|
|
|
[MonoTODO ("Not implemented")]
|
|
public void PrecompileApplication (ClientBuildManagerCallback callback, bool forceCleanBuild)
|
|
{
|
|
throw new NotImplementedException ();
|
|
}
|
|
|
|
public bool Unload ()
|
|
{
|
|
if (host != null) {
|
|
host.Shutdown ();
|
|
OnAppDomainShutdown (0);
|
|
host = null;
|
|
}
|
|
|
|
return true; // FIXME: may be we should do this synch. + timeout? Test!
|
|
}
|
|
|
|
public string CodeGenDir {
|
|
get { return Host.GetCodeGenDir (); }
|
|
}
|
|
|
|
public bool IsHostCreated {
|
|
get { return host != null; }
|
|
}
|
|
|
|
void IDisposable.Dispose ()
|
|
{
|
|
Unload ();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|