mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-10-15 11:44:58 +08:00
Move probing assembly folder behavior in separate class
The behavior of the "assembly load probing folder" is really a separate concern from managing the list of loaded extesions. --HG-- branch : dev
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Orchard.Caching;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
using Orchard.FileSystems.Dependencies;
|
||||
@@ -14,11 +13,13 @@ namespace Orchard.Environment.Extensions.Loaders {
|
||||
/// </summary>
|
||||
public class PrecompiledExtensionLoader : ExtensionLoaderBase {
|
||||
private readonly IDependenciesFolder _dependenciesFolder;
|
||||
private readonly IAssemblyProbingFolder _assemblyProbingFolder;
|
||||
private readonly IVirtualPathProvider _virtualPathProvider;
|
||||
private readonly IVirtualPathMonitor _virtualPathMonitor;
|
||||
|
||||
public PrecompiledExtensionLoader(IDependenciesFolder dependenciesFolder, IVirtualPathProvider virtualPathProvider, IVirtualPathMonitor virtualPathMonitor) {
|
||||
public PrecompiledExtensionLoader(IDependenciesFolder dependenciesFolder, IAssemblyProbingFolder assemblyProbingFolder, IVirtualPathProvider virtualPathProvider, IVirtualPathMonitor virtualPathMonitor) {
|
||||
_dependenciesFolder = dependenciesFolder;
|
||||
_assemblyProbingFolder = assemblyProbingFolder;
|
||||
_virtualPathProvider = virtualPathProvider;
|
||||
_virtualPathMonitor = virtualPathMonitor;
|
||||
Logger = NullLogger.Instance;
|
||||
@@ -33,7 +34,7 @@ namespace Orchard.Environment.Extensions.Loaders {
|
||||
}
|
||||
|
||||
public override void ExtensionRemoved(ExtensionLoadingContext ctx, DependencyDescriptor dependency) {
|
||||
var assemblyFileName = _dependenciesFolder.GetProbingAssemblyPhysicalFileName(dependency.Name);
|
||||
var assemblyFileName = _assemblyProbingFolder.GetAssemblyPhysicalFileName(dependency.Name);
|
||||
if (File.Exists(assemblyFileName)) {
|
||||
ctx.FilesToDelete.Add(assemblyFileName);
|
||||
|
||||
@@ -47,7 +48,7 @@ namespace Orchard.Environment.Extensions.Loaders {
|
||||
|
||||
public override void ExtensionActivated(ExtensionLoadingContext ctx, bool isNewExtension, ExtensionDescriptor extension) {
|
||||
string sourceFileName = _virtualPathProvider.MapPath(GetAssemblyPath(extension));
|
||||
string destinationFileName = _dependenciesFolder.GetProbingAssemblyPhysicalFileName(extension.Name);
|
||||
string destinationFileName = _assemblyProbingFolder.GetAssemblyPhysicalFileName(extension.Name);
|
||||
if (FileIsNewer(sourceFileName, destinationFileName)) {
|
||||
ctx.FilesToCopy.Add(sourceFileName, destinationFileName);
|
||||
// We need to restart the appDomain if the assembly is loaded
|
||||
@@ -59,7 +60,7 @@ namespace Orchard.Environment.Extensions.Loaders {
|
||||
}
|
||||
|
||||
public override void ExtensionDeactivated(ExtensionLoadingContext ctx, bool isNewExtension, ExtensionDescriptor extension) {
|
||||
var assemblyFileName = _dependenciesFolder.GetProbingAssemblyPhysicalFileName(extension.Name);
|
||||
var assemblyFileName = _assemblyProbingFolder.GetAssemblyPhysicalFileName(extension.Name);
|
||||
if (File.Exists(assemblyFileName)) {
|
||||
ctx.FilesToDelete.Add(assemblyFileName);
|
||||
// We need to restart the appDomain if the assembly is loaded
|
||||
@@ -95,14 +96,14 @@ namespace Orchard.Environment.Extensions.Loaders {
|
||||
var dependency = _dependenciesFolder.GetDescriptor(descriptor.Name);
|
||||
if (dependency != null && dependency.LoaderName == this.Name) {
|
||||
|
||||
var assembly = _dependenciesFolder.GetProbingAssembly(descriptor.Name);
|
||||
var assembly = _assemblyProbingFolder.LoadAssembly(descriptor.Name);
|
||||
if (assembly == null)
|
||||
return null;
|
||||
|
||||
return new ExtensionEntry {
|
||||
Descriptor = descriptor,
|
||||
Assembly = assembly.Assembly(),
|
||||
ExportedTypes = assembly.Assembly().GetExportedTypes()
|
||||
Assembly = assembly,
|
||||
ExportedTypes = assembly.GetExportedTypes()
|
||||
};
|
||||
}
|
||||
return null;
|
||||
|
@@ -1,10 +1,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Orchard.Caching;
|
||||
using System.IO;
|
||||
using Orchard.Environment.Extensions.Models;
|
||||
using Orchard.FileSystems.Dependencies;
|
||||
using Orchard.FileSystems.VirtualPath;
|
||||
using Orchard.Logging;
|
||||
|
||||
namespace Orchard.Environment.Extensions.Loaders {
|
||||
@@ -14,11 +10,11 @@ namespace Orchard.Environment.Extensions.Loaders {
|
||||
/// </summary>
|
||||
public class ProbingExtensionLoader : ExtensionLoaderBase {
|
||||
private readonly IDependenciesFolder _dependenciesFolder;
|
||||
private readonly IVirtualPathProvider _virtualPathProvider;
|
||||
private readonly IAssemblyProbingFolder _assemblyProbingFolder;
|
||||
|
||||
public ProbingExtensionLoader(IDependenciesFolder dependenciesFolder, IVirtualPathProvider virtualPathProvider) {
|
||||
public ProbingExtensionLoader(IDependenciesFolder dependenciesFolder, IAssemblyProbingFolder assemblyProbingFolder) {
|
||||
_dependenciesFolder = dependenciesFolder;
|
||||
_virtualPathProvider = virtualPathProvider;
|
||||
_assemblyProbingFolder = assemblyProbingFolder;
|
||||
Logger = NullLogger.Instance;
|
||||
}
|
||||
|
||||
@@ -31,7 +27,7 @@ namespace Orchard.Environment.Extensions.Loaders {
|
||||
}
|
||||
|
||||
public override void ExtensionRemoved(ExtensionLoadingContext ctx, DependencyDescriptor dependency) {
|
||||
var assemblyFileName = _dependenciesFolder.GetProbingAssemblyPhysicalFileName(dependency.Name);
|
||||
var assemblyFileName = _assemblyProbingFolder.GetAssemblyPhysicalFileName(dependency.Name);
|
||||
if (File.Exists(assemblyFileName)) {
|
||||
ctx.FilesToDelete.Add(assemblyFileName);
|
||||
// We need to restart the appDomain if the assembly is loaded
|
||||
@@ -43,7 +39,7 @@ namespace Orchard.Environment.Extensions.Loaders {
|
||||
}
|
||||
|
||||
public override void ExtensionDeactivated(ExtensionLoadingContext ctx, bool isNewExtension, ExtensionDescriptor extension) {
|
||||
var assemblyFileName = _dependenciesFolder.GetProbingAssemblyPhysicalFileName(extension.Name);
|
||||
var assemblyFileName = _assemblyProbingFolder.GetAssemblyPhysicalFileName(extension.Name);
|
||||
if (File.Exists(assemblyFileName)) {
|
||||
ctx.FilesToDelete.Add(assemblyFileName);
|
||||
// We need to restart the appDomain if the assembly is loaded
|
||||
@@ -55,8 +51,7 @@ namespace Orchard.Environment.Extensions.Loaders {
|
||||
}
|
||||
|
||||
public override ExtensionProbeEntry Probe(ExtensionDescriptor descriptor) {
|
||||
var probingAssembly = _dependenciesFolder.GetProbingAssembly(descriptor.Name);
|
||||
if (probingAssembly == null)
|
||||
if (!_assemblyProbingFolder.HasAssembly(descriptor.Name))
|
||||
return null;
|
||||
|
||||
var desc = _dependenciesFolder.GetDescriptor(descriptor.Name);
|
||||
@@ -65,7 +60,7 @@ namespace Orchard.Environment.Extensions.Loaders {
|
||||
|
||||
return new ExtensionProbeEntry {
|
||||
Descriptor = descriptor,
|
||||
LastModificationTimeUtc = probingAssembly.LastWriteTimeUtc(),
|
||||
LastModificationTimeUtc = _assemblyProbingFolder.GetAssemblyDateTimeUtc(descriptor.Name),
|
||||
Loader = this,
|
||||
VirtualPath = desc.VirtualPath
|
||||
};
|
||||
@@ -75,14 +70,14 @@ namespace Orchard.Environment.Extensions.Loaders {
|
||||
var dependency = _dependenciesFolder.GetDescriptor(descriptor.Name);
|
||||
if (dependency != null && dependency.LoaderName == this.Name) {
|
||||
|
||||
var assembly = _dependenciesFolder.GetProbingAssembly(descriptor.Name);
|
||||
var assembly = _assemblyProbingFolder.LoadAssembly(descriptor.Name);
|
||||
if (assembly == null)
|
||||
return null;
|
||||
|
||||
return new ExtensionEntry {
|
||||
Descriptor = descriptor,
|
||||
Assembly = assembly.Assembly(),
|
||||
ExportedTypes = assembly.Assembly().GetExportedTypes()
|
||||
Assembly = assembly,
|
||||
ExportedTypes = assembly.GetExportedTypes()
|
||||
};
|
||||
}
|
||||
return null;
|
||||
|
@@ -42,6 +42,7 @@ namespace Orchard.Environment {
|
||||
RegisterVolatileProvider<AppDataFolder, IAppDataFolder>(builder);
|
||||
RegisterVolatileProvider<Clock, IClock>(builder);
|
||||
RegisterVolatileProvider<DefaultDependenciesFolder, IDependenciesFolder>(builder);
|
||||
RegisterVolatileProvider<DefaultAssemblyProbingFolder, IAssemblyProbingFolder>(builder);
|
||||
RegisterVolatileProvider<DefaultVirtualPathMonitor, IVirtualPathMonitor>(builder);
|
||||
RegisterVolatileProvider<DefaultVirtualPathProvider, IVirtualPathProvider>(builder);
|
||||
|
||||
|
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using Orchard.FileSystems.AppData;
|
||||
|
||||
namespace Orchard.FileSystems.Dependencies {
|
||||
public class DefaultAssemblyProbingFolder : IAssemblyProbingFolder {
|
||||
private const string BasePath = "Dependencies";
|
||||
private readonly IAppDataFolder _appDataFolder;
|
||||
|
||||
public DefaultAssemblyProbingFolder(IAppDataFolder appDataFolder) {
|
||||
_appDataFolder = appDataFolder;
|
||||
}
|
||||
|
||||
public bool HasAssembly(string moduleName) {
|
||||
var path = PrecompiledAssemblyPath(moduleName);
|
||||
return _appDataFolder.FileExists(path);
|
||||
}
|
||||
|
||||
public DateTime GetAssemblyDateTimeUtc(string moduleName) {
|
||||
var path = PrecompiledAssemblyPath(moduleName);
|
||||
return File.GetLastWriteTimeUtc(_appDataFolder.MapPath(path));
|
||||
}
|
||||
|
||||
public Assembly LoadAssembly(string moduleName) {
|
||||
var path = PrecompiledAssemblyPath(moduleName);
|
||||
if (!_appDataFolder.FileExists(path))
|
||||
return null;
|
||||
|
||||
return Assembly.Load(moduleName);
|
||||
}
|
||||
|
||||
public string GetAssemblyPhysicalFileName(string moduleName) {
|
||||
return _appDataFolder.MapPath(PrecompiledAssemblyPath(moduleName));
|
||||
}
|
||||
|
||||
private string PrecompiledAssemblyPath(string moduleName) {
|
||||
return _appDataFolder.Combine(BasePath, moduleName + ".dll");
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Xml.Linq;
|
||||
using Orchard.Caching;
|
||||
using Orchard.FileSystems.AppData;
|
||||
@@ -31,74 +29,31 @@ namespace Orchard.FileSystems.Dependencies {
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<DependencyDescriptor> Descriptors {
|
||||
get {
|
||||
return _cacheManager.Get(PersistencePath,
|
||||
ctx => {
|
||||
_appDataFolder.CreateDirectory(BasePath);
|
||||
|
||||
ctx.Monitor(_appDataFolder.WhenPathChanges(ctx.Key));
|
||||
ctx.Monitor(_writeThroughToken);
|
||||
|
||||
_appDataFolder.CreateDirectory(BasePath);
|
||||
return ReadDependencies(ctx.Key).ToList();
|
||||
});
|
||||
}
|
||||
public DependencyDescriptor GetDescriptor(string moduleName) {
|
||||
return LoadDescriptors().SingleOrDefault(d => d.Name == moduleName);
|
||||
}
|
||||
|
||||
public IEnumerable<DependencyDescriptor> LoadDescriptors() {
|
||||
return Descriptors;
|
||||
return _cacheManager.Get(PersistencePath,
|
||||
ctx => {
|
||||
_appDataFolder.CreateDirectory(BasePath);
|
||||
|
||||
ctx.Monitor(_appDataFolder.WhenPathChanges(ctx.Key));
|
||||
ctx.Monitor(_writeThroughToken);
|
||||
|
||||
_appDataFolder.CreateDirectory(BasePath);
|
||||
return ReadDependencies(ctx.Key).ToList();
|
||||
});
|
||||
}
|
||||
|
||||
public void StoreDescriptors(IEnumerable<DependencyDescriptor> dependencyDescriptors) {
|
||||
var existingDescriptors = this.Descriptors.OrderBy(d => d.Name);
|
||||
var existingDescriptors = LoadDescriptors().OrderBy(d => d.Name);
|
||||
var newDescriptors = dependencyDescriptors.OrderBy(d => d.Name);
|
||||
if (!newDescriptors.SequenceEqual(existingDescriptors, new DependencyDescriptorComparer())) {
|
||||
WriteDependencies(PersistencePath, dependencyDescriptors);
|
||||
}
|
||||
}
|
||||
|
||||
private class DependencyDescriptorComparer : EqualityComparer<DependencyDescriptor> {
|
||||
public override bool Equals(DependencyDescriptor x, DependencyDescriptor y) {
|
||||
return
|
||||
StringComparer.OrdinalIgnoreCase.Equals(x.Name, y.Name) &&
|
||||
StringComparer.OrdinalIgnoreCase.Equals(x.LoaderName, y.LoaderName) &&
|
||||
StringComparer.OrdinalIgnoreCase.Equals(x.VirtualPath, y.VirtualPath);
|
||||
|
||||
}
|
||||
|
||||
public override int GetHashCode(DependencyDescriptor obj) {
|
||||
return
|
||||
StringComparer.OrdinalIgnoreCase.GetHashCode(obj.Name) ^
|
||||
StringComparer.OrdinalIgnoreCase.GetHashCode(obj.LoaderName) ^
|
||||
StringComparer.OrdinalIgnoreCase.GetHashCode(obj.VirtualPath);
|
||||
}
|
||||
}
|
||||
|
||||
public DependencyDescriptor GetDescriptor(string moduleName) {
|
||||
return Descriptors.SingleOrDefault(d => d.Name == moduleName);
|
||||
}
|
||||
|
||||
public ProbingAssembly GetProbingAssembly(string moduleName) {
|
||||
var path = PrecompiledAssemblyPath(moduleName);
|
||||
if (!_appDataFolder.FileExists(path))
|
||||
return null;
|
||||
|
||||
return new ProbingAssembly {
|
||||
Path = path,
|
||||
Assembly = () => Assembly.Load(moduleName),
|
||||
LastWriteTimeUtc = () => File.GetLastWriteTimeUtc(_appDataFolder.MapPath(path)),
|
||||
};
|
||||
}
|
||||
|
||||
public string GetProbingAssemblyPhysicalFileName(string moduleName) {
|
||||
return _appDataFolder.MapPath(PrecompiledAssemblyPath(moduleName));
|
||||
}
|
||||
|
||||
private string PrecompiledAssemblyPath(string moduleName) {
|
||||
return _appDataFolder.Combine(BasePath, moduleName + ".dll");
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -142,5 +97,22 @@ namespace Orchard.FileSystems.Dependencies {
|
||||
private class InvalidationToken : IVolatileToken {
|
||||
public bool IsCurrent { get; set; }
|
||||
}
|
||||
|
||||
private class DependencyDescriptorComparer : EqualityComparer<DependencyDescriptor> {
|
||||
public override bool Equals(DependencyDescriptor x, DependencyDescriptor y) {
|
||||
return
|
||||
StringComparer.OrdinalIgnoreCase.Equals(x.Name, y.Name) &&
|
||||
StringComparer.OrdinalIgnoreCase.Equals(x.LoaderName, y.LoaderName) &&
|
||||
StringComparer.OrdinalIgnoreCase.Equals(x.VirtualPath, y.VirtualPath);
|
||||
|
||||
}
|
||||
|
||||
public override int GetHashCode(DependencyDescriptor obj) {
|
||||
return
|
||||
StringComparer.OrdinalIgnoreCase.GetHashCode(obj.Name) ^
|
||||
StringComparer.OrdinalIgnoreCase.GetHashCode(obj.LoaderName) ^
|
||||
StringComparer.OrdinalIgnoreCase.GetHashCode(obj.VirtualPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
40
src/Orchard/FileSystems/Dependencies/IAssenblyProbyFolder.cs
Normal file
40
src/Orchard/FileSystems/Dependencies/IAssenblyProbyFolder.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Orchard.Caching;
|
||||
|
||||
namespace Orchard.FileSystems.Dependencies {
|
||||
/// <summary>
|
||||
/// Abstraction over the folder configued in web.config as an additional
|
||||
/// location to load assemblies from. This assumes a local physical file system,
|
||||
/// since Orchard will need to store assembly files locally.
|
||||
/// </summary>
|
||||
public interface IAssemblyProbingFolder : IVolatileProvider {
|
||||
/// <summary>
|
||||
/// Return "true" if the assembly corresponding to "moduleName" is
|
||||
/// present in the folder.
|
||||
/// </summary>
|
||||
bool HasAssembly(string moduleName);
|
||||
|
||||
/// <summary>
|
||||
/// Return the last modification date of the assembly corresponding
|
||||
/// to "moduleName". The assembly must be exist on disk, otherwise an
|
||||
/// exception is thrown.
|
||||
/// </summary>
|
||||
DateTime GetAssemblyDateTimeUtc(string moduleName);
|
||||
|
||||
/// <summary>
|
||||
/// Load the assembly corresponding to "moduleName" if the assembly file
|
||||
/// is present in the folder.
|
||||
/// </summary>
|
||||
Assembly LoadAssembly(string moduleName);
|
||||
|
||||
/// <summary>
|
||||
/// Return the physical location where to store the assembly
|
||||
/// corresponding to "moduleName". This will return a correct path
|
||||
/// even if the assembly is not currently stored in that location.
|
||||
/// This method can be used to answer the question "Where would the assembly
|
||||
/// for module "moduleName" be stored if it exsisted?"
|
||||
/// </summary>
|
||||
string GetAssemblyPhysicalFileName(string moduleName);
|
||||
}
|
||||
}
|
@@ -1,6 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Collections.Generic;
|
||||
using Orchard.Caching;
|
||||
|
||||
namespace Orchard.FileSystems.Dependencies {
|
||||
@@ -10,18 +8,9 @@ namespace Orchard.FileSystems.Dependencies {
|
||||
public string VirtualPath { get; set; }
|
||||
}
|
||||
|
||||
public class ProbingAssembly {
|
||||
public string Path { get; set; }
|
||||
public Func<DateTime> LastWriteTimeUtc { get; set; }
|
||||
public Func<Assembly> Assembly { get; set; }
|
||||
}
|
||||
|
||||
public interface IDependenciesFolder : IVolatileProvider {
|
||||
DependencyDescriptor GetDescriptor(string moduleName);
|
||||
IEnumerable<DependencyDescriptor> LoadDescriptors();
|
||||
void StoreDescriptors(IEnumerable<DependencyDescriptor> dependencyDescriptors);
|
||||
|
||||
ProbingAssembly GetProbingAssembly(string moduleName);
|
||||
string GetProbingAssemblyPhysicalFileName(string moduleName);
|
||||
}
|
||||
}
|
||||
|
@@ -358,7 +358,9 @@
|
||||
<Compile Include="Environment\Extensions\IExtensionLoaderCoordinator.cs" />
|
||||
<Compile Include="Environment\Extensions\Loaders\ExtensionLoaderBase.cs" />
|
||||
<Compile Include="FileSystems\AppData\IAppDataFolderRoot.cs" />
|
||||
<Compile Include="FileSystems\Dependencies\DefaultAssemblyProbingFolder.cs" />
|
||||
<Compile Include="FileSystems\Dependencies\DefaultDependenciesFolder.cs" />
|
||||
<Compile Include="FileSystems\Dependencies\IAssenblyProbyFolder.cs" />
|
||||
<Compile Include="FileSystems\VirtualPath\DefaultVirtualPathMonitor.cs" />
|
||||
<Compile Include="FileSystems\VirtualPath\DefaultVirtualPathProvider.cs" />
|
||||
<Compile Include="FileSystems\VirtualPath\ICustomVirtualPathProvider.cs" />
|
||||
|
Reference in New Issue
Block a user