U4-9588 - filesystems manager tlc
This commit is contained in:
@@ -14,13 +14,16 @@ namespace Umbraco.Core.IO
|
|||||||
private readonly FileSystemProvidersSection _config;
|
private readonly FileSystemProvidersSection _config;
|
||||||
private readonly ConcurrentSet<ShadowWrapper> _wrappers = new ConcurrentSet<ShadowWrapper>();
|
private readonly ConcurrentSet<ShadowWrapper> _wrappers = new ConcurrentSet<ShadowWrapper>();
|
||||||
|
|
||||||
private readonly ShadowWrapper _macroPartialFileSystem;
|
private readonly ConcurrentDictionary<string, ProviderConstructionInfo> _providerLookup = new ConcurrentDictionary<string, ProviderConstructionInfo>();
|
||||||
private readonly ShadowWrapper _partialViewsFileSystem;
|
private readonly ConcurrentDictionary<string, IFileSystem2> _filesystems = new ConcurrentDictionary<string, IFileSystem2>();
|
||||||
private readonly ShadowWrapper _stylesheetsFileSystem;
|
|
||||||
private readonly ShadowWrapper _scriptsFileSystem;
|
private ShadowWrapper _macroPartialFileSystem;
|
||||||
private readonly ShadowWrapper _xsltFileSystem;
|
private ShadowWrapper _partialViewsFileSystem;
|
||||||
private readonly ShadowWrapper _masterPagesFileSystem;
|
private ShadowWrapper _stylesheetsFileSystem;
|
||||||
private readonly ShadowWrapper _mvcViewsFileSystem;
|
private ShadowWrapper _scriptsFileSystem;
|
||||||
|
private ShadowWrapper _xsltFileSystem;
|
||||||
|
private ShadowWrapper _masterPagesFileSystem;
|
||||||
|
private ShadowWrapper _mvcViewsFileSystem;
|
||||||
|
|
||||||
#region Singleton & Constructor
|
#region Singleton & Constructor
|
||||||
|
|
||||||
@@ -31,16 +34,30 @@ namespace Umbraco.Core.IO
|
|||||||
get { return Instance; }
|
get { return Instance; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for tests only, totally unsafe
|
||||||
|
internal void Reset()
|
||||||
|
{
|
||||||
|
_wrappers.Clear();
|
||||||
|
_providerLookup.Clear();
|
||||||
|
_filesystems.Clear();
|
||||||
|
CreateWellKnownFileSystems();
|
||||||
|
}
|
||||||
|
|
||||||
private IScopeProviderInternal ScopeProvider
|
private IScopeProviderInternal ScopeProvider
|
||||||
{
|
{
|
||||||
// fixme - 'course this is bad, but enough for now
|
// fixme - 'course this is bad, but enough for now
|
||||||
|
// beware: means that we capture the "current" scope provider - take care in tests!
|
||||||
get { return ApplicationContext.Current == null ? null : ApplicationContext.Current.ScopeProvider as IScopeProviderInternal; }
|
get { return ApplicationContext.Current == null ? null : ApplicationContext.Current.ScopeProvider as IScopeProviderInternal; }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal FileSystemProviderManager()
|
internal FileSystemProviderManager()
|
||||||
{
|
{
|
||||||
_config = (FileSystemProvidersSection) ConfigurationManager.GetSection("umbracoConfiguration/FileSystemProviders");
|
_config = (FileSystemProvidersSection) ConfigurationManager.GetSection("umbracoConfiguration/FileSystemProviders");
|
||||||
|
CreateWellKnownFileSystems();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateWellKnownFileSystems()
|
||||||
|
{
|
||||||
var macroPartialFileSystem = new PhysicalFileSystem(SystemDirectories.MacroPartials);
|
var macroPartialFileSystem = new PhysicalFileSystem(SystemDirectories.MacroPartials);
|
||||||
var partialViewsFileSystem = new PhysicalFileSystem(SystemDirectories.PartialViews);
|
var partialViewsFileSystem = new PhysicalFileSystem(SystemDirectories.PartialViews);
|
||||||
var stylesheetsFileSystem = new PhysicalFileSystem(SystemDirectories.Css);
|
var stylesheetsFileSystem = new PhysicalFileSystem(SystemDirectories.Css);
|
||||||
@@ -88,9 +105,6 @@ namespace Umbraco.Core.IO
|
|||||||
//public string ProviderAlias { get; set; }
|
//public string ProviderAlias { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly ConcurrentDictionary<string, ProviderConstructionInfo> _providerLookup = new ConcurrentDictionary<string, ProviderConstructionInfo>();
|
|
||||||
private readonly ConcurrentDictionary<string, IFileSystem2> _filesystems = new ConcurrentDictionary<string, IFileSystem2>();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets an underlying (non-typed) filesystem supporting a strongly-typed filesystem.
|
/// Gets an underlying (non-typed) filesystem supporting a strongly-typed filesystem.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -266,6 +280,14 @@ namespace Umbraco.Core.IO
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
lock (_set)
|
||||||
|
{
|
||||||
|
_set.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public T[] ToArray()
|
public T[] ToArray()
|
||||||
{
|
{
|
||||||
lock (_set)
|
lock (_set)
|
||||||
|
|||||||
@@ -21,6 +21,17 @@ namespace Umbraco.Tests.IO
|
|||||||
|
|
||||||
// media fs wants this
|
// media fs wants this
|
||||||
ApplicationContext.Current = new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(), new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
ApplicationContext.Current = new ApplicationContext(CacheHelper.CreateDisabledCacheHelper(), new ProfilingLogger(Mock.Of<ILogger>(), Mock.Of<IProfiler>()));
|
||||||
|
|
||||||
|
// start clean
|
||||||
|
// because some tests will create corrupt or weird filesystems
|
||||||
|
FileSystemProviderManager.Current.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
[TearDown]
|
||||||
|
public void TearDown()
|
||||||
|
{
|
||||||
|
// stay clean (see note in SetUp)
|
||||||
|
FileSystemProviderManager.Current.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -39,22 +50,53 @@ namespace Umbraco.Tests.IO
|
|||||||
Assert.NotNull(fs);
|
Assert.NotNull(fs);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
public void Singleton_Typed_File_System()
|
||||||
|
{
|
||||||
|
var fs1 = FileSystemProviderManager.Current.GetFileSystemProvider<MediaFileSystem>();
|
||||||
|
var fs2 = FileSystemProviderManager.Current.GetFileSystemProvider<MediaFileSystem>();
|
||||||
|
|
||||||
|
Assert.AreSame(fs1, fs2);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
public void Exception_Thrown_On_Invalid_Typed_File_System()
|
public void Exception_Thrown_On_Invalid_Typed_File_System()
|
||||||
{
|
{
|
||||||
Assert.Throws<InvalidOperationException>(() => FileSystemProviderManager.Current.GetFileSystemProvider<InvalidTypedFileSystem>());
|
Assert.Throws<InvalidOperationException>(() => FileSystemProviderManager.Current.GetFileSystemProvider<InvalidTypedFileSystem>());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
[Test]
|
||||||
/// Used in unit tests, for a typed file system we need to inherit from FileSystemWrapper and they MUST have a ctor
|
public void Exception_Thrown_On_NonConfigured_Typed_File_System()
|
||||||
/// that only accepts a base IFileSystem object
|
{
|
||||||
/// </summary>
|
// note: we need to reset the manager between tests else the Accept_Fallback test would corrupt that one
|
||||||
internal class InvalidTypedFileSystem : FileSystemWrapper
|
Assert.Throws<ArgumentException>(() => FileSystemProviderManager.Current.GetFileSystemProvider<NonConfiguredTypeFileSystem>());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Accept_Fallback_On_NonConfigured_Typed_File_System()
|
||||||
|
{
|
||||||
|
var fs = FileSystemProviderManager.Current.GetFileSystemProvider<NonConfiguredTypeFileSystem>(() => new PhysicalFileSystem("~/App_Data/foo"));
|
||||||
|
|
||||||
|
Assert.NotNull(fs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used in unit tests, for a typed file system we need to inherit from FileSystemWrapper and they MUST have a ctor
|
||||||
|
/// that only accepts a base IFileSystem object
|
||||||
|
/// </summary>
|
||||||
|
internal class InvalidTypedFileSystem : FileSystemWrapper
|
||||||
{
|
{
|
||||||
public InvalidTypedFileSystem(IFileSystem wrapped, string invalidParam) : base(wrapped)
|
public InvalidTypedFileSystem(IFileSystem wrapped, string invalidParam)
|
||||||
{
|
: base(wrapped)
|
||||||
}
|
{ }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[FileSystemProvider("noconfig")]
|
||||||
|
internal class NonConfiguredTypeFileSystem : FileSystemWrapper
|
||||||
|
{
|
||||||
|
public NonConfiguredTypeFileSystem(IFileSystem wrapped)
|
||||||
|
: base(wrapped)
|
||||||
|
{ }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -806,6 +806,7 @@ namespace Umbraco.Tests.IO
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
[Ignore("Does not work on all environments, Directory.GetFiles is broken.")]
|
||||||
public void ShadowGetFilesUsingWildcardAndSingleCharacterFilter()
|
public void ShadowGetFilesUsingWildcardAndSingleCharacterFilter()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
@@ -846,6 +847,7 @@ namespace Umbraco.Tests.IO
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
[Ignore("Does not work on all environments, Directory.GetFiles is broken.")]
|
||||||
public void ShadowFileSystemFilterIsAsBrokenAsRealFileSystemFilter()
|
public void ShadowFileSystemFilterIsAsBrokenAsRealFileSystemFilter()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ namespace Umbraco.Tests.Scoping
|
|||||||
|
|
||||||
private static void ClearFiles()
|
private static void ClearFiles()
|
||||||
{
|
{
|
||||||
|
TestHelper.DeleteDirectory(IOHelper.MapPath("media"));
|
||||||
TestHelper.DeleteDirectory(IOHelper.MapPath("FileSysTests"));
|
TestHelper.DeleteDirectory(IOHelper.MapPath("FileSysTests"));
|
||||||
TestHelper.DeleteDirectory(IOHelper.MapPath("App_Data"));
|
TestHelper.DeleteDirectory(IOHelper.MapPath("App_Data"));
|
||||||
}
|
}
|
||||||
@@ -43,6 +44,8 @@ namespace Umbraco.Tests.Scoping
|
|||||||
var physMediaFileSystem = new PhysicalFileSystem(IOHelper.MapPath("media"), "ignore");
|
var physMediaFileSystem = new PhysicalFileSystem(IOHelper.MapPath("media"), "ignore");
|
||||||
var mediaFileSystem = FileSystemProviderManager.Current.MediaFileSystem;
|
var mediaFileSystem = FileSystemProviderManager.Current.MediaFileSystem;
|
||||||
|
|
||||||
|
Assert.IsFalse(physMediaFileSystem.FileExists("f1.txt"));
|
||||||
|
|
||||||
var scopeProvider = ApplicationContext.ScopeProvider;
|
var scopeProvider = ApplicationContext.ScopeProvider;
|
||||||
using (var scope = scopeProvider.CreateScope(scopeFileSystems: true))
|
using (var scope = scopeProvider.CreateScope(scopeFileSystems: true))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ using Umbraco.Web.PublishedCache.XmlPublishedCache;
|
|||||||
using Umbraco.Web.Security;
|
using Umbraco.Web.Security;
|
||||||
using umbraco.BusinessLogic;
|
using umbraco.BusinessLogic;
|
||||||
using Umbraco.Core.Events;
|
using Umbraco.Core.Events;
|
||||||
|
using Umbraco.Core.IO;
|
||||||
using Umbraco.Core.Scoping;
|
using Umbraco.Core.Scoping;
|
||||||
|
|
||||||
namespace Umbraco.Tests.TestHelpers
|
namespace Umbraco.Tests.TestHelpers
|
||||||
@@ -110,6 +111,7 @@ namespace Umbraco.Tests.TestHelpers
|
|||||||
{
|
{
|
||||||
IsReady = true
|
IsReady = true
|
||||||
};
|
};
|
||||||
|
|
||||||
return _appContext;
|
return _appContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ using Umbraco.Web;
|
|||||||
using Umbraco.Web.Models.Mapping;
|
using Umbraco.Web.Models.Mapping;
|
||||||
using umbraco.BusinessLogic;
|
using umbraco.BusinessLogic;
|
||||||
using Umbraco.Core.Events;
|
using Umbraco.Core.Events;
|
||||||
|
using Umbraco.Core.IO;
|
||||||
using Umbraco.Core.Scoping;
|
using Umbraco.Core.Scoping;
|
||||||
|
|
||||||
namespace Umbraco.Tests.TestHelpers
|
namespace Umbraco.Tests.TestHelpers
|
||||||
@@ -150,6 +151,11 @@ namespace Umbraco.Tests.TestHelpers
|
|||||||
{
|
{
|
||||||
var applicationContext = CreateApplicationContext();
|
var applicationContext = CreateApplicationContext();
|
||||||
ApplicationContext.Current = applicationContext;
|
ApplicationContext.Current = applicationContext;
|
||||||
|
|
||||||
|
// FileSystemProviderManager captures the current ApplicationContext ScopeProvider
|
||||||
|
// in its current static instance (yea...) so we need to reset it here to ensure
|
||||||
|
// it is using the proper ScopeProvider
|
||||||
|
FileSystemProviderManager.Current.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual ApplicationContext CreateApplicationContext()
|
protected virtual ApplicationContext CreateApplicationContext()
|
||||||
@@ -170,6 +176,7 @@ namespace Umbraco.Tests.TestHelpers
|
|||||||
{
|
{
|
||||||
IsReady = true
|
IsReady = true
|
||||||
};
|
};
|
||||||
|
|
||||||
return applicationContext;
|
return applicationContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user