using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Windows.Forms;
using JD.Kernel.Classes;
using JD.Kernel.StaticHelpers;
using JD.LogService;
using JD.TeaBoxAddinSystem.Addins;
using JD.TeaBoxAddinSystem.Addins.MEF;
using JD.TeaBoxAddinSystem.Addins.MEF.Integration;
using JD.Threading;
using Message = JD.LogService.Message;
namespace JD.TeaBoxAddinSystem.Bootstrap
{
///
/// Base class for objects used to bootstrap applications.
///
public class ApplicationStartup
{
#region Variables
internal const string CoreBootstrapPath = "Bootstrap/All";
private readonly Arguments m_arguments;
private readonly string m_applicationName;
private readonly RuntimeMode m_runtimeMode = RuntimeMode.Normal;
private readonly ApplicationConfiguration m_configuration;
private readonly LoggingContext m_bootstrapLoggingContext = new LoggingContext();
private static ApplicationStartup m_instance;
private IDisposable m_splashScreenHandle;
// Metrics
private StartupStatistic m_startupStatistic;
#endregion
#region Constructor
///
/// Constructor.
///
/// Application Arguments.
/// Application name.
/// Runtime mode.
public ApplicationStartup(string[] arguments, string applicationName, RuntimeMode runtimeMode)
{
if (string.IsNullOrEmpty(applicationName))
{
applicationName = (Runtime.EntryAssembly != null ? Runtime.EntryAssembly.FullName : Runtime.ApplicationName);
}
m_arguments = new Arguments(arguments);
m_applicationName = applicationName;
m_configuration = new ApplicationConfiguration(ApplicationName);
m_runtimeMode = runtimeMode;
}
#endregion
#region Properties
///
/// Unique instance of the started application startup. Not for external use. Back off.
///
///
/// Consider using instead.
///
public static ApplicationStartup Instance
{
get
{
return m_instance;
}
}
///
/// Arguments.
///
public Arguments Arguments
{
get
{
return m_arguments;
}
}
///
/// Application Name.
///
public string ApplicationName
{
get
{
return m_applicationName;
}
}
///
/// Whether the application was started in embedded mode.
///
public RuntimeMode RuntimeMode
{
get
{
return m_runtimeMode;
}
}
internal ApplicationConfiguration Configuration
{
get
{
return m_configuration;
}
}
///
/// Returns true if this application startup forces the application in command-line mode.
///
protected virtual bool ForceCommandLineMode
{
get
{
return false;
}
}
///
/// Addin Logging Context.
///
public LoggingContext BootstrapLoggingContext
{
get { return m_bootstrapLoggingContext; }
}
#endregion
#region Methods
#region Main Methods
///
/// Starts the application (must be in embedded mode).
///
/// Dispose the result to quit the application.
public IDisposable StartEmbedded()
{
Throw.Assert(RuntimeMode == RuntimeMode.EmbeddedInProcess || RuntimeMode == RuntimeMode.SystemTests);
Start();
return new DisposableHelper(Quit);
}
///
/// Starts the application.
///
/// Exit code for the application.
public int Start()
{
if (Runtime.Initialized)
{
throw new InvalidOperationException("Cannot start an ApplicationStartup twice in a same AppDomain");
}
if (string.IsNullOrEmpty(Thread.CurrentThread.Name))
{
Thread.CurrentThread.Name = "Main Thread";
}
Debug.Assert(m_instance == null);
m_instance = this;
m_startupStatistic = new StartupStatistic();
if (ForceCommandLineMode == false)
{
Idle.Event += Application_Idle;
}
#if DEBUG
if (Debugger.IsAttached)
{
return StartImpl();
}
#endif
return StartImpl();
}
private int StartImpl()
{
#if DEBUG
Control.CheckForIllegalCrossThreadCalls = true;
#endif
// To have invariant type conversion
ThreadHelper.SetDefaultThreadCulture(Thread.CurrentThread);
LogService.LogService.LogMessage("Starting {0}...", ApplicationName);
ConfigureInternal();
// Initialize the runtime.
LogService.LogService.LogMessage("Initializing runtime...");
Runtime.Initialize(this, m_bootstrapLoggingContext);
LogService.LogService.LogMessage("Starting core services...");
StartCoreServices();
LogService.LogService.LogMessage("Running...");
return Run();
}
private void ConfigureInternal()
{
Configure(m_configuration);
}
///
/// Starts the main services
///
protected virtual void StartCoreServices()
{
StringParserService.StringParserService.Properties["ApplicationName"] = ApplicationName;
}
///
/// Configures the application, using the given .
///
///
protected virtual void Configure(ApplicationConfiguration configuration)
{
}
///
/// Initializes and processes the command-line arguments
///
/// Thrown when some arguments are invalid.
private void InitializeCommandLineArguments()
{
Runtime.CommandLineMode = ShouldStartInCommandLineMode(Runtime.CommandLineHandlerPaths);
Runtime.CommandLineMode |= ForceCommandLineMode;
}
private bool ShouldStartInCommandLineMode(IEnumerable handlersPath)
{
bool commandLineMode = ForceCommandLineMode;
foreach (string path in handlersPath)
{
foreach (object obj in AddinManager.GetExtensionObjects