Update dependencies storage to store state of all loaded extensions

--HG--
branch : dev
This commit is contained in:
Renaud Paquay
2010-06-11 21:21:20 -07:00
parent 9b9efe02a2
commit 4ea580b54e
9 changed files with 158 additions and 58 deletions

View File

@@ -2,9 +2,19 @@
using System.Linq;
using System.Reflection;
using Orchard.Environment.Extensions.Models;
using Orchard.FileSystems.Dependencies;
using Orchard.FileSystems.VirtualPath;
namespace Orchard.Environment.Extensions.Loaders {
public class AreaExtensionLoader : IExtensionLoader {
private readonly IDependenciesFolder _dependenciesFolder;
private readonly IVirtualPathProvider _virtualPathProvider;
public AreaExtensionLoader(IDependenciesFolder dependenciesFolder, IVirtualPathProvider virtualPathProvider) {
_dependenciesFolder = dependenciesFolder;
_virtualPathProvider = virtualPathProvider;
}
public int Order { get { return 50; } }
public ExtensionProbeEntry Probe(ExtensionDescriptor descriptor) {
@@ -22,13 +32,21 @@ namespace Orchard.Environment.Extensions.Loaders {
public ExtensionEntry Load(ExtensionProbeEntry entry) {
if (entry.Loader == this) {
var assembly = Assembly.Load("Orchard.Web");
_dependenciesFolder.Store(new DependencyDescriptor { ModuleName = entry.Descriptor.Name, LoaderName = this.GetType().FullName});
return new ExtensionEntry {
Descriptor = entry.Descriptor,
Assembly = assembly,
ExportedTypes = assembly.GetExportedTypes().Where(x => IsTypeFromModule(x, entry.Descriptor))
};
}
return null;
else {
// If the extension is not loaded by us, there is no cached state
// we need to invalidate
_dependenciesFolder.Remove(entry.Descriptor.Name, this.GetType().FullName);
return null;
}
}
private static bool IsTypeFromModule(Type type, ExtensionDescriptor descriptor) {

View File

@@ -2,12 +2,22 @@
using System.Linq;
using System.Reflection;
using Orchard.Environment.Extensions.Models;
using Orchard.FileSystems.Dependencies;
using Orchard.FileSystems.VirtualPath;
namespace Orchard.Environment.Extensions.Loaders {
/// <summary>
/// Load an extension by looking into specific namespaces of the "Orchard.Core" assembly
/// </summary>
public class CoreExtensionLoader : IExtensionLoader {
private readonly IDependenciesFolder _dependenciesFolder;
private readonly IVirtualPathProvider _virtualPathProvider;
public CoreExtensionLoader(IDependenciesFolder dependenciesFolder, IVirtualPathProvider virtualPathProvider) {
_dependenciesFolder = dependenciesFolder;
_virtualPathProvider = virtualPathProvider;
}
public int Order { get { return 10; } }
public ExtensionProbeEntry Probe(ExtensionDescriptor descriptor) {
@@ -25,13 +35,21 @@ namespace Orchard.Environment.Extensions.Loaders {
public ExtensionEntry Load(ExtensionProbeEntry entry) {
if (entry.Loader == this) {
var assembly = Assembly.Load("Orchard.Core");
_dependenciesFolder.Store(new DependencyDescriptor { ModuleName = entry.Descriptor.Name, LoaderName = this.GetType().FullName });
return new ExtensionEntry {
Descriptor = entry.Descriptor,
Assembly = assembly,
ExportedTypes = assembly.GetExportedTypes().Where(x => IsTypeFromModule(x, entry.Descriptor))
};
}
return null;
else {
// If the extension is not loaded by us, there is no cached state
// we need to invalidate
_dependenciesFolder.Remove(entry.Descriptor.Name, this.GetType().FullName);
return null;
}
}
private static bool IsTypeFromModule(Type type, ExtensionDescriptor descriptor) {

View File

@@ -39,7 +39,12 @@ namespace Orchard.Environment.Extensions.Loaders {
if (entry.Loader == this) {
var assembly = _buildManager.GetCompiledAssembly(entry.VirtualPath);
_dependenciesFolder.StoreBuildProviderAssembly(entry.Descriptor.Name, entry.VirtualPath, assembly);
_dependenciesFolder.Store(new DependencyDescriptor {
ModuleName = entry.Descriptor.Name,
LoaderName = this.GetType().FullName,
VirtualPath = entry.VirtualPath,
FileName = assembly.Location
});
return new ExtensionEntry {
Descriptor = entry.Descriptor,
@@ -47,7 +52,14 @@ namespace Orchard.Environment.Extensions.Loaders {
ExportedTypes = assembly.GetExportedTypes(),
};
}
return null;
else {
// If the extension is not loaded by us, there is some cached state we need to invalidate
// 1) The webforms views which have been compiled with ".csproj" assembly source
// 2) The modules which contains features which depend on us
//TODO
_dependenciesFolder.Remove(entry.Descriptor.Name, this.GetType().FullName);
return null;
}
}
}
}

View File

@@ -9,11 +9,11 @@ namespace Orchard.Environment.Extensions.Loaders {
/// extension directory.
/// </summary>
public class PrecompiledExtensionLoader : IExtensionLoader {
private readonly IDependenciesFolder _folder;
private readonly IDependenciesFolder _dependenciesFolder;
private readonly IVirtualPathProvider _virtualPathProvider;
public PrecompiledExtensionLoader(IDependenciesFolder folder, IVirtualPathProvider virtualPathProvider) {
_folder = folder;
public PrecompiledExtensionLoader(IDependenciesFolder dependenciesFolder, IVirtualPathProvider virtualPathProvider) {
_dependenciesFolder = dependenciesFolder;
_virtualPathProvider = virtualPathProvider;
}
@@ -35,9 +35,9 @@ namespace Orchard.Environment.Extensions.Loaders {
public ExtensionEntry Load(ExtensionProbeEntry entry) {
if (entry.Loader == this) {
_folder.StorePrecompiledAssembly(entry.Descriptor.Name, entry.VirtualPath);
_dependenciesFolder.StorePrecompiledAssembly(entry.Descriptor.Name, entry.VirtualPath, this.GetType().FullName);
var assembly = _folder.LoadAssembly(entry.Descriptor.Name);
var assembly = _dependenciesFolder.LoadAssembly(entry.Descriptor.Name);
if (assembly == null)
return null;
@@ -47,7 +47,14 @@ namespace Orchard.Environment.Extensions.Loaders {
ExportedTypes = assembly.GetExportedTypes()
};
}
return null;
else {
// If the extension is not loaded by us, there is some cached state we need to invalidate
// 1) The webforms views which have been compiled with ".csproj" assembly source
// 2) The modules which contains features which depend on us
//TODO
_dependenciesFolder.Remove(entry.Descriptor.Name, this.GetType().FullName);
return null;
}
}
}
}

View File

@@ -9,32 +9,33 @@ namespace Orchard.Environment.Extensions.Loaders {
/// file can be found in the "App_Data/Dependencies" folder.
/// </summary>
public class ProbingExtensionLoader : IExtensionLoader {
private readonly IDependenciesFolder _folder;
private readonly IVirtualPathProvider _virtualPathProvider;
private readonly IDependenciesFolder _dependenciesFolder;
public ProbingExtensionLoader(IDependenciesFolder folder, IVirtualPathProvider virtualPathProvider) {
_folder = folder;
public ProbingExtensionLoader(IDependenciesFolder dependenciesFolder) {
_dependenciesFolder = dependenciesFolder;
}
public int Order { get { return 40; } }
public ExtensionProbeEntry Probe(ExtensionDescriptor descriptor) {
var desc = _folder.GetDescriptor(descriptor.Name);
if (desc != null) {
return new ExtensionProbeEntry {
if (!_dependenciesFolder.HasPrecompiledAssembly(descriptor.Name))
return null;
var desc = _dependenciesFolder.GetDescriptor(descriptor.Name);
if (desc == null)
return null;
return new ExtensionProbeEntry {
Descriptor = descriptor,
LastModificationTimeUtc = File.GetLastWriteTimeUtc(desc.FileName),
Loader = this,
VirtualPath = desc.VirtualPath
};
}
return null;
}
public ExtensionEntry Load(ExtensionProbeEntry entry) {
if (entry.Loader == this) {
var assembly = _folder.LoadAssembly(entry.Descriptor.Name);
var assembly = _dependenciesFolder.LoadAssembly(entry.Descriptor.Name);
if (assembly == null)
return null;
@@ -44,7 +45,15 @@ namespace Orchard.Environment.Extensions.Loaders {
ExportedTypes = assembly.GetExportedTypes()
};
}
return null;
else {
// If the extension is not loaded by us, there is some cached state we need to invalidate
// 1) The webforms views which have been compiled with "Assembly Name=""" directive
// 2) The modules which contains features which depend on us
// 3) The binary from the App_Data directory
//TODO
_dependenciesFolder.Remove(entry.Descriptor.Name, this.GetType().FullName);
return null;
}
}
}
}

View File

@@ -12,12 +12,13 @@ namespace Orchard.Environment.Extensions.Loaders {
/// </summary>
public class ReferencedExtensionLoader : IExtensionLoader {
private readonly IDependenciesFolder _dependenciesFolder;
public int Order { get { return 20; } }
public ReferencedExtensionLoader(IDependenciesFolder dependenciesFolder) {
_dependenciesFolder = dependenciesFolder;
}
public int Order { get { return 20; } }
public ExtensionProbeEntry Probe(ExtensionDescriptor descriptor) {
if (HostingEnvironment.IsHosted == false)
return null;
@@ -47,7 +48,13 @@ namespace Orchard.Environment.Extensions.Loaders {
.OfType<Assembly>()
.FirstOrDefault(x => x.GetName().Name == entry.Descriptor.Name);
_dependenciesFolder.StoreReferencedAssembly(entry.Descriptor.Name);
_dependenciesFolder.Store(new DependencyDescriptor {
ModuleName = entry.Descriptor.Name,
LoaderName = this.GetType().FullName,
VirtualPath = entry.VirtualPath,
FileName = assembly.Location
});
return new ExtensionEntry {
Descriptor = entry.Descriptor,
@@ -55,8 +62,12 @@ namespace Orchard.Environment.Extensions.Loaders {
ExportedTypes = assembly.GetExportedTypes()
};
}
return null;
else {
// If the extension is not loaded by us, there is no cached state
// we need to invalidate
_dependenciesFolder.Remove(entry.Descriptor.Name, this.GetType().FullName);
return null;
}
}
}
}

View File

@@ -55,47 +55,60 @@ namespace Orchard.FileSystems.Dependencies {
public bool IsCurrent { get; set; }
}
public void StoreReferencedAssembly(string moduleName) {
if (Descriptors.Any(d => d.ModuleName == moduleName)) {
// Remove the moduleName from the list of assemblies in the dependency folder
var newDescriptors = Descriptors.Where(d => d.ModuleName != moduleName);
//public void StoreReferencedAssembly(string moduleName) {
// if (Descriptors.Any(d => d.ModuleName == moduleName)) {
// // Remove the moduleName from the list of assemblies in the dependency folder
// var newDescriptors = Descriptors.Where(d => d.ModuleName != moduleName);
WriteDependencies(PersistencePath, newDescriptors);
}
}
// WriteDependencies(PersistencePath, newDescriptors);
// }
//}
public void StoreBuildProviderAssembly(string moduleName, string virtualPath, Assembly assembly) {
var descriptor = new DependencyDescriptor {
ModuleName = moduleName,
IsFromBuildProvider = true,
VirtualPath = virtualPath,
FileName = assembly.Location
};
//public void StoreBuildProviderAssembly(string moduleName, string virtualPath, Assembly assembly) {
// var descriptor = new DependencyDescriptor {
// ModuleName = moduleName,
// IsFromBuildProvider = true,
// VirtualPath = virtualPath,
// FileName = assembly.Location
// };
StoreDepencyInformation(descriptor);
// StoreDepencyInformation(descriptor);
_webSiteFolder.WhenPathChanges(virtualPath, () => _events.ModuleChanged(moduleName));
}
// _webSiteFolder.WhenPathChanges(virtualPath, () => _events.ModuleChanged(moduleName));
//}
public void StorePrecompiledAssembly(string moduleName, string virtualPath) {
public void StorePrecompiledAssembly(string moduleModuleName, string virtualPath, string loaderName) {
_appDataFolder.CreateDirectory(BasePath);
// Only store assembly if it's more recent that what we have stored already (if anything)
var assemblyFileName = _appDataFolder.MapPath(virtualPath);
if (IsNewerAssembly(moduleName, assemblyFileName)) {
if (IsNewerAssembly(moduleModuleName, assemblyFileName)) {
var destinationFileName = Path.GetFileName(assemblyFileName);
var destinationPath = _appDataFolder.MapPath(_appDataFolder.Combine(BasePath, destinationFileName));
File.Copy(assemblyFileName, destinationPath, true);
StoreDepencyInformation(new DependencyDescriptor {
ModuleName = moduleName,
IsFromBuildProvider = false,
ModuleName = moduleModuleName,
LoaderName = loaderName,
VirtualPath = virtualPath,
FileName = destinationFileName
});
}
}
public void Remove(string moduleName, string loaderName) {
Func<DependencyDescriptor, bool> predicate = (d => d.ModuleName == moduleName && d.LoaderName == loaderName);
if (Descriptors.Any(predicate)) {
var newDescriptors = Descriptors.Where(e => !predicate(e));
WriteDependencies(PersistencePath, newDescriptors);
}
}
public void Store(DependencyDescriptor descriptor) {
StoreDepencyInformation(descriptor);
}
public DependencyDescriptor GetDescriptor(string moduleName) {
return Descriptors.SingleOrDefault(d => d.ModuleName == moduleName);
}
@@ -127,10 +140,10 @@ namespace Orchard.FileSystems.Dependencies {
WriteDependencies(PersistencePath, dependencies);
}
public Assembly LoadAssembly(string assemblyName) {
public Assembly LoadAssembly(string moduleName) {
_appDataFolder.CreateDirectory(BasePath);
var dependency = Descriptors.SingleOrDefault(d => d.ModuleName == assemblyName);
var dependency = Descriptors.SingleOrDefault(d => d.ModuleName == moduleName);
if (dependency == null)
return null;
@@ -140,6 +153,17 @@ namespace Orchard.FileSystems.Dependencies {
return Assembly.Load(Path.GetFileNameWithoutExtension(dependency.FileName));
}
public bool HasPrecompiledAssembly(string moduleName) {
var dependency = Descriptors.SingleOrDefault(d => d.ModuleName == moduleName);
if (dependency == null)
return false;
if (!_appDataFolder.FileExists(_appDataFolder.Combine(BasePath, dependency.FileName)))
return false;
return true;
}
private IEnumerable<DependencyDescriptor> ReadDependencies(string persistancePath) {
Func<string, XName> ns = (name => XName.Get(name));
Func<XElement, string, string> elem = (e, name) => e.Element(ns(name)).Value;
@@ -156,7 +180,7 @@ namespace Orchard.FileSystems.Dependencies {
ModuleName = elem(e, "ModuleName"),
VirtualPath = elem(e, "VirtualPath"),
FileName = elem(e, "FileName"),
IsFromBuildProvider = bool.Parse(elem(e, "IsFromBuildProvider"))
LoaderName = elem(e, "LoaderName")
})
.ToList();
}
@@ -170,7 +194,7 @@ namespace Orchard.FileSystems.Dependencies {
var elements = dependencies.Select(d => new XElement("Dependency",
new XElement(ns("ModuleName"), d.ModuleName),
new XElement(ns("VirtualPath"), d.VirtualPath),
new XElement(ns("IsFromBuildProvider"), d.IsFromBuildProvider),
new XElement(ns("LoaderName"), d.LoaderName),
new XElement(ns("FileName"), d.FileName)));
document.Root.Add(elements);

View File

@@ -1,20 +1,20 @@
using System.Reflection;
using Orchard.Caching;
using Orchard.Environment;
namespace Orchard.FileSystems.Dependencies {
public class DependencyDescriptor {
public string ModuleName { get; set; }
public bool IsFromBuildProvider { get; set; }
public string LoaderName { get; set; }
public string VirtualPath { get; set; }
public string FileName { get; set; }
}
public interface IDependenciesFolder : IVolatileProvider {
void StoreReferencedAssembly(string moduleName);
void StorePrecompiledAssembly(string moduleName, string virtualPath);
void StoreBuildProviderAssembly(string moduleName, string virtualPath, Assembly assembly);
void Store(DependencyDescriptor descriptor);
void StorePrecompiledAssembly(string moduleName, string virtualPath, string loaderName);
void Remove(string moduleName, string loaderName);
DependencyDescriptor GetDescriptor(string moduleName);
Assembly LoadAssembly(string assemblyName);
bool HasPrecompiledAssembly(string moduleName);
Assembly LoadAssembly(string moduleName);
}
}

View File

@@ -1,5 +1,6 @@
using System.IO;
using System.Web.Hosting;
using Orchard.Environment.Extensions.Loaders;
namespace Orchard.FileSystems.Dependencies {
public class WebFormsExtensionsVirtualFile : VirtualFile {
@@ -50,7 +51,7 @@ namespace Orchard.FileSystems.Dependencies {
}
private string GetAssemblyDirective() {
if (_dependencyDescriptor.IsFromBuildProvider) {
if (_dependencyDescriptor.LoaderName == typeof(DynamicExtensionLoader).FullName) {
return string.Format("<%@ Assembly Src=\"{0}\"%>", _dependencyDescriptor.VirtualPath);
}
else {