diff --git a/src/Umbraco.Core/Composing/Current.cs b/src/Umbraco.Core/Composing/Current.cs deleted file mode 100644 index 003f3ee6a2..0000000000 --- a/src/Umbraco.Core/Composing/Current.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System; -using System.Runtime.CompilerServices; -using Microsoft.Extensions.Options; -using Microsoft.Extensions.Logging; -using Umbraco.Core; -using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; -using Umbraco.Core.Hosting; -using Umbraco.Core.IO; -using Umbraco.Core.Logging; -using Microsoft.Extensions.Logging.Abstractions; - -namespace Umbraco.Composing -{ - public static class Current - { - private static ILogger _logger = new NullLogger(); - private static IIOHelper _ioHelper; - private static IHostingEnvironment _hostingEnvironment; - private static IBackOfficeInfo _backOfficeInfo; - private static IProfiler _profiler; - private static SecuritySettings _securitySettings; - private static GlobalSettings _globalSettings; - - public static ILogger Logger => EnsureInitialized(_logger); - public static IIOHelper IOHelper => EnsureInitialized(_ioHelper); - public static IHostingEnvironment HostingEnvironment => EnsureInitialized(_hostingEnvironment); - public static IBackOfficeInfo BackOfficeInfo => EnsureInitialized(_backOfficeInfo); - public static IProfiler Profiler => EnsureInitialized(_profiler); - public static SecuritySettings SecuritySettings => EnsureInitialized(_securitySettings); - public static GlobalSettings GlobalSettings => EnsureInitialized(_globalSettings); - - public static bool IsInitialized { get; internal set; } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static T EnsureInitialized(T returnValue) - where T : class - { - if (returnValue is null && !IsInitialized) - throw new InvalidOperationException("Current cannot be used before initialize"); - return returnValue; - } - - public static void Initialize( - ILogger logger, - SecuritySettings securitySettings, - GlobalSettings globalSettings, - IIOHelper ioHelper, - IHostingEnvironment hostingEnvironment, - IBackOfficeInfo backOfficeInfo, - IProfiler profiler) - { - if (IsInitialized) - { - throw new InvalidOperationException("Current cannot be initialized more than once"); - } - - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - _ioHelper = ioHelper ?? throw new ArgumentNullException(nameof(ioHelper)); - _hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment)); - _backOfficeInfo = backOfficeInfo ?? throw new ArgumentNullException(nameof(backOfficeInfo)); - _profiler = profiler ?? throw new ArgumentNullException(nameof(profiler)); - _securitySettings = securitySettings ?? throw new ArgumentNullException(nameof(securitySettings)); - _globalSettings = globalSettings ?? throw new ArgumentNullException(nameof(globalSettings)); - - IsInitialized = true; - } - - } -} diff --git a/src/Umbraco.Core/Models/ContentEditing/UserInvite.cs b/src/Umbraco.Core/Models/ContentEditing/UserInvite.cs index 68a7a9bd3f..bf2a84fbbe 100644 --- a/src/Umbraco.Core/Models/ContentEditing/UserInvite.cs +++ b/src/Umbraco.Core/Models/ContentEditing/UserInvite.cs @@ -2,8 +2,10 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using System.Runtime.Serialization; -using Umbraco.Composing; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; using Umbraco.Core; +using Umbraco.Core.Configuration.Models; namespace Umbraco.Web.Models.ContentEditing { @@ -33,8 +35,9 @@ namespace Umbraco.Web.Models.ContentEditing if (UserGroups.Any() == false) yield return new ValidationResult("A user must be assigned to at least one group", new[] { nameof(UserGroups) }); - // TODO: this will need another way of retrieving this setting if and when Configs are removed from Current. - if (Current.SecuritySettings.UsernameIsEmail == false && Username.IsNullOrWhiteSpace()) + var securitySettings = validationContext.GetRequiredService>(); + + if (securitySettings.Value.UsernameIsEmail == false && Username.IsNullOrWhiteSpace()) yield return new ValidationResult("A username cannot be empty", new[] { nameof(Username) }); } } diff --git a/src/Umbraco.Core/Models/Member.cs b/src/Umbraco.Core/Models/Member.cs index d155db8b7c..8a765b2f25 100644 --- a/src/Umbraco.Core/Models/Member.cs +++ b/src/Umbraco.Core/Models/Member.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.ComponentModel; using System.Runtime.Serialization; using Microsoft.Extensions.Logging; -using Umbraco.Composing; namespace Umbraco.Core.Models @@ -473,7 +472,7 @@ namespace Umbraco.Core.Models { void DoLog(string logPropertyAlias, string logPropertyName) { - Current.Logger.LogWarning("Trying to access the '{PropertyName}' property on '{MemberType}' " + + StaticApplicationLogging.Logger.LogWarning("Trying to access the '{PropertyName}' property on '{MemberType}' " + "but the {PropertyAlias} property does not exist on the member type so a default value is returned. " + "Ensure that you have a property type with alias: {PropertyAlias} configured on your member type in order to use the '{PropertyName}' property on the model correctly.", logPropertyName, @@ -498,7 +497,7 @@ namespace Umbraco.Core.Models { void DoLog(string logPropertyAlias, string logPropertyName) { - Current.Logger.LogWarning("An attempt was made to set a value on the property '{PropertyName}' on type '{MemberType}' but the " + + StaticApplicationLogging.Logger.LogWarning("An attempt was made to set a value on the property '{PropertyName}' on type '{MemberType}' but the " + "property type {PropertyAlias} does not exist on the member type, ensure that this property type exists so that setting this property works correctly.", logPropertyName, typeof(Member), diff --git a/src/Umbraco.Core/PublishedContentExtensions.cs b/src/Umbraco.Core/PublishedContentExtensions.cs index 62f48917c3..1b7c460c8b 100644 --- a/src/Umbraco.Core/PublishedContentExtensions.cs +++ b/src/Umbraco.Core/PublishedContentExtensions.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using Umbraco.Composing; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Models.PublishedContent; diff --git a/src/Umbraco.Core/Services/IRuntime.cs b/src/Umbraco.Core/Services/IRuntime.cs index ff533be76e..8a1be721d0 100644 --- a/src/Umbraco.Core/Services/IRuntime.cs +++ b/src/Umbraco.Core/Services/IRuntime.cs @@ -1,7 +1,4 @@ using System; -using Microsoft.Extensions.DependencyInjection; -using Umbraco.Core.Composing; -using Umbraco.Core.Configuration; namespace Umbraco.Core { @@ -10,17 +7,12 @@ namespace Umbraco.Core /// public interface IRuntime { - /// - /// Boots the runtime. - /// - void Configure(IServiceCollection services); - /// /// Gets the runtime state. /// IRuntimeState State { get; } - void Start(IServiceProvider serviceProvider); + void Start(); /// /// Terminates the runtime. diff --git a/src/Umbraco.Core/StaticApplicationLogging.cs b/src/Umbraco.Core/StaticApplicationLogging.cs new file mode 100644 index 0000000000..a1e06bc1f8 --- /dev/null +++ b/src/Umbraco.Core/StaticApplicationLogging.cs @@ -0,0 +1,22 @@ +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; + +namespace Umbraco.Core +{ + public static class StaticApplicationLogging + { + private static ILoggerFactory _loggerFactory; + + public static void Initialize(ILoggerFactory loggerFactory) + { + _loggerFactory = loggerFactory; + } + + public static ILogger Logger => CreateLogger(); + + public static ILogger CreateLogger() + { + return _loggerFactory?.CreateLogger() ?? new NullLogger(); + } + } +} diff --git a/src/Umbraco.Core/UriExtensions.cs b/src/Umbraco.Core/UriExtensions.cs index 446e60e18f..0452373d55 100644 --- a/src/Umbraco.Core/UriExtensions.cs +++ b/src/Umbraco.Core/UriExtensions.cs @@ -2,7 +2,6 @@ using System.IO; using System.Linq; using Microsoft.Extensions.Logging; -using Umbraco.Composing; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Hosting; @@ -160,7 +159,7 @@ namespace Umbraco.Core } catch (ArgumentException) { - Current.Logger.LogDebug("Failed to determine if request was client side (invalid chars in path \"{Path}\"?)", url.LocalPath); + StaticApplicationLogging.Logger.LogDebug("Failed to determine if request was client side (invalid chars in path \"{Path}\"?)", url.LocalPath); return false; } } diff --git a/src/Umbraco.Infrastructure/CompositionExtensions_Essentials.cs b/src/Umbraco.Infrastructure/CompositionExtensions_Essentials.cs deleted file mode 100644 index d254139a04..0000000000 --- a/src/Umbraco.Infrastructure/CompositionExtensions_Essentials.cs +++ /dev/null @@ -1,62 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Umbraco.Core.Cache; -using Umbraco.Core.Composing; -using Umbraco.Core.Configuration; -using Umbraco.Core.Hosting; -using Umbraco.Core.IO; -using Umbraco.Core.Logging; -using Umbraco.Core.Persistence; - -namespace Umbraco.Core -{ - /// - /// Provides extension methods to the class. - /// - public static partial class CompositionExtensions - { - /// - /// Registers essential services. - /// - /// - /// These services are all either created by the runtime or used to construct the runtime - /// - public static void RegisterEssentials(this Composition composition, - // TODO: Configs should be here too, the reason is that we only register them before the Core Runtime in aspnetcore - // then we pre-resolve them which means that the instance re-resolved later is different... BUT if we register that - // pre-resolved instance here again, then it will be the same instance re-resolved later, just like we are doing with - // IDbProviderFactoryCreator. - ILogger logger, ILoggerFactory loggerFactory, IProfiler profiler, IProfilingLogger profilingLogger, - IMainDom mainDom, - AppCaches appCaches, - IUmbracoDatabaseFactory databaseFactory, - TypeLoader typeLoader, - IRuntimeState state, - ITypeFinder typeFinder, - IIOHelper ioHelper, - IUmbracoVersion umbracoVersion, - IDbProviderFactoryCreator dbProviderFactoryCreator, - IHostingEnvironment hostingEnvironment, - IBackOfficeInfo backOfficeInfo) - { - composition.Services.AddUnique(logger); - composition.Services.AddUnique(loggerFactory); - composition.Services.AddUnique(profiler); - composition.Services.AddUnique(profilingLogger); - composition.Services.AddUnique(mainDom); - composition.Services.AddUnique(appCaches); - composition.Services.AddUnique(appCaches.RequestCache); - composition.Services.AddUnique(databaseFactory); - composition.Services.AddUnique(factory => factory.GetRequiredService().SqlContext); - composition.Services.AddUnique(typeLoader); - composition.Services.AddUnique(state); - composition.Services.AddUnique(typeFinder); - composition.Services.AddUnique(ioHelper); - composition.Services.AddUnique(umbracoVersion); - composition.Services.AddUnique(dbProviderFactoryCreator); - composition.Services.AddUnique(factory => factory.GetRequiredService().BulkSqlInsertProvider); - composition.Services.AddUnique(hostingEnvironment); - composition.Services.AddUnique(backOfficeInfo); - } - } -} diff --git a/src/Umbraco.Infrastructure/Events/QueuingEventDispatcher.cs b/src/Umbraco.Infrastructure/Events/QueuingEventDispatcher.cs index 6260aaa176..d9adf93eb5 100644 --- a/src/Umbraco.Infrastructure/Events/QueuingEventDispatcher.cs +++ b/src/Umbraco.Infrastructure/Events/QueuingEventDispatcher.cs @@ -1,5 +1,4 @@ -using Umbraco.Composing; -using Umbraco.Core.Composing; +using Umbraco.Core.Composing; using Umbraco.Core.IO; namespace Umbraco.Core.Events diff --git a/src/Umbraco.Infrastructure/HealthCheck/HealthCheckResults.cs b/src/Umbraco.Infrastructure/HealthCheck/HealthCheckResults.cs index 281b0fc445..37159b4a49 100644 --- a/src/Umbraco.Infrastructure/HealthCheck/HealthCheckResults.cs +++ b/src/Umbraco.Infrastructure/HealthCheck/HealthCheckResults.cs @@ -4,7 +4,7 @@ using System.Linq; using System.Text; using HeyRed.MarkdownSharp; using Microsoft.Extensions.Logging; -using Umbraco.Composing; +using Umbraco.Core; using Umbraco.Core.HealthCheck; namespace Umbraco.Infrastructure.HealthCheck @@ -14,7 +14,7 @@ namespace Umbraco.Infrastructure.HealthCheck private readonly Dictionary> _results; public readonly bool AllChecksSuccessful; - private ILogger Logger => Current.Logger; // TODO: inject + private ILogger Logger => StaticApplicationLogging.Logger; // TODO: inject public HealthCheckResults(IEnumerable checks) { diff --git a/src/Umbraco.Infrastructure/Models/PropertyTagsExtensions.cs b/src/Umbraco.Infrastructure/Models/PropertyTagsExtensions.cs index bea07879fb..f92dfe751b 100644 --- a/src/Umbraco.Infrastructure/Models/PropertyTagsExtensions.cs +++ b/src/Umbraco.Infrastructure/Models/PropertyTagsExtensions.cs @@ -4,7 +4,6 @@ using System.Linq; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Newtonsoft.Json.Linq; -using Umbraco.Composing; using Umbraco.Core.PropertyEditors; using Umbraco.Core.Services; @@ -219,7 +218,7 @@ namespace Umbraco.Core.Models } catch (Exception ex) { - Current.Logger.LogWarning(ex, "Could not automatically convert stored json value to an enumerable string '{Json}'", value.ToString()); + StaticApplicationLogging.Logger.LogWarning(ex, "Could not automatically convert stored json value to an enumerable string '{Json}'", value.ToString()); } break; diff --git a/src/Umbraco.Infrastructure/Persistence/DbConnectionExtensions.cs b/src/Umbraco.Infrastructure/Persistence/DbConnectionExtensions.cs index e00288d94c..82832a3627 100644 --- a/src/Umbraco.Infrastructure/Persistence/DbConnectionExtensions.cs +++ b/src/Umbraco.Infrastructure/Persistence/DbConnectionExtensions.cs @@ -5,7 +5,6 @@ using System.Data.SqlClient; using System.Linq; using Microsoft.Extensions.Logging; using StackExchange.Profiling.Data; -using Umbraco.Composing; using Umbraco.Core.Persistence.FaultHandling; namespace Umbraco.Core.Persistence @@ -53,7 +52,7 @@ namespace Umbraco.Core.Persistence catch (DbException e) { // Don't swallow this error, the exception is super handy for knowing "why" its not available - Current.Logger.LogWarning(e, "Configured database is reporting as not being available."); + StaticApplicationLogging.Logger.LogWarning(e, "Configured database is reporting as not being available."); return false; } diff --git a/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseExtensions.cs b/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseExtensions.cs index 4e5c3a113a..714721ef2c 100644 --- a/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseExtensions.cs +++ b/src/Umbraco.Infrastructure/Persistence/UmbracoDatabaseExtensions.cs @@ -1,5 +1,6 @@ using System; using Umbraco.Core.Persistence.Dtos; +using Umbraco.Core.Runtime; namespace Umbraco.Core.Persistence { @@ -15,7 +16,7 @@ namespace Umbraco.Core.Persistence /// /// Gets a key/value directly from the database, no scope, nothing. /// - /// Used by to determine the runtime state. + /// Used by to determine the runtime state. public static string GetFromKeyValueTable(this IUmbracoDatabase database, string key) { if (database is null) return null; diff --git a/src/Umbraco.Infrastructure/PropertyEditors/DataEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/DataEditor.cs index ebac6a763d..d74f285553 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/DataEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/DataEditor.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Runtime.Serialization; using Microsoft.Extensions.Logging; -using Umbraco.Composing; using Umbraco.Core.Composing; using Umbraco.Core.Services; using Umbraco.Core.Strings; diff --git a/src/Umbraco.Infrastructure/PropertyEditors/DataValueEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/DataValueEditor.cs index df9a06515c..fec245009f 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/DataValueEditor.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/DataValueEditor.cs @@ -7,7 +7,6 @@ using System.Xml.Linq; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Newtonsoft.Json.Linq; -using Umbraco.Composing; using Umbraco.Core.Composing; using Umbraco.Core.Models; using Umbraco.Core.Models.Editors; @@ -217,7 +216,7 @@ namespace Umbraco.Core.PropertyEditors var result = TryConvertValueToCrlType(editorValue.Value); if (result.Success == false) { - Current.Logger.LogWarning("The value {EditorValue} cannot be converted to the type {StorageTypeValue}", editorValue.Value, ValueTypes.ToStorageType(ValueType)); + StaticApplicationLogging.Logger.LogWarning("The value {EditorValue} cannot be converted to the type {StorageTypeValue}", editorValue.Value, ValueTypes.ToStorageType(ValueType)); return null; } return result.Result; diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/GridValueConverter.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/GridValueConverter.cs index 83866d958f..f601dac6d9 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/GridValueConverter.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/GridValueConverter.cs @@ -6,7 +6,6 @@ using Newtonsoft.Json.Linq; using Umbraco.Core.Composing; using Umbraco.Core.Configuration.Grid; using Umbraco.Core.Models.PublishedContent; -using Umbraco.Composing; namespace Umbraco.Core.PropertyEditors.ValueConverters { @@ -92,7 +91,7 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters } catch (Exception ex) { - Current.Logger.LogError(ex, "Could not parse the string '{JsonString}' to a json object", sourceString); + StaticApplicationLogging.Logger.LogError(ex, "Could not parse the string '{JsonString}' to a json object", sourceString); } } diff --git a/src/Umbraco.Infrastructure/Routing/NotFoundHandlerHelper.cs b/src/Umbraco.Infrastructure/Routing/NotFoundHandlerHelper.cs index ae50baa5b3..80aa0f1bc6 100644 --- a/src/Umbraco.Infrastructure/Routing/NotFoundHandlerHelper.cs +++ b/src/Umbraco.Infrastructure/Routing/NotFoundHandlerHelper.cs @@ -2,7 +2,6 @@ using System.Globalization; using System.Linq; using Microsoft.Extensions.Logging; -using Umbraco.Composing; using Umbraco.Core; using Umbraco.Core.Configuration.Models; using Umbraco.Core.Configuration.UmbracoSettings; @@ -108,7 +107,7 @@ namespace Umbraco.Web.Routing } catch (Exception ex) { - Current.Logger.LogError(ex, "Could not parse xpath expression: {ContentXPath}", errorPage.ContentXPath); + StaticApplicationLogging.Logger.LogError(ex, "Could not parse xpath expression: {ContentXPath}", errorPage.ContentXPath); return null; } } diff --git a/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs b/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs index dae8bcbf69..a0c1718c07 100644 --- a/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs +++ b/src/Umbraco.Infrastructure/Runtime/CoreRuntime.cs @@ -1,426 +1,75 @@ using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; -using Umbraco.Core.Cache; using Umbraco.Core.Composing; -using Umbraco.Core.Configuration; -using Umbraco.Core.Configuration.Models; -using Umbraco.Core.Events; -using Umbraco.Core.Exceptions; using Umbraco.Core.Hosting; -using Umbraco.Core.IO; using Umbraco.Core.Logging; -using Umbraco.Core.Persistence; -using Umbraco.Core.Persistence.Mappers; namespace Umbraco.Core.Runtime { - /// - /// Represents the Core Umbraco runtime. - /// - /// Does not handle any of the web-related aspects of Umbraco (startup, etc). It - /// should be possible to use this runtime in console apps. public class CoreRuntime : IRuntime { - private ComponentCollection _components; - // runtime state, this instance will get replaced again once the essential services are available to run the check - private RuntimeState _state = RuntimeState.Booting(); - private readonly IUmbracoBootPermissionChecker _umbracoBootPermissionChecker; - private readonly GlobalSettings _globalSettings; - private readonly ConnectionStrings _connectionStrings; + public IRuntimeState State { get; } - private IServiceProvider _serviceProvider; + private readonly ComponentCollection _components; + private readonly IUmbracoBootPermissionChecker _umbracoBootPermissionChecker; + private readonly IApplicationShutdownRegistry _applicationShutdownRegistry; + private readonly IProfilingLogger _profilingLogger; + private readonly IMainDom _mainDom; public CoreRuntime( - GlobalSettings globalSettings, - ConnectionStrings connectionStrings, - IUmbracoVersion umbracoVersion, - IIOHelper ioHelper, - ILoggerFactory loggerFactory, - IProfiler profiler, + IRuntimeState state, + ComponentCollection components, IUmbracoBootPermissionChecker umbracoBootPermissionChecker, - IHostingEnvironment hostingEnvironment, - IBackOfficeInfo backOfficeInfo, - IDbProviderFactoryCreator dbProviderFactoryCreator, - IMainDom mainDom, - ITypeFinder typeFinder, - AppCaches appCaches) + IApplicationShutdownRegistry applicationShutdownRegistry, + IProfilingLogger profilingLogger, + IMainDom mainDom) { - _globalSettings = globalSettings; - _connectionStrings = connectionStrings; - - IOHelper = ioHelper; - AppCaches = appCaches; - UmbracoVersion = umbracoVersion; - Profiler = profiler; - HostingEnvironment = hostingEnvironment; - BackOfficeInfo = backOfficeInfo; - DbProviderFactoryCreator = dbProviderFactoryCreator; - - RuntimeLoggerFactory = loggerFactory; + State = state; + _components = components; _umbracoBootPermissionChecker = umbracoBootPermissionChecker; - - Logger = loggerFactory.CreateLogger(); - MainDom = mainDom; - TypeFinder = typeFinder; - - _globalSettings = globalSettings; - _connectionStrings = connectionStrings; - + _applicationShutdownRegistry = applicationShutdownRegistry; + _profilingLogger = profilingLogger; + _mainDom = mainDom; } + - /// - /// Gets the logger. - /// - private ILogger Logger { get; } - - public ILoggerFactory RuntimeLoggerFactory { get; } - - protected IBackOfficeInfo BackOfficeInfo { get; } - - public IDbProviderFactoryCreator DbProviderFactoryCreator { get; } - - /// - /// Gets the profiler. - /// - protected IProfiler Profiler { get; } - - /// - /// Gets the profiling logger. - /// - public IProfilingLogger ProfilingLogger { get; private set; } - - /// - /// Gets the - /// - protected ITypeFinder TypeFinder { get; } - - /// - /// Gets the - /// - protected IIOHelper IOHelper { get; } - - protected IHostingEnvironment HostingEnvironment { get; } - public AppCaches AppCaches { get; } - public IUmbracoVersion UmbracoVersion { get; } - - /// - public IRuntimeState State => _state; - - public IMainDom MainDom { get; } - - /// - public virtual void Configure(IServiceCollection services) + public void Start() { - if (services is null) throw new ArgumentNullException(nameof(services)); - - - // create and register the essential services - // ie the bare minimum required to boot - - // the boot loader boots using a container scope, so anything that is PerScope will - // be disposed after the boot loader has booted, and anything else will remain. - // note that this REQUIRES that perWebRequestScope has NOT been enabled yet, else - // the container will fail to create a scope since there is no http context when - // the application starts. - // the boot loader is kept in the runtime for as long as Umbraco runs, and components - // are NOT disposed - which is not a big deal as long as they remain lightweight - // objects. - - var umbracoVersion = new UmbracoVersion(); - var profilingLogger = ProfilingLogger = new ProfilingLogger(Logger, Profiler); - using (var timer = profilingLogger.TraceDuration( - $"Booting Umbraco {umbracoVersion.SemanticVersion.ToSemanticString()}.", - "Booted.", - "Boot failed.")) - { - - Logger.LogInformation("Booting site '{HostingSiteName}', app '{HostingApplicationId}', path '{HostingPhysicalPath}', server '{MachineName}'.", - HostingEnvironment?.SiteName, - HostingEnvironment?.ApplicationId, - HostingEnvironment?.ApplicationPhysicalPath, - NetworkHelper.MachineName); - Logger.LogDebug("Runtime: {Runtime}", GetType().FullName); - - AppDomain.CurrentDomain.SetData("DataDirectory", HostingEnvironment?.MapPathContentRoot(Constants.SystemDirectories.Data)); - - // application environment - ConfigureUnhandledException(); - Configure(services, timer); - } - } - - /// - /// Configure the runtime within a timer. - /// - private void Configure(IServiceCollection services, DisposableTimer timer) - { - if (services is null) throw new ArgumentNullException(nameof(services)); - if (timer is null) throw new ArgumentNullException(nameof(timer)); - - Composition composition = null; - - try - { - // run handlers - OnRuntimeBoot(); - - // database factory - var databaseFactory = CreateDatabaseFactory(); - - // type finder/loader - var typeLoader = new TypeLoader(TypeFinder, AppCaches.RuntimeCache, new DirectoryInfo(HostingEnvironment.LocalTempPath), RuntimeLoggerFactory.CreateLogger(), ProfilingLogger); - - // re-create the state object with the essential services - _state = new RuntimeState(_globalSettings, UmbracoVersion, databaseFactory, RuntimeLoggerFactory.CreateLogger()); - - // create the composition - composition = new Composition(services, typeLoader, ProfilingLogger, _state, IOHelper, AppCaches); - - composition.RegisterEssentials(Logger, RuntimeLoggerFactory, Profiler, ProfilingLogger, MainDom, AppCaches, databaseFactory, typeLoader, _state, TypeFinder, IOHelper, UmbracoVersion, DbProviderFactoryCreator, HostingEnvironment, BackOfficeInfo); - - // register ourselves (TODO: Should we put this in RegisterEssentials?) - composition.Services.AddSingleton(_ => this); - - // run handlers - OnRuntimeEssentials(composition, AppCaches, typeLoader, databaseFactory); - - try - { - // determine our runtime level - DetermineRuntimeLevel(databaseFactory); - } - finally - { - // always run composers - RunComposers(typeLoader, composition); - } - - composition.RegisterBuilders(); - // TODO: We "should" be able to avoid this - _serviceProvider = composition.Services.BuildServiceProvider(); - } - catch (Exception e) - { - var bfe = e as BootFailedException ?? new BootFailedException("Boot failed.", e); - - if (_state != null) - { - _state.Level = RuntimeLevel.BootFailed; - _state.BootFailedException = bfe; - } - - timer?.Fail(exception: bfe); // be sure to log the exception - even if we repeat ourselves - - // if something goes wrong above, we may end up with no factory - // meaning nothing can get the runtime state, etc - so let's try - // to make sure we have a factory - - try - { - composition?.RegisterBuilders(); - // TODO: We "should" be able to avoid this - _serviceProvider = composition?.Services.BuildServiceProvider(); - } - catch { /* yea */ } - - - Debugger.Break(); - - // throwing here can cause w3wp to hard-crash and we want to avoid it. - // instead, we're logging the exception and setting level to BootFailed. - // various parts of Umbraco such as UmbracoModule and UmbracoDefaultOwinStartup - // understand this and will nullify themselves, while UmbracoModule will - // throw a BootFailedException for every requests. - } - } - - public void Start(IServiceProvider serviceProvider) - { - // Capture for CreateDatabaseFactory - // TODO: MSDI - Split core runtime into configure vs startup classes - // TODO: MSDI - Fix CreateDatabaseFactory - _serviceProvider = serviceProvider; - - if (_state.Level <= RuntimeLevel.BootFailed) + if (State.Level <= RuntimeLevel.BootFailed) throw new InvalidOperationException($"Cannot start the runtime if the runtime level is less than or equal to {RuntimeLevel.BootFailed}"); // throws if not full-trust _umbracoBootPermissionChecker.ThrowIfNotPermissions(); - var hostingEnvironmentLifetime = serviceProvider.GetService(); + var hostingEnvironmentLifetime = _applicationShutdownRegistry; if (hostingEnvironmentLifetime == null) throw new InvalidOperationException($"An instance of {typeof(IApplicationShutdownRegistry)} could not be resolved from the container, ensure that one if registered in your runtime before calling {nameof(IRuntime)}.{nameof(Start)}"); // acquire the main domain - if this fails then anything that should be registered with MainDom will not operate - AcquireMainDom(MainDom, serviceProvider.GetService()); + AcquireMainDom(_mainDom, _applicationShutdownRegistry); // create & initialize the components - _components = serviceProvider.GetService(); _components.Initialize(); } - protected virtual void ConfigureUnhandledException() - { - //take care of unhandled exceptions - there is nothing we can do to - // prevent the launch process to go down but at least we can try - // and log the exception - AppDomain.CurrentDomain.UnhandledException += (_, args) => - { - var exception = (Exception)args.ExceptionObject; - var isTerminating = args.IsTerminating; // always true? - - var msg = "Unhandled exception in AppDomain"; - if (isTerminating) msg += " (terminating)"; - msg += "."; - Logger.LogError(exception, msg); - }; - } - - private void RunComposers(TypeLoader typeLoader, Composition composition) - { - // get composers, and compose - var composerTypes = ResolveComposerTypes(typeLoader); - - IEnumerable enableDisableAttributes; - using (ProfilingLogger.DebugDuration("Scanning enable/disable composer attributes")) - { - enableDisableAttributes = typeLoader.GetAssemblyAttributes(typeof(EnableComposerAttribute), typeof(DisableComposerAttribute)); - } - - var composers = new Composers(composition, composerTypes, enableDisableAttributes, RuntimeLoggerFactory.CreateLogger(), ProfilingLogger); - composers.Compose(); - } - - private bool AcquireMainDom(IMainDom mainDom, IApplicationShutdownRegistry applicationShutdownRegistry) - { - using (var timer = ProfilingLogger.DebugDuration("Acquiring MainDom.", "Acquired.")) - { - try - { - return mainDom.Acquire(applicationShutdownRegistry); - } - catch - { - timer?.Fail(); - throw; - } - } - } - - private void DetermineRuntimeLevel(IUmbracoDatabaseFactory databaseFactory) - { - using var timer = ProfilingLogger.DebugDuration("Determining runtime level.", "Determined."); - - try - { - _state.DetermineRuntimeLevel(); - - Logger.LogDebug("Runtime level: {RuntimeLevel} - {RuntimeLevelReason}", _state.Level, _state.Reason); - - if (_state.Level == RuntimeLevel.Upgrade) - { - Logger.LogDebug("Configure database factory for upgrades."); - databaseFactory.ConfigureForUpgrade(); - } - } - catch - { - _state.Level = RuntimeLevel.BootFailed; - _state.Reason = RuntimeLevelReason.BootFailedOnException; - timer?.Fail(); - throw; - } - } - - private IEnumerable ResolveComposerTypes(TypeLoader typeLoader) - { - using (var timer = ProfilingLogger.TraceDuration("Resolving composer types.", "Resolved.")) - { - try - { - return GetComposerTypes(typeLoader); - } - catch - { - timer?.Fail(); - throw; - } - } - } - - /// - public virtual void Terminate() + public void Terminate() { _components?.Terminate(); } - #region Getters - - // getters can be implemented by runtimes inheriting from CoreRuntime - - /// - /// Gets all composer types. - /// - protected virtual IEnumerable GetComposerTypes(TypeLoader typeLoader) - => typeLoader.GetTypes(); - - /// - /// Returns the application path of the site/solution - /// - /// - /// - /// By default is null which means it's not running in any virtual folder. If the site is running in a virtual folder, this - /// can be overridden and the virtual path returned (i.e. /mysite/) - /// - protected virtual string GetApplicationRootPath() - => null; - - /// - /// Creates the database factory. - /// - /// This is strictly internal, for tests only. - protected internal virtual IUmbracoDatabaseFactory CreateDatabaseFactory() - => new UmbracoDatabaseFactory( - RuntimeLoggerFactory.CreateLogger(), - RuntimeLoggerFactory, - Options.Create(_globalSettings), - Options.Create(_connectionStrings), - new Lazy(() => + private void AcquireMainDom(IMainDom mainDom, IApplicationShutdownRegistry applicationShutdownRegistry) + { + using (var timer = _profilingLogger.DebugDuration("Acquiring MainDom.", "Acquired.")) + { + try { - if (_serviceProvider == null) - { - throw new ApplicationException("_serviceProvider should have been captured from CoreRuntime.Start (or built during configure)"); - } - return _serviceProvider.GetRequiredService(); - }), - DbProviderFactoryCreator); - - - #endregion - - #region Events - - protected void OnRuntimeBoot() - { - RuntimeOptions.DoRuntimeBoot(ProfilingLogger); - RuntimeBooting?.Invoke(this, ProfilingLogger); + mainDom.Acquire(applicationShutdownRegistry); + } + catch + { + timer?.Fail(); + throw; + } + } } - - protected void OnRuntimeEssentials(Composition composition, AppCaches appCaches, TypeLoader typeLoader, IUmbracoDatabaseFactory databaseFactory) - { - RuntimeOptions.DoRuntimeEssentials(composition, appCaches, typeLoader, databaseFactory); - RuntimeEssentials?.Invoke(this, new RuntimeEssentialsEventArgs(composition, appCaches, typeLoader, databaseFactory)); - } - - public event TypedEventHandler RuntimeBooting; - public event TypedEventHandler RuntimeEssentials; - - #endregion - } } diff --git a/src/Umbraco.Infrastructure/Runtime/CoreRuntimeBootstrapper.cs b/src/Umbraco.Infrastructure/Runtime/CoreRuntimeBootstrapper.cs new file mode 100644 index 0000000000..9b576324bd --- /dev/null +++ b/src/Umbraco.Infrastructure/Runtime/CoreRuntimeBootstrapper.cs @@ -0,0 +1,376 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Umbraco.Core.Cache; +using Umbraco.Core.Composing; +using Umbraco.Core.Configuration; +using Umbraco.Core.Configuration.Models; +using Umbraco.Core.Events; +using Umbraco.Core.Exceptions; +using Umbraco.Core.Hosting; +using Umbraco.Core.IO; +using Umbraco.Core.Logging; +using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.Mappers; + +namespace Umbraco.Core.Runtime +{ + /// + /// Bootstraps the Core Umbraco runtime. + /// + /// Does not handle any of the web-related aspects of Umbraco (startup, etc). It + /// should be possible to use this runtime in console apps. + public class CoreRuntimeBootstrapper + { + // runtime state, this instance will get replaced again once the essential services are available to run the check + private RuntimeState _state = RuntimeState.Booting(); + private readonly IUmbracoBootPermissionChecker _umbracoBootPermissionChecker; + private readonly GlobalSettings _globalSettings; + private readonly ConnectionStrings _connectionStrings; + + public CoreRuntimeBootstrapper( + GlobalSettings globalSettings, + ConnectionStrings connectionStrings, + IUmbracoVersion umbracoVersion, + IIOHelper ioHelper, + ILoggerFactory loggerFactory, + IProfiler profiler, + IUmbracoBootPermissionChecker umbracoBootPermissionChecker, + IHostingEnvironment hostingEnvironment, + IBackOfficeInfo backOfficeInfo, + IDbProviderFactoryCreator dbProviderFactoryCreator, + IMainDom mainDom, + ITypeFinder typeFinder, + AppCaches appCaches) + { + _globalSettings = globalSettings; + _connectionStrings = connectionStrings; + + IOHelper = ioHelper; + AppCaches = appCaches; + UmbracoVersion = umbracoVersion; + Profiler = profiler; + HostingEnvironment = hostingEnvironment; + BackOfficeInfo = backOfficeInfo; + DbProviderFactoryCreator = dbProviderFactoryCreator; + + RuntimeLoggerFactory = loggerFactory; + _umbracoBootPermissionChecker = umbracoBootPermissionChecker; + + Logger = loggerFactory.CreateLogger(); + MainDom = mainDom; + TypeFinder = typeFinder; + } + + /// + /// Gets the logger. + /// + private ILogger Logger { get; } + + public ILoggerFactory RuntimeLoggerFactory { get; } + + protected IBackOfficeInfo BackOfficeInfo { get; } + + public IDbProviderFactoryCreator DbProviderFactoryCreator { get; } + + /// + /// Gets the profiler. + /// + protected IProfiler Profiler { get; } + + /// + /// Gets the profiling logger. + /// + public IProfilingLogger ProfilingLogger { get; private set; } + + /// + /// Gets the + /// + protected ITypeFinder TypeFinder { get; } + + /// + /// Gets the + /// + protected IIOHelper IOHelper { get; } + + protected IHostingEnvironment HostingEnvironment { get; } + public AppCaches AppCaches { get; } + public IUmbracoVersion UmbracoVersion { get; } + + /// + public IRuntimeState State => _state; + + public IMainDom MainDom { get; } + + /// + public virtual void Configure(IServiceCollection services) + { + if (services is null) throw new ArgumentNullException(nameof(services)); + + + // create and register the essential services + // ie the bare minimum required to boot + + // the boot loader boots using a container scope, so anything that is PerScope will + // be disposed after the boot loader has booted, and anything else will remain. + // note that this REQUIRES that perWebRequestScope has NOT been enabled yet, else + // the container will fail to create a scope since there is no http context when + // the application starts. + // the boot loader is kept in the runtime for as long as Umbraco runs, and components + // are NOT disposed - which is not a big deal as long as they remain lightweight + // objects. + + var umbracoVersion = new UmbracoVersion(); + var profilingLogger = ProfilingLogger = new ProfilingLogger(Logger, Profiler); + using (var timer = profilingLogger.TraceDuration( + $"Booting Umbraco {umbracoVersion.SemanticVersion.ToSemanticString()}.", + "Booted.", + "Boot failed.")) + { + + Logger.LogInformation("Booting site '{HostingSiteName}', app '{HostingApplicationId}', path '{HostingPhysicalPath}', server '{MachineName}'.", + HostingEnvironment?.SiteName, + HostingEnvironment?.ApplicationId, + HostingEnvironment?.ApplicationPhysicalPath, + NetworkHelper.MachineName); + Logger.LogDebug("Runtime: {Runtime}", GetType().FullName); + + AppDomain.CurrentDomain.SetData("DataDirectory", HostingEnvironment?.MapPathContentRoot(Constants.SystemDirectories.Data)); + + // application environment + ConfigureUnhandledException(); + Configure(services, timer); + } + } + + /// + /// Configure the runtime within a timer. + /// + private void Configure(IServiceCollection services, DisposableTimer timer) + { + if (services is null) throw new ArgumentNullException(nameof(services)); + if (timer is null) throw new ArgumentNullException(nameof(timer)); + + Composition composition = null; + + try + { + // run handlers + OnRuntimeBoot(); + + // type finder/loader + var typeLoader = new TypeLoader(TypeFinder, AppCaches.RuntimeCache, + new DirectoryInfo(HostingEnvironment.LocalTempPath), + RuntimeLoggerFactory.CreateLogger(), ProfilingLogger); + + services.AddUnique(Logger); + services.AddUnique(RuntimeLoggerFactory); + services.AddUnique(_umbracoBootPermissionChecker); + services.AddUnique(Profiler); + services.AddUnique(ProfilingLogger); + services.AddUnique(MainDom); + services.AddUnique(AppCaches); + services.AddUnique(AppCaches.RequestCache); + services.AddUnique(typeLoader); + services.AddUnique(TypeFinder); + services.AddUnique(IOHelper); + services.AddUnique(UmbracoVersion); + services.AddUnique(DbProviderFactoryCreator); + services.AddUnique(HostingEnvironment); + services.AddUnique(BackOfficeInfo); + services.AddUnique(); + + // NOTE: This instance of IUmbracoDatabaseFactory is only used to determine runtime state. + var bootstrapDatabaseFactory = CreateBootstrapDatabaseFactory(); + + // after bootstrapping we let the container wire up for us. + services.AddUnique(); + services.AddUnique(factory => factory.GetRequiredService().SqlContext); + services.AddUnique(factory => factory.GetRequiredService().BulkSqlInsertProvider); + + // re-create the state object with the essential services + _state = new RuntimeState(_globalSettings, UmbracoVersion, bootstrapDatabaseFactory, RuntimeLoggerFactory.CreateLogger()); + services.AddUnique(_state); + + + // create the composition + composition = new Composition(services, typeLoader, ProfilingLogger, _state, IOHelper, AppCaches); + + // run handlers + OnRuntimeEssentials(composition, AppCaches, typeLoader, bootstrapDatabaseFactory); + + try + { + // determine our runtime level + DetermineRuntimeLevel(bootstrapDatabaseFactory); + } + finally + { + // always run composers + RunComposers(typeLoader, composition); + } + + } + catch (Exception e) + { + var bfe = e as BootFailedException ?? new BootFailedException("Boot failed.", e); + + if (_state != null) + { + _state.Level = RuntimeLevel.BootFailed; + _state.BootFailedException = bfe; + } + + timer?.Fail(exception: bfe); // be sure to log the exception - even if we repeat ourselves + + Debugger.Break(); + + // throwing here can cause w3wp to hard-crash and we want to avoid it. + // instead, we're logging the exception and setting level to BootFailed. + // various parts of Umbraco such as UmbracoModule and UmbracoDefaultOwinStartup + // understand this and will nullify themselves, while UmbracoModule will + // throw a BootFailedException for every requests. + } + finally + { + composition?.RegisterBuilders(); + } + } + + protected virtual void ConfigureUnhandledException() + { + //take care of unhandled exceptions - there is nothing we can do to + // prevent the launch process to go down but at least we can try + // and log the exception + AppDomain.CurrentDomain.UnhandledException += (_, args) => + { + var exception = (Exception)args.ExceptionObject; + var isTerminating = args.IsTerminating; // always true? + + var msg = "Unhandled exception in AppDomain"; + if (isTerminating) msg += " (terminating)"; + msg += "."; + Logger.LogError(exception, msg); + }; + } + + private void RunComposers(TypeLoader typeLoader, Composition composition) + { + // get composers, and compose + var composerTypes = ResolveComposerTypes(typeLoader); + + IEnumerable enableDisableAttributes; + using (ProfilingLogger.DebugDuration("Scanning enable/disable composer attributes")) + { + enableDisableAttributes = typeLoader.GetAssemblyAttributes(typeof(EnableComposerAttribute), typeof(DisableComposerAttribute)); + } + + var composers = new Composers(composition, composerTypes, enableDisableAttributes, RuntimeLoggerFactory.CreateLogger(), ProfilingLogger); + composers.Compose(); + } + + + private void DetermineRuntimeLevel(IUmbracoDatabaseFactory databaseFactory) + { + using var timer = ProfilingLogger.DebugDuration("Determining runtime level.", "Determined."); + + try + { + _state.DetermineRuntimeLevel(); + + Logger.LogDebug("Runtime level: {RuntimeLevel} - {RuntimeLevelReason}", _state.Level, _state.Reason); + + if (_state.Level == RuntimeLevel.Upgrade) + { + Logger.LogDebug("Configure database factory for upgrades."); + databaseFactory.ConfigureForUpgrade(); + } + } + catch + { + _state.Level = RuntimeLevel.BootFailed; + _state.Reason = RuntimeLevelReason.BootFailedOnException; + timer?.Fail(); + throw; + } + } + + private IEnumerable ResolveComposerTypes(TypeLoader typeLoader) + { + using (var timer = ProfilingLogger.TraceDuration("Resolving composer types.", "Resolved.")) + { + try + { + return GetComposerTypes(typeLoader); + } + catch + { + timer?.Fail(); + throw; + } + } + } + + #region Getters + + // getters can be implemented by runtimes inheriting from CoreRuntime + + /// + /// Gets all composer types. + /// + protected virtual IEnumerable GetComposerTypes(TypeLoader typeLoader) + => typeLoader.GetTypes(); + + /// + /// Returns the application path of the site/solution + /// + /// + /// + /// By default is null which means it's not running in any virtual folder. If the site is running in a virtual folder, this + /// can be overridden and the virtual path returned (i.e. /mysite/) + /// + protected virtual string GetApplicationRootPath() + => null; + + /// + /// Creates the database factory. + /// + /// This is strictly internal, for tests only. + protected internal virtual IUmbracoDatabaseFactory CreateBootstrapDatabaseFactory() + => new UmbracoDatabaseFactory( + RuntimeLoggerFactory.CreateLogger(), + RuntimeLoggerFactory, + Options.Create(_globalSettings), + Options.Create(_connectionStrings), + new Lazy(() => new MapperCollection(Enumerable.Empty())), + DbProviderFactoryCreator); + + + #endregion + + #region Events + + protected void OnRuntimeBoot() + { + RuntimeOptions.DoRuntimeBoot(ProfilingLogger); + RuntimeBooting?.Invoke(this, ProfilingLogger); + } + + protected void OnRuntimeEssentials(Composition composition, AppCaches appCaches, TypeLoader typeLoader, IUmbracoDatabaseFactory databaseFactory) + { + RuntimeOptions.DoRuntimeEssentials(composition, appCaches, typeLoader, databaseFactory); + RuntimeEssentials?.Invoke(this, new RuntimeEssentialsEventArgs(composition, appCaches, typeLoader, databaseFactory)); + } + + public event TypedEventHandler RuntimeBooting; + public event TypedEventHandler RuntimeEssentials; + + #endregion + + } +} diff --git a/src/Umbraco.Infrastructure/Services/Implement/ContentService.cs b/src/Umbraco.Infrastructure/Services/Implement/ContentService.cs index b796f9b686..120c0500e2 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/ContentService.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/ContentService.cs @@ -1767,7 +1767,7 @@ namespace Umbraco.Core.Services.Implement #region Delete /// - public OperationResult Delete(IContent content, int userId) + public OperationResult Delete(IContent content, int userId = Constants.Security.SuperUserId) { var evtMsgs = EventMessagesFactory.Get(); @@ -1897,7 +1897,7 @@ namespace Umbraco.Core.Services.Implement #region Move, RecycleBin /// - public OperationResult MoveToRecycleBin(IContent content, int userId) + public OperationResult MoveToRecycleBin(IContent content, int userId = Constants.Security.SuperUserId) { var evtMsgs = EventMessagesFactory.Get(); var moves = new List<(IContent, string)>(); diff --git a/src/Umbraco.Infrastructure/Services/Implement/EntityXmlSerializer.cs b/src/Umbraco.Infrastructure/Services/Implement/EntityXmlSerializer.cs index d69297eb57..2d0a44986c 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/EntityXmlSerializer.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/EntityXmlSerializer.cs @@ -5,7 +5,6 @@ using System.Linq; using System.Net; using System.Xml.Linq; using Newtonsoft.Json; -using Umbraco.Composing; using Umbraco.Core.Composing; using Umbraco.Core.Models; using Umbraco.Core.PropertyEditors; diff --git a/src/Umbraco.Infrastructure/Services/Implement/LocalizedTextServiceFileSources.cs b/src/Umbraco.Infrastructure/Services/Implement/LocalizedTextServiceFileSources.cs index b4c49b9509..78bb71bcf1 100644 --- a/src/Umbraco.Infrastructure/Services/Implement/LocalizedTextServiceFileSources.cs +++ b/src/Umbraco.Infrastructure/Services/Implement/LocalizedTextServiceFileSources.cs @@ -5,7 +5,6 @@ using System.IO; using System.Linq; using System.Xml; using System.Xml.Linq; -using Umbraco.Composing; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Microsoft.Extensions.Logging; diff --git a/src/Umbraco.Infrastructure/Suspendable.cs b/src/Umbraco.Infrastructure/Suspendable.cs index e03931d0d7..33677062f1 100644 --- a/src/Umbraco.Infrastructure/Suspendable.cs +++ b/src/Umbraco.Infrastructure/Suspendable.cs @@ -1,5 +1,5 @@ using Microsoft.Extensions.Logging; -using Umbraco.Composing; +using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Examine; using Umbraco.Web.Cache; @@ -30,7 +30,7 @@ namespace Umbraco.Web public static void SuspendDocumentCache() { - Current.Logger.LogInformation("Suspend document cache."); + StaticApplicationLogging.Logger.LogInformation("Suspend document cache."); _suspended = true; } @@ -38,7 +38,7 @@ namespace Umbraco.Web { _suspended = false; - Current.Logger.LogInformation("Resume document cache (reload:{Tried}).", _tried); + StaticApplicationLogging.Logger.LogInformation("Resume document cache (reload:{Tried}).", _tried); if (_tried == false) return; _tried = false; @@ -74,7 +74,7 @@ namespace Umbraco.Web { _suspended = false; - Current.Logger.LogInformation("Resume indexers (rebuild:{Tried}).", _tried); + StaticApplicationLogging.Logger.LogInformation("Resume indexers (rebuild:{Tried}).", _tried); if (_tried == false) return; _tried = false; @@ -91,13 +91,13 @@ namespace Umbraco.Web public static void Suspend() { - Current.Logger.LogInformation("Suspend scheduled publishing."); + StaticApplicationLogging.Logger.LogInformation("Suspend scheduled publishing."); _suspended = true; } public static void Resume() { - Current.Logger.LogInformation("Resume scheduled publishing."); + StaticApplicationLogging.Logger.LogInformation("Resume scheduled publishing."); _suspended = false; } } diff --git a/src/Umbraco.Infrastructure/Sync/ServerMessengerBase.cs b/src/Umbraco.Infrastructure/Sync/ServerMessengerBase.cs index d115bc7595..f2918ffe96 100644 --- a/src/Umbraco.Infrastructure/Sync/ServerMessengerBase.cs +++ b/src/Umbraco.Infrastructure/Sync/ServerMessengerBase.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.Linq; using Newtonsoft.Json; -using Umbraco.Composing; using Umbraco.Core.Cache; using Microsoft.Extensions.Logging; @@ -157,7 +156,7 @@ namespace Umbraco.Core.Sync { if (refresher == null) throw new ArgumentNullException(nameof(refresher)); - Current.Logger.LogDebug("Invoking refresher {RefresherType} on local server for message type RefreshByPayload", refresher.GetType()); + StaticApplicationLogging.Logger.LogDebug("Invoking refresher {RefresherType} on local server for message type RefreshByPayload", refresher.GetType()); var payloadRefresher = refresher as IPayloadCacheRefresher; if (payloadRefresher == null) @@ -179,7 +178,7 @@ namespace Umbraco.Core.Sync { if (refresher == null) throw new ArgumentNullException(nameof(refresher)); - Current.Logger.LogDebug("Invoking refresher {RefresherType} on local server for message type {MessageType}", refresher.GetType(), messageType); + StaticApplicationLogging.Logger.LogDebug("Invoking refresher {RefresherType} on local server for message type {MessageType}", refresher.GetType(), messageType); switch (messageType) { @@ -240,7 +239,7 @@ namespace Umbraco.Core.Sync { if (refresher == null) throw new ArgumentNullException(nameof(refresher)); - Current.Logger.LogDebug("Invoking refresher {RefresherType} on local server for message type {MessageType}", refresher.GetType(), messageType); + StaticApplicationLogging.Logger.LogDebug("Invoking refresher {RefresherType} on local server for message type {MessageType}", refresher.GetType(), messageType); var typedRefresher = refresher as ICacheRefresher; diff --git a/src/Umbraco.Infrastructure/Trees/TreeNode.cs b/src/Umbraco.Infrastructure/Trees/TreeNode.cs index 5cf1054fc8..ad64f3dc5e 100644 --- a/src/Umbraco.Infrastructure/Trees/TreeNode.cs +++ b/src/Umbraco.Infrastructure/Trees/TreeNode.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Runtime.Serialization; -using Umbraco.Composing; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; @@ -106,20 +105,8 @@ namespace Umbraco.Web.Models.Trees { get { - if (IconIsClass) - return string.Empty; - - //absolute path with or without tilde - if (Icon.StartsWith("~") || Icon.StartsWith("/")) - return Current.IOHelper.ResolveUrl("~" + Icon.TrimStart('~')); - - //legacy icon path - - // TODO: replace this when we have something other than Current.Configs available - var backOfficePath = Current.GlobalSettings.GetUmbracoMvcArea(Current.HostingEnvironment); - - - return string.Format("{0}images/umbraco/{1}", backOfficePath.EnsureEndsWith("/"), Icon); + // TODO: Is this ever actually used? If not remove, if so, add setter. + return string.Empty; } } diff --git a/src/Umbraco.Tests.Integration/RuntimeTests.cs b/src/Umbraco.Tests.Integration/RuntimeTests.cs index 4070a9ea74..db7f7499e3 100644 --- a/src/Umbraco.Tests.Integration/RuntimeTests.cs +++ b/src/Umbraco.Tests.Integration/RuntimeTests.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System; +using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; @@ -10,6 +11,8 @@ using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Composing; using Umbraco.Core.Configuration.Models; +using Umbraco.Core.Persistence; +using Umbraco.Core.Persistence.Mappers; using Umbraco.Core.Runtime; using Umbraco.Extensions; using Umbraco.Tests.Common; @@ -43,7 +46,6 @@ namespace Umbraco.Tests.Integration [Test] public void Boot_Core_Runtime() { - // TODO: MSDI - cleanup after initial merge. var services = new ServiceCollection().AddLazySupport(); // Special case since we are not using the Generic Host, we need to manually add an AspNetCore service to the container @@ -64,6 +66,7 @@ namespace Umbraco.Tests.Integration var webRoutingSettings = new WebRoutingSettings(); services.AddTransient(x => Options.Create(globalSettings)); + services.AddTransient(x => Options.Create(connectionStrings)); services.AddTransient(x => Options.Create(contentSettings)); services.AddTransient(x => Options.Create(coreDebugSettings)); services.AddTransient(x => Options.Create(nuCacheSettings)); @@ -73,26 +76,30 @@ namespace Umbraco.Tests.Integration services.AddSingleton(typeof(ILogger<>), typeof(Logger<>)); // Create the core runtime - var coreRuntime = new CoreRuntime(globalSettings, connectionStrings, testHelper.GetUmbracoVersion(), + var bootstrapper = new CoreRuntimeBootstrapper(globalSettings, connectionStrings, testHelper.GetUmbracoVersion(), testHelper.IOHelper, testHelper.ConsoleLoggerFactory, testHelper.Profiler, testHelper.UmbracoBootPermissionChecker, testHelper.GetHostingEnvironment(), testHelper.GetBackOfficeInfo(), testHelper.DbProviderFactoryCreator, testHelper.MainDom, testHelper.GetTypeFinder(), AppCaches.NoCache); - coreRuntime.Configure(services); + bootstrapper.Configure(services); - Assert.IsTrue(coreRuntime.MainDom.IsMainDom); - Assert.IsNull(coreRuntime.State.BootFailedException); - Assert.AreEqual(RuntimeLevel.Install, coreRuntime.State.Level); + Assert.IsTrue(bootstrapper.MainDom.IsMainDom); + Assert.IsNull(bootstrapper.State.BootFailedException); + Assert.AreEqual(RuntimeLevel.Install, bootstrapper.State.Level); Assert.IsTrue(MyComposer.IsComposed); Assert.IsFalse(MyComponent.IsInit); Assert.IsFalse(MyComponent.IsTerminated); - coreRuntime.Start(services.BuildServiceProvider()); + var container = services.BuildServiceProvider(); + + var runtime = container.GetRequiredService(); + + runtime.Start(); Assert.IsTrue(MyComponent.IsInit); Assert.IsFalse(MyComponent.IsTerminated); - coreRuntime.Terminate(); + runtime.Terminate(); Assert.IsTrue(MyComponent.IsTerminated); } diff --git a/src/Umbraco.Tests.Integration/TestServerTest/UmbracoBuilderExtensions.cs b/src/Umbraco.Tests.Integration/TestServerTest/UmbracoBuilderExtensions.cs index 23b4b17be8..171914ecd6 100644 --- a/src/Umbraco.Tests.Integration/TestServerTest/UmbracoBuilderExtensions.cs +++ b/src/Umbraco.Tests.Integration/TestServerTest/UmbracoBuilderExtensions.cs @@ -16,7 +16,7 @@ namespace Umbraco.Tests.Integration.TestServerTest /// /// public static IUmbracoBuilder WithTestCore(this IUmbracoBuilder builder, TestHelper testHelper, - Action dbInstallEventHandler) + Action dbInstallEventHandler) { return builder.AddWith(nameof(global::Umbraco.Web.Common.Builder.UmbracoBuilderExtensions.WithCore), () => diff --git a/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs b/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs index a7ea7e0315..0595e3477b 100644 --- a/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs +++ b/src/Umbraco.Tests.Integration/TestServerTest/UmbracoTestServerTestBase.cs @@ -13,7 +13,6 @@ using Microsoft.AspNetCore.TestHost; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using NUnit.Framework; -using Umbraco.Composing; using Umbraco.Core; using Umbraco.Extensions; using Umbraco.Tests.Integration.Testing; @@ -118,13 +117,9 @@ namespace Umbraco.Tests.Integration.TestServerTest public override void TearDown() { base.TearDown(); + base.TerminateCoreRuntime(); Factory.Dispose(); - - if (Current.IsInitialized) - { - Current.IsInitialized = false; - } } #region IStartup diff --git a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs index 437a282ecf..ecdaac53b2 100644 --- a/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs +++ b/src/Umbraco.Tests.Integration/Testing/UmbracoIntegrationTest.cs @@ -71,7 +71,10 @@ namespace Umbraco.Tests.Integration.Testing [TearDown] public virtual void TearDown() { - foreach (var a in _testTeardown) a(); + if (_testTeardown != null) + { + foreach (var a in _testTeardown) a(); + } _testTeardown = null; FirstTestInFixture = false; FirstTestInSession = false; @@ -88,6 +91,7 @@ namespace Umbraco.Tests.Integration.Testing { TestContext.Progress.Write($"Start test {TestCount++}: {TestContext.CurrentContext.Test.Name}"); } + [SetUp] public virtual void Setup() { @@ -157,7 +161,7 @@ namespace Umbraco.Tests.Integration.Testing } /// - /// Creates a instance for testing and registers an event handler for database install + /// Creates a instance for testing and registers an event handler for database install /// /// /// @@ -172,7 +176,7 @@ namespace Umbraco.Tests.Integration.Testing /// /// /// - public CoreRuntime CreateTestRuntime( + public CoreRuntimeBootstrapper CreateTestRuntime( GlobalSettings globalSettings, ConnectionStrings connectionStrings, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, @@ -199,7 +203,7 @@ namespace Umbraco.Tests.Integration.Testing } /// - /// Creates a instance for testing and registers an event handler for database install + /// Creates a instance for testing and registers an event handler for database install /// /// /// @@ -216,15 +220,15 @@ namespace Umbraco.Tests.Integration.Testing /// The event handler used for DB installation /// /// - public static CoreRuntime CreateTestRuntime( + public static CoreRuntimeBootstrapper CreateTestRuntime( GlobalSettings globalSettings, ConnectionStrings connectionStrings, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILoggerFactory loggerFactory, IProfiler profiler, Core.Hosting.IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo, ITypeFinder typeFinder, AppCaches appCaches, IDbProviderFactoryCreator dbProviderFactoryCreator, - IMainDom mainDom, Action eventHandler) + IMainDom mainDom, Action eventHandler) { - var runtime = new CoreRuntime( + var runtime = new CoreRuntimeBootstrapper( globalSettings, connectionStrings, umbracoVersion, @@ -292,9 +296,21 @@ namespace Umbraco.Tests.Integration.Testing Services.GetRequiredService().EnsureBackofficeSecurity(); Services.GetRequiredService().EnsureUmbracoContext(); app.UseUmbracoCore(); // Takes 200 ms + + OnTestTearDown(TerminateCoreRuntime); } } + /// + /// Some IComponents hook onto static events (e.g. Published in ContentService) + /// If these fire after the components host has been shutdown, errors can occur. + /// If CoreRuntime.Start() is called We also need to de-register the events. + /// + protected void TerminateCoreRuntime() + { + Services.GetRequiredService().Terminate(); + } + #endregion #region LocalDb @@ -303,19 +319,23 @@ namespace Umbraco.Tests.Integration.Testing private static LocalDbTestDatabase _dbInstance; /// - /// Event handler for the to install the database and register the to Terminate + /// Event handler for the to install the database /// - /// + /// /// - protected void UseTestLocalDb(CoreRuntime runtime, RuntimeEssentialsEventArgs args) + protected void UseTestLocalDb(CoreRuntimeBootstrapper runtimeBootstrapper, RuntimeEssentialsEventArgs args) { - // MUST be terminated on teardown - OnTestTearDown(() => runtime.Terminate()); - // This will create a db, install the schema and ensure the app is configured to run - InstallTestLocalDb(args.DatabaseFactory, runtime.RuntimeLoggerFactory, runtime.State, TestHelper.WorkingDirectory, out var connectionString); - TestDBConnectionString = connectionString; + InstallTestLocalDb(args.DatabaseFactory, runtimeBootstrapper.RuntimeLoggerFactory, runtimeBootstrapper.State, TestHelper.WorkingDirectory); + TestDBConnectionString = args.DatabaseFactory.ConnectionString; InMemoryConfiguration["ConnectionStrings:" + Constants.System.UmbracoConnectionName] = TestDBConnectionString; + + // Re-configure IOptions now that we have a test db + // This is what will be resolved first time IUmbracoDatabaseFactory is resolved from container (e.g. post CoreRuntime bootstrap) + args.Composition.Services.Configure((x) => + { + x.UmbracoConnectionString = new ConfigConnectionString(Constants.System.UmbracoConnectionName, TestDBConnectionString); + }); } /// @@ -356,9 +376,8 @@ namespace Umbraco.Tests.Integration.Testing /// private void InstallTestLocalDb( IUmbracoDatabaseFactory databaseFactory, ILoggerFactory loggerFactory, - IRuntimeState runtimeState, string workingDirectory, out string connectionString) + IRuntimeState runtimeState, string workingDirectory) { - connectionString = null; var dbFilePath = Path.Combine(workingDirectory, "LocalDb"); // get the currently set db options @@ -461,7 +480,6 @@ namespace Umbraco.Tests.Integration.Testing default: throw new ArgumentOutOfRangeException(nameof(testOptions), testOptions, null); } - connectionString = db.ConnectionString; } #endregion diff --git a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEventsTests.cs b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEventsTests.cs index ce98e4f5a8..d5f9f41cbb 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEventsTests.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentEventsTests.cs @@ -7,7 +7,6 @@ using Umbraco.Core.Cache; using Microsoft.Extensions.Logging; using Umbraco.Core.Models; using Umbraco.Core.Persistence.Repositories.Implement; -using Umbraco.Core.Services; using Umbraco.Core.Sync; using Umbraco.Tests.Common.Builders; using Umbraco.Tests.Integration.Testing; @@ -24,8 +23,6 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Services private CacheRefresherCollection CacheRefresherCollection => GetRequiredService(); private IUmbracoContextFactory UmbracoContextFactory => GetRequiredService(); private ILogger Logger => GetRequiredService>(); - private IContentService ContentService => GetRequiredService(); - private IFileService FileService => GetRequiredService(); #region Setup diff --git a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentServicePerformanceTest.cs b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentServicePerformanceTest.cs index b7839d485c..072fbe04a3 100644 --- a/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentServicePerformanceTest.cs +++ b/src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentServicePerformanceTest.cs @@ -5,7 +5,7 @@ using System.Linq; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using NUnit.Framework; -using Umbraco.Composing; +using Umbraco.Core; using Umbraco.Core.Logging; using Umbraco.Core.Models; using Umbraco.Core.Persistence.Repositories; @@ -109,7 +109,7 @@ namespace Umbraco.Tests.Integration.Umbraco.Infrastructure.Services total.AddRange(ContentService.GetPagedDescendants(content.Id, 0, int.MaxValue, out var _)); } TestProfiler.Disable(); - Current.Logger.LogInformation("Returned {Total} items", total.Count); + StaticApplicationLogging.Logger.LogInformation("Returned {Total} items", total.Count); } } diff --git a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs index 19fccab900..de20211774 100644 --- a/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs +++ b/src/Umbraco.Tests/Routing/RenderRouteHandlerTests.cs @@ -53,9 +53,9 @@ namespace Umbraco.Tests.Routing HostingEnvironment); } - public class TestRuntime : CoreRuntime + public class TestRuntimeBootstrapper : CoreRuntimeBootstrapper { - public TestRuntime(GlobalSettings globalSettings, ConnectionStrings connectionStrings, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo) + public TestRuntimeBootstrapper(GlobalSettings globalSettings, ConnectionStrings connectionStrings, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo) : base(globalSettings, connectionStrings,umbracoVersion, ioHelper, NullLoggerFactory.Instance, Mock.Of(), new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, TestHelper.GetTypeFinder(), AppCaches.NoCache) { } diff --git a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs index 60e395344d..70beb3643a 100644 --- a/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs +++ b/src/Umbraco.Tests/Runtimes/CoreRuntimeTests.cs @@ -60,18 +60,18 @@ namespace Umbraco.Tests.Runtimes private static readonly IProfiler _profiler = new TestProfiler(); private static readonly GlobalSettings _globalSettings = new GlobalSettings(); - public IRuntime Runtime { get; private set; } - protected override IRuntime GetRuntime(GlobalSettings globalSettings, ConnectionStrings connectionStrings, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger, ILoggerFactory loggerFactory, IProfiler profiler, IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo) + + protected override CoreRuntimeBootstrapper GetRuntime(GlobalSettings globalSettings, ConnectionStrings connectionStrings, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger, ILoggerFactory loggerFactory, IProfiler profiler, IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo) { - return Runtime = new TestRuntime(globalSettings, connectionStrings, umbracoVersion, ioHelper, logger, loggerFactory, profiler, hostingEnvironment, backOfficeInfo); + return new TestRuntimeBootstrapper(globalSettings, connectionStrings, umbracoVersion, ioHelper, logger, loggerFactory, profiler, hostingEnvironment, backOfficeInfo); } } // test runtime - public class TestRuntime : CoreRuntime + public class TestRuntimeBootstrapper : CoreRuntimeBootstrapper { - public TestRuntime(GlobalSettings globalSettings, ConnectionStrings connectionStrings, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger, ILoggerFactory loggerFactory, IProfiler profiler, IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo) + public TestRuntimeBootstrapper(GlobalSettings globalSettings, ConnectionStrings connectionStrings, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger, ILoggerFactory loggerFactory, IProfiler profiler, IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo) :base(globalSettings, connectionStrings,umbracoVersion, ioHelper, loggerFactory, profiler, new AspNetUmbracoBootPermissionChecker(), hostingEnvironment, backOfficeInfo, TestHelper.DbProviderFactoryCreator, TestHelper.MainDom, TestHelper.GetTypeFinder(), AppCaches.NoCache) { @@ -79,7 +79,7 @@ namespace Umbraco.Tests.Runtimes // must override the database factory // else BootFailedException because U cannot connect to the configured db - protected internal override IUmbracoDatabaseFactory CreateDatabaseFactory() + protected internal override IUmbracoDatabaseFactory CreateBootstrapDatabaseFactory() { var mock = new Mock(); mock.Setup(x => x.Configured).Returns(true); diff --git a/src/Umbraco.Tests/Web/Mvc/ValidateUmbracoFormRouteStringAttributeTests.cs b/src/Umbraco.Tests/Web/Mvc/ValidateUmbracoFormRouteStringAttributeTests.cs index 9d9c965440..d4c3b7c887 100644 --- a/src/Umbraco.Tests/Web/Mvc/ValidateUmbracoFormRouteStringAttributeTests.cs +++ b/src/Umbraco.Tests/Web/Mvc/ValidateUmbracoFormRouteStringAttributeTests.cs @@ -1,5 +1,4 @@ using NUnit.Framework; -using Umbraco.Composing; using Umbraco.Web; using Umbraco.Web.Mvc; diff --git a/src/Umbraco.Web.BackOffice/Controllers/ContentControllerBase.cs b/src/Umbraco.Web.BackOffice/Controllers/ContentControllerBase.cs index d2b751837c..a3c1cfb89a 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/ContentControllerBase.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/ContentControllerBase.cs @@ -4,7 +4,6 @@ using System.Net; using System.Net.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; -using Umbraco.Composing; using Umbraco.Core; using Umbraco.Core.Cache; using Umbraco.Core.Configuration; diff --git a/src/Umbraco.Web.BackOffice/Controllers/UpdateCheckController.cs b/src/Umbraco.Web.BackOffice/Controllers/UpdateCheckController.cs index 71dc97c835..6bed6a2b2c 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/UpdateCheckController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/UpdateCheckController.cs @@ -5,7 +5,6 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.Extensions.Options; using Semver; -using Umbraco.Composing; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; diff --git a/src/Umbraco.Web.BackOffice/Extensions/BackOfficeApplicationBuilderExtensions.cs b/src/Umbraco.Web.BackOffice/Extensions/BackOfficeApplicationBuilderExtensions.cs index 8b38211794..3c6b538506 100644 --- a/src/Umbraco.Web.BackOffice/Extensions/BackOfficeApplicationBuilderExtensions.cs +++ b/src/Umbraco.Web.BackOffice/Extensions/BackOfficeApplicationBuilderExtensions.cs @@ -1,13 +1,7 @@ using System; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Options; using SixLabors.ImageSharp.Web.DependencyInjection; -using Umbraco.Composing; -using Umbraco.Core; -using Umbraco.Core.Configuration.Models; -using Umbraco.Core.IO; using Umbraco.Web.BackOffice.Routing; using Umbraco.Web.BackOffice.Security; @@ -29,18 +23,6 @@ namespace Umbraco.Extensions app.UseUmbracoPreview(); app.UseUmbracoInstaller(); - - // TODO: remove current class, it's on its last legs. - Current.Initialize( - app.ApplicationServices.GetService>(), - app.ApplicationServices.GetService>().Value, - app.ApplicationServices.GetService>().Value, - app.ApplicationServices.GetService(), - app.ApplicationServices.GetService(), - app.ApplicationServices.GetService(), - app.ApplicationServices.GetService() - ); - return app; } diff --git a/src/Umbraco.Web.BackOffice/Trees/PartialViewMacrosTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/PartialViewMacrosTreeController.cs index f651c86cae..5baeac7d17 100644 --- a/src/Umbraco.Web.BackOffice/Trees/PartialViewMacrosTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/PartialViewMacrosTreeController.cs @@ -1,5 +1,4 @@ -using Umbraco.Composing; -using Umbraco.Core.IO; +using Umbraco.Core.IO; using Umbraco.Core.Services; using Umbraco.Web.BackOffice.Filters; using Umbraco.Web.Common.Attributes; diff --git a/src/Umbraco.Web.BackOffice/Trees/PartialViewsTreeController.cs b/src/Umbraco.Web.BackOffice/Trees/PartialViewsTreeController.cs index 258f77fe17..dcb98ac5b4 100644 --- a/src/Umbraco.Web.BackOffice/Trees/PartialViewsTreeController.cs +++ b/src/Umbraco.Web.BackOffice/Trees/PartialViewsTreeController.cs @@ -1,5 +1,4 @@ -using Umbraco.Composing; -using Umbraco.Core.IO; +using Umbraco.Core.IO; using Umbraco.Core.Services; using Umbraco.Web.BackOffice.Filters; using Umbraco.Web.Common.Attributes; diff --git a/src/Umbraco.Web.Common/Controllers/UmbracoController.cs b/src/Umbraco.Web.Common/Controllers/UmbracoController.cs index 1498b2c75c..50ec620741 100644 --- a/src/Umbraco.Web.Common/Controllers/UmbracoController.cs +++ b/src/Umbraco.Web.Common/Controllers/UmbracoController.cs @@ -2,7 +2,6 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using Umbraco.Composing; using Umbraco.Core.Cache; using Umbraco.Core.Logging; using Umbraco.Core.Configuration.Models; diff --git a/src/Umbraco.Web.Common/Extensions/ApplicationBuilderExtensions.cs b/src/Umbraco.Web.Common/Extensions/ApplicationBuilderExtensions.cs index 9688e5794a..36d4ddbd42 100644 --- a/src/Umbraco.Web.Common/Extensions/ApplicationBuilderExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/ApplicationBuilderExtensions.cs @@ -2,6 +2,7 @@ using System; using System.Net; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Serilog.Context; using Smidge; using Smidge.Nuglify; @@ -51,9 +52,11 @@ namespace Umbraco.Extensions // Register our global threadabort enricher for logging var threadAbortEnricher = app.ApplicationServices.GetRequiredService(); LogContext.Push(threadAbortEnricher); // NOTE: We are not in a using clause because we are not removing it, it is on the global context - + + StaticApplicationLogging.Initialize(app.ApplicationServices.GetRequiredService()); + // Start the runtime! - runtime.Start(app.ApplicationServices); + runtime.Start(); return app; } diff --git a/src/Umbraco.Web.Common/Extensions/ImageCropperTemplateExtensions.cs b/src/Umbraco.Web.Common/Extensions/ImageCropperTemplateExtensions.cs index 77c07e85b2..3af01da3de 100644 --- a/src/Umbraco.Web.Common/Extensions/ImageCropperTemplateExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/ImageCropperTemplateExtensions.cs @@ -1,7 +1,6 @@ using System; using System.Globalization; using Newtonsoft.Json; -using Umbraco.Composing; using Umbraco.Core; using Umbraco.Core.PropertyEditors.ValueConverters; using Microsoft.Extensions.Logging; @@ -28,7 +27,7 @@ namespace Umbraco.Extensions } catch (Exception ex) { - Current.Logger.LogError(ex, "Could not parse the json string: {Json}", json); + StaticApplicationLogging.Logger.LogError(ex, "Could not parse the json string: {Json}", json); } } diff --git a/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs b/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs index 80be943eb7..48ef00e1c8 100644 --- a/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs +++ b/src/Umbraco.Web.Common/Extensions/UmbracoCoreServiceCollectionExtensions.cs @@ -142,7 +142,7 @@ namespace Umbraco.Extensions /// /// /// - /// Delegate to create an + /// Delegate to create an /// /// public static IServiceCollection AddUmbracoCore( @@ -153,7 +153,7 @@ namespace Umbraco.Extensions ILoggingConfiguration loggingConfiguration, IConfiguration configuration, //TODO: Yep that's extremely ugly - Func getRuntime) + Func getRuntimeBootstrapper) { if (services is null) throw new ArgumentNullException(nameof(services)); if (entryAssembly is null) throw new ArgumentNullException(nameof(entryAssembly)); @@ -208,7 +208,7 @@ namespace Umbraco.Extensions var umbracoVersion = new UmbracoVersion(); var typeFinder = CreateTypeFinder(loggerFactory, profiler, webHostEnvironment, entryAssembly, typeFinderSettings); - var coreRuntime = getRuntime( + var bootstrapper = getRuntimeBootstrapper( globalSettings.CurrentValue, connectionStrings.Value, umbracoVersion, @@ -221,7 +221,7 @@ namespace Umbraco.Extensions appCaches, dbProviderFactoryCreator); - coreRuntime.Configure(services); + bootstrapper.Configure(services); return services; } @@ -320,7 +320,7 @@ namespace Umbraco.Extensions return new TypeFinder(loggerFactory.CreateLogger(), new DefaultUmbracoAssemblyProvider(entryAssembly), runtimeHash, new TypeFinderConfig(typeFinderSettings)); } - private static IRuntime GetCoreRuntime( + private static CoreRuntimeBootstrapper GetCoreRuntime( GlobalSettings globalSettings, ConnectionStrings connectionStrings, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILoggerFactory loggerFactory, IProfiler profiler, IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo, ITypeFinder typeFinder, AppCaches appCaches, IDbProviderFactoryCreator dbProviderFactoryCreator) @@ -335,7 +335,7 @@ namespace Umbraco.Extensions var mainDom = new MainDom(loggerFactory.CreateLogger(), mainDomLock); - var coreRuntime = new CoreRuntime( + var coreRuntime = new CoreRuntimeBootstrapper( globalSettings, connectionStrings, umbracoVersion, diff --git a/src/Umbraco.Web.Common/UmbracoContext/UmbracoContext.cs b/src/Umbraco.Web.Common/UmbracoContext/UmbracoContext.cs index 5e5b6f6910..ab7423c5be 100644 --- a/src/Umbraco.Web.Common/UmbracoContext/UmbracoContext.cs +++ b/src/Umbraco.Web.Common/UmbracoContext/UmbracoContext.cs @@ -1,6 +1,5 @@ using System; using Microsoft.Extensions.Options; -using Umbraco.Composing; using Umbraco.Core; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.Models; diff --git a/src/Umbraco.Web.UI.NetCore/umbraco/UmbracoInstall/Index.cshtml b/src/Umbraco.Web.UI.NetCore/umbraco/UmbracoInstall/Index.cshtml index 21a42dcb63..79cbe8305a 100644 --- a/src/Umbraco.Web.UI.NetCore/umbraco/UmbracoInstall/Index.cshtml +++ b/src/Umbraco.Web.UI.NetCore/umbraco/UmbracoInstall/Index.cshtml @@ -1,5 +1,4 @@ @using Umbraco.Extensions -@using Umbraco.Composing @{ Layout = null; } diff --git a/src/Umbraco.Web/Composing/Current.cs b/src/Umbraco.Web/Composing/Current.cs index d49aca86d5..1d50154214 100644 --- a/src/Umbraco.Web/Composing/Current.cs +++ b/src/Umbraco.Web/Composing/Current.cs @@ -39,7 +39,6 @@ using Umbraco.Web.WebApi; namespace Umbraco.Web.Composing { - // TODO: MSDI - let's kill this class once and for all... // see notes in Umbraco.Core.Composing.Current. public static class Current { diff --git a/src/Umbraco.Web/Logging/OwinLoggerFactory.cs b/src/Umbraco.Web/Logging/OwinLoggerFactory.cs index 278fa3f0b4..d8b76145c6 100644 --- a/src/Umbraco.Web/Logging/OwinLoggerFactory.cs +++ b/src/Umbraco.Web/Logging/OwinLoggerFactory.cs @@ -1,6 +1,6 @@ using System; using Microsoft.Owin.Logging; -using Umbraco.Composing; +using Umbraco.Core; namespace Umbraco.Web.Logging { @@ -13,7 +13,7 @@ namespace Umbraco.Web.Logging /// public Microsoft.Owin.Logging.ILogger Create(string name) { - return new OwinLogger(Current.Logger, new Lazy(() => Type.GetType(name) ?? typeof (OwinLogger))); + return new OwinLogger(StaticApplicationLogging.Logger, new Lazy(() => Type.GetType(name) ?? typeof (OwinLogger))); } } } diff --git a/src/Umbraco.Web/UmbracoApplication.cs b/src/Umbraco.Web/UmbracoApplication.cs index 90b2569c67..3218710902 100644 --- a/src/Umbraco.Web/UmbracoApplication.cs +++ b/src/Umbraco.Web/UmbracoApplication.cs @@ -19,7 +19,7 @@ namespace Umbraco.Web /// public class UmbracoApplication : UmbracoApplicationBase { - protected override IRuntime GetRuntime(GlobalSettings globalSettings, ConnectionStrings connectionStrings, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger, ILoggerFactory loggerFactory, IProfiler profiler, IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo) + protected override CoreRuntimeBootstrapper GetRuntime(GlobalSettings globalSettings, ConnectionStrings connectionStrings, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger, ILoggerFactory loggerFactory, IProfiler profiler, IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo) { var dbProviderFactoryCreator = new UmbracoDbProviderFactoryCreator(); @@ -44,7 +44,7 @@ namespace Umbraco.Web new IsolatedCaches(type => new DeepCloneAppCache(new ObjectCacheAppCache()))); var umbracoBootPermissionChecker = new AspNetUmbracoBootPermissionChecker(); - return new CoreRuntime(globalSettings, connectionStrings,umbracoVersion, ioHelper, loggerFactory, profiler, umbracoBootPermissionChecker, hostingEnvironment, backOfficeInfo, dbProviderFactoryCreator, mainDom, + return new CoreRuntimeBootstrapper(globalSettings, connectionStrings,umbracoVersion, ioHelper, loggerFactory, profiler, umbracoBootPermissionChecker, hostingEnvironment, backOfficeInfo, dbProviderFactoryCreator, mainDom, GetTypeFinder(hostingEnvironment, logger, profiler), appCaches); } diff --git a/src/Umbraco.Web/UmbracoApplicationBase.cs b/src/Umbraco.Web/UmbracoApplicationBase.cs index 83f056c77d..fe10cfba81 100644 --- a/src/Umbraco.Web/UmbracoApplicationBase.cs +++ b/src/Umbraco.Web/UmbracoApplicationBase.cs @@ -22,6 +22,7 @@ using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Logging.Serilog; using Umbraco.Core.Logging.Serilog.Enrichers; +using Umbraco.Core.Runtime; using Umbraco.Net; using Umbraco.Web.Hosting; using Umbraco.Web.Logging; @@ -48,8 +49,7 @@ namespace Umbraco.Web protected UmbracoApplicationBase() { - if (!Umbraco.Composing.Current.IsInitialized) - { + HostingSettings hostingSettings = null; GlobalSettings globalSettings = null; SecuritySettings securitySettings = null; @@ -63,12 +63,8 @@ namespace Umbraco.Web var backOfficeInfo = new AspNetBackOfficeInfo(globalSettings, ioHelper, _loggerFactory.CreateLogger(), Options.Create(webRoutingSettings)); var profiler = GetWebProfiler(hostingEnvironment); - Umbraco.Composing.Current.Initialize(NullLogger.Instance, - securitySettings, - globalSettings, - ioHelper, hostingEnvironment, backOfficeInfo, profiler); + StaticApplicationLogging.Initialize(_loggerFactory); Logger = NullLogger.Instance; - } } private IProfiler GetWebProfiler(IHostingEnvironment hostingEnvironment) @@ -93,11 +89,8 @@ namespace Umbraco.Web _ioHelper = ioHelper; _loggerFactory = loggerFactory; - if (!Umbraco.Composing.Current.IsInitialized) - { - Logger = logger; - Umbraco.Composing.Current.Initialize(logger, securitySettings, globalSettings, ioHelper, hostingEnvironment, backOfficeInfo, profiler); - } + Logger = logger; + StaticApplicationLogging.Initialize(_loggerFactory); } protected ILogger Logger { get; } @@ -139,7 +132,7 @@ namespace Umbraco.Web /// /// Gets a runtime. /// - protected abstract IRuntime GetRuntime(GlobalSettings globalSettings, ConnectionStrings connectionStrings, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger, ILoggerFactory loggerFactory, IProfiler profiler, IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo); + protected abstract CoreRuntimeBootstrapper GetRuntime(GlobalSettings globalSettings, ConnectionStrings connectionStrings, IUmbracoVersion umbracoVersion, IIOHelper ioHelper, ILogger logger, ILoggerFactory loggerFactory, IProfiler profiler, IHostingEnvironment hostingEnvironment, IBackOfficeInfo backOfficeInfo); /// /// Gets the application register. @@ -184,24 +177,27 @@ namespace Umbraco.Web // create the register for the application, and boot // the boot manager is responsible for registrations var register = GetRegister(globalSettings); - _runtime = GetRuntime( + var boostrapper = GetRuntime( _globalSettings, _connectionStrings, umbracoVersion, _ioHelper, _logger, _loggerFactory, - Umbraco.Composing.Current.Profiler, - Umbraco.Composing.Current.HostingEnvironment, - Umbraco.Composing.Current.BackOfficeInfo); + null, // TODO get from somewhere that isn't Current. + null, // TODO get from somewhere that isn't Current. + null // TODO get from somewhere that isn't Current. + ); //_factory = Current.Factory = _runtime.Configure(register); + // now we can add our request based logging enrichers (globally, which is what we were doing in netframework before) LogContext.Push(new HttpSessionIdEnricher(_factory.GetRequiredService())); LogContext.Push(new HttpRequestNumberEnricher(_factory.GetRequiredService())); LogContext.Push(new HttpRequestIdEnricher(_factory.GetRequiredService())); - _runtime.Start(null); + _runtime = _factory.GetRequiredService(); + _runtime.Start(); } // called by ASP.NET (auto event wireup) once per app domain diff --git a/src/Umbraco.Web/UmbracoHelper.cs b/src/Umbraco.Web/UmbracoHelper.cs index d81bb61251..c55e5ccb51 100644 --- a/src/Umbraco.Web/UmbracoHelper.cs +++ b/src/Umbraco.Web/UmbracoHelper.cs @@ -3,7 +3,6 @@ using System.Collections.Generic; using System.Linq; using System.Web; using System.Xml.XPath; -using Umbraco.Composing; using Umbraco.Core; using Umbraco.Core.Dictionary; using Umbraco.Core.Models.PublishedContent; @@ -456,7 +455,7 @@ namespace Umbraco.Web } catch (Exception ex) when (ex is FormatException || ex is ArgumentException) { - Current.Logger.LogWarning("A value was detected in the ufprt parameter but Umbraco could not decrypt the string"); + StaticApplicationLogging.Logger.LogWarning("A value was detected in the ufprt parameter but Umbraco could not decrypt the string"); parts = null; return false; }