Resvolution - Components, Runtime & Booting
This commit is contained in:
@@ -3,12 +3,9 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Web.Http;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence;
|
||||
using Umbraco.Web.Install.Models;
|
||||
using Umbraco.Web.WebApi;
|
||||
|
||||
@@ -18,48 +15,40 @@ namespace Umbraco.Web.Install.Controllers
|
||||
[HttpInstallAuthorize]
|
||||
public class InstallApiController : ApiController
|
||||
{
|
||||
public InstallApiController()
|
||||
: this(UmbracoContext.Current)
|
||||
{
|
||||
private readonly DatabaseContext _databaseContext;
|
||||
private readonly ProfilingLogger _proflog;
|
||||
private readonly ILogger _logger;
|
||||
private InstallHelper _helper;
|
||||
|
||||
}
|
||||
|
||||
public InstallApiController(UmbracoContext umbracoContext)
|
||||
public InstallApiController(UmbracoContext umbracoContext, DatabaseContext databaseContext, ILogger logger, ProfilingLogger proflog)
|
||||
{
|
||||
if (umbracoContext == null) throw new ArgumentNullException("umbracoContext");
|
||||
if (umbracoContext == null) throw new ArgumentNullException(nameof(umbracoContext));
|
||||
if (databaseContext == null) throw new ArgumentNullException(nameof(databaseContext));
|
||||
if (proflog == null) throw new ArgumentNullException(nameof(proflog));
|
||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
||||
UmbracoContext = umbracoContext;
|
||||
_databaseContext = databaseContext;
|
||||
_logger = logger;
|
||||
_proflog = proflog;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current UmbracoContext
|
||||
/// Gets the Umbraco context.
|
||||
/// </summary>
|
||||
public UmbracoContext UmbracoContext { get; private set; }
|
||||
public UmbracoContext UmbracoContext { get; }
|
||||
|
||||
public ApplicationContext ApplicationContext
|
||||
{
|
||||
get { return UmbracoContext.Application; }
|
||||
}
|
||||
|
||||
private InstallHelper _helper;
|
||||
internal InstallHelper InstallHelper
|
||||
{
|
||||
get
|
||||
{
|
||||
return _helper ?? (_helper = new InstallHelper(UmbracoContext));
|
||||
}
|
||||
}
|
||||
internal InstallHelper InstallHelper => _helper ?? (_helper = new InstallHelper(UmbracoContext, _databaseContext, _logger));
|
||||
|
||||
public bool PostValidateDatabaseConnection(DatabaseModel model)
|
||||
{
|
||||
var dbHelper = new DatabaseHelper();
|
||||
var canConnect = dbHelper.CheckConnection(ApplicationContext.DatabaseContext, model);
|
||||
var canConnect = dbHelper.CheckConnection(model);
|
||||
return canConnect;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the install setup
|
||||
/// Gets the install setup.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public InstallSetup GetSetup()
|
||||
{
|
||||
var setup = new InstallSetup();
|
||||
@@ -78,21 +67,20 @@ namespace Umbraco.Web.Install.Controllers
|
||||
|
||||
return setup;
|
||||
}
|
||||
|
||||
|
||||
public IEnumerable<Package> GetPackages()
|
||||
{
|
||||
var installHelper = new InstallHelper(UmbracoContext);
|
||||
var installHelper = new InstallHelper(UmbracoContext, _databaseContext, _logger);
|
||||
var starterKits = installHelper.GetStarterKits();
|
||||
return starterKits;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Does the install
|
||||
/// Installs.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public InstallProgressResultModel PostPerformInstall(InstallInstructions installModel)
|
||||
{
|
||||
if (installModel == null) throw new ArgumentNullException("installModel");
|
||||
if (installModel == null) throw new ArgumentNullException(nameof(installModel));
|
||||
|
||||
var status = InstallStatusTracker.GetStatus().ToArray();
|
||||
//there won't be any statuses returned if the app pool has restarted so we need to re-read from file.
|
||||
@@ -105,22 +93,18 @@ namespace Umbraco.Web.Install.Controllers
|
||||
var queue = new Queue<InstallTrackingItem>(status.Where(x => x.IsComplete == false));
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
var stepStatus = queue.Dequeue();
|
||||
|
||||
var step = InstallHelper.GetAllSteps().Single(x => x.Name == stepStatus.Name);
|
||||
var item = queue.Dequeue();
|
||||
var step = InstallHelper.GetAllSteps().Single(x => x.Name == item.Name);
|
||||
|
||||
JToken instruction = null;
|
||||
//If this step has any instructions then extract them
|
||||
if (installModel.Instructions.Any(x => x.Key == step.Name))
|
||||
{
|
||||
instruction = installModel.Instructions[step.Name];
|
||||
}
|
||||
|
||||
//If this step doesn't require execution then continue to the next one, this is just a fail-safe check.
|
||||
// if this step has any instructions then extract them
|
||||
JToken instruction;
|
||||
installModel.Instructions.TryGetValue(item.Name, out instruction); // else null
|
||||
|
||||
// if this step doesn't require execution then continue to the next one, this is just a fail-safe check.
|
||||
if (StepRequiresExecution(step, instruction) == false)
|
||||
{
|
||||
//set this as complete and continue
|
||||
InstallStatusTracker.SetComplete(installModel.InstallId, stepStatus.Name, null);
|
||||
// set this as complete and continue
|
||||
InstallStatusTracker.SetComplete(installModel.InstallId, item.Name);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -128,13 +112,13 @@ namespace Umbraco.Web.Install.Controllers
|
||||
{
|
||||
var setupData = ExecuteStep(step, instruction);
|
||||
|
||||
//update the status
|
||||
InstallStatusTracker.SetComplete(installModel.InstallId, step.Name, setupData != null ? setupData.SavedStepData : null);
|
||||
// update the status
|
||||
InstallStatusTracker.SetComplete(installModel.InstallId, step.Name, setupData?.SavedStepData);
|
||||
|
||||
//Determine's the next step in the queue and dequeue's any items that don't need to execute
|
||||
var nextStep = IterateNextRequiredStep(step, queue, installModel.InstallId, installModel);
|
||||
|
||||
//check if there's a custom view to return for this step
|
||||
// determine's the next step in the queue and dequeue's any items that don't need to execute
|
||||
var nextStep = IterateSteps(step, queue, installModel.InstallId, installModel);
|
||||
|
||||
// check if there's a custom view to return for this step
|
||||
if (setupData != null && setupData.View.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
return new InstallProgressResultModel(false, step.Name, nextStep, setupData.View, setupData.ViewModel);
|
||||
@@ -185,65 +169,53 @@ namespace Umbraco.Web.Install.Controllers
|
||||
/// <param name="installId"></param>
|
||||
/// <param name="installModel"></param>
|
||||
/// <returns></returns>
|
||||
private string IterateNextRequiredStep(InstallSetupStep current, Queue<InstallTrackingItem> queue, Guid installId, InstallInstructions installModel)
|
||||
private string IterateSteps(InstallSetupStep current, Queue<InstallTrackingItem> queue, Guid installId, InstallInstructions installModel)
|
||||
{
|
||||
if (queue.Count > 0)
|
||||
while (queue.Count > 0)
|
||||
{
|
||||
var next = queue.Peek();
|
||||
var step = InstallHelper.GetAllSteps().Single(x => x.Name == next.Name);
|
||||
var item = queue.Peek();
|
||||
|
||||
//If the current step restarts the app pool then we must simply return the next one in the queue,
|
||||
// we cannot peek ahead as the next step might rely on the app restart and therefore RequiresExecution
|
||||
// will rely on that too.
|
||||
// if the current step restarts the app pool then we must simply return the next one in the queue,
|
||||
// we cannot peek ahead as the next step might rely on the app restart and therefore RequiresExecution
|
||||
// will rely on that too.
|
||||
if (current.PerformsAppRestart)
|
||||
{
|
||||
return step.Name;
|
||||
}
|
||||
return item.Name;
|
||||
|
||||
JToken instruction = null;
|
||||
//If this step has any instructions then extract them
|
||||
if (installModel.Instructions.Any(x => x.Key == step.Name))
|
||||
{
|
||||
instruction = installModel.Instructions[step.Name];
|
||||
}
|
||||
var step = InstallHelper.GetAllSteps().Single(x => x.Name == item.Name);
|
||||
|
||||
//if the step requires execution then return it's name
|
||||
// if this step has any instructions then extract them
|
||||
JToken instruction;
|
||||
installModel.Instructions.TryGetValue(item.Name, out instruction); // else null
|
||||
|
||||
// if the step requires execution then return its name
|
||||
if (StepRequiresExecution(step, instruction))
|
||||
{
|
||||
return step.Name;
|
||||
}
|
||||
|
||||
//this step no longer requires execution, this could be due to a new config change during installation,
|
||||
// so we'll dequeue this one from the queue and recurse
|
||||
// no longer requires execution, could be due to a new config change during installation
|
||||
// dequeue
|
||||
queue.Dequeue();
|
||||
|
||||
//set this as complete
|
||||
InstallStatusTracker.SetComplete(installId, step.Name, null);
|
||||
// complete
|
||||
InstallStatusTracker.SetComplete(installId, step.Name);
|
||||
|
||||
//recurse
|
||||
return IterateNextRequiredStep(step, queue, installId, installModel);
|
||||
// and continue
|
||||
current = step;
|
||||
}
|
||||
|
||||
//there is no more steps
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the step requires execution
|
||||
/// </summary>
|
||||
/// <param name="step"></param>
|
||||
/// <param name="instruction"></param>
|
||||
/// <returns></returns>
|
||||
// determines whether the step requires execution
|
||||
internal bool StepRequiresExecution(InstallSetupStep step, JToken instruction)
|
||||
{
|
||||
var model = instruction == null ? null : instruction.ToObject(step.StepType);
|
||||
var model = instruction?.ToObject(step.StepType);
|
||||
var genericStepType = typeof(InstallSetupStep<>);
|
||||
Type[] typeArgs = { step.StepType };
|
||||
var typedStepType = genericStepType.MakeGenericType(typeArgs);
|
||||
try
|
||||
{
|
||||
var method = typedStepType.GetMethods().Single(x => x.Name == "RequiresExecution");
|
||||
return (bool)method.Invoke(step, new object[] { model });
|
||||
return (bool) method.Invoke(step, new[] { model });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -252,18 +224,19 @@ namespace Umbraco.Web.Install.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
// executes the step
|
||||
internal InstallSetupResult ExecuteStep(InstallSetupStep step, JToken instruction)
|
||||
{
|
||||
using (ApplicationContext.ProfilingLogger.TraceDuration<InstallApiController>("Executing installation step: " + step.Name, "Step completed"))
|
||||
using (_proflog.TraceDuration<InstallApiController>("Executing installation step: " + step.Name, "Step completed"))
|
||||
{
|
||||
var model = instruction == null ? null : instruction.ToObject(step.StepType);
|
||||
var model = instruction?.ToObject(step.StepType);
|
||||
var genericStepType = typeof(InstallSetupStep<>);
|
||||
Type[] typeArgs = { step.StepType };
|
||||
var typedStepType = genericStepType.MakeGenericType(typeArgs);
|
||||
try
|
||||
{
|
||||
var method = typedStepType.GetMethods().Single(x => x.Name == "Execute");
|
||||
return (InstallSetupResult)method.Invoke(step, new object[] { model });
|
||||
return (InstallSetupResult) method.Invoke(step, new[] { model });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user