using System; using System.Collections.Generic; using System.Threading; using System.Web; using Semver; using Umbraco.Core.Configuration; using Umbraco.Core.Configuration.UmbracoSettings; using Umbraco.Core.Exceptions; 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 IUmbracoSettingsSection _settings; private readonly IGlobalSettings _globalSettings; private readonly HashSet _applicationUrls = new HashSet(); private readonly Lazy _mainDom; private readonly Lazy _serverRegistrar; private RuntimeLevel _level; /// /// Initializes a new instance of the class. /// public RuntimeState(ILogger logger, IUmbracoSettingsSection settings, IGlobalSettings globalSettings, Lazy mainDom, Lazy serverRegistrar) { _logger = logger; _settings = settings; _globalSettings = globalSettings; _mainDom = mainDom; _serverRegistrar = serverRegistrar; } /// /// Gets the server registrar. /// /// /// This is NOT exposed in the interface. /// 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; /// public Version Version => UmbracoVersion.Current; /// public string VersionComment => UmbracoVersion.Comment; /// public SemVersion SemanticVersion => UmbracoVersion.SemanticVersion; /// public bool Debug { get; } = GlobalSettings.DebugMode; /// public bool IsMainDom => MainDom.IsMainDom; /// public ServerRole ServerRole => ServerRegistrar.GetCurrentServerRole(); /// public Uri ApplicationUrl { get; private set; } /// public string ApplicationVirtualPath { get; } = HttpRuntime.AppDomainAppVirtualPath; /// public string CurrentMigrationState { get; internal set; } /// public string FinalMigrationState { get; internal set; } /// public RuntimeLevel Level { get => _level; internal set { _level = value; if (value == RuntimeLevel.Run) _runLevel.Set(); } } /// /// Ensures that the property has a value. /// /// internal void EnsureApplicationUrl(HttpRequestBase request = null) { // see U4-10626 - in some cases we want to reset the application url // (this is a simplified version of what was in 7.x) // note: should this be optional? is it expensive? var url = request == null ? null : ApplicationUrlHelper.GetApplicationUrlFromCurrentRequest(request, _globalSettings); var change = url != null && !_applicationUrls.Contains(url); if (change) { _logger.Info(typeof(ApplicationUrlHelper), "New url {Url} detected, re-discovering application url.", url); _applicationUrls.Add(url); } if (ApplicationUrl != null && !change) return; ApplicationUrl = new Uri(ApplicationUrlHelper.GetApplicationUrl(_logger, _globalSettings, _settings, ServerRegistrar, request)); } 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); } /// public BootFailedException BootFailedException { get; internal set; } } }