From ea6d5849ecb67f0c5c7f946ff3b1ce1bddb4275a Mon Sep 17 00:00:00 2001 From: Renaud Paquay Date: Thu, 15 Jul 2010 13:43:11 -0700 Subject: [PATCH] Fix dynaic compilation When a new set of assemblies is enabled, we need to invalidate the nhibernate serialized configuration (since it contains not only types names for records, but also assembly names) --HG-- branch : dev --- .../Dependencies/DependenciesFolderTests.cs | 47 +++++++++++------ src/Orchard.Tests/Stubs/StubAppDataFolder.cs | 4 ++ .../Data/ISessionConfigurationCache.cs | 8 +++ src/Orchard/Data/SessionConfigurationCache.cs | 50 +++++++++++++++++++ src/Orchard/Data/SessionFactoryHolder.cs | 49 +----------------- .../ShellBuilders/ShellContextFactory.cs | 2 +- .../FileSystems/AppData/AppDataFolder.cs | 4 ++ .../FileSystems/AppData/IAppDataFolder.cs | 1 + .../Dependencies/DefaultDependenciesFolder.cs | 6 ++- src/Orchard/Orchard.Framework.csproj | 2 + 10 files changed, 107 insertions(+), 66 deletions(-) create mode 100644 src/Orchard/Data/ISessionConfigurationCache.cs create mode 100644 src/Orchard/Data/SessionConfigurationCache.cs diff --git a/src/Orchard.Tests/FileSystems/Dependencies/DependenciesFolderTests.cs b/src/Orchard.Tests/FileSystems/Dependencies/DependenciesFolderTests.cs index f60e1b852..0f4aef2ce 100644 --- a/src/Orchard.Tests/FileSystems/Dependencies/DependenciesFolderTests.cs +++ b/src/Orchard.Tests/FileSystems/Dependencies/DependenciesFolderTests.cs @@ -1,18 +1,31 @@ using System; using System.IO; using System.Linq; +using Autofac; using NUnit.Framework; +using Orchard.Caching; +using Orchard.Data; +using Orchard.FileSystems.AppData; using Orchard.FileSystems.Dependencies; +using Orchard.Services; using Orchard.Tests.Stubs; namespace Orchard.Tests.FileSystems.Dependencies { [TestFixture] public class DependenciesFolderTests { + public IContainer BuildContainer() { + var builder = new ContainerBuilder(); + builder.RegisterType().As().SingleInstance(); + builder.RegisterType().As().SingleInstance(); + builder.RegisterType().As().SingleInstance(); + builder.RegisterType().As().SingleInstance(); + builder.RegisterType().As(); + return builder.Build(); + } + [Test] public void LoadDescriptorsShouldReturnEmptyList() { - var clock = new StubClock(); - var appDataFolder = new StubAppDataFolder(clock); - var dependenciesFolder = new DefaultDependenciesFolder(new StubCacheManager(), appDataFolder); + var dependenciesFolder = BuildContainer().Resolve(); var e = dependenciesFolder.LoadDescriptors(); Assert.That(e, Is.Empty); @@ -20,9 +33,7 @@ namespace Orchard.Tests.FileSystems.Dependencies { [Test] public void StoreDescriptorsShouldWork() { - var clock = new StubClock(); - var appDataFolder = new StubAppDataFolder(clock); - var dependenciesFolder = new DefaultDependenciesFolder(new StubCacheManager(), appDataFolder); + var dependenciesFolder = BuildContainer().Resolve(); var d = new DependencyDescriptor { Name = "name", @@ -40,9 +51,10 @@ namespace Orchard.Tests.FileSystems.Dependencies { [Test] public void StoreDescriptorsShouldNoOpIfNoChanges() { - var clock = new StubClock(); - var appDataFolder = new StubAppDataFolder(clock); - var dependenciesFolder = new DefaultDependenciesFolder(new StubCacheManager(), appDataFolder); + var container = BuildContainer(); + var clock = (StubClock)container.Resolve(); + var appDataFolder = (StubAppDataFolder)container.Resolve(); + var dependenciesFolder = container.Resolve(); var d1 = new DependencyDescriptor { Name = "name1", @@ -67,9 +79,10 @@ namespace Orchard.Tests.FileSystems.Dependencies { [Test] public void StoreDescriptorsShouldStoreIfChanges() { - var clock = new StubClock(); - var appDataFolder = new StubAppDataFolder(clock); - var dependenciesFolder = new DefaultDependenciesFolder(new StubCacheManager(), appDataFolder); + var container = BuildContainer(); + var clock = (StubClock)container.Resolve(); + var appDataFolder = (StubAppDataFolder)container.Resolve(); + var dependenciesFolder = container.Resolve(); var d1 = new DependencyDescriptor { Name = "name1", @@ -96,9 +109,10 @@ namespace Orchard.Tests.FileSystems.Dependencies { [Test] public void LoadDescriptorsShouldWorkAcrossInstances() { - var clock = new StubClock(); - var appDataFolder = new StubAppDataFolder(clock); - var dependenciesFolder = new DefaultDependenciesFolder(new StubCacheManager(), appDataFolder); + var container = BuildContainer(); + var clock = (StubClock)container.Resolve(); + var appDataFolder = (StubAppDataFolder)container.Resolve(); + var dependenciesFolder = container.Resolve(); var d1 = new DependencyDescriptor { Name = "name1", @@ -115,7 +129,8 @@ namespace Orchard.Tests.FileSystems.Dependencies { dependenciesFolder.StoreDescriptors(new[] { d1, d2 }); // Create a new instance over the same appDataFolder - var dependenciesFolder2 = new DefaultDependenciesFolder(new StubCacheManager(), appDataFolder); + var dependenciesFolder2 = container.Resolve(); + Assert.That(dependenciesFolder2, Is.Not.SameAs(dependenciesFolder)); // Ensure descriptors were persisted properly var result = dependenciesFolder2.LoadDescriptors(); diff --git a/src/Orchard.Tests/Stubs/StubAppDataFolder.cs b/src/Orchard.Tests/Stubs/StubAppDataFolder.cs index a57bf3baa..e68441701 100644 --- a/src/Orchard.Tests/Stubs/StubAppDataFolder.cs +++ b/src/Orchard.Tests/Stubs/StubAppDataFolder.cs @@ -97,6 +97,10 @@ namespace Orchard.Tests.Stubs { _fileSystem.CreateDirectoryEntry(path); } + public bool DirectoryExists(string path) { + return _fileSystem.GetDirectoryEntry(path) != null; + } + public IVolatileToken WhenPathChanges(string path) { return _fileSystem.WhenPathChanges(path); } diff --git a/src/Orchard/Data/ISessionConfigurationCache.cs b/src/Orchard/Data/ISessionConfigurationCache.cs new file mode 100644 index 000000000..b39556e35 --- /dev/null +++ b/src/Orchard/Data/ISessionConfigurationCache.cs @@ -0,0 +1,8 @@ +using NHibernate.Cfg; +using Orchard.Environment.ShellBuilders.Models; + +namespace Orchard.Data { + public interface ISessionConfigurationCache { + Configuration GetConfiguration(ShellBlueprint shellBlueprint); + } +} \ No newline at end of file diff --git a/src/Orchard/Data/SessionConfigurationCache.cs b/src/Orchard/Data/SessionConfigurationCache.cs new file mode 100644 index 000000000..beae75125 --- /dev/null +++ b/src/Orchard/Data/SessionConfigurationCache.cs @@ -0,0 +1,50 @@ +using System.Runtime.Serialization.Formatters.Binary; +using NHibernate.Cfg; +using Orchard.FileSystems.AppData; + +namespace Orchard.Data { + public class SessionConfigurationCache : ISessionConfigurationCache { + private readonly IAppDataFolder _appDataFolder; + + public SessionConfigurationCache(IAppDataFolder appDataFolder) { + _appDataFolder = appDataFolder; + } + + public void StoreConfiguration(string shellName, Configuration config) { + var pathName = GetPathName(shellName); + + using (var stream = _appDataFolder.CreateFile(pathName)) { + new BinaryFormatter().Serialize(stream, config); + } + } + + public void DeleteConfiguration(string shellName) { + var pathName = GetPathName(shellName); + _appDataFolder.DeleteFile(pathName); + } + + public void DeleteAll() { + if (!_appDataFolder.DirectoryExists("Sites")) + return; + + foreach (var shellName in _appDataFolder.ListDirectories("Sites")) + DeleteConfiguration(shellName); + } + + public Configuration GetConfiguration(string shellName) { + var pathName = GetPathName(shellName); + + if (!_appDataFolder.FileExists(pathName)) { + return null; + } + + using (var stream = _appDataFolder.OpenFile(pathName)) { + return new BinaryFormatter().Deserialize(stream) as Configuration; + } + } + + private string GetPathName(string shellName) { + return _appDataFolder.Combine("Sites", shellName, "mappings.bin"); + } + } +} \ No newline at end of file diff --git a/src/Orchard/Data/SessionFactoryHolder.cs b/src/Orchard/Data/SessionFactoryHolder.cs index 76eac4cae..92667a03c 100644 --- a/src/Orchard/Data/SessionFactoryHolder.cs +++ b/src/Orchard/Data/SessionFactoryHolder.cs @@ -1,6 +1,4 @@ using System; -using System.IO; -using System.Runtime.Serialization.Formatters.Binary; using NHibernate; using NHibernate.Cfg; using Orchard.Data; @@ -18,51 +16,6 @@ namespace Orchard.Data { SessionFactoryParameters GetSessionFactoryParameters(); } - public interface ISessionConfigurationCache { - void StoreConfig(string shellName, Configuration config); - void DeleteConfig(string shellName); - Configuration GetConfiguration(string shellName); - } - - public class SessionConfigurationCache : ISessionConfigurationCache { - private readonly IAppDataFolder _appDataFolder; - - public SessionConfigurationCache(IAppDataFolder appDataFolder) { - _appDataFolder = appDataFolder; - } - - public void StoreConfig(string shellName, Configuration config) { - var filename = GetFileName(shellName); - - using ( var stream = File.OpenWrite(filename) ) { - new BinaryFormatter().Serialize(stream, config); - } - } - - public void DeleteConfig(string shellName) { - var filename = GetFileName(shellName); - if(File.Exists(filename)) { - File.Delete(filename); - } - } - - public Configuration GetConfiguration(string shellName) { - var filename = GetFileName(shellName); - - if (!_appDataFolder.FileExists(filename)) { - return null; - } - - using (var stream = File.OpenRead(filename)) { - return new BinaryFormatter().Deserialize(stream) as Configuration; - } - } - - private string GetFileName(string shellName) { - return _appDataFolder.MapPath(_appDataFolder.Combine("Sites", shellName, "mappings.bin")); - } - } - public class SessionFactoryHolder : ISessionFactoryHolder { private readonly ShellSettings _shellSettings; private readonly ShellBlueprint _shellBlueprint; @@ -127,7 +80,7 @@ namespace Orchard.Data { .CreateProvider(parameters) .BuildConfiguration(parameters); - _sessionConfigurationCache.StoreConfig(_shellSettings.Name, config); + _sessionConfigurationCache.StoreConfiguration(_shellSettings.Name, config); } return config; diff --git a/src/Orchard/Environment/ShellBuilders/ShellContextFactory.cs b/src/Orchard/Environment/ShellBuilders/ShellContextFactory.cs index d79598aed..4f3f723b5 100644 --- a/src/Orchard/Environment/ShellBuilders/ShellContextFactory.cs +++ b/src/Orchard/Environment/ShellBuilders/ShellContextFactory.cs @@ -74,7 +74,7 @@ namespace Orchard.Environment.ShellBuilders { if (currentDescriptor != null && knownDescriptor.SerialNumber != currentDescriptor.SerialNumber) { Logger.Information("Newer descriptor obtained. Rebuilding shell container."); - _sessionConfigurationCache.DeleteConfig(settings.Name); + _sessionConfigurationCache.DeleteConfiguration(settings.Name); _shellDescriptorCache.Store(settings.Name, currentDescriptor); blueprint = _compositionStrategy.Compose(settings, currentDescriptor); shellScope = _shellContainerFactory.CreateContainer(settings, blueprint); diff --git a/src/Orchard/FileSystems/AppData/AppDataFolder.cs b/src/Orchard/FileSystems/AppData/AppDataFolder.cs index c1e408144..6312196be 100644 --- a/src/Orchard/FileSystems/AppData/AppDataFolder.cs +++ b/src/Orchard/FileSystems/AppData/AppDataFolder.cs @@ -138,6 +138,10 @@ namespace Orchard.FileSystems.AppData { return File.Exists(CombineToPhysicalPath(path)); } + public bool DirectoryExists(string path) { + return Directory.Exists(CombineToPhysicalPath(path)); + } + public IEnumerable ListFiles(string path) { var directoryPath = CombineToPhysicalPath(path); if (!Directory.Exists(directoryPath)) diff --git a/src/Orchard/FileSystems/AppData/IAppDataFolder.cs b/src/Orchard/FileSystems/AppData/IAppDataFolder.cs index 491afcf93..ad4012b01 100644 --- a/src/Orchard/FileSystems/AppData/IAppDataFolder.cs +++ b/src/Orchard/FileSystems/AppData/IAppDataFolder.cs @@ -26,6 +26,7 @@ namespace Orchard.FileSystems.AppData { DateTime GetFileLastWriteTimeUtc(string path); void CreateDirectory(string path); + bool DirectoryExists(string path); IVolatileToken WhenPathChanges(string path); diff --git a/src/Orchard/FileSystems/Dependencies/DefaultDependenciesFolder.cs b/src/Orchard/FileSystems/Dependencies/DefaultDependenciesFolder.cs index e489af549..bbb045fbd 100644 --- a/src/Orchard/FileSystems/Dependencies/DefaultDependenciesFolder.cs +++ b/src/Orchard/FileSystems/Dependencies/DefaultDependenciesFolder.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Xml.Linq; using Orchard.Caching; +using Orchard.Data; using Orchard.FileSystems.AppData; using Orchard.Localization; @@ -12,11 +13,13 @@ namespace Orchard.FileSystems.Dependencies { private const string FileName = "dependencies.xml"; private readonly ICacheManager _cacheManager; private readonly IAppDataFolder _appDataFolder; + private readonly ISessionConfigurationCache _sessionConfigurationCache; private readonly InvalidationToken _writeThroughToken; - public DefaultDependenciesFolder(ICacheManager cacheManager, IAppDataFolder appDataFolder) { + public DefaultDependenciesFolder(ICacheManager cacheManager, IAppDataFolder appDataFolder, ISessionConfigurationCache sessionConfigurationCache) { _cacheManager = cacheManager; _appDataFolder = appDataFolder; + _sessionConfigurationCache = sessionConfigurationCache; _writeThroughToken = new InvalidationToken(); T = NullLocalizer.Instance; } @@ -50,6 +53,7 @@ namespace Orchard.FileSystems.Dependencies { var existingDescriptors = LoadDescriptors().OrderBy(d => d.Name); var newDescriptors = dependencyDescriptors.OrderBy(d => d.Name); if (!newDescriptors.SequenceEqual(existingDescriptors, new DependencyDescriptorComparer())) { + _sessionConfigurationCache.DeleteAll(); WriteDependencies(PersistencePath, dependencyDescriptors); } } diff --git a/src/Orchard/Orchard.Framework.csproj b/src/Orchard/Orchard.Framework.csproj index 20e72b6d3..1bb0afc46 100644 --- a/src/Orchard/Orchard.Framework.csproj +++ b/src/Orchard/Orchard.Framework.csproj @@ -360,6 +360,7 @@ Code + @@ -398,6 +399,7 @@ +