mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 19:54:57 +08:00
Update dependencies storage to store state of all loaded extensions
--HG-- branch : dev
This commit is contained in:
@@ -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) {
|
||||
|
@@ -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) {
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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 {
|
||||
|
Reference in New Issue
Block a user