diff --git a/src/Umbraco.Core/ApplicationContext.cs b/src/Umbraco.Core/ApplicationContext.cs
deleted file mode 100644
index 3e8982d8a7..0000000000
--- a/src/Umbraco.Core/ApplicationContext.cs
+++ /dev/null
@@ -1,333 +0,0 @@
-using System;
-using System.Configuration;
-using System.Threading;
-using Umbraco.Core.Cache;
-using Umbraco.Core.Configuration;
-using Umbraco.Core.Logging;
-using Umbraco.Core.Services;
-using Umbraco.Core.Sync;
-
-namespace Umbraco.Core
-{
- ///
- /// Represents the Umbraco application context.
- ///
- /// Only one singleton instance per running Umbraco application (AppDomain)
- public class ApplicationContext : IDisposable
- {
- private volatile bool _disposed;
- private readonly ReaderWriterLockSlim _disposalLocker = new ReaderWriterLockSlim();
- private bool _isReady;
- readonly ManualResetEventSlim _isReadyEvent = new ManualResetEventSlim(false);
- private DatabaseContext _databaseContext;
- private ServiceContext _services;
- private Lazy _configured;
-
- // ReSharper disable once InconsistentNaming
- internal string _umbracoApplicationUrl;
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// A database context.
- /// A service context.
- /// A cache helper.
- /// A logger.
- public ApplicationContext(DatabaseContext dbContext, ServiceContext serviceContext, CacheHelper cache, ProfilingLogger logger)
- {
- if (dbContext == null) throw new ArgumentNullException(nameof(dbContext));
- if (serviceContext == null) throw new ArgumentNullException(nameof(serviceContext));
- if (cache == null) throw new ArgumentNullException(nameof(cache));
- if (logger == null) throw new ArgumentNullException(nameof(logger));
-
- _databaseContext = dbContext;
- _services = serviceContext;
- ApplicationCache = cache;
- ProfilingLogger = logger;
-
- Initialize();
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// A cache helper.
- /// A logger.
- /// For Unit Tests only.
- public ApplicationContext(CacheHelper cache, ProfilingLogger logger)
- {
- if (cache == null) throw new ArgumentNullException(nameof(cache));
- if (logger == null) throw new ArgumentNullException(nameof(logger));
-
- ApplicationCache = cache;
- ProfilingLogger = logger;
-
- Initialize();
- }
-
- ///
- /// Gets the current global application context.
- ///
- public static ApplicationContext Current => DependencyInjection.Current.ApplicationContext; // fixme - obsolete
-
- ///
- /// Returns the application wide cache accessor
- ///
- ///
- /// Any caching that is done in the application (app wide) should be done through this property
- ///
- public CacheHelper ApplicationCache { get; private set; }
-
- ///
- /// Gets the profiling logger.
- ///
- public ProfilingLogger ProfilingLogger { get; }
-
- ///
- /// Gets the MainDom.
- ///
- internal MainDom MainDom { get; private set; }
-
- ///
- /// Gets a value indicating whether the application is configured.
- ///
- /// Meaning: installed and no need to upgrade anything.
- public virtual bool IsConfigured => _configured.Value;
-
- ///
- /// Gets a value indicating whether the application is ready.
- ///
- /// Meaning: ready to run, boot has completed, though maybe the application is not configured.
- /// IsReady is set to true by the boot manager once it has successfully booted. The original
- /// Umbraco module checked on content.Instance, now the boot task that sets the content
- /// store ensures that it is ready.
- ///
- public bool IsReady
- {
- get
- {
- return _isReady;
- }
- internal set
- {
- if (IsReady)
- throw new Exception("ApplicationContext has already been initialized.");
- if (value == false)
- throw new Exception("Value must be true.");
-
- _isReady = true;
- _isReadyEvent.Set();
- }
- }
-
- ///
- /// Blocks until the application is ready.
- ///
- /// The time to wait, or -1 to wait indefinitely.
- /// A value indicating whether the application is ready.
- public bool WaitForReady(int timeout)
- {
- return _isReadyEvent.WaitHandle.WaitOne(timeout);
- }
-
- ///
- /// Gets a value indicating whether the application is upgrading.
- ///
- /// Meaning: the database is configured and the database context has access to an existing Umbraco schema,
- /// however we are not 'configured' because we still need to upgrade.
- public bool IsUpgrading
- {
- get
- {
- if (IsConfigured // configured already
- || DatabaseContext == null // no database context
- || DatabaseContext.IsDatabaseConfigured == false // database is not configured
- || DatabaseContext.CanConnect == false) // database cannot connect
- return false;
-
- // upgrading if we have some valid tables (else, no schema, need to install)
- var schemaresult = DatabaseContext.ValidateDatabaseSchema();
- return schemaresult.ValidTables.Count > 0;
- }
- }
-
- ///
- /// Gets the application Url.
- ///
- ///
- /// The application url is the url that should be used by services to talk to the application,
- /// eg keep alive or scheduled publishing services. It must exist on a global context because
- /// some of these services may not run within a web context.
- /// The format of the application url is:
- /// - has a scheme (http or https)
- /// - has the SystemDirectories.Umbraco path
- /// - does not end with a slash
- /// It is initialized on the first request made to the server, by UmbracoModule.EnsureApplicationUrl:
- /// - if umbracoSettings:settings/web.routing/@umbracoApplicationUrl is set, use the value (new setting)
- /// - if umbracoSettings:settings/scheduledTasks/@baseUrl is set, use the value (backward compatibility)
- /// - otherwise, use the url of the (first) request.
- /// Not locking, does not matter if several threads write to this.
- /// See also issues:
- /// - http://issues.umbraco.org/issue/U4-2059
- /// - http://issues.umbraco.org/issue/U4-6788
- /// - http://issues.umbraco.org/issue/U4-5728
- /// - http://issues.umbraco.org/issue/U4-5391
- ///
- internal string UmbracoApplicationUrl
- {
- get
- {
- ApplicationUrlHelper.EnsureApplicationUrl(this);
- return _umbracoApplicationUrl;
- }
- }
-
- private void Initialize()
- {
- MainDom = new MainDom(ProfilingLogger.Logger);
- MainDom.Acquire();
-
- ResetConfigured();
- }
-
- ///
- /// Resets the IsConfigured value, which will then be discovered again.
- ///
- /// For Unit Tests usage, though it is harmless.
- public void ResetConfigured()
- {
- // create the lazy value to resolve whether or not the application is 'configured'
- // meaning: installed and no need to upgrade anything
- _configured = new Lazy(() =>
- {
- try
- {
- var configStatus = ConfigurationStatus; // the value in the web.config
- var currentVersion = UmbracoVersion.GetSemanticVersion(); // the hard-coded current version of the binaries that are executing
-
- // if we have no value in web.config or value differs, we are not configured yet
- if (string.IsNullOrWhiteSpace(configStatus) || configStatus != currentVersion)
- {
- ProfilingLogger.Logger.Debug($"CurrentVersion different from configStatus: '{currentVersion.ToSemanticString()}','{configStatus}'.");
- return false;
- }
-
- // versions match, now look for database state and migrations
- // which requires that we do have a database that we can connect to
- if (DatabaseContext.IsDatabaseConfigured == false || DatabaseContext.CanConnect == false)
- {
- ProfilingLogger.Logger.Debug("Database is not configured, or could not connect to the database.");
- return false;
- }
-
- // look for a migration entry for the current version
- var entry = Services.MigrationEntryService.FindEntry(GlobalSettings.UmbracoMigrationName, UmbracoVersion.GetSemanticVersion());
- if (entry != null)
- return true; // all clear!
-
- // even though the versions match, the db has not been properly upgraded
- ProfilingLogger.Logger.Debug($"The migration for version: '{currentVersion.ToSemanticString()} has not been executed, there is no record in the database.");
- return false;
- }
- catch (Exception ex)
- {
- LogHelper.Error("Error determining if application is configured, returning false.", ex);
- return false;
- }
- });
- }
-
- // gets the configuration status, ie the version that's in web.config
- private string ConfigurationStatus
- {
- get
- {
- try
- {
- return ConfigurationManager.AppSettings["umbracoConfigurationStatus"];
- }
- catch
- {
- return string.Empty;
- }
- }
- }
-
- ///
- /// Gets the current database context.
- ///
- public DatabaseContext DatabaseContext
- {
- get
- {
- if (_databaseContext == null)
- throw new InvalidOperationException("The DatabaseContext has not been set on the ApplicationContext.");
- return _databaseContext;
- }
- // INTERNAL FOR UNIT TESTS
- internal set { _databaseContext = value; }
- }
-
- ///
- /// Gets the current service context.
- ///
- public ServiceContext Services
- {
- get
- {
- if (_services == null)
- throw new InvalidOperationException("The ServiceContext has not been set on the ApplicationContext.");
- return _services;
- }
- // INTERNAL FOR UNIT TESTS
- internal set { _services = value; }
- }
-
- ///
- /// Gets the server role.
- ///
- ///
- internal ServerRole GetCurrentServerRole()
- {
- return DependencyInjection.Current.ServerRegistrar.GetCurrentServerRole();
- }
-
- ///
- /// Disposes the application context.
- ///
- /// Do not this object if you require the Umbraco application to run. Disposing this object
- /// is generally used for unit testing and when your application is shutting down after you have booted Umbraco.
- ///
- void IDisposable.Dispose()
- {
- if (_disposed) return;
-
- using (new WriteLock(_disposalLocker))
- {
- // double check... bah...
- if (_disposed) return;
-
- // clear the cache
- if (ApplicationCache != null)
- {
- ApplicationCache.RuntimeCache.ClearAllCache();
- ApplicationCache.IsolatedRuntimeCache.ClearAllCaches();
- }
-
- // reset the instance objects
- ApplicationCache = null;
- if (_databaseContext != null) //need to check the internal field here
- {
- if (DatabaseContext.IsDatabaseConfigured)
- DatabaseContext.Database?.Dispose();
- }
-
- DatabaseContext = null;
- Services = null;
- _isReady = false; //set the internal field
-
- _disposed = true;
- }
- }
- }
-}
diff --git a/src/Umbraco.Core/ApplicationEventHandler.cs b/src/Umbraco.Core/ApplicationEventHandler.cs
index 8d97baac95..47035f80dd 100644
--- a/src/Umbraco.Core/ApplicationEventHandler.cs
+++ b/src/Umbraco.Core/ApplicationEventHandler.cs
@@ -1,3 +1,11 @@
+using System;
+using System.Linq;
+using LightInject;
+using Umbraco.Core.Components;
+using Umbraco.Core.DependencyInjection;
+using Umbraco.Core.Plugins;
+using Umbraco.Core.Services;
+
namespace Umbraco.Core
{
///
@@ -5,115 +13,147 @@ namespace Umbraco.Core
///
///
/// Allows you to override the methods that you would like to execute code for: ApplicationInitialized, ApplicationStarting, ApplicationStarted.
- ///
+ ///
/// By default none of these methods will execute if the Umbraco application is not configured or if the Umbraco database is not configured, however
- /// if you need these methods to execute even if either of these are not configured you can override the properties:
+ /// if you need these methods to execute even if either of these are not configured you can override the properties:
/// ExecuteWhenApplicationNotConfigured and ExecuteWhenDatabaseNotConfigured
///
+ // fixme - kill.kill.kill
public abstract class ApplicationEventHandler : IApplicationEventHandler
{
- public void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
+ public void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication)
{
- if (ShouldExecute(applicationContext))
- {
- ApplicationInitialized(umbracoApplication, applicationContext);
- }
+ if (ShouldExecute()) ApplicationInitialized(umbracoApplication);
}
- public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
+ public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication)
{
- if (ShouldExecute(applicationContext))
- {
- ApplicationStarting(umbracoApplication, applicationContext);
- }
+ if (ShouldExecute()) ApplicationStarting(umbracoApplication);
}
- public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
+ public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication)
{
- if (ShouldExecute(applicationContext))
- {
- ApplicationStarted(umbracoApplication, applicationContext);
- }
+ if (ShouldExecute()) ApplicationStarted(umbracoApplication);
}
///
/// Overridable method to execute when the ApplicationContext is created and other static objects that require initialization have been setup
///
///
- ///
- protected virtual void ApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
- {
-
- }
+ protected virtual void ApplicationInitialized(UmbracoApplicationBase umbracoApplication)
+ { }
///
/// Overridable method to execute when All resolvers have been initialized but resolution is not frozen so they can be modified in this method
///
///
- ///
- protected virtual void ApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
- {
-
- }
+ protected virtual void ApplicationStarting(UmbracoApplicationBase umbracoApplication)
+ { }
///
/// Overridable method to execute when Bootup is completed, this allows you to perform any other bootup logic required for the application.
/// Resolution is frozen so now they can be used to resolve instances.
///
///
- ///
- protected virtual void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
- {
+ protected virtual void ApplicationStarted(UmbracoApplicationBase umbracoApplication)
+ { }
+ private bool ShouldExecute()
+ {
+ var level = Current.RuntimeState.Level;
+
+ switch (Current.RuntimeState.Level)
+ {
+ case RuntimeLevel.Unknown:
+ case RuntimeLevel.Failed:
+ case RuntimeLevel.Boot:
+ return false;
+ case RuntimeLevel.Install:
+ case RuntimeLevel.Upgrade:
+ // sort-of equivalent I assume?
+ //if (!applicationContext.IsConfigured && ExecuteWhenApplicationNotConfigured)
+ if (ExecuteWhenApplicationNotConfigured)
+ return true;
+ //if (!applicationContext.DatabaseContext.IsDatabaseConfigured && ExecuteWhenDatabaseNotConfigured)
+ if (level == RuntimeLevel.Install && ExecuteWhenDatabaseNotConfigured)
+ return true;
+ return false;
+ case RuntimeLevel.Run:
+ //if (applicationContext.IsConfigured && applicationContext.DatabaseContext.IsDatabaseConfigured)
+ return true;
+ default:
+ throw new NotSupportedException($"Invalid runtime level {level}");
+ }
}
///
- /// Determine if the methods should execute based on the configuration status of the application.
- ///
- ///
- ///
- private bool ShouldExecute(ApplicationContext applicationContext)
- {
- if (applicationContext.IsConfigured && applicationContext.DatabaseContext.IsDatabaseConfigured)
- {
- return true;
- }
-
- if (!applicationContext.IsConfigured && ExecuteWhenApplicationNotConfigured)
- {
- return true;
- }
-
- if (!applicationContext.DatabaseContext.IsDatabaseConfigured && ExecuteWhenDatabaseNotConfigured)
- {
- return true;
- }
- return false;
- }
-
- ///
- /// A flag to determine if the overridable methods for this class will execute even if the
+ /// A flag to determine if the overridable methods for this class will execute even if the
/// Umbraco application is not configured
///
///
/// An Umbraco Application is not configured when it requires a new install or upgrade. When the latest version in the
/// assembly does not match the version in the config.
///
- protected virtual bool ExecuteWhenApplicationNotConfigured
- {
- get { return false; }
- }
+ protected virtual bool ExecuteWhenApplicationNotConfigured => false;
///
- /// A flag to determine if the overridable methods for this class will execute even if the
+ /// A flag to determine if the overridable methods for this class will execute even if the
/// Umbraco database is not configured
///
///
/// The Umbraco database is not configured when we cannot connect to the database or when the database tables are not installed.
///
- protected virtual bool ExecuteWhenDatabaseNotConfigured
+ protected virtual bool ExecuteWhenDatabaseNotConfigured => false;
+ }
+
+ // that *could* replace CoreRuntime mess almost entirely
+ // but what about what's in WebRuntime?
+
+ [DisableComponent] // disabled for now, breaks
+ public class ApplicationEventHandlerComponent : UmbracoComponentBase, IUmbracoCoreComponent
+ {
+ public override void Compose(ServiceContainer container)
{
- get { return false; }
+ base.Compose(container);
+
+ // assuming we don't do anything in Compose? or is this where we should create the handlers?
+ }
+
+ public void Initialize(PluginManager pluginManager, UmbracoApplicationBase umbracoApplication)
+ {
+ var startupHandlerTypes = pluginManager.ResolveApplicationStartupHandlers();
+ var handlers = startupHandlerTypes.Select(x =>
+ {
+ try
+ {
+ return Activator.CreateInstance(x);
+ }
+ catch
+ {
+ // fixme - breaks here!
+ // cannot unstanciate GridPropertyEditor and other oddities BUT they have been refactored in 7.6?
+ // well, no, so NOW is the time... bah... first we need to figure out STATES
+ throw new Exception("cannot instanciate " + x.FullName);
+ }
+ }).Cast().ToArray();
+
+ // just a test at that point
+ return;
+
+ foreach (var handler in handlers)
+ handler.OnApplicationInitialized(umbracoApplication);
+ foreach (var handler in handlers)
+ handler.OnApplicationStarting(umbracoApplication);
+
+ //This is a special case for the user service, we need to tell it if it's an upgrade, if so we need to ensure that
+ // exceptions are bubbled up if a user is attempted to be persisted during an upgrade (i.e. when they auth to login)
+ // fixme - wtf? never going back to FALSE !
+ ((UserService) Current.Services.UserService).IsUpgrading = true;
+
+ foreach (var handler in handlers)
+ handler.OnApplicationStarted(umbracoApplication);
+
+ //applicationContext.IsReady = true;
}
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Components/BootLoader.cs b/src/Umbraco.Core/Components/BootLoader.cs
index 6f600c402e..f40ea424dd 100644
--- a/src/Umbraco.Core/Components/BootLoader.cs
+++ b/src/Umbraco.Core/Components/BootLoader.cs
@@ -4,6 +4,7 @@ using System.Linq;
using System.Reflection;
using LightInject;
using Umbraco.Core.Configuration;
+using Umbraco.Core.Exceptions;
using Umbraco.Core.Logging;
namespace Umbraco.Core.Components
@@ -36,18 +37,15 @@ namespace Umbraco.Core.Components
public int Weight = -1;
}
- public void Boot(IEnumerable componentTypes)
+ public void Boot(IEnumerable componentTypes, RuntimeLevel level)
{
if (_booted) throw new InvalidOperationException("Can not boot, has already booted.");
- using (_proflog.TraceDuration($"Booting Umbraco {UmbracoVersion.GetSemanticVersion().ToSemanticString()} on {NetworkHelper.MachineName}.", "Booted."))
- {
- var orderedComponentTypes = PrepareComponentTypes(componentTypes);
+ var orderedComponentTypes = PrepareComponentTypes(componentTypes);
- InstanciateComponents(orderedComponentTypes);
- ComposeComponents();
- InitializeComponents();
- }
+ InstanciateComponents(orderedComponentTypes);
+ ComposeComponents(level);
+ InitializeComponents();
// rejoice!
_booted = true;
@@ -175,7 +173,7 @@ namespace Umbraco.Core.Components
}
}
- private void ComposeComponents()
+ private void ComposeComponents(RuntimeLevel level)
{
using (_proflog.DebugDuration($"Composing components. (log when >{LogThresholdMilliseconds}ms)", "Composed components."))
{
@@ -184,7 +182,7 @@ namespace Umbraco.Core.Components
var componentType = component.GetType();
using (_proflog.DebugDuration($"Composing {componentType.FullName}.", $"Composed {componentType.FullName}.", LogThresholdMilliseconds))
{
- component.Compose(_container);
+ component.Compose(_container, level);
}
}
}
@@ -200,14 +198,14 @@ namespace Umbraco.Core.Components
foreach (var component in _components)
{
var componentType = component.GetType();
- var initializers = componentType.GetMethods(BindingFlags.Instance | BindingFlags.Public)
+ var initializers = componentType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.Where(x => x.Name == "Initialize" && x.IsGenericMethod == false);
using (_proflog.DebugDuration($"Initializing {componentType.FullName}.", $"Initialised {componentType.FullName}.", LogThresholdMilliseconds))
{
foreach (var initializer in initializers)
{
var parameters = initializer.GetParameters()
- .Select(x => _container.GetInstance(x.ParameterType))
+ .Select(x => GetParameter(componentType, x.ParameterType))
.ToArray();
initializer.Invoke(component, parameters);
}
@@ -216,6 +214,13 @@ namespace Umbraco.Core.Components
}
}
+ private object GetParameter(Type componentType, Type parameterType)
+ {
+ var param = _container.TryGetInstance(parameterType);
+ if (param == null) throw new BootFailedException($"Could not get parameter of type {parameterType.FullName} for component {componentType.FullName}.");
+ return param;
+ }
+
public void Terminate()
{
if (_booted == false) throw new InvalidOperationException("Cannot terminate, has not booted.");
diff --git a/src/Umbraco.Core/Components/IUmbracoComponent.cs b/src/Umbraco.Core/Components/IUmbracoComponent.cs
index 787ce3c792..01e9e6fbf0 100644
--- a/src/Umbraco.Core/Components/IUmbracoComponent.cs
+++ b/src/Umbraco.Core/Components/IUmbracoComponent.cs
@@ -2,10 +2,21 @@
namespace Umbraco.Core.Components
{
+ ///
+ /// Represents an Umbraco component.
+ ///
public interface IUmbracoComponent
{
- void Compose(ServiceContainer container);
+ ///
+ /// Composes the component.
+ ///
+ /// The container.
+ /// The runtime level.
+ void Compose(ServiceContainer container, RuntimeLevel level);
+ ///
+ /// Terminates the component.
+ ///
void Terminate();
}
}
diff --git a/src/Umbraco.Core/Components/UmbracoComponentBase.cs b/src/Umbraco.Core/Components/UmbracoComponentBase.cs
index 7b89b25a31..7d67153b95 100644
--- a/src/Umbraco.Core/Components/UmbracoComponentBase.cs
+++ b/src/Umbraco.Core/Components/UmbracoComponentBase.cs
@@ -2,11 +2,25 @@
namespace Umbraco.Core.Components
{
+ ///
+ /// Provides a base class for implementations.
+ ///
public abstract class UmbracoComponentBase : IUmbracoComponent
{
+ ///
+ public virtual void Compose(ServiceContainer container, RuntimeLevel level)
+ {
+ Compose(container);
+ }
+
+ ///
+ /// Composes the component.
+ ///
+ /// The container.
public virtual void Compose(ServiceContainer container)
{ }
+ ///
public virtual void Terminate()
{ }
}
diff --git a/src/Umbraco.Core/Configuration/GlobalSettings.cs b/src/Umbraco.Core/Configuration/GlobalSettings.cs
index b718edbf39..068d1a574a 100644
--- a/src/Umbraco.Core/Configuration/GlobalSettings.cs
+++ b/src/Umbraco.Core/Configuration/GlobalSettings.cs
@@ -10,6 +10,7 @@ using System.Web.Security;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;
+using Umbraco.Core.DependencyInjection;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Security;
@@ -19,12 +20,12 @@ namespace Umbraco.Core.Configuration
//NOTE: Do not expose this class ever until we cleanup all configuration including removal of static classes, etc...
// we have this two tasks logged:
// http://issues.umbraco.org/issue/U4-58
- // http://issues.umbraco.org/issue/U4-115
+ // http://issues.umbraco.org/issue/U4-115
//TODO: Replace checking for if the app settings exist and returning an empty string, instead return the defaults!
///
- /// The GlobalSettings Class contains general settings information for the entire Umbraco instance based on information from web.config appsettings
+ /// The GlobalSettings Class contains general settings information for the entire Umbraco instance based on information from web.config appsettings
///
[Obsolete("TODO: Need to move this configuration class into the proper configuration accesors for v8!")]
public class GlobalSettings
@@ -72,7 +73,7 @@ namespace Umbraco.Core.Configuration
public static string ReservedUrls
{
get
- {
+ {
if (_reservedUrls == null)
{
var urls = ConfigurationManager.AppSettings.ContainsKey("umbracoReservedUrls")
@@ -80,7 +81,7 @@ namespace Umbraco.Core.Configuration
: string.Empty;
//ensure the built on (non-changeable) reserved paths are there at all times
- _reservedUrls = StaticReservedUrls + urls;
+ _reservedUrls = StaticReservedUrls + urls;
}
return _reservedUrls;
}
@@ -167,11 +168,11 @@ namespace Umbraco.Core.Configuration
///
/// THIS IS TEMPORARY AND SHOULD BE REMOVED WHEN WE MIGRATE/UPDATE THE CONFIG SETTINGS TO BE A REAL CONFIG SECTION
/// AND SHOULD PROBABLY BE HANDLED IN A MORE ROBUST WAY.
- ///
+ ///
/// This will return the MVC area that we will route all custom routes through like surface controllers, etc...
/// We will use the 'Path' (default ~/umbraco) to create it but since it cannot contain '/' and people may specify a path of ~/asdf/asdf/admin
/// we will convert the '/' to '-' and use that as the path. its a bit lame but will work.
- ///
+ ///
/// We also make sure that the virtual directory (SystemDirectories.Root) is stripped off first, otherwise we'd end up with something
/// like "MyVirtualDirectory-Umbraco" instead of just "Umbraco".
///
@@ -233,12 +234,12 @@ namespace Umbraco.Core.Configuration
{
if (value.ToLower().Contains("SQLCE4Umbraco.SqlCEHelper".ToLower()))
{
- ApplicationContext.Current.DatabaseContext.ConfigureEmbeddedDatabaseConnection();
+ Current.DatabaseContext.ConfigureEmbeddedDatabaseConnection();
}
else
{
- ApplicationContext.Current.DatabaseContext.ConfigureDatabaseConnection(value);
- }
+ Current.DatabaseContext.ConfigureDatabaseConnection(value);
+ }
}
}
}
@@ -264,7 +265,7 @@ namespace Umbraco.Core.Configuration
SaveSetting("umbracoConfigurationStatus", value);
}
}
-
+
///
/// Gets or sets the Umbraco members membership providers' useLegacyEncoding state. This will return a boolean
///
@@ -280,7 +281,7 @@ namespace Umbraco.Core.Configuration
SetMembershipProvidersLegacyEncoding(Constants.Conventions.Member.UmbracoMemberProviderName, value);
}
}
-
+
///
/// Gets or sets the Umbraco users membership providers' useLegacyEncoding state. This will return a boolean
///
@@ -296,7 +297,7 @@ namespace Umbraco.Core.Configuration
SetMembershipProvidersLegacyEncoding(UmbracoConfig.For.UmbracoSettings().Providers.DefaultBackOfficeUserProvider, value);
}
}
-
+
///
/// Saves a setting into the configuration file.
///
@@ -337,7 +338,7 @@ namespace Umbraco.Core.Configuration
setting.Remove();
xml.Save(fileName, SaveOptions.DisableFormatting);
ConfigurationManager.RefreshSection("appSettings");
- }
+ }
}
private static void SetMembershipProvidersLegacyEncoding(string providerName, bool useLegacyEncoding)
@@ -359,16 +360,16 @@ namespace Umbraco.Core.Configuration
var membershipConfigs = webConfigXml.XPathSelectElements("configuration/system.web/membership/providers/add").ToList();
- if (membershipConfigs.Any() == false)
+ if (membershipConfigs.Any() == false)
return;
var provider = membershipConfigs.SingleOrDefault(c => c.Attribute("name") != null && c.Attribute("name").Value == providerName);
- if (provider == null)
+ if (provider == null)
return;
provider.SetAttributeValue("useLegacyEncoding", useLegacyEncoding);
-
+
webConfigXml.Save(webConfigFilename, SaveOptions.DisableFormatting);
}
@@ -381,7 +382,7 @@ namespace Umbraco.Core.Configuration
return false;
}
- return membershipProvider.UseLegacyEncoding;
+ return membershipProvider.UseLegacyEncoding;
}
///
@@ -418,36 +419,6 @@ namespace Umbraco.Core.Configuration
}
}
- ///
- /// Gets a value indicating whether the current version of umbraco is configured.
- ///
- /// true if configured; otherwise, false.
- [Obsolete("Do not use this, it is no longer in use and will be removed from the codebase in future versions")]
- internal static bool Configured
- {
- get
- {
- try
- {
- string configStatus = ConfigurationStatus;
- string currentVersion = UmbracoVersion.GetSemanticVersion().ToSemanticString();
-
-
- if (currentVersion != configStatus)
- {
- LogHelper.Debug("CurrentVersion different from configStatus: '" + currentVersion + "','" + configStatus + "'");
- }
-
-
- return (configStatus == currentVersion);
- }
- catch
- {
- return false;
- }
- }
- }
-
///
/// Gets the time out in minutes.
///
@@ -525,7 +496,7 @@ namespace Umbraco.Core.Configuration
get
{
//defaults to false
- return ConfigurationManager.AppSettings.ContainsKey("umbracoContentXMLUseLocalTemp")
+ return ConfigurationManager.AppSettings.ContainsKey("umbracoContentXMLUseLocalTemp")
&& bool.Parse(ConfigurationManager.AppSettings["umbracoContentXMLUseLocalTemp"]); //default to false
}
}
@@ -597,7 +568,7 @@ namespace Umbraco.Core.Configuration
[Obsolete("Use Umbraco.Core.Configuration.UmbracoVersion.Current instead", false)]
public static string CurrentVersion
{
- get { return UmbracoVersion.GetSemanticVersion().ToSemanticString(); }
+ get { return UmbracoVersion.SemanticVersion.ToSemanticString(); }
}
///
@@ -729,7 +700,7 @@ namespace Umbraco.Core.Configuration
}
///
- /// Determines whether the current request is reserved based on the route table and
+ /// Determines whether the current request is reserved based on the route table and
/// whether the specified URL is reserved or is inside a reserved path.
///
///
@@ -768,7 +739,7 @@ namespace Umbraco.Core.Configuration
// store references to strings to determine changes
_reservedPathsCache = GlobalSettings.ReservedPaths;
_reservedUrlsCache = GlobalSettings.ReservedUrls;
-
+
// add URLs and paths to a new list
var newReservedList = new HashSet();
foreach (var reservedUrlTrimmed in _reservedUrlsCache
@@ -810,7 +781,7 @@ namespace Umbraco.Core.Configuration
return _reservedList.Any(x => pathPart.InvariantStartsWith(x));
}
-
+
}
diff --git a/src/Umbraco.Core/Configuration/UmbracoVersion.cs b/src/Umbraco.Core/Configuration/UmbracoVersion.cs
index 2e10a7b1e4..ee87379d90 100644
--- a/src/Umbraco.Core/Configuration/UmbracoVersion.cs
+++ b/src/Umbraco.Core/Configuration/UmbracoVersion.cs
@@ -4,39 +4,41 @@ using Semver;
namespace Umbraco.Core.Configuration
{
- public class UmbracoVersion
+ ///
+ /// Represents the version of the executing code.
+ ///
+ public static class UmbracoVersion
{
// BEWARE!
// This class is parsed and updated by the build scripts.
// Do NOT modify it unless you understand what you are doing.
///
- /// Gets the current version of Umbraco.
- /// Version class with the specified major, minor, build (Patch), and revision numbers.
+ /// Gets the version of the executing code.
///
- ///
- /// CURRENT UMBRACO VERSION ID.
- ///
public static Version Current { get; } = new Version("8.0.0");
///
- /// Gets the version comment (like beta or RC).
+ /// Gets the version comment of the executing code (eg "beta").
///
- /// The version comment.
public static string CurrentComment => "alpha0016";
- // Get the version of the Umbraco.Core.dll by looking at a class in that dll
- // Had to do it like this due to medium trust issues, see: http://haacked.com/archive/2010/11/04/assembly-location-and-medium-trust.aspx
+ ///
+ /// Gets the assembly version of Umbraco.Code.dll.
+ ///
+ /// Get it by looking at a class in that dll, due to medium trust issues,
+ /// see http://haacked.com/archive/2010/11/04/assembly-location-and-medium-trust.aspx,
+ /// however fixme we don't support medium trust anymore?
public static string AssemblyVersion => new AssemblyName(typeof(UmbracoVersion).Assembly.FullName).Version.ToString();
- public static SemVersion GetSemanticVersion()
- {
- return new SemVersion(
+ ///
+ /// Gets the semantic version of the executing code.
+ ///
+ public static SemVersion SemanticVersion => new SemVersion(
Current.Major,
Current.Minor,
Current.Build,
CurrentComment.IsNullOrWhiteSpace() ? null : CurrentComment,
Current.Revision > 0 ? Current.Revision.ToInvariantString() : null);
- }
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/CoreRuntime.cs b/src/Umbraco.Core/CoreRuntime.cs
index e176f3cc1c..f5db9f8cbe 100644
--- a/src/Umbraco.Core/CoreRuntime.cs
+++ b/src/Umbraco.Core/CoreRuntime.cs
@@ -1,28 +1,22 @@
using System;
using System.Collections.Generic;
-using System.IO;
+using System.Configuration;
using System.Threading.Tasks;
using System.Threading;
-using AutoMapper;
using LightInject;
using Umbraco.Core.Cache;
using Umbraco.Core.Components;
using Umbraco.Core.Configuration;
-using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.DependencyInjection;
using Umbraco.Core.Exceptions;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
-using Umbraco.Core.Manifest;
-using Umbraco.Core.Models.Mapping;
-using Umbraco.Core.Models.PublishedContent;
-using Umbraco.Core.Persistence.Migrations;
+using Umbraco.Core.Models.Rdbms;
+using Umbraco.Core.Persistence;
+using Umbraco.Core.Persistence.Mappers;
+using Umbraco.Core.Persistence.SqlSyntax;
using Umbraco.Core.Plugins;
-using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Services;
-using Umbraco.Core.Sync;
-using Umbraco.Core.Strings;
-using Umbraco.Core._Legacy.PackageActions;
namespace Umbraco.Core
{
@@ -35,46 +29,7 @@ namespace Umbraco.Core
public class CoreRuntime : IRuntime
{
private BootLoader _bootLoader;
- private DisposableTimer _timer;
-
- // fixme cleanup these
- private IServiceContainer _appStartupEvtContainer;
- private bool _isInitialized;
- private bool _isStarted;
- private bool _isComplete;
-
-
- // what the UmbracoApplication does is...
- // create the container and configure for core
- // create and register a logger
- // then:
- //GetBootManager()
- // .Initialize()
- // .Startup(appContext => OnApplicationStarting(sender, e))
- // .Complete(appContext => OnApplicationStarted(sender, e));
- //
- // edit so it becomes:
- //GetBootLoader()
- // .Boot();
- //
- // merge all RegisterX into one Register
- //
- // WebBootLoader should
- // configure the container for web BUT that should be AFTER the components have initialized? OR?
- //
- // Startup runs all app event handler OnApplicationStarting methods
- // then triggers the OnApplicationStarting event of the app
- // Complete
- // freezes resolution
- // ensures database connection (else?)
- // tells user service it is upgrading (?)
- // runs all app event handler OnApplicationStarted methods
- // then triggers the OnApplicationStarted event of the app
- // and sets Ready
- //
- // note: what's deciding whether install, upgrade, run?
-
- private RuntimeState _state; // fixme what about web?!
+ private RuntimeState _state;
///
/// Initializes a new instance of the class.
@@ -89,16 +44,19 @@ namespace Umbraco.Core
///
public virtual void Boot(ServiceContainer container)
{
- // create and register essential stuff
+ Compose(container);
+
+ // prepare essential stuff
+
+ _state = (RuntimeState) container.GetInstance();
+ _state.Level = RuntimeLevel.Boot;
Logger = container.GetInstance();
- container.RegisterInstance(Profiler = GetProfiler());
- container.RegisterInstance(ProfilingLogger = new ProfilingLogger(Current.Logger, Profiler));
+ Profiler = container.GetInstance();
+ ProfilingLogger = container.GetInstance();
- container.RegisterInstance(_state = new RuntimeState());
-
- // then compose
- Compose(container);
+ // fixme - totally temp
+ container.RegisterInstance(UmbracoApplication);
// 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.
@@ -109,33 +67,202 @@ namespace Umbraco.Core
// are NOT disposed - which is not a big deal as long as they remain lightweight
// objects.
- _bootLoader = new BootLoader(container);
- _bootLoader.Boot(GetComponentTypes());
+ using (ProfilingLogger.TraceDuration($"Booting Umbraco {UmbracoVersion.SemanticVersion.ToSemanticString()} on {NetworkHelper.MachineName}.", "Booted."))
+ {
+ Logger.Debug($"Runtime: {GetType().FullName}");
+
+ using (ProfilingLogger.DebugDuration("Acquiring MainDom.", "Aquired."))
+ {
+ // become the main domain - before anything else
+ var mainDom = container.GetInstance();
+ mainDom.Acquire();
+ }
+
+ using (ProfilingLogger.DebugDuration("Determining runtime level.", "Determined."))
+ {
+ var dbfactory = container.GetInstance();
+ SetRuntimeStateLevel(_state, dbfactory, Logger);
+ }
+
+ Logger.Debug($"Runtime level: {_state.Level}");
+
+ IEnumerable componentTypes;
+ using (ProfilingLogger.TraceDuration("Resolving component types.", "Resolved."))
+ {
+ componentTypes = GetComponentTypes();
+ }
+
+ // boot
+ _bootLoader = new BootLoader(container);
+ _bootLoader.Boot(componentTypes, _state.Level);
+ }
}
+ ///
public virtual void Terminate()
{
_bootLoader?.Terminate();
}
+ ///
public virtual void Compose(ServiceContainer container)
{
- // create and register essential stuff
+ container.RegisterSingleton();
+ container.RegisterSingleton();
+ container.RegisterSingleton();
- var cache = GetApplicationCache();
- container.RegisterInstance(cache);
- container.RegisterInstance(cache.RuntimeCache);
+ container.RegisterSingleton(_ => new CacheHelper(
+ // we need to have the dep clone runtime cache provider to ensure
+ // all entities are cached properly (cloned in and cloned out)
+ new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()),
+ new StaticCacheProvider(),
+ // we have no request based cache when not running in web-based context
+ new NullCacheProvider(),
+ new IsolatedRuntimeCache(type =>
+ // we need to have the dep clone runtime cache provider to ensure
+ // all entities are cached properly (cloned in and cloned out)
+ new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()))));
+ container.RegisterSingleton(factory => factory.GetInstance().RuntimeCache);
- container.RegisterInstance(new PluginManager(cache.RuntimeCache, ProfilingLogger));
+ container.RegisterSingleton(factory => new PluginManager(factory.GetInstance(), factory.GetInstance()));
+
+ // register syntax providers
+ container.Register("MySqlSyntaxProvider");
+ container.Register("SqlCeSyntaxProvider");
+ container.Register("SqlServerSyntaxProvider");
+
+ // register persistence mappers - means the only place the collection can be modified
+ // is in a runtime - afterwards it has been frozen and it is too late
+ MapperCollectionBuilder.Register(container)
+ .AddProducer(f => f.GetInstance().ResolveAssignedMapperTypes());
+
+ // register database factory
+ // will be initialized with syntax providers and a logger, and will try to configure
+ // from the default connection string name, if possible, else will remain non-configured
+ // until the database context configures it properly (eg when installing)
+ container.RegisterSingleton();
+
+ // register a database accessor - will be replaced
+ // by HybridUmbracoDatabaseAccessor in the web runtime
+ container.RegisterSingleton();
+
+ // register MainDom
+ container.RegisterSingleton();
}
- ///
- /// Gets the Umbraco HttpApplication.
- ///
- protected UmbracoApplicationBase UmbracoApplication { get; }
+ private static void SetRuntimeStateLevel(RuntimeState runtimeState, IDatabaseFactory databaseFactory, ILogger logger)
+ {
+ var localVersion = LocalVersion; // the local, files, version
+ var codeVersion = runtimeState.SemanticVersion; // the executing code version
+ var connect = false;
+
+ if (string.IsNullOrWhiteSpace(localVersion))
+ {
+ // there is no local version, we are not installed
+ logger.Debug("No local version, need to install Umbraco.");
+ runtimeState.Level = RuntimeLevel.Install;
+ }
+ else if (localVersion != codeVersion)
+ {
+ // there *is* a local version, but it does not match the code version
+ // need to upgrade
+ logger.Debug($"Local version \"{localVersion}\" != code version, need to upgrade Umbraco.");
+ runtimeState.Level = RuntimeLevel.Upgrade;
+ }
+ else if (databaseFactory.Configured == false)
+ {
+ // local version *does* match code version, but the database is not configured
+ // install (again? this is a weird situation...)
+ logger.Debug("Database is not configured, need to install Umbraco.");
+ runtimeState.Level = RuntimeLevel.Install;
+ }
+
+ // anything other than install wants a database - see if we can connect
+ if (runtimeState.Level != RuntimeLevel.Install)
+ {
+ for (var i = 0; i < 5; i++)
+ {
+ connect = databaseFactory.CanConnect;
+ if (connect) break;
+ logger.Debug(i == 0
+ ? "Could not immediately connect to database, trying again."
+ : "Could not connect to database.");
+ Thread.Sleep(1000);
+ }
+
+ if (connect == false)
+ {
+ // cannot connect to configured database, this is bad, fail
+ logger.Debug("Could not connect to database.");
+ runtimeState.Level = RuntimeLevel.Failed;
+
+ // in fact, this is bad enough that we want to throw
+ throw new BootFailedException("A connection string is configured but Umbraco could not connect to the database.");
+ }
+ }
+
+ // if we cannot connect, cannot do more
+ if (connect == false) return;
+
+ // else
+ // look for a matching migration entry - bypassing services entirely - they are not 'up' yet
+ // fixme - in a LB scenario, ensure that the DB gets upgraded only once!
+ // fixme - eventually move to yol-style guid-based transitions
+ var database = databaseFactory.GetDatabase();
+ var codeVersionString = codeVersion.ToString();
+ var sql = database.Sql()
+ .Select()
+ .From()
+ .Where(x => x.Name.InvariantEquals(GlobalSettings.UmbracoMigrationName) && x.Version == codeVersionString);
+ bool exists;
+ try
+ {
+ exists = database.FirstOrDefault(sql) != null;
+ }
+ catch
+ {
+ // can connect to the database but cannot access the migration table... need to install
+ logger.Debug("Could not check migrations, need to install Umbraco.");
+ runtimeState.Level = RuntimeLevel.Install;
+ return;
+ }
+
+ if (exists)
+ {
+ // the database version matches the code & files version, all clear, can run
+ runtimeState.Level = RuntimeLevel.Run;
+ return;
+ }
+
+ // the db version does not match... but we do have a migration table
+ // so, at least one valid table, so we quite probably are installed & need to upgrade
+
+ // although the files version matches the code version, the database version does not
+ // which means the local files have been upgraded but not the database - need to upgrade
+ logger.Debug("Database migrations have not executed, need to upgrade Umbraco.");
+ runtimeState.Level = RuntimeLevel.Upgrade;
+ }
+
+ private static string LocalVersion
+ {
+ get
+ {
+ try
+ {
+ // fixme - this should live in its own independent file! NOT web.config!
+ return ConfigurationManager.AppSettings["umbracoConfigurationStatus"];
+ }
+ catch
+ {
+ return string.Empty;
+ }
+ }
+ }
#region Locals
+ // fixme - we almost certainly DONT need these!
+
protected ILogger Logger { get; private set; }
protected IProfiler Profiler { get; private set; }
@@ -150,39 +277,32 @@ namespace Umbraco.Core
protected virtual IEnumerable GetComponentTypes() => Current.PluginManager.ResolveTypes();
- protected virtual IProfiler GetProfiler() => new LogProfiler(Logger);
+ //protected virtual IProfiler GetProfiler() => new LogProfiler(Logger);
- protected virtual CacheHelper GetApplicationCache() => new CacheHelper(
- // we need to have the dep clone runtime cache provider to ensure
- // all entities are cached properly (cloned in and cloned out)
- new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()),
- new StaticCacheProvider(),
- // we have no request based cache when not running in web-based context
- new NullCacheProvider(),
- new IsolatedRuntimeCache(type =>
- // we need to have the dep clone runtime cache provider to ensure
- // all entities are cached properly (cloned in and cloned out)
- new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider())));
+ //protected virtual CacheHelper GetApplicationCache() => new CacheHelper(
+ // // we need to have the dep clone runtime cache provider to ensure
+ // // all entities are cached properly (cloned in and cloned out)
+ // new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider()),
+ // new StaticCacheProvider(),
+ // // we have no request based cache when not running in web-based context
+ // new NullCacheProvider(),
+ // new IsolatedRuntimeCache(type =>
+ // // we need to have the dep clone runtime cache provider to ensure
+ // // all entities are cached properly (cloned in and cloned out)
+ // new DeepCloneRuntimeCacheProvider(new ObjectCacheRuntimeCacheProvider())));
#endregion
- #region Core
+ // fixme - kill everything below!
- // cannot run if the db is not there
- // tries to connect to db (if configured)
- private void EnsureDatabaseConnection()
- {
- if (Current.ApplicationContext.IsConfigured == false) return;
- if (Current.ApplicationContext.DatabaseContext.IsDatabaseConfigured == false) return;
+ private IServiceContainer _appStartupEvtContainer;
+ private bool _isInitialized;
+ private bool _isStarted;
+ private bool _isComplete;
- for (var i = 0; i < 5; i++)
- {
- if (Current.ApplicationContext.DatabaseContext.CanConnect) return;
- Thread.Sleep(1000);
- }
+ protected UmbracoApplicationBase UmbracoApplication { get; }
- throw new UmbracoStartupFailedException("Umbraco cannot start: a connection string is configured but Umbraco could not connect to the database.");
- }
+ protected ServiceContainer Container => Current.Container;
///
/// Special method to extend the use of Umbraco by enabling the consumer to overwrite
@@ -195,33 +315,18 @@ namespace Umbraco.Core
IOHelper.SetRootDirectory(rootPath);
}
- #endregion
-
- // FIXME everything below needs to be sorted out!
-
-
- protected ServiceContainer Container => Current.Container; // fixme kill
-
public virtual IRuntime Initialize()
{
if (_isInitialized)
throw new InvalidOperationException("The boot manager has already been initialized");
- //ApplicationCache = Container.GetInstance(); //GetApplicationCache();
-
- _timer = ProfilingLogger.TraceDuration(
- string.Format("Umbraco {0} application starting on {1}", UmbracoVersion.GetSemanticVersion().ToSemanticString(), NetworkHelper.MachineName),
- "Umbraco application startup complete");
-
-
//now we need to call the initialize methods
//Create a 'child'container which is a copy of all of the current registrations and begin a sub scope for it
// this child container will be used to manage the application event handler instances and the scope will be
// completed at the end of the boot process to allow garbage collection
// using (Container.BeginScope()) { } // fixme - throws
_appStartupEvtContainer = Container.Clone(); // fixme - but WHY clone? because *then* it has its own scope?! bah ;-(
- //using (_appStartupEvtContainer.BeginScope()) // fixme - works wtf?
- _appStartupEvtContainer.BeginScope(); // fixme - but then attend to end a scope before all child scopes are completed wtf?!
+ _appStartupEvtContainer.BeginScope();
_appStartupEvtContainer.RegisterCollection(factory => factory.GetInstance().ResolveApplicationStartupHandlers());
// fixme - parallel? what about our dependencies?
@@ -235,7 +340,7 @@ namespace Umbraco.Core
//only log if more than 150ms
150))
{
- x.OnApplicationInitialized(UmbracoApplication, Current.ApplicationContext);
+ x.OnApplicationInitialized(UmbracoApplication);
}
}
catch (Exception ex)
@@ -257,7 +362,7 @@ namespace Umbraco.Core
///
///
///
- public virtual IRuntime Startup(Action afterStartup)
+ public virtual IRuntime Startup(Action afterStartup)
{
if (_isStarted)
throw new InvalidOperationException("The boot manager has already been initialized");
@@ -273,7 +378,7 @@ namespace Umbraco.Core
//only log if more than 150ms
150))
{
- x.OnApplicationStarting(UmbracoApplication, Current.ApplicationContext);
+ x.OnApplicationStarting(UmbracoApplication);
}
}
catch (Exception ex)
@@ -285,7 +390,7 @@ namespace Umbraco.Core
if (afterStartup != null)
{
- afterStartup(ApplicationContext.Current);
+ afterStartup();
}
_isStarted = true;
@@ -298,22 +403,15 @@ namespace Umbraco.Core
///
///
///
- public virtual IRuntime Complete(Action afterComplete)
+ public virtual IRuntime Complete(Action afterComplete)
{
if (_isComplete)
throw new InvalidOperationException("The boot manager has already been completed");
- Complete2();
-
- //Here we need to make sure the db can be connected to
- EnsureDatabaseConnection();
-
-
//This is a special case for the user service, we need to tell it if it's an upgrade, if so we need to ensure that
// exceptions are bubbled up if a user is attempted to be persisted during an upgrade (i.e. when they auth to login)
- ((UserService) Current.ApplicationContext.Services.UserService).IsUpgrading = true;
-
-
+ // fixme - wtf? never going back to FALSE !
+ ((UserService) Current.Services.UserService).IsUpgrading = true;
//call OnApplicationStarting of each application events handler
Parallel.ForEach(_appStartupEvtContainer.GetAllInstances(), x =>
@@ -326,7 +424,7 @@ namespace Umbraco.Core
//only log if more than 150ms
150))
{
- x.OnApplicationStarted(UmbracoApplication, Current.ApplicationContext);
+ x.OnApplicationStarted(UmbracoApplication);
}
}
catch (Exception ex)
@@ -345,20 +443,12 @@ namespace Umbraco.Core
if (afterComplete != null)
{
- afterComplete(ApplicationContext.Current);
+ afterComplete();
}
_isComplete = true;
- // we're ready to serve content!
- Current.ApplicationContext.IsReady = true;
-
- //stop the timer and log the output
- _timer.Dispose();
return this;
}
-
- protected virtual void Complete2()
- { }
}
}
diff --git a/src/Umbraco.Core/CoreRuntimeComponent.cs b/src/Umbraco.Core/CoreRuntimeComponent.cs
index b000d4a5bb..2927a6e23e 100644
--- a/src/Umbraco.Core/CoreRuntimeComponent.cs
+++ b/src/Umbraco.Core/CoreRuntimeComponent.cs
@@ -1,8 +1,10 @@
using System;
using System.Collections.Generic;
+using System.Configuration;
using System.IO;
using System.Linq;
using System.Text;
+using System.Threading;
using System.Threading.Tasks;
using AutoMapper;
using LightInject;
@@ -11,6 +13,7 @@ using Umbraco.Core.Components;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.DependencyInjection;
+using Umbraco.Core.Exceptions;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Manifest;
@@ -23,6 +26,7 @@ using Umbraco.Core.Services;
using Umbraco.Core.Strings;
using Umbraco.Core.Sync;
using Umbraco.Core._Legacy.PackageActions;
+using IntegerValidator = Umbraco.Core.PropertyEditors.IntegerValidator;
namespace Umbraco.Core
{
@@ -38,9 +42,20 @@ namespace Umbraco.Core
container.RegisterFrom();
container.RegisterFrom();
+
+
+
+
+
+
+
+
+
+
+
//TODO: Don't think we'll need this when the resolvers are all container resolvers
container.RegisterSingleton();
- container.RegisterSingleton();
+
container.Register(factory => FileSystemProviderManager.Current.GetFileSystemProvider());
// fixme - should we capture Logger, etc here or use factory?
@@ -70,7 +85,7 @@ namespace Umbraco.Core
container.RegisterSingleton(factory => UmbracoConfig.For.UmbracoSettings().DistributedCall.Enabled
? (IServerRegistrar)new ConfigServerRegistrar(UmbracoConfig.For.UmbracoSettings())
: (IServerRegistrar)new DatabaseServerRegistrar(
- new Lazy(() => factory.GetInstance().Services.ServerRegistrationService),
+ new Lazy(factory.GetInstance),
new DatabaseServerRegistrarOptions()));
// by default we'll use the database server messenger with default options (no callbacks),
@@ -78,7 +93,12 @@ namespace Umbraco.Core
// fixme - painful, have to take care of lifetime! - we CANNOT ask users to remember!
// fixme - same issue with PublishedContentModelFactory and many more, I guess!
container.RegisterSingleton(factory
- => new DatabaseServerMessenger(factory.GetInstance(), true, new DatabaseServerMessengerOptions()));
+ => new DatabaseServerMessenger(
+ factory.GetInstance(),
+ factory.GetInstance(),
+ factory.GetInstance(),
+ factory.GetInstance(),
+ true, new DatabaseServerMessengerOptions()));
CacheRefresherCollectionBuilder.Register(container)
.AddProducer(factory => factory.GetInstance().ResolveCacheRefreshers());
@@ -103,27 +123,18 @@ namespace Umbraco.Core
container.RegisterSingleton();
}
- public void Initialize(IEnumerable modelMapperConfigurations)
+ internal void Initialize(
+ IEnumerable modelMapperConfigurations)
{
//TODO: Remove these for v8!
LegacyPropertyEditorIdToAliasConverter.CreateMappingsForCoreEditors();
LegacyParameterEditorAliasConverter.CreateMappingsForCoreEditors();
- InitializeModelMappers(modelMapperConfigurations);
-
- }
-
- private void InitializeModelMappers(IEnumerable modelMapperConfigurations)
- {
+ // model mapper configurations have been registered & are created by the container
Mapper.Initialize(configuration =>
{
- // fixme why ApplicationEventHandler?!
- //foreach (var m in ApplicationEventsResolver.Current.ApplicationEventHandlers.OfType())
foreach (var m in modelMapperConfigurations)
- {
- //Logger.Debug("FIXME " + m.GetType().FullName);
- m.ConfigureMappings(configuration, Current.ApplicationContext);
- }
+ m.ConfigureMappings(configuration);
});
}
}
diff --git a/src/Umbraco.Core/DatabaseContext.cs b/src/Umbraco.Core/DatabaseContext.cs
index 59b92a31eb..e28b44e723 100644
--- a/src/Umbraco.Core/DatabaseContext.cs
+++ b/src/Umbraco.Core/DatabaseContext.cs
@@ -28,24 +28,30 @@ namespace Umbraco.Core
{
private readonly IDatabaseFactory _factory;
private readonly ILogger _logger;
+ private readonly IRuntimeState _runtime;
+ private readonly IMigrationEntryService _migrationEntryService;
private DatabaseSchemaResult _databaseSchemaValidationResult;
///
- /// Initializes a new instance of the class with a database factory and a logger.
+ /// Initializes a new instance of the class.
///
/// A database factory.
/// A logger.
+ ///
+ ///
/// The database factory will try to configure itself but may fail eg if the default
/// Umbraco connection string is not available because we are installing. In which case this
/// database context must sort things out and configure the database factory before it can be
/// used.
- public DatabaseContext(IDatabaseFactory factory, ILogger logger)
+ public DatabaseContext(IDatabaseFactory factory, ILogger logger, IRuntimeState runtime, IMigrationEntryService migrationEntryService)
{
if (factory == null) throw new ArgumentNullException(nameof(factory));
if (logger == null) throw new ArgumentNullException(nameof(logger));
_factory = factory;
_logger = logger;
+ _runtime = runtime;
+ _migrationEntryService = migrationEntryService;
}
///
@@ -69,8 +75,8 @@ namespace Umbraco.Core
public UmbracoDatabase Database => _factory.GetDatabase();
///
- /// Gets a value indicating whether the database is configured, ie whether it exists
- /// and can be reached. It does not necessarily mean that Umbraco is installed nor
+ /// Gets a value indicating whether the database is configured. It does not necessarily
+ /// mean that it is possible to connect, nor that Umbraco is installed, nor
/// up-to-date.
///
public bool IsDatabaseConfigured => _factory.Configured;
@@ -161,7 +167,7 @@ namespace Umbraco.Core
/// The name the provider (Sql, Sql Azure, Sql Ce, MySql).
///
/// A connection string.
- public string GetDatabaseConnectionString(string server, string databaseName, string user, string password, string databaseProvider, out string providerName)
+ public static string GetDatabaseConnectionString(string server, string databaseName, string user, string password, string databaseProvider, out string providerName)
{
providerName = Constants.DbProviderNames.SqlServer;
var test = databaseProvider.ToLower();
@@ -195,7 +201,7 @@ namespace Umbraco.Core
/// The name or address of the database server.
/// The name of the database
/// A connection string.
- public string GetIntegratedSecurityDatabaseConnectionString(string server, string databaseName)
+ public static string GetIntegratedSecurityDatabaseConnectionString(string server, string databaseName)
{
return $"Server={server};Database={databaseName};Integrated Security=true";
}
@@ -208,7 +214,7 @@ namespace Umbraco.Core
/// The user name.
/// The user password.
/// A connection string.
- public string GetAzureConnectionString(string server, string databaseName, string user, string password)
+ public static string GetAzureConnectionString(string server, string databaseName, string user, string password)
{
if (server.Contains(".") && ServerStartsWithTcp(server) == false)
server = $"tcp:{server}";
@@ -358,7 +364,7 @@ namespace Umbraco.Core
return _databaseSchemaValidationResult;
}
- internal Result CreateDatabaseSchemaAndData(ApplicationContext applicationContext)
+ internal Result CreateDatabaseSchemaAndData()
{
try
{
@@ -398,7 +404,7 @@ namespace Umbraco.Core
if (string.IsNullOrEmpty(GlobalSettings.ConfigurationStatus) && installedSchemaVersion.Equals(new Version(0, 0, 0)))
{
var helper = new DatabaseSchemaHelper(database, _logger);
- helper.CreateDatabaseSchema(true, applicationContext);
+ helper.CreateDatabaseSchema(_runtime, _migrationEntryService, true);
message = message + "
Installation completed!
";
@@ -487,7 +493,7 @@ namespace Umbraco.Core
//DO the upgrade!
- var runner = new MigrationRunner(builder, migrationEntryService, _logger, currentInstalledVersion, UmbracoVersion.GetSemanticVersion(), GlobalSettings.UmbracoMigrationName);
+ var runner = new MigrationRunner(builder, migrationEntryService, _logger, currentInstalledVersion, UmbracoVersion.SemanticVersion, GlobalSettings.UmbracoMigrationName);
var migrationContext = new MigrationContext(database, _logger);
var upgraded = runner.Execute(migrationContext /*, true*/);
diff --git a/src/Umbraco.Core/DependencyInjection/Current.cs b/src/Umbraco.Core/DependencyInjection/Current.cs
index 5b9e033a50..3f83d33291 100644
--- a/src/Umbraco.Core/DependencyInjection/Current.cs
+++ b/src/Umbraco.Core/DependencyInjection/Current.cs
@@ -7,6 +7,7 @@ using Umbraco.Core.Logging;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Plugins;
using Umbraco.Core.PropertyEditors;
+using Umbraco.Core.Services;
using Umbraco.Core.Strings;
using Umbraco.Core.Sync;
using Umbraco.Core._Legacy.PackageActions;
@@ -29,7 +30,7 @@ namespace Umbraco.Core.DependencyInjection
if (_container == null) throw new Exception("No container has been set.");
return _container;
}
- set // ok to set - don't be stupid
+ set
{
if (_container != null) throw new Exception("A container has already been set.");
_container = value;
@@ -39,6 +40,7 @@ namespace Umbraco.Core.DependencyInjection
internal static bool HasContainer => _container != null;
// for UNIT TESTS exclusively!
+ // resets *everything* that is 'current'
internal static void Reset()
{
_container = null;
@@ -47,7 +49,7 @@ namespace Umbraco.Core.DependencyInjection
_logger = null;
_profiler = null;
_profilingLogger = null;
- _applicationContext = null;
+ _pluginManager = null; // fixme - some of our tests don't reset it?
Resetted?.Invoke(null, EventArgs.Empty);
}
@@ -56,17 +58,8 @@ namespace Umbraco.Core.DependencyInjection
#region Getters
- // fixme - refactor
- // some of our tests want to *set* the current application context and bypass the container
- // so for the time being we support it, however we should fix our tests
-
- private static ApplicationContext _applicationContext;
-
- public static ApplicationContext ApplicationContext
- {
- get { return _applicationContext ?? (_applicationContext = Container.GetInstance()); }
- set { _applicationContext = value; }
- }
+ public static IRuntimeState RuntimeState
+ => Container.GetInstance();
// fixme - refactor
// some of our tests did mess with the current plugin manager
@@ -76,7 +69,9 @@ namespace Umbraco.Core.DependencyInjection
public static PluginManager PluginManager
{
- get { return _pluginManager ?? (_pluginManager = Container.TryGetInstance() ?? PluginManager.Default); }
+ get { return _pluginManager
+ ?? (_pluginManager = Container.TryGetInstance()
+ ?? new PluginManager(ApplicationCache.RuntimeCache, ProfilingLogger)); }
set { _pluginManager = value; }
}
@@ -122,7 +117,7 @@ namespace Umbraco.Core.DependencyInjection
private static IShortStringHelper _shortStringHelper;
public static IShortStringHelper ShortStringHelper
- => _shortStringHelper ?? (_shortStringHelper = _container?.TryGetInstance()
+ => _shortStringHelper ?? (_shortStringHelper = _container?.TryGetInstance()
?? new DefaultShortStringHelper(new DefaultShortStringHelperConfig().WithDefault(UmbracoConfig.For.UmbracoSettings())));
private static ILogger _logger;
@@ -130,17 +125,26 @@ namespace Umbraco.Core.DependencyInjection
private static ProfilingLogger _profilingLogger;
public static ILogger Logger
- => _logger ?? (_logger = _container?.TryGetInstance()
+ => _logger ?? (_logger = _container?.TryGetInstance()
?? new DebugDiagnosticsLogger());
public static IProfiler Profiler
- => _profiler ?? (_profiler = _container?.TryGetInstance()
+ => _profiler ?? (_profiler = _container?.TryGetInstance()
?? new LogProfiler(Logger));
public static ProfilingLogger ProfilingLogger
=> _profilingLogger ?? (_profilingLogger = _container?.TryGetInstance())
?? new ProfilingLogger(Logger, Profiler);
+ public static CacheHelper ApplicationCache
+ => Container.GetInstance();
+
+ public static ServiceContext Services
+ => Container.GetInstance();
+
+ public static DatabaseContext DatabaseContext
+ => Container.GetInstance();
+
#endregion
}
}
diff --git a/src/Umbraco.Core/DependencyInjection/LightInjectExtensions.cs b/src/Umbraco.Core/DependencyInjection/LightInjectExtensions.cs
index 72b06e1918..5ce859ae74 100644
--- a/src/Umbraco.Core/DependencyInjection/LightInjectExtensions.cs
+++ b/src/Umbraco.Core/DependencyInjection/LightInjectExtensions.cs
@@ -25,6 +25,10 @@ namespace Umbraco.Core.DependencyInjection
// in Umbraco we do NOT want to do property injection by default, so we have to disable it.
// from the docs, the following line will cause the container to "now only try to inject
// dependencies for properties that is annotated with the InjectAttribute."
+ //
+ // could not find it documented, but tests & code review shows that LightInject considers a
+ // property to be "injectable" when its setter exists and is not static, nor private, nor
+ // it is an index property. which means that eg protected or internal setters are OK.
container.EnableAnnotatedPropertyInjection();
// see notes in MixedScopeManagerProvider
@@ -204,5 +208,46 @@ namespace Umbraco.Core.DependencyInjection
foreach (var type in implementationTypes(container))
container.Register(type);
}
+
+ ///
+ /// Registers a base type for auto-registration.
+ ///
+ /// The base type.
+ /// The container.
+ ///
+ /// Any type that inherits/implements the base type will be auto-registered on-demand.
+ /// This methods works with actual types. Use the other overload for eg generic definitions.
+ ///
+ public static void RegisterAuto(this IServiceContainer container)
+ {
+ container.RegisterFallback((serviceType, serviceName) =>
+ {
+ // https://github.com/seesharper/LightInject/issues/173
+ if (typeof(T).IsAssignableFrom(serviceType))
+ container.Register(serviceType);
+ return false;
+ }, null);
+ }
+
+ ///
+ /// Registers a base type for auto-registration.
+ ///
+ /// The container.
+ /// The base type.
+ ///
+ /// Any type that inherits/implements the base type will be auto-registered on-demand.
+ /// This methods works with actual types, as well as generic definitions eg typeof(MyBase{}).
+ ///
+ public static void RegisterAuto(this IServiceContainer container, Type type)
+ {
+ container.RegisterFallback((serviceType, serviceName) =>
+ {
+ //Current.Logger.Debug(typeof(LightInjectExtensions), $"Fallback for type {serviceType.FullName}.");
+ // https://github.com/seesharper/LightInject/issues/173
+ if (type.IsAssignableFromGtd(serviceType))
+ container.Register(serviceType);
+ return false;
+ }, null);
+ }
}
}
diff --git a/src/Umbraco.Core/DependencyInjection/RepositoryCompositionRoot.cs b/src/Umbraco.Core/DependencyInjection/RepositoryCompositionRoot.cs
index 71f9968dc5..02f0b6d6d1 100644
--- a/src/Umbraco.Core/DependencyInjection/RepositoryCompositionRoot.cs
+++ b/src/Umbraco.Core/DependencyInjection/RepositoryCompositionRoot.cs
@@ -20,6 +20,8 @@ namespace Umbraco.Core.DependencyInjection
public void Compose(IServiceRegistry container)
{
+ // fixme - moved these to CoreRuntime
+ /*
// register syntax providers
container.Register("MySqlSyntaxProvider");
container.Register("SqlCeSyntaxProvider");
@@ -31,8 +33,10 @@ namespace Umbraco.Core.DependencyInjection
// until the database context configures it properly (eg when installing)
container.RegisterSingleton();
- // register a database accessor - will be replaced
+ // register a database accessor - will be replaced - fixme - what does this mean?
+ // by HybridUmbracoDatabaseAccessor in the web project - so what?
container.RegisterSingleton();
+ */
// register database context
container.RegisterSingleton();
@@ -117,9 +121,10 @@ namespace Umbraco.Core.DependencyInjection
var serviceContainer = container as IServiceContainer;
if (serviceContainer == null) throw new Exception("Container is not IServiceContainer.");
+ // fixme fixme fixme more
// register persistence mappers
- MapperCollectionBuilder.Register(serviceContainer)
- .AddProducer(f => f.GetInstance().ResolveAssignedMapperTypes());
+ //MapperCollectionBuilder.Register(serviceContainer)
+ // .AddProducer(f => f.GetInstance().ResolveAssignedMapperTypes());
}
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Exceptions/BootFailedException.cs b/src/Umbraco.Core/Exceptions/BootFailedException.cs
new file mode 100644
index 0000000000..b2836f22ed
--- /dev/null
+++ b/src/Umbraco.Core/Exceptions/BootFailedException.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace Umbraco.Core.Exceptions
+{
+ ///
+ /// An exception that is thrown if the Umbraco application cannnot boot.
+ ///
+ public class BootFailedException : Exception
+ {
+ ///
+ /// Initializes a new instance of the class with a specified error message.
+ ///
+ /// The message that describes the error.
+ public BootFailedException(string message)
+ : base(message)
+ { }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Exceptions/UmbracoStartupFailedException.cs b/src/Umbraco.Core/Exceptions/UmbracoStartupFailedException.cs
deleted file mode 100644
index d27d38de9a..0000000000
--- a/src/Umbraco.Core/Exceptions/UmbracoStartupFailedException.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using System;
-
-namespace Umbraco.Core.Exceptions
-{
- ///
- /// An exception that is thrown if the umbraco application cannnot boot
- ///
- public class UmbracoStartupFailedException : Exception
- {
- ///
- /// Initializes a new instance of the class with a specified error message.
- ///
- /// The message that describes the error.
- public UmbracoStartupFailedException(string message) : base(message)
- {
- }
- }
-}
\ No newline at end of file
diff --git a/src/Umbraco.Core/IApplicationEventHandler.cs b/src/Umbraco.Core/IApplicationEventHandler.cs
index 866ce220d4..1421af63ea 100644
--- a/src/Umbraco.Core/IApplicationEventHandler.cs
+++ b/src/Umbraco.Core/IApplicationEventHandler.cs
@@ -11,22 +11,19 @@ namespace Umbraco.Core
/// ApplicationContext is created and other static objects that require initialization have been setup
///
///
- ///
- void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext);
+ void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication);
///
/// All resolvers have been initialized but resolution is not frozen so they can be modified in this method
///
///
- ///
- void OnApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext);
+ void OnApplicationStarting(UmbracoApplicationBase umbracoApplication);
///
/// Bootup is completed, this allows you to perform any other bootup logic required for the application.
/// Resolution is frozen so now they can be used to resolve instances.
///
///
- ///
- void OnApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext);
+ void OnApplicationStarted(UmbracoApplicationBase umbracoApplication);
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/IRuntime.cs b/src/Umbraco.Core/IRuntime.cs
index 5321e91272..ce0f77ffe4 100644
--- a/src/Umbraco.Core/IRuntime.cs
+++ b/src/Umbraco.Core/IRuntime.cs
@@ -3,24 +3,7 @@ using LightInject;
namespace Umbraco.Core
{
- // fixme - move!
- public class RuntimeState
- {
- ///
- /// Gets a value indicating whether the application is running in debug mode.
- ///
- public bool Debug { get; }
-
- public RuntimeSomething Something { get; }
- }
-
- public enum RuntimeSomething
- {
- Boot,
- Run
- }
-
- ///
+ ///
/// Defines the Umbraco runtime.
///
public interface IRuntime
@@ -35,28 +18,5 @@ namespace Umbraco.Core
/// Terminates the runtime.
///
void Terminate();
-
- // fixme - everything below is obsolete!
-
- ///
- /// Fires first in the application startup process before any customizations can occur
- ///
- ///
- IRuntime Initialize();
-
- ///
- /// Fires after initialization and calls the callback to allow for customizations to occur
- ///
- ///
- ///
- IRuntime Startup(Action afterStartup);
-
- ///
- /// Fires after startup and calls the callback once customizations are locked
- ///
- ///
- ///
- IRuntime Complete(Action afterComplete);
-
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/IRuntimeState.cs b/src/Umbraco.Core/IRuntimeState.cs
new file mode 100644
index 0000000000..3c399f6a92
--- /dev/null
+++ b/src/Umbraco.Core/IRuntimeState.cs
@@ -0,0 +1,59 @@
+using System;
+using Semver;
+using Umbraco.Core.Sync;
+
+namespace Umbraco.Core
+{
+ ///
+ /// Represents the state of the Umbraco runtime.
+ ///
+ public interface IRuntimeState
+ {
+ ///
+ /// Gets the version of the executing code.
+ ///
+ Version Version { get; }
+
+ ///
+ /// Gets the version comment of the executing code.
+ ///
+ string VersionComment { get; }
+
+ ///
+ /// Gets the semantic version of the executing code.
+ ///
+ SemVersion SemanticVersion { get; }
+
+ ///
+ /// Gets a value indicating whether the application is running in debug mode.
+ ///
+ bool Debug { get; }
+
+ ///
+ /// Gets a value indicating whether the runtime is the current main domain.
+ ///
+ bool IsMainDom { get; }
+
+ ///
+ /// Get the server's current role.
+ ///
+ ServerRole ServerRole { get; }
+
+ ///
+ /// Gets the Umbraco application url.
+ ///
+ /// This is eg "http://www.example.com".
+ Uri ApplicationUrl { get; }
+
+ ///
+ /// Gets the Umbraco application virtual path.
+ ///
+ /// This is either "/" or eg "/virtual".
+ string ApplicationVirtualPath { get; }
+
+ ///
+ /// Gets the runtime level of execution.
+ ///
+ RuntimeLevel Level { get; }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Logging/WebProfiler.cs b/src/Umbraco.Core/Logging/WebProfiler.cs
index 244835f792..6b5d98e46c 100644
--- a/src/Umbraco.Core/Logging/WebProfiler.cs
+++ b/src/Umbraco.Core/Logging/WebProfiler.cs
@@ -15,8 +15,7 @@ namespace Umbraco.Core.Logging
///Binds to application events to enable the MiniProfiler
///
///
- ///
- protected override void ApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
+ protected override void ApplicationInitialized(UmbracoApplicationBase umbracoApplication)
{
UmbracoApplicationBase.ApplicationInit += UmbracoApplicationApplicationInit;
}
diff --git a/src/Umbraco.Core/MainDom.cs b/src/Umbraco.Core/MainDom.cs
index 4fd8b0862b..e30f2eecac 100644
--- a/src/Umbraco.Core/MainDom.cs
+++ b/src/Umbraco.Core/MainDom.cs
@@ -92,7 +92,7 @@ namespace Umbraco.Core
try
{
- _logger.Debug("Stopping...");
+ _logger.Debug("Stopping.");
foreach (var callback in _callbacks.OrderBy(x => x.Key).Select(x => x.Value))
{
try
@@ -113,7 +113,7 @@ namespace Umbraco.Core
// in any case...
_isMainDom = false;
_asyncLocker.Dispose();
- _logger.Debug("Released MainDom.");
+ _logger.Debug("Released.");
}
}
@@ -126,11 +126,11 @@ namespace Umbraco.Core
// the handler is not installed so that would be the hosting environment
if (_signaled)
{
- _logger.Debug("Cannot acquire MainDom (signaled).");
+ _logger.Debug("Cannot acquire (signaled).");
return false;
}
- _logger.Debug("Acquiring MainDom...");
+ _logger.Debug("Acquiring.");
// signal other instances that we want the lock, then wait one the lock,
// which may timeout, and this is accepted - see comments below
@@ -157,7 +157,7 @@ namespace Umbraco.Core
HostingEnvironment.RegisterObject(this);
- _logger.Debug("Acquired MainDom.");
+ _logger.Debug("Acquired.");
return true;
}
}
diff --git a/src/Umbraco.Core/Models/ContentExtensions.cs b/src/Umbraco.Core/Models/ContentExtensions.cs
index 6a8ee044bf..be8deeb8f9 100644
--- a/src/Umbraco.Core/Models/ContentExtensions.cs
+++ b/src/Umbraco.Core/Models/ContentExtensions.cs
@@ -11,6 +11,7 @@ using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
+using Umbraco.Core.DependencyInjection;
using Umbraco.Core.IO;
using Umbraco.Core.Media;
using Umbraco.Core.Models.EntityBase;
@@ -233,7 +234,7 @@ namespace Umbraco.Core.Models
[EditorBrowsable(EditorBrowsableState.Never)]
public static IEnumerable Ancestors(this IContent content)
{
- return ApplicationContext.Current.Services.ContentService.GetAncestors(content);
+ return Current.Services.ContentService.GetAncestors(content);
}
///
@@ -251,7 +252,7 @@ namespace Umbraco.Core.Models
[EditorBrowsable(EditorBrowsableState.Never)]
public static IEnumerable Children(this IContent content)
{
- return ApplicationContext.Current.Services.ContentService.GetChildren(content.Id);
+ return Current.Services.ContentService.GetChildren(content.Id);
}
///
@@ -269,7 +270,7 @@ namespace Umbraco.Core.Models
[EditorBrowsable(EditorBrowsableState.Never)]
public static IEnumerable Descendants(this IContent content)
{
- return ApplicationContext.Current.Services.ContentService.GetDescendants(content);
+ return Current.Services.ContentService.GetDescendants(content);
}
///
@@ -287,7 +288,7 @@ namespace Umbraco.Core.Models
[EditorBrowsable(EditorBrowsableState.Never)]
public static IContent Parent(this IContent content)
{
- return ApplicationContext.Current.Services.ContentService.GetById(content.ParentId);
+ return Current.Services.ContentService.GetById(content.ParentId);
}
#endregion
@@ -308,7 +309,7 @@ namespace Umbraco.Core.Models
[EditorBrowsable(EditorBrowsableState.Never)]
public static IEnumerable Ancestors(this IMedia media)
{
- return ApplicationContext.Current.Services.MediaService.GetAncestors(media);
+ return Current.Services.MediaService.GetAncestors(media);
}
///
@@ -326,7 +327,7 @@ namespace Umbraco.Core.Models
[EditorBrowsable(EditorBrowsableState.Never)]
public static IEnumerable Children(this IMedia media)
{
- return ApplicationContext.Current.Services.MediaService.GetChildren(media.Id);
+ return Current.Services.MediaService.GetChildren(media.Id);
}
///
@@ -344,7 +345,7 @@ namespace Umbraco.Core.Models
[EditorBrowsable(EditorBrowsableState.Never)]
public static IEnumerable Descendants(this IMedia media)
{
- return ApplicationContext.Current.Services.MediaService.GetDescendants(media);
+ return Current.Services.MediaService.GetDescendants(media);
}
///
@@ -362,7 +363,7 @@ namespace Umbraco.Core.Models
[EditorBrowsable(EditorBrowsableState.Never)]
public static IMedia Parent(this IMedia media)
{
- return ApplicationContext.Current.Services.MediaService.GetById(media.ParentId);
+ return Current.Services.MediaService.GetById(media.ParentId);
}
#endregion
@@ -528,7 +529,7 @@ namespace Umbraco.Core.Models
[EditorBrowsable(EditorBrowsableState.Never)]
public static void SetValue(this IContentBase content, string propertyTypeAlias, HttpPostedFileBase value)
{
- content.SetValue(propertyTypeAlias, value, ApplicationContext.Current.Services.DataTypeService);
+ content.SetValue(propertyTypeAlias, value, Current.Services.DataTypeService);
}
///
@@ -583,7 +584,7 @@ namespace Umbraco.Core.Models
[EditorBrowsable(EditorBrowsableState.Never)]
public static void SetValue(this IContentBase content, string propertyTypeAlias, string fileName, Stream fileStream)
{
- content.SetValue(propertyTypeAlias, fileName, fileStream, ApplicationContext.Current.Services.DataTypeService);
+ content.SetValue(propertyTypeAlias, fileName, fileStream, Current.Services.DataTypeService);
}
private static void SetFileOnContent(IContentBase content, string propertyTypeAlias, string filename, Stream fileStream, IDataTypeService dataTypeService)
@@ -676,12 +677,12 @@ namespace Umbraco.Core.Models
#region User/Profile methods
-
+
[Obsolete("Use the overload that declares the IUserService to use")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static IProfile GetCreatorProfile(this IMedia media)
{
- return ApplicationContext.Current.Services.UserService.GetProfileById(media.CreatorId);
+ return Current.Services.UserService.GetProfileById(media.CreatorId);
}
///
@@ -691,12 +692,12 @@ namespace Umbraco.Core.Models
{
return userService.GetProfileById(media.CreatorId);
}
-
+
[Obsolete("Use the overload that declares the IUserService to use")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static IProfile GetCreatorProfile(this IContentBase content)
{
- return ApplicationContext.Current.Services.UserService.GetProfileById(content.CreatorId);
+ return Current.Services.UserService.GetProfileById(content.CreatorId);
}
///
@@ -706,12 +707,12 @@ namespace Umbraco.Core.Models
{
return userService.GetProfileById(content.CreatorId);
}
-
+
[Obsolete("Use the overload that declares the IUserService to use")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static IProfile GetWriterProfile(this IContent content)
{
- return ApplicationContext.Current.Services.UserService.GetProfileById(content.WriterId);
+ return Current.Services.UserService.GetProfileById(content.WriterId);
}
///
@@ -737,7 +738,7 @@ namespace Umbraco.Core.Models
#region Tag methods
-
+
///
/// Sets tags for the property - will add tags to the tags table and set the property value to be the comma delimited value of the tags.
@@ -864,11 +865,11 @@ namespace Umbraco.Core.Models
return packagingService.Export(content, true, raiseEvents: false);
}
-
+
[Obsolete("Use the overload that declares the IPackagingService to use")]
public static XElement ToXml(this IContent content)
{
- return ApplicationContext.Current.Services.PackagingService.Export(content, raiseEvents: false);
+ return Current.Services.PackagingService.Export(content, raiseEvents: false);
}
///
@@ -885,7 +886,7 @@ namespace Umbraco.Core.Models
[Obsolete("Use the overload that declares the IPackagingService to use")]
public static XElement ToXml(this IMedia media)
{
- return ApplicationContext.Current.Services.PackagingService.Export(media, raiseEvents: false);
+ return Current.Services.PackagingService.Export(media, raiseEvents: false);
}
///
@@ -935,7 +936,7 @@ namespace Umbraco.Core.Models
[Obsolete("Use the overload that declares the IPackagingService to use")]
public static XElement ToXml(this IMember member)
{
- return ((PackagingService)(ApplicationContext.Current.Services.PackagingService)).Export(member);
+ return ((PackagingService)(Current.Services.PackagingService)).Export(member);
}
///
diff --git a/src/Umbraco.Core/Models/Identity/IdentityModelMappings.cs b/src/Umbraco.Core/Models/Identity/IdentityModelMappings.cs
index 534b4367ff..898ce49ce2 100644
--- a/src/Umbraco.Core/Models/Identity/IdentityModelMappings.cs
+++ b/src/Umbraco.Core/Models/Identity/IdentityModelMappings.cs
@@ -4,12 +4,20 @@ using AutoMapper;
using Umbraco.Core.Models.Mapping;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Security;
+using Umbraco.Core.Services;
namespace Umbraco.Core.Models.Identity
{
public class IdentityModelMappings : ModelMapperConfiguration
{
- public override void ConfigureMappings(IMapperConfiguration config, ApplicationContext applicationContext)
+ private readonly ILocalizedTextService _textService;
+
+ public IdentityModelMappings(ILocalizedTextService textService)
+ {
+ _textService = textService;
+ }
+
+ public override void ConfigureMappings(IMapperConfiguration config)
{
config.CreateMap()
.ForMember(user => user.Email, expression => expression.MapFrom(user => user.Email))
@@ -17,7 +25,7 @@ namespace Umbraco.Core.Models.Identity
.ForMember(user => user.LockoutEndDateUtc, expression => expression.MapFrom(user => user.IsLockedOut ? DateTime.MaxValue.ToUniversalTime() : (DateTime?) null))
.ForMember(user => user.UserName, expression => expression.MapFrom(user => user.Username))
.ForMember(user => user.PasswordHash, expression => expression.MapFrom(user => GetPasswordHash(user.RawPasswordValue)))
- .ForMember(user => user.Culture, expression => expression.MapFrom(user => user.GetUserCulture(applicationContext.Services.TextService)))
+ .ForMember(user => user.Culture, expression => expression.MapFrom(user => user.GetUserCulture(_textService)))
.ForMember(user => user.Name, expression => expression.MapFrom(user => user.Name))
.ForMember(user => user.StartMediaId, expression => expression.MapFrom(user => user.StartMediaId))
.ForMember(user => user.StartContentId, expression => expression.MapFrom(user => user.StartContentId))
diff --git a/src/Umbraco.Core/Models/Mapping/ModelMapperConfiguration.cs b/src/Umbraco.Core/Models/Mapping/ModelMapperConfiguration.cs
index 8febce06d5..8768776281 100644
--- a/src/Umbraco.Core/Models/Mapping/ModelMapperConfiguration.cs
+++ b/src/Umbraco.Core/Models/Mapping/ModelMapperConfiguration.cs
@@ -7,8 +7,6 @@ namespace Umbraco.Core.Models.Mapping
///
public abstract class ModelMapperConfiguration
{
- public abstract void ConfigureMappings(IMapperConfiguration config, ApplicationContext applicationContext);
+ public abstract void ConfigureMappings(IMapperConfiguration config);
}
-
-
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Models/Membership/MembershipUserExtensions.cs b/src/Umbraco.Core/Models/Membership/MembershipUserExtensions.cs
index 2289983033..943be94c84 100644
--- a/src/Umbraco.Core/Models/Membership/MembershipUserExtensions.cs
+++ b/src/Umbraco.Core/Models/Membership/MembershipUserExtensions.cs
@@ -1,5 +1,6 @@
using System;
using System.Web.Security;
+using Umbraco.Core.DependencyInjection;
using Umbraco.Core.Security;
using Umbraco.Core.Services;
@@ -38,7 +39,7 @@ namespace Umbraco.Core.Models.Membership
{
return MembershipScenario.NativeUmbraco;
}
- var memberType = ApplicationContext.Current.Services.MemberTypeService.Get(Constants.Conventions.MemberTypes.DefaultAlias);
+ var memberType = Current.Services.MemberTypeService.Get(Constants.Conventions.MemberTypes.DefaultAlias);
return memberType != null
? MembershipScenario.CustomProviderWithUmbracoLink
: MembershipScenario.StandaloneCustomProvider;
diff --git a/src/Umbraco.Core/Models/PropertyExtensions.cs b/src/Umbraco.Core/Models/PropertyExtensions.cs
index 53119d4931..65f91d201f 100644
--- a/src/Umbraco.Core/Models/PropertyExtensions.cs
+++ b/src/Umbraco.Core/Models/PropertyExtensions.cs
@@ -2,6 +2,7 @@
using System.Xml;
using System.Xml.Linq;
using Umbraco.Core.Configuration;
+using Umbraco.Core.DependencyInjection;
using Umbraco.Core.PropertyEditors;
using Umbraco.Core.Services;
@@ -17,8 +18,8 @@ namespace Umbraco.Core.Models
public static XElement ToXml(this Property property)
{
var xmlSerializer = new EntityXmlSerializer();
- return xmlSerializer.Serialize(ApplicationContext.Current.Services.DataTypeService, property);
+ return xmlSerializer.Serialize(Current.Services.DataTypeService, property);
}
-
+
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Persistence/DatabaseSchemaHelper.cs b/src/Umbraco.Core/Persistence/DatabaseSchemaHelper.cs
index ba30d48548..dd723f2eca 100644
--- a/src/Umbraco.Core/Persistence/DatabaseSchemaHelper.cs
+++ b/src/Umbraco.Core/Persistence/DatabaseSchemaHelper.cs
@@ -44,10 +44,9 @@ namespace Umbraco.Core.Persistence
/// Safe method that is only able to create the schema in non-configured
/// umbraco instances.
///
- public void CreateDatabaseSchema(ApplicationContext applicationContext)
+ public void CreateDatabaseSchema(IRuntimeState runtime, IMigrationEntryService migrationEntryService)
{
- if (applicationContext == null) throw new ArgumentNullException(nameof(applicationContext));
- CreateDatabaseSchema(true, applicationContext);
+ CreateDatabaseSchema(runtime, migrationEntryService, true);
}
///
@@ -55,24 +54,15 @@ namespace Umbraco.Core.Persistence
/// with the option to guard the db from having the schema created
/// multiple times.
///
+ ///
///
- ///
- public void CreateDatabaseSchema(bool guardConfiguration, ApplicationContext applicationContext)
+ ///
+ public void CreateDatabaseSchema(IRuntimeState runtime, IMigrationEntryService migrationEntryService, bool guardConfiguration)
{
- if (applicationContext == null) throw new ArgumentNullException(nameof(applicationContext));
-
- if (guardConfiguration && applicationContext.IsConfigured)
+ if (guardConfiguration && runtime.Level == RuntimeLevel.Run)
throw new Exception("Umbraco is already configured!");
- CreateDatabaseSchemaDo(applicationContext.Services.MigrationEntryService);
- }
-
- internal void CreateDatabaseSchemaDo(bool guardConfiguration, ApplicationContext applicationContext)
- {
- if (guardConfiguration && applicationContext.IsConfigured)
- throw new Exception("Umbraco is already configured!");
-
- CreateDatabaseSchemaDo(applicationContext.Services.MigrationEntryService);
+ CreateDatabaseSchemaDo(migrationEntryService);
}
internal void CreateDatabaseSchemaDo(IMigrationEntryService migrationEntryService)
diff --git a/src/Umbraco.Core/Persistence/DbConnectionExtensions.cs b/src/Umbraco.Core/Persistence/DbConnectionExtensions.cs
index 1a257f3ce8..7762978355 100644
--- a/src/Umbraco.Core/Persistence/DbConnectionExtensions.cs
+++ b/src/Umbraco.Core/Persistence/DbConnectionExtensions.cs
@@ -38,13 +38,13 @@ namespace Umbraco.Core.Persistence
throw new NotSupportedException($"Provider \"{providerName}\" is not supported.");
var factory = DbProviderFactories.GetFactory(providerName);
- var conn = factory.CreateConnection();
+ var connection = factory.CreateConnection();
- if (conn == null)
+ if (connection == null)
throw new InvalidOperationException($"Could not create a connection for provider \"{providerName}\".");
- conn.ConnectionString = connectionString;
- using (var connection = conn)
+ connection.ConnectionString = connectionString;
+ using (connection)
{
return connection.IsAvailable();
}
@@ -60,7 +60,7 @@ namespace Umbraco.Core.Persistence
catch (DbException e)
{
// Don't swallow this error, the exception is super handy for knowing "why" its not available
- LogHelper.WarnWithException("Configured database is reporting as not being available!", e);
+ LogHelper.WarnWithException("Configured database is reporting as not being available.", e);
return false;
}
diff --git a/src/Umbraco.Core/Persistence/DefaultDatabaseFactory.cs b/src/Umbraco.Core/Persistence/DefaultDatabaseFactory.cs
index a9e2777514..79bd5931b3 100644
--- a/src/Umbraco.Core/Persistence/DefaultDatabaseFactory.cs
+++ b/src/Umbraco.Core/Persistence/DefaultDatabaseFactory.cs
@@ -44,25 +44,6 @@ namespace Umbraco.Core.Persistence
private IQueryFactory _queryFactory;
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
- public bool Configured { get; private set; }
- public ISqlSyntaxProvider SqlSyntax
- {
- get
- {
- EnsureConfigured();
- return _sqlSyntax;
- }
- }
-
- public IQueryFactory QueryFactory
- {
- get
- {
- EnsureConfigured();
- return _queryFactory ?? (_queryFactory = new QueryFactory(SqlSyntax, _mappers));
- }
- }
-
///
/// Initializes a new instance of the with the default connection, and a logger.
///
@@ -100,8 +81,6 @@ namespace Umbraco.Core.Persistence
_logger = logger;
_umbracoDatabaseAccessor = umbracoDatabaseAccessor;
- _logger.Debug("Created!");
-
var settings = ConfigurationManager.ConnectionStrings[connectionStringName];
if (settings == null)
return; // not configured
@@ -111,7 +90,10 @@ namespace Umbraco.Core.Persistence
var connectionString = settings.ConnectionString;
var providerName = settings.ProviderName;
if (string.IsNullOrWhiteSpace(connectionString) || string.IsNullOrWhiteSpace(providerName))
+ {
+ logger.Debug("Missing connection string or provider name, defer configuration.");
return; // not configured
+ }
Configure(settings.ConnectionString, settings.ProviderName);
}
@@ -138,19 +120,56 @@ namespace Umbraco.Core.Persistence
_logger = logger;
_umbracoDatabaseAccessor = umbracoDatabaseAccessor;
- _logger.Debug("Created!");
-
if (string.IsNullOrWhiteSpace(connectionString) || string.IsNullOrWhiteSpace(providerName))
+ {
+ logger.Debug("Missing connection string or provider name, defer configuration.");
return; // not configured
+ }
Configure(connectionString, providerName);
}
+ ///
+ /// Gets a value indicating whether the database is configured (no connect test).
+ ///
+ ///
+ public bool Configured { get; private set; }
+
+ ///
+ /// Gets a value indicating whether it is possible to connect to the database.
+ ///
+ public bool CanConnect => Configured && DbConnectionExtensions.IsConnectionAvailable(_connectionString, _providerName);
+
+ ///
+ /// Gets the database sql syntax provider.
+ ///
+ public ISqlSyntaxProvider SqlSyntax
+ {
+ get
+ {
+ EnsureConfigured();
+ return _sqlSyntax;
+ }
+ }
+
+ ///
+ /// Gets the database query factory.
+ ///
+ public IQueryFactory QueryFactory
+ {
+ get
+ {
+ EnsureConfigured();
+ return _queryFactory ?? (_queryFactory = new QueryFactory(SqlSyntax, _mappers));
+ }
+ }
+
+ // will be configured by the database context
public void Configure(string connectionString, string providerName)
{
using (new WriteLock(_lock))
{
- _logger.Debug("Configuring!");
+ _logger.Debug("Configuring.");
if (Configured) throw new InvalidOperationException("Already configured.");
@@ -186,9 +205,9 @@ namespace Umbraco.Core.Persistence
.UsingDatabase(CreateDatabaseInstance) // creating UmbracoDatabase instances
.WithFluentConfig(config)); // with proper configuration
- if (_databaseFactory == null) throw new NullReferenceException("The call to DatabaseFactory.Config yielded a null DatabaseFactory instance");
+ if (_databaseFactory == null) throw new NullReferenceException("The call to DatabaseFactory.Config yielded a null DatabaseFactory instance.");
- _logger.Debug("Created _nonHttpInstance");
+ _logger.Debug("Configured.");
Configured = true;
}
}
@@ -209,12 +228,6 @@ namespace Umbraco.Core.Persistence
//provider = _syntaxProviders.FirstOrDefault(x => x.GetType() == typeof(SqlServerSyntaxProvider));
}
- ///
- /// Gets a value indicating whether it is possible to connect to the database.
- ///
- ///
- public bool CanConnect => Configured && DbConnectionExtensions.IsConnectionAvailable(_connectionString, _providerName);
-
private void EnsureConfigured()
{
using (new ReadLock(_lock))
diff --git a/src/Umbraco.Core/Persistence/Mappers/IMapperCollection.cs b/src/Umbraco.Core/Persistence/Mappers/IMapperCollection.cs
index 313c5a5bd3..ba80ae053c 100644
--- a/src/Umbraco.Core/Persistence/Mappers/IMapperCollection.cs
+++ b/src/Umbraco.Core/Persistence/Mappers/IMapperCollection.cs
@@ -1,8 +1,9 @@
using System;
+using Umbraco.Core.DependencyInjection;
namespace Umbraco.Core.Persistence.Mappers
{
- public interface IMapperCollection
+ public interface IMapperCollection : IBuilderCollection
{
BaseMapper this[Type type] { get; }
}
diff --git a/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs b/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs
index 6a22749f15..8f2bab7dcb 100644
--- a/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs
+++ b/src/Umbraco.Core/Persistence/Migrations/Initial/BaseDataCreation.cs
@@ -316,7 +316,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
{
Id = 1,
Name = GlobalSettings.UmbracoMigrationName,
- Version = UmbracoVersion.GetSemanticVersion().ToString(),
+ Version = UmbracoVersion.SemanticVersion.ToString(),
CreateDate = DateTime.Now
};
diff --git a/src/Umbraco.Core/Plugins/PluginManager.cs b/src/Umbraco.Core/Plugins/PluginManager.cs
index 0185991869..9d37874598 100644
--- a/src/Umbraco.Core/Plugins/PluginManager.cs
+++ b/src/Umbraco.Core/Plugins/PluginManager.cs
@@ -93,20 +93,6 @@ namespace Umbraco.Core.Plugins
}
}
- public static PluginManager Current => DependencyInjection.Current.PluginManager;
-
- internal static PluginManager Default
- {
- get
- {
- var appctx = ApplicationContext.Current;
- var cacheProvider = appctx == null // fixme - should Current have an ApplicationCache?
- ? new NullCacheProvider()
- : appctx.ApplicationCache.RuntimeCache;
- return new PluginManager(cacheProvider, DependencyInjection.Current.ProfilingLogger);
- }
- }
-
#region Hash checking methods
///
diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/GridValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/GridValueConverter.cs
index 7b55c9462b..57f268040e 100644
--- a/src/Umbraco.Core/PropertyEditors/ValueConverters/GridValueConverter.cs
+++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/GridValueConverter.cs
@@ -6,6 +6,7 @@ using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.Grid;
+using Umbraco.Core.DependencyInjection;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.PublishedContent;
@@ -50,12 +51,12 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
//TODO: Change all singleton access to use ctor injection in v8!!!
//TODO: That would mean that property value converters would need to be request lifespan, hrm....
var gridConfig = UmbracoConfig.For.GridConfig(
- ApplicationContext.Current.ProfilingLogger.Logger,
- ApplicationContext.Current.ApplicationCache.RuntimeCache,
+ Current.ProfilingLogger.Logger,
+ Current.ApplicationCache.RuntimeCache,
new DirectoryInfo(HttpContext.Current.Server.MapPath(SystemDirectories.AppPlugins)),
new DirectoryInfo(HttpContext.Current.Server.MapPath(SystemDirectories.Config)),
HttpContext.Current.IsDebuggingEnabled);
-
+
var sections = GetArray(obj, "sections");
foreach (var section in sections.Cast())
{
diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/ImageCropperValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/ImageCropperValueConverter.cs
index f1d00f22ab..54f64823fb 100644
--- a/src/Umbraco.Core/PropertyEditors/ValueConverters/ImageCropperValueConverter.cs
+++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/ImageCropperValueConverter.cs
@@ -3,6 +3,7 @@ using System.Globalization;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
+using Umbraco.Core.DependencyInjection;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Services;
@@ -34,7 +35,7 @@ namespace Umbraco.Core.PropertyEditors.ValueConverters
public ImageCropperValueConverter()
{
- _dataTypeService = ApplicationContext.Current.Services.DataTypeService;
+ _dataTypeService = Current.Services.DataTypeService;
}
public ImageCropperValueConverter(IDataTypeService dataTypeService)
diff --git a/src/Umbraco.Core/RuntimeLevel.cs b/src/Umbraco.Core/RuntimeLevel.cs
new file mode 100644
index 0000000000..456c0e3296
--- /dev/null
+++ b/src/Umbraco.Core/RuntimeLevel.cs
@@ -0,0 +1,37 @@
+namespace Umbraco.Core
+{
+ public enum RuntimeLevel
+ {
+ ///
+ /// The runtime has failed to boot and cannot run.
+ ///
+ Failed = -1,
+
+ ///
+ /// The level is unknown.
+ ///
+ Unknown = 0,
+
+ ///
+ /// The runtime is booting.
+ ///
+ Boot = 1,
+
+ ///
+ /// The runtime has detected that Umbraco is not installed at all, ie there is
+ /// no database, and is currently installing Umbraco.
+ ///
+ Install = 2,
+
+ ///
+ /// The runtime has detected an Umbraco install which needed to be upgraded, and
+ /// is currently upgrading Umbraco.
+ ///
+ Upgrade = 3,
+
+ ///
+ /// The runtime has detected an up-to-date Umbraco install and is running.
+ ///
+ Run = 4
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/RuntimeState.cs b/src/Umbraco.Core/RuntimeState.cs
new file mode 100644
index 0000000000..7c3f9b3d6a
--- /dev/null
+++ b/src/Umbraco.Core/RuntimeState.cs
@@ -0,0 +1,117 @@
+using System;
+using System.Threading;
+using System.Web;
+using Semver;
+using Umbraco.Core.Configuration;
+using Umbraco.Core.Configuration.UmbracoSettings;
+using Umbraco.Core.Logging;
+using Umbraco.Core.Sync;
+
+namespace Umbraco.Core
+{
+ ///
+ /// Represents the state of the Umbraco runtime.
+ ///
+ internal class RuntimeState : IRuntimeState
+ {
+ private readonly ILogger _logger;
+ private readonly Lazy _serverRegistrar;
+ private readonly Lazy _mainDom;
+ private RuntimeLevel _level;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// A logger.
+ /// A (lazy) server registrar.
+ /// A (lazy) MainDom.
+ public RuntimeState(ILogger logger, Lazy serverRegistrar, Lazy mainDom)
+ {
+ _logger = logger;
+ _serverRegistrar = serverRegistrar;
+ _mainDom = mainDom;
+ }
+
+ private IServerRegistrar ServerRegistrar => _serverRegistrar.Value;
+
+ ///
+ /// Gets the application MainDom.
+ ///
+ /// This is NOT exposed in the interface as MainDom is internal.
+ public MainDom MainDom => _mainDom.Value;
+
+ ///
+ /// Gets the version of the executing code.
+ ///
+ public Version Version => UmbracoVersion.Current;
+
+ ///
+ /// Gets the version comment of the executing code.
+ ///
+ public string VersionComment => UmbracoVersion.CurrentComment;
+
+ ///
+ /// Gets the semantic version of the executing code.
+ ///
+ public SemVersion SemanticVersion => UmbracoVersion.SemanticVersion;
+
+ ///
+ /// Gets a value indicating whether the application is running in debug mode.
+ ///
+ public bool Debug { get; } = GlobalSettings.DebugMode;
+
+ ///
+ /// Gets a value indicating whether the runtime is the current main domain.
+ ///
+ public bool IsMainDom => MainDom.IsMainDom;
+
+ ///
+ /// Get the server's current role.
+ ///
+ public ServerRole ServerRole => ServerRegistrar.GetCurrentServerRole();
+
+ ///
+ /// Gets the Umbraco application url.
+ ///
+ /// This is eg "http://www.example.com".
+ public Uri ApplicationUrl { get; private set; }
+
+ ///
+ /// Gets the Umbraco application virtual path.
+ ///
+ /// This is either "/" or eg "/virtual".
+ public string ApplicationVirtualPath { get; } = HttpRuntime.AppDomainAppVirtualPath;
+
+ ///
+ /// Gets the runtime level of execution.
+ ///
+ public RuntimeLevel Level
+ {
+ get { return _level; }
+ internal set { _level = value; if (value == RuntimeLevel.Run) _runLevel.Set(); }
+ }
+
+ ///
+ /// Ensures that the property has a value.
+ ///
+ ///
+ ///
+ internal void EnsureApplicationUrl(HttpRequestBase request = null, IUmbracoSettingsSection settings = null)
+ {
+ if (ApplicationUrl != null) return;
+ ApplicationUrl = new Uri(ApplicationUrlHelper.GetApplicationUrl(_logger, request, settings));
+ }
+
+ private readonly ManualResetEventSlim _runLevel = new ManualResetEventSlim(false);
+
+ ///
+ /// Waits for the runtime level to become RuntimeLevel.Run.
+ ///
+ /// A timeout.
+ /// True if the runtime level became RuntimeLevel.Run before the timeout, otherwise false.
+ internal bool WaitForRunLevel(TimeSpan timeout)
+ {
+ return _runLevel.WaitHandle.WaitOne(timeout);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Services/PackagingService.cs b/src/Umbraco.Core/Services/PackagingService.cs
index 02eb0e97e3..9eacaa792f 100644
--- a/src/Umbraco.Core/Services/PackagingService.cs
+++ b/src/Umbraco.Core/Services/PackagingService.cs
@@ -9,6 +9,7 @@ using System.Xml.Linq;
using System.Xml.XPath;
using Newtonsoft.Json;
using Umbraco.Core.Configuration;
+using Umbraco.Core.DependencyInjection;
using Umbraco.Core.Events;
using Umbraco.Core.IO;
using Umbraco.Core.Logging;
@@ -261,7 +262,7 @@ namespace Umbraco.Core.Services
{
//TODO: We need to refactor this so the packager isn't making direct db calls for an 'edge' case
- var database = ApplicationContext.Current.DatabaseContext.Database;
+ var database = Current.DatabaseContext.Database;
var dtos = database.Fetch("WHERE datatypeNodeId = @Id", new { Id = propertyType.DataTypeDefinitionId });
var propertyValueList = new List();
diff --git a/src/Umbraco.Core/Strategies/ManifestWatcherHandler.cs b/src/Umbraco.Core/Strategies/ManifestWatcherHandler.cs
index ad28f2e0bf..efa9138306 100644
--- a/src/Umbraco.Core/Strategies/ManifestWatcherHandler.cs
+++ b/src/Umbraco.Core/Strategies/ManifestWatcherHandler.cs
@@ -1,5 +1,6 @@
using System;
using System.IO;
+using Umbraco.Core.DependencyInjection;
using Umbraco.Core.IO;
using Umbraco.Core.Manifest;
@@ -9,7 +10,7 @@ namespace Umbraco.Core.Strategies
{
private ManifestWatcher _mw;
- protected override void ApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
+ protected override void ApplicationInitialized(UmbracoApplicationBase umbracoApplication)
{
UmbracoApplicationBase.ApplicationEnd += app_ApplicationEnd;
}
@@ -22,9 +23,9 @@ namespace Umbraco.Core.Strategies
}
}
- protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
+ protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication)
{
- _mw = new ManifestWatcher(applicationContext.ProfilingLogger.Logger);
+ _mw = new ManifestWatcher(Current.ProfilingLogger.Logger);
_mw.Start(Directory.GetDirectories(IOHelper.MapPath("~/App_Plugins/")));
}
}
diff --git a/src/Umbraco.Core/Strategies/RelateOnCopyHandler.cs b/src/Umbraco.Core/Strategies/RelateOnCopyHandler.cs
index 7a172ae1a8..b7db0fdf47 100644
--- a/src/Umbraco.Core/Strategies/RelateOnCopyHandler.cs
+++ b/src/Umbraco.Core/Strategies/RelateOnCopyHandler.cs
@@ -1,13 +1,14 @@
using System;
+using Umbraco.Core.DependencyInjection;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
namespace Umbraco.Core.Strategies
{
- //TODO: This should just exist in the content service/repo!
+ //TODO: This should just exist in the content service/repo!
public sealed class RelateOnCopyHandler : ApplicationEventHandler
{
- protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
+ protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication)
{
ContentService.Copied += ContentServiceCopied;
}
@@ -16,7 +17,7 @@ namespace Umbraco.Core.Strategies
{
if (e.RelateToOriginal)
{
- var relationService = ApplicationContext.Current.Services.RelationService;
+ var relationService = Current.Services.RelationService;
var relationType = relationService.GetRelationTypeByAlias(Constants.Conventions.RelationTypes.RelateDocumentOnCopyAlias);
@@ -33,7 +34,7 @@ namespace Umbraco.Core.Strategies
var relation = new Relation(e.Original.Id, e.Copy.Id, relationType);
relationService.Save(relation);
- ApplicationContext.Current.Services.AuditService.Add(
+ Current.Services.AuditService.Add(
AuditType.Copy,
string.Format("Copied content with Id: '{0}' related to original content with Id: '{1}'",
e.Copy.Id, e.Original.Id), e.Copy.WriterId, e.Copy.Id);
diff --git a/src/Umbraco.Core/Strategies/RelateOnTrashHandler.cs b/src/Umbraco.Core/Strategies/RelateOnTrashHandler.cs
index 7628332738..f2cfc3ac3b 100644
--- a/src/Umbraco.Core/Strategies/RelateOnTrashHandler.cs
+++ b/src/Umbraco.Core/Strategies/RelateOnTrashHandler.cs
@@ -1,5 +1,6 @@
using System;
using System.Linq;
+using Umbraco.Core.DependencyInjection;
using Umbraco.Core.Events;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
@@ -8,7 +9,7 @@ namespace Umbraco.Core.Strategies
{
public sealed class RelateOnTrashHandler : ApplicationEventHandler
{
- protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
+ protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication)
{
ContentService.Moved += ContentService_Moved;
ContentService.Trashed += ContentService_Trashed;
@@ -18,7 +19,7 @@ namespace Umbraco.Core.Strategies
{
foreach (var item in e.MoveInfoCollection.Where(x => x.OriginalPath.Contains(Constants.System.RecycleBinContent.ToInvariantString())))
{
- var relationService = ApplicationContext.Current.Services.RelationService;
+ var relationService = Current.Services.RelationService;
var relationTypeAlias = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteAlias;
var relations = relationService.GetByChildId(item.Entity.Id);
@@ -31,7 +32,7 @@ namespace Umbraco.Core.Strategies
private void ContentService_Trashed(IContentService sender, MoveEventArgs e)
{
- var relationService = ApplicationContext.Current.Services.RelationService;
+ var relationService = Current.Services.RelationService;
var relationTypeAlias = Constants.Conventions.RelationTypes.RelateParentDocumentOnDeleteAlias;
var relationType = relationService.GetRelationTypeByAlias(relationTypeAlias);
@@ -56,7 +57,7 @@ namespace Umbraco.Core.Strategies
var relation = new Relation(originalParentId, item.Entity.Id, relationType);
relationService.Save(relation);
- ApplicationContext.Current.Services.AuditService.Add(AuditType.Delete,
+ Current.Services.AuditService.Add(AuditType.Delete,
string.Format("Trashed content with Id: '{0}' related to original parent content with Id: '{1}'", item.Entity.Id, originalParentId),
item.Entity.WriterId,
item.Entity.Id);
diff --git a/src/Umbraco.Core/Sync/ApplicationUrlHelper.cs b/src/Umbraco.Core/Sync/ApplicationUrlHelper.cs
index 556c0e73a3..a321aa583e 100644
--- a/src/Umbraco.Core/Sync/ApplicationUrlHelper.cs
+++ b/src/Umbraco.Core/Sync/ApplicationUrlHelper.cs
@@ -4,6 +4,7 @@ using Umbraco.Core.Configuration;
using Umbraco.Core.Configuration.UmbracoSettings;
using Umbraco.Core.DependencyInjection;
using Umbraco.Core.IO;
+using Umbraco.Core.Logging;
namespace Umbraco.Core.Sync
{
@@ -15,8 +16,6 @@ namespace Umbraco.Core.Sync
// because we cannot logger.Info because type is static
private static readonly Type TypeOfApplicationUrlHelper = typeof(ApplicationUrlHelper);
- private static Func _applicationUrlProvider;
-
///
/// Gets or sets a custom provider for the umbraco application url.
///
@@ -27,54 +26,32 @@ namespace Umbraco.Core.Sync
/// in config files but is determined programmatically.
/// Must be assigned before resolution is frozen.
///
- public static Func ApplicationUrlProvider // FIXME need another way to do it, eg an interface, injected!
+ // FIXME need another way to do it, eg an interface, injected!
+ public static Func ApplicationUrlProvider { get; set; }
+
+ internal static string GetApplicationUrl(ILogger logger, HttpRequestBase request = null, IUmbracoSettingsSection settings = null)
{
- get
+ var umbracoApplicationUrl = TryGetApplicationUrl(settings ?? UmbracoConfig.For.UmbracoSettings(), logger);
+ if (umbracoApplicationUrl != null)
+ return umbracoApplicationUrl;
+
+ umbracoApplicationUrl = ApplicationUrlProvider?.Invoke(request);
+ if (string.IsNullOrWhiteSpace(umbracoApplicationUrl) == false)
{
- return _applicationUrlProvider;
- }
- set
- {
- _applicationUrlProvider = value;
- }
- }
-
- // request: will be null if called from ApplicationContext
- // settings: for unit tests only
- internal static void EnsureApplicationUrl(ApplicationContext appContext, HttpRequestBase request = null, IUmbracoSettingsSection settings = null)
- {
- // if initialized, return
- if (appContext._umbracoApplicationUrl != null) return;
-
- var logger = appContext.ProfilingLogger.Logger;
-
- // try settings and IServerRegistrar
- if (TrySetApplicationUrl(appContext, settings ?? UmbracoConfig.For.UmbracoSettings()))
- return;
-
- // try custom provider
- if (_applicationUrlProvider != null)
- {
- var url = _applicationUrlProvider(request);
- if (url.IsNullOrWhiteSpace() == false)
- {
- appContext._umbracoApplicationUrl = url.TrimEnd('/');
- logger.Info(TypeOfApplicationUrlHelper, "ApplicationUrl: " + appContext.UmbracoApplicationUrl + " (provider)");
- return;
- }
+ umbracoApplicationUrl = umbracoApplicationUrl.TrimEnd('/');
+ logger.Info(TypeOfApplicationUrlHelper, "ApplicationUrl: " + umbracoApplicationUrl + " (provider)");
+ return umbracoApplicationUrl;
}
- // last chance,
- // use the current request as application url
- if (request == null) return;
- SetApplicationUrlFromCurrentRequest(appContext, request);
+ if (request == null) return null;
+
+ umbracoApplicationUrl = GetApplicationUrlFromCurrentRequest(request);
+ logger.Info(TypeOfApplicationUrlHelper, "ApplicationUrl: " + umbracoApplicationUrl + " (UmbracoModule request)");
+ return umbracoApplicationUrl;
}
- // internal for tests
- internal static bool TrySetApplicationUrl(ApplicationContext appContext, IUmbracoSettingsSection settings)
+ internal static string TryGetApplicationUrl(IUmbracoSettingsSection settings, ILogger logger)
{
- var logger = appContext.ProfilingLogger.Logger;
-
// try umbracoSettings:settings/web.routing/@umbracoApplicationUrl
// which is assumed to:
// - end with SystemDirectories.Umbraco
@@ -84,9 +61,9 @@ namespace Umbraco.Core.Sync
var url = settings.WebRouting.UmbracoApplicationUrl;
if (url.IsNullOrWhiteSpace() == false)
{
- appContext._umbracoApplicationUrl = url.TrimEnd('/');
- logger.Info(TypeOfApplicationUrlHelper, "ApplicationUrl: " + appContext.UmbracoApplicationUrl + " (using web.routing/@umbracoApplicationUrl)");
- return true;
+ var umbracoApplicationUrl = url.TrimEnd('/');
+ logger.Info(TypeOfApplicationUrlHelper, "ApplicationUrl: " + umbracoApplicationUrl + " (using web.routing/@umbracoApplicationUrl)");
+ return umbracoApplicationUrl;
}
// try umbracoSettings:settings/scheduledTasks/@baseUrl
@@ -100,9 +77,9 @@ namespace Umbraco.Core.Sync
{
var ssl = GlobalSettings.UseSSL ? "s" : "";
url = "http" + ssl + "://" + url;
- appContext._umbracoApplicationUrl = url.TrimEnd('/');
- logger.Info(TypeOfApplicationUrlHelper, "ApplicationUrl: " + appContext.UmbracoApplicationUrl + " (using scheduledTasks/@baseUrl)");
- return true;
+ var umbracoApplicationUrl = url.TrimEnd('/');
+ logger.Info(TypeOfApplicationUrlHelper, "ApplicationUrl: " + umbracoApplicationUrl + " (using scheduledTasks/@baseUrl)");
+ return umbracoApplicationUrl;
}
// try the server registrar
@@ -114,19 +91,17 @@ namespace Umbraco.Core.Sync
url = Current.ServerRegistrar.GetCurrentServerUmbracoApplicationUrl();
if (url.IsNullOrWhiteSpace() == false)
{
- appContext._umbracoApplicationUrl = url.TrimEnd('/');
- logger.Info(TypeOfApplicationUrlHelper, "ApplicationUrl: " + appContext.UmbracoApplicationUrl + " (IServerRegistrar)");
- return true;
+ var umbracoApplicationUrl = url.TrimEnd('/');
+ logger.Info(TypeOfApplicationUrlHelper, "ApplicationUrl: " + umbracoApplicationUrl + " (IServerRegistrar)");
+ return umbracoApplicationUrl;
}
// else give up...
- return false;
+ return null;
}
- private static void SetApplicationUrlFromCurrentRequest(ApplicationContext appContext, HttpRequestBase request)
+ private static string GetApplicationUrlFromCurrentRequest(HttpRequestBase request)
{
- var logger = appContext.ProfilingLogger.Logger;
-
// if (HTTP and SSL not required) or (HTTPS and SSL required),
// use ports from request
// otherwise,
@@ -141,8 +116,7 @@ namespace Umbraco.Core.Sync
var ssl = GlobalSettings.UseSSL ? "s" : ""; // force, whatever the first request
var url = "http" + ssl + "://" + request.ServerVariables["SERVER_NAME"] + port + IOHelper.ResolveUrl(SystemDirectories.Umbraco);
- appContext._umbracoApplicationUrl = url.TrimEnd('/');
- logger.Info(TypeOfApplicationUrlHelper, "ApplicationUrl: " + appContext.UmbracoApplicationUrl + " (UmbracoModule request)");
+ return url.TrimEnd('/');
}
}
}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Sync/DatabaseServerMessenger.cs b/src/Umbraco.Core/Sync/DatabaseServerMessenger.cs
index 46c5aa3681..48658d6d0b 100644
--- a/src/Umbraco.Core/Sync/DatabaseServerMessenger.cs
+++ b/src/Umbraco.Core/Sync/DatabaseServerMessenger.cs
@@ -6,6 +6,7 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Web;
+using LightInject;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NPoco;
@@ -15,7 +16,6 @@ using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.Rdbms;
using Umbraco.Core.Persistence;
-using Umbraco.Core.Persistence.SqlSyntax;
namespace Umbraco.Core.Sync
{
@@ -29,35 +29,45 @@ namespace Umbraco.Core.Sync
//
public class DatabaseServerMessenger : ServerMessengerBase
{
- private readonly ApplicationContext _appContext;
+ private readonly IRuntimeState _runtime;
private readonly DatabaseServerMessengerOptions _options;
private readonly ManualResetEvent _syncIdle;
private readonly object _locko = new object();
- private readonly ILogger _logger;
+ private readonly ProfilingLogger _profilingLogger;
private int _lastId = -1;
private DateTime _lastSync;
private DateTime _lastPruned;
private bool _initialized;
private bool _syncing;
private bool _released;
- private readonly ProfilingLogger _profilingLogger;
- protected ApplicationContext ApplicationContext { get { return _appContext; } }
-
- public DatabaseServerMessenger(ApplicationContext appContext, bool distributedEnabled, DatabaseServerMessengerOptions options)
+ public DatabaseServerMessenger(
+ IRuntimeState runtime, DatabaseContext dbContext, ILogger logger, ProfilingLogger proflog,
+ bool distributedEnabled, DatabaseServerMessengerOptions options)
: base(distributedEnabled)
{
- if (appContext == null) throw new ArgumentNullException("appContext");
- if (options == null) throw new ArgumentNullException("options");
+ if (dbContext == null) throw new ArgumentNullException(nameof(dbContext));
+ if (logger == null) throw new ArgumentNullException(nameof(logger));
+ if (proflog == null) throw new ArgumentNullException(nameof(proflog));
+ if (options == null) throw new ArgumentNullException(nameof(options));
- _appContext = appContext;
+ DatabaseContext = dbContext;
+ Logger = logger;
+ _runtime = runtime;
+ _profilingLogger = proflog;
_options = options;
_lastPruned = _lastSync = DateTime.UtcNow;
_syncIdle = new ManualResetEvent(true);
- _profilingLogger = appContext.ProfilingLogger;
- _logger = appContext.ProfilingLogger.Logger;
}
+ protected ILogger Logger { get; }
+
+ protected DatabaseContext DatabaseContext { get; }
+
+ protected UmbracoDatabase Database => DatabaseContext.Database;
+
+ protected Sql Sql() => DatabaseContext.Sql();
+
#region Messenger
protected override bool RequiresDistributed(IEnumerable servers, ICacheRefresher refresher, MessageType dispatchType)
@@ -74,11 +84,11 @@ namespace Umbraco.Core.Sync
IEnumerable