diff --git a/src/Umbraco.Core/Cache/ObjectCacheAppCache.cs b/src/Umbraco.Core/Cache/ObjectCacheAppCache.cs index 7096d077a2..b5103f4338 100644 --- a/src/Umbraco.Core/Cache/ObjectCacheAppCache.cs +++ b/src/Umbraco.Core/Cache/ObjectCacheAppCache.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Caching; @@ -107,19 +107,34 @@ namespace Umbraco.Cms.Core.Cache Lazy result; - using (var lck = new UpgradeableReadLock(_locker)) + try { + _locker.EnterUpgradeableReadLock(); + result = MemoryCache.Get(key) as Lazy; if (result == null || SafeLazy.GetSafeLazyValue(result, true) == null) // get non-created as NonCreatedValue & exceptions as null { result = SafeLazy.GetSafeLazy(factory); var policy = GetPolicy(timeout, isSliding, dependentFiles); - lck.UpgradeToWriteLock(); - //NOTE: This does an add or update - MemoryCache.Set(key, result, policy); + try + { + _locker.EnterWriteLock(); + //NOTE: This does an add or update + MemoryCache.Set(key, result, policy); + } + finally + { + if (_locker.IsWriteLockHeld) + _locker.ExitWriteLock(); + } } } + finally + { + if (_locker.IsUpgradeableReadLockHeld) + _locker.ExitUpgradeableReadLock(); + } //return result.Value; diff --git a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs index add0ec3fa7..366c411ade 100644 --- a/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs +++ b/src/Umbraco.Core/DependencyInjection/UmbracoBuilder.cs @@ -167,7 +167,7 @@ namespace Umbraco.Cms.Core.DependencyInjection Services.AddUnique(); Services.AddUnique(); - Services.AddUnique(); + Services.AddUnique(); Services.AddUnique(); Services.AddUnique(); diff --git a/src/Umbraco.Core/ReadLock.cs b/src/Umbraco.Core/ReadLock.cs deleted file mode 100644 index 67aeb7062a..0000000000 --- a/src/Umbraco.Core/ReadLock.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.Threading; - -namespace Umbraco.Cms.Core -{ - /// - /// Provides a convenience methodology for implementing locked access to resources. - /// - /// - /// Intended as an infrastructure class. - /// This is a very inefficient way to lock as it allocates one object each time we lock, - /// so it's OK to use this class for things that happen once, where it is convenient, but not - /// for performance-critical code! - /// - public class ReadLock : IDisposable - { - private readonly ReaderWriterLockSlim _rwLock; - - /// - /// Initializes a new instance of the class. - /// - public ReadLock(ReaderWriterLockSlim rwLock) - { - _rwLock = rwLock; - _rwLock.EnterReadLock(); - } - - void IDisposable.Dispose() - { - _rwLock.ExitReadLock(); - } - } -} diff --git a/src/Umbraco.Core/Routing/AliasUrlProvider.cs b/src/Umbraco.Core/Routing/AliasUrlProvider.cs index 8b4c633158..6ef6348de8 100644 --- a/src/Umbraco.Core/Routing/AliasUrlProvider.cs +++ b/src/Umbraco.Core/Routing/AliasUrlProvider.cs @@ -15,15 +15,15 @@ namespace Umbraco.Cms.Core.Routing public class AliasUrlProvider : IUrlProvider { private readonly RequestHandlerSettings _requestConfig; - private readonly ISiteDomainHelper _siteDomainHelper; + private readonly ISiteDomainMapper _siteDomainMapper; private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly UriUtility _uriUtility; private readonly IPublishedValueFallback _publishedValueFallback; - public AliasUrlProvider(IOptions requestConfig, ISiteDomainHelper siteDomainHelper, UriUtility uriUtility, IPublishedValueFallback publishedValueFallback, IUmbracoContextAccessor umbracoContextAccessor) + public AliasUrlProvider(IOptions requestConfig, ISiteDomainMapper siteDomainMapper, UriUtility uriUtility, IPublishedValueFallback publishedValueFallback, IUmbracoContextAccessor umbracoContextAccessor) { _requestConfig = requestConfig.Value; - _siteDomainHelper = siteDomainHelper; + _siteDomainMapper = siteDomainMapper; _uriUtility = uriUtility; _publishedValueFallback = publishedValueFallback; _umbracoContextAccessor = umbracoContextAccessor; @@ -68,12 +68,12 @@ namespace Umbraco.Cms.Core.Routing // look for domains, walking up the tree var n = node; - var domainUris = DomainUtilities.DomainsForNode(umbracoContext.PublishedSnapshot.Domains, _siteDomainHelper, n.Id, current, false); + var domainUris = DomainUtilities.DomainsForNode(umbracoContext.PublishedSnapshot.Domains, _siteDomainMapper, n.Id, current, false); while (domainUris == null && n != null) // n is null at root { // move to parent node n = n.Parent; - domainUris = n == null ? null : DomainUtilities.DomainsForNode(umbracoContext.PublishedSnapshot.Domains, _siteDomainHelper, n.Id, current, excludeDefault: false); + domainUris = n == null ? null : DomainUtilities.DomainsForNode(umbracoContext.PublishedSnapshot.Domains, _siteDomainMapper, n.Id, current, excludeDefault: false); } // determine whether the alias property varies diff --git a/src/Umbraco.Core/Routing/DefaultUrlProvider.cs b/src/Umbraco.Core/Routing/DefaultUrlProvider.cs index 2b1693e03f..98e5376cea 100644 --- a/src/Umbraco.Core/Routing/DefaultUrlProvider.cs +++ b/src/Umbraco.Core/Routing/DefaultUrlProvider.cs @@ -15,15 +15,15 @@ namespace Umbraco.Cms.Core.Routing { private readonly RequestHandlerSettings _requestSettings; private readonly ILogger _logger; - private readonly ISiteDomainHelper _siteDomainHelper; + private readonly ISiteDomainMapper _siteDomainMapper; private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly UriUtility _uriUtility; - public DefaultUrlProvider(IOptions requestSettings, ILogger logger, ISiteDomainHelper siteDomainHelper, IUmbracoContextAccessor umbracoContextAccessor, UriUtility uriUtility) + public DefaultUrlProvider(IOptions requestSettings, ILogger logger, ISiteDomainMapper siteDomainMapper, IUmbracoContextAccessor umbracoContextAccessor, UriUtility uriUtility) { _requestSettings = requestSettings.Value; _logger = logger; - _siteDomainHelper = siteDomainHelper; + _siteDomainMapper = siteDomainMapper; _uriUtility = uriUtility; _umbracoContextAccessor = umbracoContextAccessor; } @@ -56,7 +56,7 @@ namespace Umbraco.Cms.Core.Routing var path = pos == 0 ? route : route.Substring(pos); var domainUri = pos == 0 ? null - : DomainUtilities.DomainForNode(umbracoContext.PublishedSnapshot.Domains, _siteDomainHelper, int.Parse(route.Substring(0, pos)), current, culture); + : DomainUtilities.DomainForNode(umbracoContext.PublishedSnapshot.Domains, _siteDomainMapper, int.Parse(route.Substring(0, pos)), current, culture); // assemble the URL from domainUri (maybe null) and path var url = AssembleUrl(domainUri, path, current, mode).ToString(); @@ -90,11 +90,11 @@ namespace Umbraco.Cms.Core.Routing // look for domains, walking up the tree var n = node; - var domainUris = DomainUtilities.DomainsForNode(umbracoContext.PublishedSnapshot.Domains, _siteDomainHelper, n.Id, current, false); + var domainUris = DomainUtilities.DomainsForNode(umbracoContext.PublishedSnapshot.Domains, _siteDomainMapper, n.Id, current, false); while (domainUris == null && n != null) // n is null at root { n = n.Parent; // move to parent node - domainUris = n == null ? null : DomainUtilities.DomainsForNode(umbracoContext.PublishedSnapshot.Domains, _siteDomainHelper, n.Id, current, excludeDefault: true); + domainUris = n == null ? null : DomainUtilities.DomainsForNode(umbracoContext.PublishedSnapshot.Domains, _siteDomainMapper, n.Id, current, excludeDefault: true); } // no domains = exit diff --git a/src/Umbraco.Core/Routing/DomainUtilities.cs b/src/Umbraco.Core/Routing/DomainUtilities.cs index 76266f9704..153eb9d4e8 100644 --- a/src/Umbraco.Core/Routing/DomainUtilities.cs +++ b/src/Umbraco.Core/Routing/DomainUtilities.cs @@ -21,14 +21,14 @@ namespace Umbraco.Cms.Core.Routing /// The document path. /// An optional current Uri. /// An Umbraco context. - /// The site domain helper. + /// The site domain helper. /// The culture assigned to the document by domains. /// /// In 1:1 multilingual setup, a document contains several cultures (there is not /// one document per culture), and domains, withing the context of a current Uri, assign /// a culture to that document. /// - public static string GetCultureFromDomains(int contentId, string contentPath, Uri current, IUmbracoContext umbracoContext, ISiteDomainHelper siteDomainHelper) + public static string GetCultureFromDomains(int contentId, string contentPath, Uri current, IUmbracoContext umbracoContext, ISiteDomainMapper siteDomainMapper) { if (umbracoContext == null) throw new InvalidOperationException("A current UmbracoContext is required."); @@ -47,7 +47,7 @@ namespace Umbraco.Cms.Core.Routing var pos = route.IndexOf('/'); var domain = pos == 0 ? null - : DomainForNode(umbracoContext.Domains, siteDomainHelper, int.Parse(route.Substring(0, pos)), current); + : DomainForNode(umbracoContext.Domains, siteDomainMapper, int.Parse(route.Substring(0, pos)), current); var rootContentId = domain?.ContentId ?? -1; var wcDomain = FindWildcardDomainInPath(umbracoContext.Domains.GetAll(true), contentPath, rootContentId); @@ -65,7 +65,7 @@ namespace Umbraco.Cms.Core.Routing /// Finds the domain for the specified node, if any, that best matches a specified uri. /// /// A domain cache. - /// The site domain helper. + /// The site domain helper. /// The node identifier. /// The uri, or null. /// The culture, or null. @@ -76,7 +76,7 @@ namespace Umbraco.Cms.Core.Routing /// If culture is null, uses the default culture for the installation instead. Otherwise, /// will try with the specified culture, else return null. /// - internal static DomainAndUri DomainForNode(IDomainCache domainCache, ISiteDomainHelper siteDomainHelper, int nodeId, Uri current, string culture = null) + internal static DomainAndUri DomainForNode(IDomainCache domainCache, ISiteDomainMapper siteDomainMapper, int nodeId, Uri current, string culture = null) { // be safe if (nodeId <= 0) @@ -91,21 +91,21 @@ namespace Umbraco.Cms.Core.Routing // else filter // it could be that none apply (due to culture) - return SelectDomain(domains, current, culture, domainCache.DefaultCulture, siteDomainHelper.MapDomain); + return SelectDomain(domains, current, culture, domainCache.DefaultCulture, siteDomainMapper.MapDomain); } /// /// Find the domains for the specified node, if any, that match a specified uri. /// /// A domain cache. - /// The site domain helper. + /// The site domain helper. /// The node identifier. /// The uri, or null. /// A value indicating whether to exclude the current/default domain. True by default. /// The domains and their uris, that match the specified uri, else null. /// If at least a domain is set on the node then the method returns the domains that /// best match the specified uri, else it returns null. - internal static IEnumerable DomainsForNode(IDomainCache domainCache, ISiteDomainHelper siteDomainHelper, int nodeId, Uri current, bool excludeDefault = true) + internal static IEnumerable DomainsForNode(IDomainCache domainCache, ISiteDomainMapper siteDomainMapper, int nodeId, Uri current, bool excludeDefault = true) { // be safe if (nodeId <= 0) @@ -122,7 +122,7 @@ namespace Umbraco.Cms.Core.Routing var domainAndUris = SelectDomains(domains, current).ToArray(); // filter - return siteDomainHelper.MapDomains(domainAndUris, current, excludeDefault, null, domainCache.DefaultCulture).ToArray(); + return siteDomainMapper.MapDomains(domainAndUris, current, excludeDefault, null, domainCache.DefaultCulture).ToArray(); } #endregion diff --git a/src/Umbraco.Core/Routing/ISiteDomainHelper.cs b/src/Umbraco.Core/Routing/ISiteDomainMapper.cs similarity index 97% rename from src/Umbraco.Core/Routing/ISiteDomainHelper.cs rename to src/Umbraco.Core/Routing/ISiteDomainMapper.cs index 86a8e584b3..3ec280f007 100644 --- a/src/Umbraco.Core/Routing/ISiteDomainHelper.cs +++ b/src/Umbraco.Core/Routing/ISiteDomainMapper.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; namespace Umbraco.Cms.Core.Routing @@ -6,7 +6,7 @@ namespace Umbraco.Cms.Core.Routing /// /// Provides utilities to handle site domains. /// - public interface ISiteDomainHelper + public interface ISiteDomainMapper { /// /// Filters a list of DomainAndUri to pick one that best matches the current request. diff --git a/src/Umbraco.Core/Routing/SiteDomainHelper.cs b/src/Umbraco.Core/Routing/SiteDomainMapper.cs similarity index 63% rename from src/Umbraco.Core/Routing/SiteDomainHelper.cs rename to src/Umbraco.Core/Routing/SiteDomainMapper.cs index 5b475f72e8..d10ee8fc10 100644 --- a/src/Umbraco.Core/Routing/SiteDomainHelper.cs +++ b/src/Umbraco.Core/Routing/SiteDomainMapper.cs @@ -7,61 +7,54 @@ using Umbraco.Extensions; namespace Umbraco.Cms.Core.Routing { - /// + /// /// Provides utilities to handle site domains. - /// - public class SiteDomainHelper : ISiteDomainHelper + /// + public class SiteDomainMapper : ISiteDomainMapper, IDisposable { #region Configure - private static readonly ReaderWriterLockSlim ConfigLock = new ReaderWriterLockSlim(); - private static Dictionary _sites; - private static Dictionary> _bindings; - private static Dictionary> _qualifiedSites; + private readonly ReaderWriterLockSlim _configLock = new ReaderWriterLockSlim(); + private Dictionary> _qualifiedSites; + private bool _disposedValue; - // these are for unit tests *only* - // ReSharper disable ConvertToAutoPropertyWithPrivateSetter - internal static Dictionary Sites => _sites; - internal static Dictionary> Bindings => _bindings; - // ReSharper restore ConvertToAutoPropertyWithPrivateSetter + internal Dictionary Sites { get; private set; } + internal Dictionary> Bindings { get; private set; } // these are for validation //private const string DomainValidationSource = @"^(\*|((?i:http[s]?://)?([-\w]+(\.[-\w]+)*)(:\d+)?(/[-\w]*)?))$"; private const string DomainValidationSource = @"^(((?i:http[s]?://)?([-\w]+(\.[-\w]+)*)(:\d+)?(/)?))$"; - private static readonly Regex DomainValidation = new Regex(DomainValidationSource, RegexOptions.IgnoreCase | RegexOptions.Compiled); - - /// - /// Returns a disposable object that represents safe write access to config. - /// - /// Should be used in a using(SiteDomainHelper.ConfigWriteLock) { ... } mode. - protected static IDisposable ConfigWriteLock => new WriteLock(ConfigLock); - - /// - /// Returns a disposable object that represents safe read access to config. - /// - /// Should be used in a using(SiteDomainHelper.ConfigWriteLock) { ... } mode. - protected static IDisposable ConfigReadLock => new ReadLock(ConfigLock); + private static readonly Regex s_domainValidation = new Regex(DomainValidationSource, RegexOptions.IgnoreCase | RegexOptions.Compiled); /// /// Clears the entire configuration. /// - public static void Clear() + public void Clear() { - using (ConfigWriteLock) + try { - _sites = null; - _bindings = null; + _configLock.EnterWriteLock(); + + Sites = null; + Bindings = null; _qualifiedSites = null; } + finally + { + if (_configLock.IsWriteLockHeld) + { + _configLock.ExitWriteLock(); + } + } } - private static IEnumerable ValidateDomains(IEnumerable domains) + private IEnumerable ValidateDomains(IEnumerable domains) { // must use authority format w/optional scheme and port, but no path // any domain should appear only once return domains.Select(domain => { - if (!DomainValidation.IsMatch(domain)) + if (!s_domainValidation.IsMatch(domain)) throw new ArgumentOutOfRangeException(nameof(domains), $"Invalid domain: \"{domain}\"."); return domain; }); @@ -73,14 +66,23 @@ namespace Umbraco.Cms.Core.Routing /// A key uniquely identifying the site. /// The site domains. /// At the moment there is no public way to remove a site. Clear and reconfigure. - public static void AddSite(string key, IEnumerable domains) + public void AddSite(string key, IEnumerable domains) { - using (ConfigWriteLock) + try { - _sites = _sites ?? new Dictionary(); - _sites[key] = ValidateDomains(domains).ToArray(); + _configLock.EnterWriteLock(); + + Sites = Sites ?? new Dictionary(); + Sites[key] = ValidateDomains(domains).ToArray(); _qualifiedSites = null; } + finally + { + if (_configLock.IsWriteLockHeld) + { + _configLock.ExitWriteLock(); + } + } } /// @@ -89,66 +91,86 @@ namespace Umbraco.Cms.Core.Routing /// A key uniquely identifying the site. /// The site domains. /// At the moment there is no public way to remove a site. Clear and reconfigure. - public static void AddSite(string key, params string[] domains) + public void AddSite(string key, params string[] domains) { - using (ConfigWriteLock) + try { - _sites = _sites ?? new Dictionary(); - _sites[key] = ValidateDomains(domains).ToArray(); + _configLock.EnterWriteLock(); + + Sites = Sites ?? new Dictionary(); + Sites[key] = ValidateDomains(domains).ToArray(); _qualifiedSites = null; } + finally + { + if (_configLock.IsWriteLockHeld) + { + _configLock.ExitWriteLock(); + } + } } /// /// Removes a site. /// /// A key uniquely identifying the site. - internal static void RemoveSite(string key) + internal void RemoveSite(string key) { - using (ConfigWriteLock) + try { - if (_sites == null || !_sites.ContainsKey(key)) + _configLock.EnterWriteLock(); + + if (Sites == null || !Sites.ContainsKey(key)) return; - _sites.Remove(key); - if (_sites.Count == 0) - _sites = null; + Sites.Remove(key); + if (Sites.Count == 0) + Sites = null; - if (_bindings != null && _bindings.ContainsKey(key)) + if (Bindings != null && Bindings.ContainsKey(key)) { - foreach (var b in _bindings[key]) + foreach (var b in Bindings[key]) { - _bindings[b].Remove(key); - if (_bindings[b].Count == 0) - _bindings.Remove(b); + Bindings[b].Remove(key); + if (Bindings[b].Count == 0) + Bindings.Remove(b); } - _bindings.Remove(key); - if (_bindings.Count > 0) - _bindings = null; + Bindings.Remove(key); + if (Bindings.Count > 0) + Bindings = null; } _qualifiedSites = null; } + finally + { + if (_configLock.IsWriteLockHeld) + { + _configLock.ExitWriteLock(); + } + } } /// /// Binds some sites. /// /// The keys uniquely identifying the sites to bind. - /// + /// /// At the moment there is no public way to unbind sites. Clear and reconfigure. /// If site1 is bound to site2 and site2 is bound to site3 then site1 is bound to site3. - /// - public static void BindSites(params string[] keys) - { - using (ConfigWriteLock) + /// + public void BindSites(params string[] keys) + { + try { - foreach (var key in keys.Where(key => !_sites.ContainsKey(key))) + _configLock.EnterWriteLock(); + + foreach (var key in keys.Where(key => !Sites.ContainsKey(key))) throw new ArgumentException($"Not an existing site key: {key}.", nameof(keys)); - _bindings = _bindings ?? new Dictionary>(); + Bindings = Bindings ?? new Dictionary>(); - var allkeys = _bindings + var allkeys = Bindings .Where(kvp => keys.Contains(kvp.Key)) .SelectMany(kvp => kvp.Value) .Union(keys) @@ -156,11 +178,18 @@ namespace Umbraco.Cms.Core.Routing foreach (var key in allkeys) { - if (!_bindings.ContainsKey(key)) - _bindings[key] = new List(); + if (!Bindings.ContainsKey(key)) + Bindings[key] = new List(); var xkey = key; - var addKeys = allkeys.Where(k => k != xkey).Except(_bindings[key]); - _bindings[key].AddRange(addKeys); + var addKeys = allkeys.Where(k => k != xkey).Except(Bindings[key]); + Bindings[key].AddRange(addKeys); + } + } + finally + { + if (_configLock.IsWriteLockHeld) + { + _configLock.ExitWriteLock(); } } } @@ -185,10 +214,12 @@ namespace Umbraco.Cms.Core.Routing var currentAuthority = current.GetLeftPart(UriPartial.Authority); KeyValuePair[] candidateSites = null; - IEnumerable ret = domainAndUris; + IEnumerable ret = domainAndUris; - using (ConfigReadLock) // so nothing changes between GetQualifiedSites and access to bindings + try { + _configLock.EnterReadLock(); + var qualifiedSites = GetQualifiedSitesInsideLock(current); if (excludeDefault) @@ -223,15 +254,22 @@ namespace Umbraco.Cms.Core.Routing if (!currentSite.Equals(default(KeyValuePair))) { candidateSites = new[] { currentSite }; - if (_bindings != null && _bindings.ContainsKey(currentSite.Key)) + if (Bindings != null && Bindings.ContainsKey(currentSite.Key)) { - var boundSites = qualifiedSites.Where(site => _bindings[currentSite.Key].Contains(site.Key)); + var boundSites = qualifiedSites.Where(site => Bindings[currentSite.Key].Contains(site.Key)); candidateSites = candidateSites.Union(boundSites).ToArray(); // .ToArray ensures it is evaluated before the configuration lock is exited } } } + finally + { + if (_configLock.IsReadLockHeld) + { + _configLock.ExitReadLock(); + } + } // if we are able to filter, then filter, else return the whole lot return candidateSites == null ? ret : ret.Where(d => @@ -241,18 +279,27 @@ namespace Umbraco.Cms.Core.Routing }); } - private static Dictionary GetQualifiedSites(Uri current) + private Dictionary GetQualifiedSites(Uri current) { - using (ConfigReadLock) + try { + _configLock.EnterReadLock(); + return GetQualifiedSitesInsideLock(current); } + finally + { + if (_configLock.IsReadLockHeld) + { + _configLock.ExitReadLock(); + } + } } - private static Dictionary GetQualifiedSitesInsideLock(Uri current) + private Dictionary GetQualifiedSitesInsideLock(Uri current) { // we do our best, but can't do the impossible - if (_sites == null) + if (Sites == null) return null; // cached? @@ -263,7 +310,7 @@ namespace Umbraco.Cms.Core.Routing // convert sites into authority sites based upon current scheme // because some domains in the sites might not have a scheme -- and cache - return _qualifiedSites[current.Scheme] = _sites + return _qualifiedSites[current.Scheme] = Sites .ToDictionary( kvp => kvp.Key, kvp => kvp.Value.Select(d => new Uri(UriUtilityCore.StartWithScheme(d, current.Scheme)).GetLeftPart(UriPartial.Authority)).ToArray() @@ -274,10 +321,12 @@ namespace Umbraco.Cms.Core.Routing // therefore it is safe to return and exit the configuration lock } - private static DomainAndUri MapDomain(IReadOnlyCollection domainAndUris, Dictionary qualifiedSites, string currentAuthority, string culture, string defaultCulture) + private DomainAndUri MapDomain(IReadOnlyCollection domainAndUris, Dictionary qualifiedSites, string currentAuthority, string culture, string defaultCulture) { - if (domainAndUris == null) throw new ArgumentNullException(nameof(domainAndUris)); - if (domainAndUris.Count == 0) throw new ArgumentException("Cannot be empty.", nameof(domainAndUris)); + if (domainAndUris == null) + throw new ArgumentNullException(nameof(domainAndUris)); + if (domainAndUris.Count == 0) + throw new ArgumentException("Cannot be empty.", nameof(domainAndUris)); // TODO: how shall we deal with cultures? @@ -316,5 +365,26 @@ namespace Umbraco.Cms.Core.Routing } #endregion + + protected virtual void Dispose(bool disposing) + { + if (!_disposedValue) + { + if (disposing) + { + // This is pretty nasty disposing a static on an instance but it's because this whole class + // is pretty fubar. I'm sure we've fixed this all up in netcore now? We need to remove all statics. + _configLock.Dispose(); + } + + _disposedValue = true; + } + } + + public void Dispose() + { + // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method + Dispose(disposing: true); + } } } diff --git a/src/Umbraco.Core/UpgradeableReadLock.cs b/src/Umbraco.Core/UpgradeableReadLock.cs deleted file mode 100644 index 4b6fc9219a..0000000000 --- a/src/Umbraco.Core/UpgradeableReadLock.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Threading; - -namespace Umbraco.Cms.Core -{ - /// - /// Provides a convenience methodology for implementing locked access to resources. - /// - /// - /// Intended as an infrastructure class. - /// - public class UpgradeableReadLock : IDisposable - { - private readonly ReaderWriterLockSlim _rwLock; - private bool _upgraded = false; - - /// - /// Initializes a new instance of the class. - /// - /// The rw lock. - public UpgradeableReadLock(ReaderWriterLockSlim rwLock) - { - _rwLock = rwLock; - _rwLock.EnterUpgradeableReadLock(); - } - - public void UpgradeToWriteLock() - { - _rwLock.EnterWriteLock(); - _upgraded = true; - } - - void IDisposable.Dispose() - { - if (_upgraded) - { - _rwLock.ExitWriteLock(); - } - _rwLock.ExitUpgradeableReadLock(); - } - } -} diff --git a/src/Umbraco.Core/WriteLock.cs b/src/Umbraco.Core/WriteLock.cs deleted file mode 100644 index 7484c26869..0000000000 --- a/src/Umbraco.Core/WriteLock.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; -using System.Threading; - -namespace Umbraco.Cms.Core -{ - /// - /// Provides a convenience methodology for implementing locked access to resources. - /// - /// - /// Intended as an infrastructure class. - /// This is a very inefficient way to lock as it allocates one object each time we lock, - /// so it's OK to use this class for things that happen once, where it is convenient, but not - /// for performance-critical code! - /// - public class WriteLock : IDisposable - { - private readonly ReaderWriterLockSlim _rwLock; - - /// - /// Initializes a new instance of the class. - /// - /// The rw lock. - public WriteLock(ReaderWriterLockSlim rwLock) - { - _rwLock = rwLock; - _rwLock.EnterWriteLock(); - } - - void IDisposable.Dispose() - { - _rwLock.ExitWriteLock(); - } - } -} diff --git a/src/Umbraco.Infrastructure/Scoping/Scope.cs b/src/Umbraco.Infrastructure/Scoping/Scope.cs index 71dde14d13..7e748cd57c 100644 --- a/src/Umbraco.Infrastructure/Scoping/Scope.cs +++ b/src/Umbraco.Infrastructure/Scoping/Scope.cs @@ -42,11 +42,14 @@ namespace Umbraco.Cms.Core.Scoping // eventually this may need to be injectable - for now we'll create it explicitly and let future needs determine if it should be injectable private IScopedNotificationPublisher _notificationPublisher; - private object _dictionaryLocker; + private readonly object _dictionaryLocker; private HashSet _readLocks; private HashSet _writeLocks; - internal Dictionary> ReadLocks; - internal Dictionary> WriteLocks; + private Dictionary> _readLockDictionary; + private Dictionary> _writeLockDictionary; + + internal Dictionary> ReadLocks => _readLockDictionary; + internal Dictionary> WriteLocks => _writeLockDictionary; // initializes a new scope private Scope( @@ -770,7 +773,7 @@ namespace Umbraco.Cms.Core.Scoping else { // We are the outermost scope, handle the lock request. - LockInner(instanceId, ref ReadLocks, ref _readLocks, ObtainReadLock, ObtainTimeoutReadLock, timeout, lockIds); + LockInner(instanceId, ref _readLockDictionary, ref _readLocks, ObtainReadLock, ObtainTimeoutReadLock, timeout, lockIds); } } @@ -790,7 +793,7 @@ namespace Umbraco.Cms.Core.Scoping else { // We are the outermost scope, handle the lock request. - LockInner(instanceId, ref WriteLocks, ref _writeLocks, ObtainWriteLock, ObtainTimeoutWriteLock, timeout, lockIds); + LockInner(instanceId, ref _writeLockDictionary, ref _writeLocks, ObtainWriteLock, ObtainTimeoutWriteLock, timeout, lockIds); } } diff --git a/src/Umbraco.PublishedCache.NuCache/ContentNode.cs b/src/Umbraco.PublishedCache.NuCache/ContentNode.cs index 9386b7faf1..23088df3ad 100644 --- a/src/Umbraco.PublishedCache.NuCache/ContentNode.cs +++ b/src/Umbraco.PublishedCache.NuCache/ContentNode.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Diagnostics; using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Core.PublishedCache; @@ -115,7 +115,7 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache // everything that is common to both draft and published versions // keep this as small as possible - +#pragma warning disable IDE1006 // Naming Styles public readonly int Id; public readonly Guid Uid; public IPublishedContentType ContentType; @@ -123,9 +123,11 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache public readonly string Path; public readonly int SortOrder; public readonly int ParentContentId; +#pragma warning restore IDE1006 // Naming Styles // TODO: Can we make everything readonly?? This would make it easier to debug and be less error prone especially for new developers. // Once a Node is created and exists in the cache it is readonly so we should be able to make that happen at the API level too. +#pragma warning disable IDE1006 // Naming Styles public int FirstChildContentId; public int LastChildContentId; public int NextSiblingContentId; @@ -133,6 +135,7 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache public readonly DateTime CreateDate; public readonly int CreatorId; +#pragma warning restore IDE1006 // Naming Styles private ContentData _draftData; private ContentData _publishedData; diff --git a/src/Umbraco.PublishedCache.NuCache/PublishedSnapshot.cs b/src/Umbraco.PublishedCache.NuCache/PublishedSnapshot.cs index 6c158daf31..ead279a199 100644 --- a/src/Umbraco.PublishedCache.NuCache/PublishedSnapshot.cs +++ b/src/Umbraco.PublishedCache.NuCache/PublishedSnapshot.cs @@ -1,4 +1,4 @@ -using System; +using System; using Umbraco.Cms.Core; using Umbraco.Cms.Core.Cache; using Umbraco.Cms.Core.PublishedCache; @@ -22,12 +22,14 @@ namespace Umbraco.Cms.Infrastructure.PublishedCache public class PublishedSnapshotElements : IDisposable { +#pragma warning disable IDE1006 // Naming Styles public ContentCache ContentCache; public MediaCache MediaCache; public MemberCache MemberCache; public DomainCache DomainCache; public IAppCache SnapshotCache; public IAppCache ElementsCache; +#pragma warning restore IDE1006 // Naming Styles public void Dispose() { diff --git a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Routing/SiteDomainHelperTests.cs b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Routing/SiteDomainMapperTests.cs similarity index 76% rename from src/Umbraco.Tests.UnitTests/Umbraco.Core/Routing/SiteDomainHelperTests.cs rename to src/Umbraco.Tests.UnitTests/Umbraco.Core/Routing/SiteDomainMapperTests.cs index 729ec5fb7f..c9109a5c14 100644 --- a/src/Umbraco.Tests.UnitTests/Umbraco.Core/Routing/SiteDomainHelperTests.cs +++ b/src/Umbraco.Tests.UnitTests/Umbraco.Core/Routing/SiteDomainMapperTests.cs @@ -10,13 +10,10 @@ using Umbraco.Cms.Core.Routing; namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Routing { [TestFixture] - public class SiteDomainHelperTests + public class SiteDomainMapperTests { - [SetUp] - public void SetUp() => SiteDomainHelper.Clear(); // assuming this works! - [TearDown] - public void TearDown() => SiteDomainHelper.Clear(); // assuming this works! + private SiteDomainMapper CreateSut() => new SiteDomainMapper(); private static readonly string s_cultureFr = "fr-fr"; private static readonly string s_cultureGb = "en-gb"; @@ -24,10 +21,12 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Routing [Test] public void AddSites() { - SiteDomainHelper.AddSite("site1", "domain1.com", "domain1.net", "domain1.org"); - SiteDomainHelper.AddSite("site2", "domain2.com", "domain2.net", "domain2.org"); + SiteDomainMapper siteDomainMapper = CreateSut(); - Dictionary sites = SiteDomainHelper.Sites; + siteDomainMapper.AddSite("site1", "domain1.com", "domain1.net", "domain1.org"); + siteDomainMapper.AddSite("site2", "domain2.com", "domain2.net", "domain2.org"); + + Dictionary sites = siteDomainMapper.Sites; Assert.AreEqual(2, sites.Count); @@ -57,23 +56,35 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Routing [TestCase("http://www.domain.com:12/")] [TestCase("https://foo.www.domain.com")] [TestCase("https://foo.www.domain.com:5478/")] - public void AddValidSite(string domain) => SiteDomainHelper.AddSite("site1", domain); + public void AddValidSite(string domain) + { + SiteDomainMapper siteDomainMapper = CreateSut(); + + siteDomainMapper.AddSite("site1", domain); + } [TestCase("domain.com/foo")] [TestCase("http:/domain.com")] [TestCase("*")] - public void AddInvalidSite(string domain) => Assert.Throws(() => SiteDomainHelper.AddSite("site1", domain)); + public void AddInvalidSite(string domain) + { + SiteDomainMapper siteDomainMapper = CreateSut(); + + Assert.Throws(() => siteDomainMapper.AddSite("site1", domain)); + } [Test] public void AddRemoveSites() { - SiteDomainHelper.AddSite("site1", "domain1.com", "domain1.net", "domain1.org"); - SiteDomainHelper.AddSite("site2", "domain2.com", "domain2.net", "domain2.org"); + SiteDomainMapper siteDomainMapper = CreateSut(); - Dictionary sites = SiteDomainHelper.Sites; + siteDomainMapper.AddSite("site1", "domain1.com", "domain1.net", "domain1.org"); + siteDomainMapper.AddSite("site2", "domain2.com", "domain2.net", "domain2.org"); - SiteDomainHelper.RemoveSite("site1"); - SiteDomainHelper.RemoveSite("site3"); + Dictionary sites = siteDomainMapper.Sites; + + siteDomainMapper.RemoveSite("site1"); + siteDomainMapper.RemoveSite("site3"); Assert.AreEqual(1, sites.Count); @@ -83,10 +94,12 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Routing [Test] public void AddSiteAgain() { - SiteDomainHelper.AddSite("site1", "domain1.com", "domain1.net", "domain1.org"); - SiteDomainHelper.AddSite("site1", "domain2.com", "domain1.net"); + SiteDomainMapper siteDomainMapper = CreateSut(); - Dictionary sites = SiteDomainHelper.Sites; + siteDomainMapper.AddSite("site1", "domain1.com", "domain1.net", "domain1.org"); + siteDomainMapper.AddSite("site1", "domain2.com", "domain1.net"); + + Dictionary sites = siteDomainMapper.Sites; Assert.AreEqual(1, sites.Count); @@ -101,14 +114,16 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Routing [Test] public void BindSitesOnce() { - SiteDomainHelper.AddSite("site1", "domain1.com", "domain1.net", "domain1.org"); - SiteDomainHelper.AddSite("site2", "domain2.com", "domain2.net", "domain2.org"); - SiteDomainHelper.AddSite("site3", "domain3.com", "domain3.net", "domain3.org"); - SiteDomainHelper.AddSite("site4", "domain4.com", "domain4.net", "domain4.org"); + SiteDomainMapper siteDomainMapper = CreateSut(); - SiteDomainHelper.BindSites("site1", "site2"); + siteDomainMapper.AddSite("site1", "domain1.com", "domain1.net", "domain1.org"); + siteDomainMapper.AddSite("site2", "domain2.com", "domain2.net", "domain2.org"); + siteDomainMapper.AddSite("site3", "domain3.com", "domain3.net", "domain3.org"); + siteDomainMapper.AddSite("site4", "domain4.com", "domain4.net", "domain4.org"); - Dictionary> bindings = SiteDomainHelper.Bindings; + siteDomainMapper.BindSites("site1", "site2"); + + Dictionary> bindings = siteDomainMapper.Bindings; Assert.AreEqual(2, bindings.Count); Assert.Contains("site1", bindings.Keys); @@ -126,15 +141,17 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Routing [Test] public void BindMoreSites() { - SiteDomainHelper.AddSite("site1", "domain1.com", "domain1.net", "domain1.org"); - SiteDomainHelper.AddSite("site2", "domain2.com", "domain2.net", "domain2.org"); - SiteDomainHelper.AddSite("site3", "domain3.com", "domain3.net", "domain3.org"); - SiteDomainHelper.AddSite("site4", "domain4.com", "domain4.net", "domain4.org"); + SiteDomainMapper siteDomainMapper = CreateSut(); - SiteDomainHelper.BindSites("site1", "site2"); - SiteDomainHelper.BindSites("site1", "site3"); + siteDomainMapper.AddSite("site1", "domain1.com", "domain1.net", "domain1.org"); + siteDomainMapper.AddSite("site2", "domain2.com", "domain2.net", "domain2.org"); + siteDomainMapper.AddSite("site3", "domain3.com", "domain3.net", "domain3.org"); + siteDomainMapper.AddSite("site4", "domain4.com", "domain4.net", "domain4.org"); - Dictionary> bindings = SiteDomainHelper.Bindings; + siteDomainMapper.BindSites("site1", "site2"); + siteDomainMapper.BindSites("site1", "site3"); + + Dictionary> bindings = siteDomainMapper.Bindings; Assert.AreEqual(3, bindings.Count); Assert.Contains("site1", bindings.Keys); @@ -167,13 +184,12 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Routing [Test] public void MapDomainWithScheme() { - SiteDomainHelper.AddSite("site1", "domain1.com", "domain1.net", "domain1.org"); - SiteDomainHelper.AddSite("site2", "domain2.com", "domain2.net", "domain2.org"); - SiteDomainHelper.AddSite("site3", "domain3.com", "domain3.net", "domain3.org"); - SiteDomainHelper.AddSite("site4", "https://domain4.com", "https://domain4.net", "https://domain4.org"); + SiteDomainMapper siteDomainMapper = CreateSut(); - // map methods are not static because we can override them - var helper = new SiteDomainHelper(); + siteDomainMapper.AddSite("site1", "domain1.com", "domain1.net", "domain1.org"); + siteDomainMapper.AddSite("site2", "domain2.com", "domain2.net", "domain2.org"); + siteDomainMapper.AddSite("site3", "domain3.com", "domain3.net", "domain3.org"); + siteDomainMapper.AddSite("site4", "https://domain4.com", "https://domain4.net", "https://domain4.org"); // this works, but it's purely by chance / arbitrary // don't use the www in tests here! @@ -184,7 +200,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Routing new Domain(1, "domain1.com", -1, s_cultureGb, false), }; DomainAndUri[] domainAndUris = DomainAndUris(current, domains); - string output = helper.MapDomain(domainAndUris, current, s_cultureFr, s_cultureFr).Uri.ToString(); + string output = siteDomainMapper.MapDomain(domainAndUris, current, s_cultureFr, s_cultureFr).Uri.ToString(); Assert.AreEqual("https://domain1.com/", output); // will pick it all right @@ -195,7 +211,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Routing new Domain(1, "https://domain2.com", -1, s_cultureGb, false) }; domainAndUris = DomainAndUris(current, domains); - output = helper.MapDomain(domainAndUris, current, s_cultureFr, s_cultureFr).Uri.ToString(); + output = siteDomainMapper.MapDomain(domainAndUris, current, s_cultureFr, s_cultureFr).Uri.ToString(); Assert.AreEqual("https://domain1.com/", output); current = new Uri("https://domain1.com/foo/bar"); @@ -205,7 +221,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Routing new Domain(1, "https://domain4.com", -1, s_cultureGb, false) }; domainAndUris = DomainAndUris(current, domains); - output = helper.MapDomain(domainAndUris, current, s_cultureFr, s_cultureFr).Uri.ToString(); + output = siteDomainMapper.MapDomain(domainAndUris, current, s_cultureFr, s_cultureFr).Uri.ToString(); Assert.AreEqual("https://domain1.com/", output); current = new Uri("https://domain4.com/foo/bar"); @@ -215,25 +231,24 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Routing new Domain(1, "https://domain4.com", -1, s_cultureGb, false) }; domainAndUris = DomainAndUris(current, domains); - output = helper.MapDomain(domainAndUris, current, s_cultureFr, s_cultureFr).Uri.ToString(); + output = siteDomainMapper.MapDomain(domainAndUris, current, s_cultureFr, s_cultureFr).Uri.ToString(); Assert.AreEqual("https://domain4.com/", output); } [Test] public void MapDomain() { - SiteDomainHelper.AddSite("site1", "domain1.com", "domain1.net", "domain1.org"); - SiteDomainHelper.AddSite("site2", "domain2.com", "domain2.net", "domain2.org"); - SiteDomainHelper.AddSite("site3", "domain3.com", "domain3.net", "domain3.org"); - SiteDomainHelper.AddSite("site4", "domain4.com", "domain4.net", "domain4.org"); + SiteDomainMapper siteDomainMapper = CreateSut(); - // map methods are not static because we can override them - var helper = new SiteDomainHelper(); + siteDomainMapper.AddSite("site1", "domain1.com", "domain1.net", "domain1.org"); + siteDomainMapper.AddSite("site2", "domain2.com", "domain2.net", "domain2.org"); + siteDomainMapper.AddSite("site3", "domain3.com", "domain3.net", "domain3.org"); + siteDomainMapper.AddSite("site4", "domain4.com", "domain4.net", "domain4.org"); // current is a site1 uri, domains contain current // so we'll get current var current = new Uri("http://domain1.com/foo/bar"); - string output = helper.MapDomain( + string output = siteDomainMapper.MapDomain( new[] { new DomainAndUri(new Domain(1, "domain1.com", -1, s_cultureFr, false), current), @@ -246,7 +261,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Routing // current is a site1 uri, domains do not contain current // so we'll get the corresponding site1 domain current = new Uri("http://domain1.com/foo/bar"); - output = helper.MapDomain( + output = siteDomainMapper.MapDomain( new[] { new DomainAndUri(new Domain(1, "domain1.net", -1, s_cultureFr, false), current), @@ -260,7 +275,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Routing // so we'll get the corresponding site1 domain // order does not matter current = new Uri("http://domain1.com/foo/bar"); - output = helper.MapDomain( + output = siteDomainMapper.MapDomain( new[] { new DomainAndUri(new Domain(1, "domain2.net", -1, s_cultureFr, false), current), @@ -274,13 +289,12 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Routing [Test] public void MapDomains() { - SiteDomainHelper.AddSite("site1", "domain1.com", "domain1.net", "domain1.org"); - SiteDomainHelper.AddSite("site2", "domain2.com", "domain2.net", "domain2.org"); - SiteDomainHelper.AddSite("site3", "domain3.com", "domain3.net", "domain3.org"); - SiteDomainHelper.AddSite("site4", "domain4.com", "domain4.net", "domain4.org"); + SiteDomainMapper siteDomainMapper = CreateSut(); - // map methods are not static because we can override them - var helper = new SiteDomainHelper(); + siteDomainMapper.AddSite("site1", "domain1.com", "domain1.net", "domain1.org"); + siteDomainMapper.AddSite("site2", "domain2.com", "domain2.net", "domain2.org"); + siteDomainMapper.AddSite("site3", "domain3.com", "domain3.net", "domain3.org"); + siteDomainMapper.AddSite("site4", "domain4.com", "domain4.net", "domain4.org"); // the rule is: // - exclude the current domain @@ -289,7 +303,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Routing // current is a site1 uri, domains contains current var current = new Uri("http://domain1.com/foo/bar"); - DomainAndUri[] output = helper.MapDomains( + DomainAndUri[] output = siteDomainMapper.MapDomains( new[] { new DomainAndUri(new Domain(1, "domain1.com", -1, s_cultureFr, false), current), // no: current + what MapDomain would pick @@ -308,7 +322,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Routing // current is a site1 uri, domains does not contain current current = new Uri("http://domain1.com/foo/bar"); - output = helper.MapDomains( + output = siteDomainMapper.MapDomains( new[] { new DomainAndUri(new Domain(1, "domain1.net", -1, s_cultureFr, false), current), // no: what MapDomain would pick @@ -325,12 +339,12 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Routing Assert.AreEqual(1, output.Count()); Assert.Contains("http://domain1.org/", output.Select(d => d.Uri.ToString()).ToArray()); - SiteDomainHelper.BindSites("site1", "site3"); - SiteDomainHelper.BindSites("site2", "site4"); + siteDomainMapper.BindSites("site1", "site3"); + siteDomainMapper.BindSites("site2", "site4"); // current is a site1 uri, domains contains current current = new Uri("http://domain1.com/foo/bar"); - output = helper.MapDomains( + output = siteDomainMapper.MapDomains( new[] { new DomainAndUri(new Domain(1, "domain1.com", -1, s_cultureFr, false), current), // no: current + what MapDomain would pick @@ -352,7 +366,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Routing // current is a site1 uri, domains does not contain current current = new Uri("http://domain1.com/foo/bar"); - output = helper.MapDomains( + output = siteDomainMapper.MapDomains( new[] { new DomainAndUri(new Domain(1, "domain1.net", -1, s_cultureFr, false), current), // no: what MapDomain would pick diff --git a/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlPublishedSnapshotService.cs b/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlPublishedSnapshotService.cs index 76650144dc..45f8582eff 100644 --- a/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlPublishedSnapshotService.cs +++ b/src/Umbraco.Tests/LegacyXmlPublishedCache/XmlPublishedSnapshotService.cs @@ -9,7 +9,6 @@ using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Core.Persistence.Repositories; using Umbraco.Cms.Core.PublishedCache; -using Umbraco.Cms.Core.Routing; using Umbraco.Cms.Core.Runtime; using Umbraco.Cms.Core.Scoping; using Umbraco.Cms.Core.Services; @@ -34,12 +33,9 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache private readonly IAppCache _requestCache; private readonly GlobalSettings _globalSettings; private readonly IDefaultCultureAccessor _defaultCultureAccessor; - private readonly ISiteDomainHelper _siteDomainHelper; private readonly IEntityXmlSerializer _entitySerializer; private readonly IVariationContextAccessor _variationContextAccessor; private readonly IUmbracoContextAccessor _umbracoContextAccessor; - private readonly IApplicationShutdownRegistry _hostingLifetime; - private readonly IHostingEnvironment _hostingEnvironment; #region Constructors @@ -61,7 +57,6 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache IHostingEnvironment hostingEnvironment, IApplicationShutdownRegistry hostingLifetime, IShortStringHelper shortStringHelper, - ISiteDomainHelper siteDomainHelper, IEntityXmlSerializer entitySerializer, MainDom mainDom, bool testing = false, @@ -70,7 +65,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache publishedSnapshotAccessor, variationContextAccessor, umbracoContextAccessor, documentRepository, mediaRepository, memberRepository, defaultCultureAccessor, - loggerFactory, globalSettings, hostingEnvironment, hostingLifetime, shortStringHelper, siteDomainHelper, entitySerializer, null, mainDom, testing, enableRepositoryEvents) + loggerFactory, globalSettings, hostingEnvironment, hostingLifetime, shortStringHelper, entitySerializer, null, mainDom, testing, enableRepositoryEvents) { _umbracoContextAccessor = umbracoContextAccessor; } @@ -93,7 +88,6 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache IHostingEnvironment hostingEnvironment, IApplicationShutdownRegistry hostingLifetime, IShortStringHelper shortStringHelper, - ISiteDomainHelper siteDomainHelper, IEntityXmlSerializer entitySerializer, PublishedContentTypeCache contentTypeCache, MainDom mainDom, @@ -118,10 +112,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache _requestCache = requestCache; _umbracoContextAccessor = umbracoContextAccessor; _globalSettings = globalSettings; - _siteDomainHelper = siteDomainHelper; _entitySerializer = entitySerializer; - _hostingEnvironment = hostingEnvironment; - _hostingLifetime = hostingLifetime; } public void Dispose() diff --git a/src/Umbraco.Tests/Routing/BaseUrlProviderTest.cs b/src/Umbraco.Tests/Routing/BaseUrlProviderTest.cs index 53e1fcd1f3..6be2b72ad1 100644 --- a/src/Umbraco.Tests/Routing/BaseUrlProviderTest.cs +++ b/src/Umbraco.Tests/Routing/BaseUrlProviderTest.cs @@ -19,7 +19,7 @@ namespace Umbraco.Tests.Routing protected override void Compose() { base.Compose(); - Builder.Services.AddTransient(); + Builder.Services.AddTransient(); } protected override void ComposeSettings() diff --git a/src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs b/src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs index cb77ea63c9..73a88abfab 100644 --- a/src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs +++ b/src/Umbraco.Tests/Routing/DomainsAndCulturesTests.cs @@ -15,7 +15,7 @@ namespace Umbraco.Tests.Routing { base.Compose(); - Builder.Services.AddTransient(); + Builder.Services.AddTransient(); } private void SetDomains1() diff --git a/src/Umbraco.Tests/Routing/GetContentUrlsTests.cs b/src/Umbraco.Tests/Routing/GetContentUrlsTests.cs index 20b44dca9b..fe371e7302 100644 --- a/src/Umbraco.Tests/Routing/GetContentUrlsTests.cs +++ b/src/Umbraco.Tests/Routing/GetContentUrlsTests.cs @@ -95,7 +95,7 @@ namespace Umbraco.Tests.Routing var urlProvider = new DefaultUrlProvider( Microsoft.Extensions.Options.Options.Create(_requestHandlerSettings), LoggerFactory.CreateLogger(), - new SiteDomainHelper(), + new SiteDomainMapper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = new UrlProvider( umbracoContextAccessor, @@ -143,7 +143,7 @@ namespace Umbraco.Tests.Routing var urlProvider = new DefaultUrlProvider( Microsoft.Extensions.Options.Options.Create(_requestHandlerSettings), LoggerFactory.CreateLogger(), - new SiteDomainHelper(), umbracoContextAccessor, UriUtility); + new SiteDomainMapper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = new UrlProvider( umbracoContextAccessor, Microsoft.Extensions.Options.Options.Create(_webRoutingSettings), diff --git a/src/Umbraco.Tests/Routing/UrlProviderWithHideTopLevelNodeFromPathTests.cs b/src/Umbraco.Tests/Routing/UrlProviderWithHideTopLevelNodeFromPathTests.cs index d777738d7d..3a2ccc23df 100644 --- a/src/Umbraco.Tests/Routing/UrlProviderWithHideTopLevelNodeFromPathTests.cs +++ b/src/Umbraco.Tests/Routing/UrlProviderWithHideTopLevelNodeFromPathTests.cs @@ -49,7 +49,7 @@ namespace Umbraco.Tests.Routing var urlProvider = new DefaultUrlProvider( Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), LoggerFactory.CreateLogger(), - new SiteDomainHelper(), umbracoContextAccessor, UriUtility); + new SiteDomainMapper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); var result = publishedUrlProvider.GetUrl(nodeId); diff --git a/src/Umbraco.Tests/Routing/UrlProviderWithoutHideTopLevelNodeFromPathTests.cs b/src/Umbraco.Tests/Routing/UrlProviderWithoutHideTopLevelNodeFromPathTests.cs index 8454c2aa1c..bbadf897d0 100644 --- a/src/Umbraco.Tests/Routing/UrlProviderWithoutHideTopLevelNodeFromPathTests.cs +++ b/src/Umbraco.Tests/Routing/UrlProviderWithoutHideTopLevelNodeFromPathTests.cs @@ -51,7 +51,7 @@ namespace Umbraco.Tests.Routing var urlProvider = new DefaultUrlProvider( Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), LoggerFactory.CreateLogger(), - new SiteDomainHelper(), umbracoContextAccessor, UriUtility); + new SiteDomainMapper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); @@ -111,7 +111,7 @@ namespace Umbraco.Tests.Routing var urlProvider = new DefaultUrlProvider( Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), LoggerFactory.CreateLogger(), - new SiteDomainHelper(), umbracoContextAccessor, UriUtility); + new SiteDomainMapper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); var result = publishedUrlProvider.GetUrl(nodeId); @@ -151,7 +151,7 @@ namespace Umbraco.Tests.Routing var urlProvider = new DefaultUrlProvider( Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), LoggerFactory.CreateLogger(), - new SiteDomainHelper(), umbracoContextAccessor, UriUtility); + new SiteDomainMapper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); //even though we are asking for a specific culture URL, there are no domains assigned so all that can be returned is a normal relative URL. @@ -205,7 +205,7 @@ namespace Umbraco.Tests.Routing var urlProvider = new DefaultUrlProvider( Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), LoggerFactory.CreateLogger(), - new SiteDomainHelper(), umbracoContextAccessor, UriUtility); + new SiteDomainMapper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); @@ -259,7 +259,7 @@ namespace Umbraco.Tests.Routing var urlProvider = new DefaultUrlProvider( Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), LoggerFactory.CreateLogger(), - new SiteDomainHelper(), umbracoContextAccessor, UriUtility); + new SiteDomainMapper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); @@ -279,7 +279,7 @@ namespace Umbraco.Tests.Routing var urlProvider = new DefaultUrlProvider( Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), LoggerFactory.CreateLogger(), - new SiteDomainHelper(), umbracoContextAccessor, UriUtility); + new SiteDomainMapper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); Assert.AreEqual("/home/sub1/custom-sub-1/", publishedUrlProvider.GetUrl(1177)); @@ -295,7 +295,7 @@ namespace Umbraco.Tests.Routing var urlProvider = new DefaultUrlProvider(Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), LoggerFactory.CreateLogger(), - new SiteDomainHelper(), UmbracoContextAccessor, UriUtility); + new SiteDomainMapper(), UmbracoContextAccessor, UriUtility); var umbracoContext = GetUmbracoContext("http://example.com/test", 1111, globalSettings: _globalSettings); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); diff --git a/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs b/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs index 9820b96455..4f9fdef8e0 100644 --- a/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs +++ b/src/Umbraco.Tests/Routing/UrlsProviderWithDomainsTests.cs @@ -26,7 +26,7 @@ namespace Umbraco.Tests.Routing base.Compose(); Builder.Services.AddUnique(Mock.Of()); - Builder.Services.AddTransient(); + Builder.Services.AddTransient(); } void SetDomains1() @@ -186,7 +186,7 @@ namespace Umbraco.Tests.Routing var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); var urlProvider = new DefaultUrlProvider(Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), LoggerFactory.CreateLogger(), - new SiteDomainHelper(), umbracoContextAccessor, UriUtility); + new SiteDomainMapper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); SetDomains1(); @@ -219,7 +219,7 @@ namespace Umbraco.Tests.Routing var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); var urlProvider = new DefaultUrlProvider(Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), LoggerFactory.CreateLogger(), - new SiteDomainHelper(), umbracoContextAccessor, UriUtility); + new SiteDomainMapper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); SetDomains2(); @@ -244,7 +244,7 @@ namespace Umbraco.Tests.Routing var umbracoContextAccessor = new TestUmbracoContextAccessor(umbracoContext); var urlProvider = new DefaultUrlProvider(Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), LoggerFactory.CreateLogger(), - new SiteDomainHelper(), umbracoContextAccessor, UriUtility); + new SiteDomainMapper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); SetDomains3(); @@ -276,7 +276,7 @@ namespace Umbraco.Tests.Routing var urlProvider = new DefaultUrlProvider( Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), LoggerFactory.CreateLogger(), - new SiteDomainHelper(), umbracoContextAccessor, UriUtility); + new SiteDomainMapper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); SetDomains4(); @@ -298,7 +298,7 @@ namespace Umbraco.Tests.Routing var urlProvider = new DefaultUrlProvider( Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), LoggerFactory.CreateLogger(), - new SiteDomainHelper(), umbracoContextAccessor, UriUtility); + new SiteDomainMapper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); SetDomains4(); @@ -362,7 +362,7 @@ namespace Umbraco.Tests.Routing var urlProvider = new DefaultUrlProvider( Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), LoggerFactory.CreateLogger(), - new SiteDomainHelper(), umbracoContextAccessor, UriUtility); + new SiteDomainMapper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); SetDomains4(); @@ -387,7 +387,7 @@ namespace Umbraco.Tests.Routing var urlProvider = new DefaultUrlProvider( Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), LoggerFactory.CreateLogger(), - new SiteDomainHelper(), umbracoContextAccessor, UriUtility); + new SiteDomainMapper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); SetDomains5(); diff --git a/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs b/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs index 25428765a3..ab9058bc9c 100644 --- a/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs +++ b/src/Umbraco.Tests/Routing/UrlsWithNestedDomains.cs @@ -29,7 +29,7 @@ namespace Umbraco.Tests.Routing { base.Compose(); Builder.Services.AddUnique(Mock.Of()); - Builder.Services.AddTransient(); + Builder.Services.AddTransient(); } [Test] @@ -48,7 +48,7 @@ namespace Umbraco.Tests.Routing var urlProvider = new DefaultUrlProvider( Microsoft.Extensions.Options.Options.Create(requestHandlerSettings), LoggerFactory.CreateLogger(), - new SiteDomainHelper(), umbracoContextAccessor, UriUtility); + new SiteDomainMapper(), umbracoContextAccessor, UriUtility); var publishedUrlProvider = GetPublishedUrlProvider(umbracoContext, urlProvider); Assert.AreEqual("http://domain2.com/1001-1-1/", publishedUrlProvider.GetUrl(100111, UrlMode.Absolute)); diff --git a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs index 550586cbbf..763b4959b4 100644 --- a/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs +++ b/src/Umbraco.Tests/TestHelpers/TestWithDatabaseBase.cs @@ -268,7 +268,6 @@ namespace Umbraco.Tests.TestHelpers HostingEnvironment, HostingLifetime, ShortStringHelper, - new SiteDomainHelper(), Factory.GetRequiredService(), ContentTypesCache, null, true, Options.PublishedRepositoryEvents); diff --git a/src/Umbraco.Web.BackOffice/Controllers/MacroRenderingController.cs b/src/Umbraco.Web.BackOffice/Controllers/MacroRenderingController.cs index c8b1070d66..d869d0ca34 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/MacroRenderingController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/MacroRenderingController.cs @@ -30,7 +30,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers private readonly IMacroService _macroService; private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly IShortStringHelper _shortStringHelper; - private readonly ISiteDomainHelper _siteDomainHelper; + private readonly ISiteDomainMapper _siteDomainHelper; private readonly IUmbracoMapper _umbracoMapper; private readonly IUmbracoComponentRenderer _componentRenderer; private readonly IVariationContextAccessor _variationContextAccessor; @@ -43,7 +43,7 @@ namespace Umbraco.Cms.Web.BackOffice.Controllers IMacroService macroService, IUmbracoContextAccessor umbracoContextAccessor, IShortStringHelper shortStringHelper, - ISiteDomainHelper siteDomainHelper) + ISiteDomainMapper siteDomainHelper) { _umbracoMapper = umbracoMapper ?? throw new ArgumentNullException(nameof(umbracoMapper)); diff --git a/src/Umbraco.Web.Common/Extensions/FriendlyPublishedContentExtensions.cs b/src/Umbraco.Web.Common/Extensions/FriendlyPublishedContentExtensions.cs index b9cdddfdeb..2a0b77461d 100644 --- a/src/Umbraco.Web.Common/Extensions/FriendlyPublishedContentExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/FriendlyPublishedContentExtensions.cs @@ -32,8 +32,8 @@ namespace Umbraco.Extensions private static IUmbracoContextAccessor UmbracoContextAccessor { get; } = StaticServiceProvider.Instance.GetRequiredService(); - private static ISiteDomainHelper SiteDomainHelper { get; } = - StaticServiceProvider.Instance.GetRequiredService(); + private static ISiteDomainMapper SiteDomainHelper { get; } = + StaticServiceProvider.Instance.GetRequiredService(); private static IExamineManager ExamineManager { get; } = StaticServiceProvider.Instance.GetRequiredService(); diff --git a/src/Umbraco.Web.Common/Extensions/PublishedContentExtensions.cs b/src/Umbraco.Web.Common/Extensions/PublishedContentExtensions.cs index c02e609372..f5a943f4e3 100644 --- a/src/Umbraco.Web.Common/Extensions/PublishedContentExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/PublishedContentExtensions.cs @@ -47,7 +47,7 @@ namespace Umbraco.Extensions /// one document per culture), and domains, withing the context of a current Uri, assign /// a culture to that document. /// - public static string GetCultureFromDomains(this IPublishedContent content, IUmbracoContextAccessor umbracoContextAccessor, ISiteDomainHelper siteDomainHelper, Uri current = null) + public static string GetCultureFromDomains(this IPublishedContent content, IUmbracoContextAccessor umbracoContextAccessor, ISiteDomainMapper siteDomainHelper, Uri current = null) => DomainUtilities.GetCultureFromDomains(content.Id, content.Path, current, umbracoContextAccessor.UmbracoContext, siteDomainHelper); #endregion diff --git a/src/Umbraco.Web.Website/Extensions/WebsiteUmbracoBuilderExtensions.cs b/src/Umbraco.Web.Website/Extensions/WebsiteUmbracoBuilderExtensions.cs index d7414ed60c..72994992fa 100644 --- a/src/Umbraco.Web.Website/Extensions/WebsiteUmbracoBuilderExtensions.cs +++ b/src/Umbraco.Web.Website/Extensions/WebsiteUmbracoBuilderExtensions.cs @@ -48,9 +48,9 @@ namespace Umbraco.Extensions /// The type of the site domain helper. /// public static void SetSiteDomainHelper(this IUmbracoBuilder builder) - where T : class, ISiteDomainHelper + where T : class, ISiteDomainMapper { - builder.Services.AddUnique(); + builder.Services.AddUnique(); } /// @@ -58,7 +58,7 @@ namespace Umbraco.Extensions /// /// The builder. /// A function creating a helper. - public static void SetSiteDomainHelper(this IUmbracoBuilder builder, Func factory) + public static void SetSiteDomainHelper(this IUmbracoBuilder builder, Func factory) { builder.Services.AddUnique(factory); } @@ -68,7 +68,7 @@ namespace Umbraco.Extensions /// /// The builder. /// A helper. - public static void SetSiteDomainHelper(this IUmbracoBuilder builder, ISiteDomainHelper helper) + public static void SetSiteDomainHelper(this IUmbracoBuilder builder, ISiteDomainMapper helper) { builder.Services.AddUnique(helper); }