From ed410cba617cd97d30ba51e8cb3799e0f00427bb Mon Sep 17 00:00:00 2001 From: Renaud Paquay Date: Wed, 16 Jun 2010 14:35:13 -0700 Subject: [PATCH] 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 --- .../Loaders/PrecompiledExtensionLoader.cs | 17 ++-- .../Loaders/ProbingExtensionLoader.cs | 27 +++--- src/Orchard/Environment/OrchardStarter.cs | 1 + .../DefaultAssemblyProbingFolder.cs | 41 +++++++++ .../Dependencies/DefaultDependenciesFolder.cs | 88 +++++++------------ .../Dependencies/IAssenblyProbyFolder.cs | 40 +++++++++ .../Dependencies/IDependenciesFolder.cs | 13 +-- src/Orchard/Orchard.Framework.csproj | 2 + 8 files changed, 135 insertions(+), 94 deletions(-) create mode 100644 src/Orchard/FileSystems/Dependencies/DefaultAssemblyProbingFolder.cs create mode 100644 src/Orchard/FileSystems/Dependencies/IAssenblyProbyFolder.cs diff --git a/src/Orchard/Environment/Extensions/Loaders/PrecompiledExtensionLoader.cs b/src/Orchard/Environment/Extensions/Loaders/PrecompiledExtensionLoader.cs index 196eaa2cb..93bd35c62 100644 --- a/src/Orchard/Environment/Extensions/Loaders/PrecompiledExtensionLoader.cs +++ b/src/Orchard/Environment/Extensions/Loaders/PrecompiledExtensionLoader.cs @@ -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 { /// 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; diff --git a/src/Orchard/Environment/Extensions/Loaders/ProbingExtensionLoader.cs b/src/Orchard/Environment/Extensions/Loaders/ProbingExtensionLoader.cs index 719d4530b..bcda5e6e8 100644 --- a/src/Orchard/Environment/Extensions/Loaders/ProbingExtensionLoader.cs +++ b/src/Orchard/Environment/Extensions/Loaders/ProbingExtensionLoader.cs @@ -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 { /// 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; diff --git a/src/Orchard/Environment/OrchardStarter.cs b/src/Orchard/Environment/OrchardStarter.cs index f6cd710e0..83c96d895 100644 --- a/src/Orchard/Environment/OrchardStarter.cs +++ b/src/Orchard/Environment/OrchardStarter.cs @@ -42,6 +42,7 @@ namespace Orchard.Environment { RegisterVolatileProvider(builder); RegisterVolatileProvider(builder); RegisterVolatileProvider(builder); + RegisterVolatileProvider(builder); RegisterVolatileProvider(builder); RegisterVolatileProvider(builder); diff --git a/src/Orchard/FileSystems/Dependencies/DefaultAssemblyProbingFolder.cs b/src/Orchard/FileSystems/Dependencies/DefaultAssemblyProbingFolder.cs new file mode 100644 index 000000000..2033ca9a3 --- /dev/null +++ b/src/Orchard/FileSystems/Dependencies/DefaultAssemblyProbingFolder.cs @@ -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"); + } + } +} \ No newline at end of file diff --git a/src/Orchard/FileSystems/Dependencies/DefaultDependenciesFolder.cs b/src/Orchard/FileSystems/Dependencies/DefaultDependenciesFolder.cs index 68bed103e..9e721be2a 100644 --- a/src/Orchard/FileSystems/Dependencies/DefaultDependenciesFolder.cs +++ b/src/Orchard/FileSystems/Dependencies/DefaultDependenciesFolder.cs @@ -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 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 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 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 { - 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 ReadDependencies(string persistancePath) { Func ns = (name => XName.Get(name)); Func 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 { + 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); + } + } } } \ No newline at end of file diff --git a/src/Orchard/FileSystems/Dependencies/IAssenblyProbyFolder.cs b/src/Orchard/FileSystems/Dependencies/IAssenblyProbyFolder.cs new file mode 100644 index 000000000..6423486c0 --- /dev/null +++ b/src/Orchard/FileSystems/Dependencies/IAssenblyProbyFolder.cs @@ -0,0 +1,40 @@ +using System; +using System.Reflection; +using Orchard.Caching; + +namespace Orchard.FileSystems.Dependencies { + /// + /// 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. + /// + public interface IAssemblyProbingFolder : IVolatileProvider { + /// + /// Return "true" if the assembly corresponding to "moduleName" is + /// present in the folder. + /// + bool HasAssembly(string moduleName); + + /// + /// Return the last modification date of the assembly corresponding + /// to "moduleName". The assembly must be exist on disk, otherwise an + /// exception is thrown. + /// + DateTime GetAssemblyDateTimeUtc(string moduleName); + + /// + /// Load the assembly corresponding to "moduleName" if the assembly file + /// is present in the folder. + /// + Assembly LoadAssembly(string moduleName); + + /// + /// 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?" + /// + string GetAssemblyPhysicalFileName(string moduleName); + } +} \ No newline at end of file diff --git a/src/Orchard/FileSystems/Dependencies/IDependenciesFolder.cs b/src/Orchard/FileSystems/Dependencies/IDependenciesFolder.cs index a045b1775..3b51e98af 100644 --- a/src/Orchard/FileSystems/Dependencies/IDependenciesFolder.cs +++ b/src/Orchard/FileSystems/Dependencies/IDependenciesFolder.cs @@ -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 LastWriteTimeUtc { get; set; } - public Func Assembly { get; set; } - } - public interface IDependenciesFolder : IVolatileProvider { DependencyDescriptor GetDescriptor(string moduleName); IEnumerable LoadDescriptors(); void StoreDescriptors(IEnumerable dependencyDescriptors); - - ProbingAssembly GetProbingAssembly(string moduleName); - string GetProbingAssemblyPhysicalFileName(string moduleName); } } diff --git a/src/Orchard/Orchard.Framework.csproj b/src/Orchard/Orchard.Framework.csproj index a71212ea6..d9e774a4e 100644 --- a/src/Orchard/Orchard.Framework.csproj +++ b/src/Orchard/Orchard.Framework.csproj @@ -358,7 +358,9 @@ + +