Bugfix FileSystems vs Scopes

This commit is contained in:
Stephan
2017-05-31 15:25:24 +02:00
parent d0abbf0664
commit e11b267ef4
4 changed files with 111 additions and 44 deletions

View File

@@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Reflection;
using System.Threading;
using Umbraco.Core.Configuration;
using Umbraco.Core.Logging;
using Umbraco.Core.Composing;
@@ -29,6 +30,13 @@ namespace Umbraco.Core.IO
private ShadowWrapper _masterPagesFileSystem;
private ShadowWrapper _mvcViewsFileSystem;
// well-known file systems lazy initialization
private object _wkfsLock = new object();
private bool _wkfsInitialized;
private object _wkfsObject;
private MediaFileSystem _mediaFileSystem;
#region Constructor
// DI wants a public ctor
@@ -37,7 +45,6 @@ namespace Umbraco.Core.IO
{
_config = (FileSystemProvidersSection)ConfigurationManager.GetSection("umbracoConfiguration/FileSystemProviders");
_logger = logger;
CreateWellKnownFileSystems();
}
// for tests only, totally unsafe
@@ -46,25 +53,95 @@ namespace Umbraco.Core.IO
_wrappers.Clear();
_providerLookup.Clear();
_filesystems.Clear();
CreateWellKnownFileSystems();
Volatile.Write(ref _wkfsInitialized, false);
}
internal Func<bool> IsScoped { get; set; }
internal Func<bool> IsScoped { get; set; } = () => false;
#endregion
#region Well-Known FileSystems
public IFileSystem MacroPartialsFileSystem => _macroPartialFileSystem;
public IFileSystem PartialViewsFileSystem => _partialViewsFileSystem;
public IFileSystem StylesheetsFileSystem => _stylesheetsFileSystem;
public IFileSystem ScriptsFileSystem => _scriptsFileSystem;
public IFileSystem XsltFileSystem => _xsltFileSystem;
public IFileSystem MasterPagesFileSystem => _masterPagesFileSystem; // fixme - see 7.6?!
public IFileSystem MvcViewsFileSystem => _mvcViewsFileSystem;
public MediaFileSystem MediaFileSystem { get; private set; }
public IFileSystem MacroPartialsFileSystem
{
get
{
if (Volatile.Read(ref _wkfsInitialized) == false) EnsureWellKnownFileSystems();
return _macroPartialFileSystem;
}
}
private void CreateWellKnownFileSystems()
public IFileSystem PartialViewsFileSystem
{
get
{
if (Volatile.Read(ref _wkfsInitialized) == false) EnsureWellKnownFileSystems();
return _partialViewsFileSystem;
}
}
public IFileSystem StylesheetsFileSystem
{
get
{
if (Volatile.Read(ref _wkfsInitialized) == false) EnsureWellKnownFileSystems();
return _stylesheetsFileSystem;
}
}
public IFileSystem ScriptsFileSystem
{
get
{
if (Volatile.Read(ref _wkfsInitialized) == false) EnsureWellKnownFileSystems();
return _scriptsFileSystem;
}
}
public IFileSystem XsltFileSystem
{
get
{
if (Volatile.Read(ref _wkfsInitialized) == false) EnsureWellKnownFileSystems();
return _xsltFileSystem;
}
}
public IFileSystem MasterPagesFileSystem
{
get
{
if (Volatile.Read(ref _wkfsInitialized) == false) EnsureWellKnownFileSystems();
return _masterPagesFileSystem;// fixme - see 7.6?!
}
}
public IFileSystem MvcViewsFileSystem
{
get
{
if (Volatile.Read(ref _wkfsInitialized) == false) EnsureWellKnownFileSystems();
return _mvcViewsFileSystem;
}
}
public MediaFileSystem MediaFileSystem
{
get
{
if (Volatile.Read(ref _wkfsInitialized) == false) EnsureWellKnownFileSystems();
return _mediaFileSystem;
}
}
private void EnsureWellKnownFileSystems()
{
LazyInitializer.EnsureInitialized(ref _wkfsObject, ref _wkfsInitialized, ref _wkfsLock, CreateWellKnownFileSystems);
}
// need to return something to LazyInitializer.EnsureInitialized
// but it does not really matter what we return - here, null
private object CreateWellKnownFileSystems()
{
var macroPartialFileSystem = new PhysicalFileSystem(SystemDirectories.MacroPartials);
var partialViewsFileSystem = new PhysicalFileSystem(SystemDirectories.PartialViews);
@@ -74,16 +151,18 @@ namespace Umbraco.Core.IO
var masterPagesFileSystem = new PhysicalFileSystem(SystemDirectories.Masterpages);
var mvcViewsFileSystem = new PhysicalFileSystem(SystemDirectories.MvcViews);
_macroPartialFileSystem = new ShadowWrapper(macroPartialFileSystem, "Views/MacroPartials", IsScoped);
_partialViewsFileSystem = new ShadowWrapper(partialViewsFileSystem, "Views/Partials", IsScoped);
_stylesheetsFileSystem = new ShadowWrapper(stylesheetsFileSystem, "css", IsScoped);
_scriptsFileSystem = new ShadowWrapper(scriptsFileSystem, "scripts", IsScoped);
_xsltFileSystem = new ShadowWrapper(xsltFileSystem, "xslt", IsScoped);
_masterPagesFileSystem = new ShadowWrapper(masterPagesFileSystem, "masterpages", IsScoped);
_mvcViewsFileSystem = new ShadowWrapper(mvcViewsFileSystem, "Views", IsScoped);
_macroPartialFileSystem = new ShadowWrapper(macroPartialFileSystem, "Views/MacroPartials", () => IsScoped());
_partialViewsFileSystem = new ShadowWrapper(partialViewsFileSystem, "Views/Partials", () => IsScoped());
_stylesheetsFileSystem = new ShadowWrapper(stylesheetsFileSystem, "css", () => IsScoped());
_scriptsFileSystem = new ShadowWrapper(scriptsFileSystem, "scripts", () => IsScoped());
_xsltFileSystem = new ShadowWrapper(xsltFileSystem, "xslt", () => IsScoped());
_masterPagesFileSystem = new ShadowWrapper(masterPagesFileSystem, "masterpages", () => IsScoped());
_mvcViewsFileSystem = new ShadowWrapper(mvcViewsFileSystem, "Views", () => IsScoped());
// filesystems obtained from GetFileSystemProvider are already wrapped and do not need to be wrapped again
MediaFileSystem = GetFileSystemProvider<MediaFileSystem>();
_mediaFileSystem = GetFileSystemProvider<MediaFileSystem>();
return null;
}
#endregion
@@ -215,7 +294,7 @@ namespace Umbraco.Core.IO
// so we are double-wrapping here
// could be optimized by having FileSystemWrapper inherit from ShadowWrapper, maybe
var innerFs = GetUnderlyingFileSystemNoCache(alias, fallback);
var shadowWrapper = new ShadowWrapper(innerFs, "typed/" + alias, IsScoped);
var shadowWrapper = new ShadowWrapper(innerFs, "typed/" + alias, () => IsScoped());
var fs = (IFileSystem) Activator.CreateInstance(typeof(TFileSystem), shadowWrapper);
_wrappers.Add(shadowWrapper); // keeping a reference to the wrapper
return fs;

View File

@@ -19,7 +19,7 @@ namespace Umbraco.Core.IO
{
_innerFileSystem = innerFileSystem;
_shadowPath = shadowPath;
_isScoped = isScoped ?? (() => false);
_isScoped = isScoped;
}
internal void Shadow(Guid id)

View File

@@ -12,12 +12,9 @@ namespace Umbraco.Core.Persistence.Migrations
{
public MigrationContext(IUmbracoDatabase database, ILogger logger)
{
if (database == null) throw new ArgumentNullException(nameof(database));
if (logger == null) throw new ArgumentNullException(nameof(logger));
Expressions = new Collection<IMigrationExpression>();
Database = database;
Logger = logger;
Database = database ?? throw new ArgumentNullException(nameof(database));
Logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public ICollection<IMigrationExpression> Expressions { get; set; }

View File

@@ -31,6 +31,8 @@ namespace Umbraco.Core.Scoping
// take control of the FileSystems
_fileSystems.IsScoped = () => AmbientScope != null && AmbientScope.ScopedFileSystems;
_scopeReference = new ScopeReference(this);
}
static ScopeProvider()
@@ -230,7 +232,7 @@ namespace Umbraco.Core.Scoping
internal const string ContextItemKey = "Umbraco.Core.Scoping.ScopeContext";
internal static ScopeContext AmbientContextStatic
public ScopeContext AmbientContext
{
get
{
@@ -251,9 +253,6 @@ namespace Umbraco.Core.Scoping
}
}
/// <inheritdoc />
public ScopeContext AmbientContext => AmbientContextStatic;
#endregion
#region Ambient Scope
@@ -262,10 +261,9 @@ namespace Umbraco.Core.Scoping
internal const string ScopeRefItemKey = "Umbraco.Core.Scoping.ScopeReference";
// only 1 instance which can be disposed and disposed again
// fixme - more weird static - we should try to get rid of all static & use an accessor
private static readonly ScopeReference StaticScopeReference = new ScopeReference(new ScopeProvider(null, null, null));
private readonly ScopeReference _scopeReference;
private static Scope AmbientScopeStatic
public Scope AmbientScope
{
get
{
@@ -283,19 +281,12 @@ namespace Umbraco.Core.Scoping
// set http/call context
if (value.CallContext == false && SetHttpContextObject(ScopeItemKey, value, false))
SetHttpContextObject(ScopeRefItemKey, StaticScopeReference);
SetHttpContextObject(ScopeRefItemKey, _scopeReference);
else
SetCallContextObject(ScopeItemKey, value);
}
}
/// <inheritdoc />
public Scope AmbientScope
{
get => AmbientScopeStatic;
set => AmbientScopeStatic = value;
}
#endregion
public void SetAmbient(Scope scope, ScopeContext context = null)
@@ -315,7 +306,7 @@ namespace Umbraco.Core.Scoping
if (scope.CallContext == false && SetHttpContextObject(ScopeItemKey, scope, false))
{
SetHttpContextObject(ScopeRefItemKey, StaticScopeReference);
SetHttpContextObject(ScopeRefItemKey, _scopeReference);
SetHttpContextObject(ContextItemKey, context);
}
else
@@ -410,7 +401,7 @@ namespace Umbraco.Core.Scoping
var scope = AmbientScope as Scope;
scope?.Reset();
StaticScopeReference.Dispose();
_scopeReference.Dispose();
}
/// <inheritdoc />