366 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			366 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|  | using System; | ||
|  | using System.IO; | ||
|  | using System.Linq; | ||
|  | 
 | ||
|  | using UnityEditor; | ||
|  | using UnityEngine; | ||
|  | 
 | ||
|  | using Codice.Client.BaseCommands; | ||
|  | using Codice.Client.Common; | ||
|  | using Codice.Client.Common.Connection; | ||
|  | using Codice.Client.Common.Encryption; | ||
|  | using Codice.Client.Common.EventTracking; | ||
|  | using Codice.Client.Common.Threading; | ||
|  | using Codice.Client.Common.WebApi; | ||
|  | using Codice.CM.Common; | ||
|  | using Codice.CM.ConfigureHelper; | ||
|  | using Codice.LogWrapper; | ||
|  | using CodiceApp.EventTracking; | ||
|  | using PlasticGui; | ||
|  | using PlasticPipe.Certificates; | ||
|  | using PlasticPipe.Client; | ||
|  | using Unity.PlasticSCM.Editor.CloudDrive; | ||
|  | using Unity.PlasticSCM.Editor.Configuration; | ||
|  | using Unity.PlasticSCM.Editor.Tool; | ||
|  | using Unity.PlasticSCM.Editor.UI; | ||
|  | 
 | ||
|  | namespace Unity.PlasticSCM.Editor | ||
|  | { | ||
|  |     internal static class PlasticApp | ||
|  |     { | ||
|  |         internal static bool IsUnitTesting { get; set; } | ||
|  | 
 | ||
|  |         internal static ILog GetLogger(string name) | ||
|  |         { | ||
|  |             if (!mIsDomainUnloadHandlerRegistered) | ||
|  |             { | ||
|  |                 // Register the Domain Unload Handler before the LogManager is initialized, | ||
|  |                 // so the domain unload handler for the app is processed before the log manager one, | ||
|  |                 // and thus the AppDomainUnload is printed in the log | ||
|  |                 RegisterDomainUnloadHandler(); | ||
|  |                 mIsDomainUnloadHandlerRegistered = true; | ||
|  |             } | ||
|  | 
 | ||
|  |             return LogManager.GetLogger(name); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static void InitializeIfNeeded() | ||
|  |         { | ||
|  |             if (mIsInitialized) | ||
|  |                 return; | ||
|  | 
 | ||
|  |             mIsInitialized = true; | ||
|  | 
 | ||
|  |             // Configure logging on initialize to avoid adding the performance cost of it | ||
|  |             // on every Editor load and Domain reload for non-UVCS users. | ||
|  |             ConfigureLogging(); | ||
|  | 
 | ||
|  |             mLog.Debug("InitializeIfNeeded"); | ||
|  | 
 | ||
|  |             mLog.DebugFormat("Unity version: {0}", Application.unityVersion); | ||
|  |             mLog.DebugFormat("unityplastic.dll version: {0}", UnityPlasticDllVersion.GetFileVersion()); | ||
|  | 
 | ||
|  |             // Ensures that the Edition Token is initialized | ||
|  |             UnityConfigurationChecker.SynchronizeUnityEditionToken(); | ||
|  |             PlasticInstallPath.LogInstallationInfo(); | ||
|  | 
 | ||
|  |             if (!IsUnitTesting) | ||
|  |                 GuiMessage.Initialize(new UnityPlasticGuiMessage()); | ||
|  | 
 | ||
|  |             RegisterExceptionHandlers(); | ||
|  |             RegisterApplicationFocusHandlers(); | ||
|  |             RegisterBeforeAssemblyReloadHandler(); | ||
|  |             RegisterEditorWantsToQuit(); | ||
|  |             RegisterEditorQuitting(); | ||
|  | 
 | ||
|  |             InitLocalization(); | ||
|  | 
 | ||
|  |             if (!IsUnitTesting) | ||
|  |                 ThreadWaiter.Initialize(new UnityThreadWaiterBuilder()); | ||
|  | 
 | ||
|  |             ServicePointConfigurator.ConfigureServicePoint(); | ||
|  |             CertificateUi.RegisterHandler(new ChannelCertificateUiImpl()); | ||
|  | 
 | ||
|  |             EditionManager.Get().DisableCapability(EnumEditionCapabilities.Extensions); | ||
|  | 
 | ||
|  |             ClientHandlers.Register(); | ||
|  | 
 | ||
|  |             PlasticGuiConfig.SetConfigFile(PlasticGuiConfig.UNITY_GUI_CONFIG_FILE); | ||
|  | 
 | ||
|  |             if (!IsUnitTesting) | ||
|  |             { | ||
|  |                 mEventSenderScheduler = EventTracking.Configure( | ||
|  |                     (PlasticWebRestApi)PlasticGui.Plastic.WebRestAPI, | ||
|  |                     ApplicationIdentifier.UnityPackage, | ||
|  |                     IdentifyEventPlatform.Get()); | ||
|  |             } | ||
|  | 
 | ||
|  |             PackageInfo.Initialize(); | ||
|  | 
 | ||
|  |             PlasticMethodExceptionHandling.InitializeAskCredentialsUi( | ||
|  |                 new CredentialsUiImpl()); | ||
|  |             ClientEncryptionServiceProvider.SetEncryptionPasswordProvider( | ||
|  |                 new MissingEncryptionPasswordPromptHandler()); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static void Enable() | ||
|  |         { | ||
|  |             string webApiToken = CmConnection.Get().BuildWebApiTokenForCloudEditionDefaultUser(); | ||
|  | 
 | ||
|  |             if (string.IsNullOrEmpty(webApiToken)) | ||
|  |                 return; | ||
|  | 
 | ||
|  |             PlasticGui.Plastic.WebRestAPI.SetToken(webApiToken); | ||
|  | 
 | ||
|  |             OrganizationsInformation.UpdateCloudOrganizationSlugsAsync( | ||
|  |                 PlasticGui.Plastic.WebRestAPI, PlasticGui.Plastic.API); | ||
|  |         } | ||
|  | 
 | ||
|  |         internal static void DisposeIfNeeded() | ||
|  |         { | ||
|  |             if (!mIsInitialized) | ||
|  |                 return; | ||
|  | 
 | ||
|  |             if (UVCSPlugin.Instance.IsEnabled() || | ||
|  |                 CloudDrivePlugin.Instance.IsEnabled()) | ||
|  |                 return; | ||
|  | 
 | ||
|  |             mLog.Debug("Dispose"); | ||
|  | 
 | ||
|  |             mIsInitialized = false; | ||
|  | 
 | ||
|  |             UnRegisterDomainUnloadHandler(); | ||
|  |             UnRegisterExceptionHandlers(); | ||
|  |             UnRegisterApplicationFocusHandlers(); | ||
|  |             UnRegisterBeforeAssemblyReloadHandler(); | ||
|  |             UnRegisterEditorWantsToQuit(); | ||
|  |             UnRegisterEditorQuitting(); | ||
|  | 
 | ||
|  |             if (mEventSenderScheduler != null) | ||
|  |             { | ||
|  |                 // Launching and forgetting to avoid a timeout when sending events files and no | ||
|  |                 // network connection is available. | ||
|  |                 // This will be refactored once a better mechanism to send event is in place | ||
|  |                 mEventSenderScheduler.EndAndSendEventsAsync(); | ||
|  |             } | ||
|  | 
 | ||
|  |             ClientConnectionPool.Shutdown(); | ||
|  |         } | ||
|  | 
 | ||
|  |         static void Shutdown() | ||
|  |         { | ||
|  |             UVCSPlugin.Instance.Shutdown(); | ||
|  | 
 | ||
|  |             CloudDrivePlugin.Instance.Shutdown(); | ||
|  | 
 | ||
|  |             DisposeIfNeeded(); | ||
|  |         } | ||
|  | 
 | ||
|  |         static void RegisterDomainUnloadHandler() | ||
|  |         { | ||
|  |             AppDomain.CurrentDomain.DomainUnload += AppDomainUnload; | ||
|  |         } | ||
|  | 
 | ||
|  |         static void RegisterExceptionHandlers() | ||
|  |         { | ||
|  |             AppDomain.CurrentDomain.UnhandledException += HandleUnhandledException; | ||
|  | 
 | ||
|  |             Application.logMessageReceivedThreaded += HandleLog; | ||
|  |         } | ||
|  | 
 | ||
|  |         static void RegisterApplicationFocusHandlers() | ||
|  |         { | ||
|  |             EditorWindowFocus.OnApplicationActivated += OnApplicationActivated; | ||
|  | 
 | ||
|  |             EditorWindowFocus.OnApplicationDeactivated += OnApplicationDeactivated; | ||
|  |         } | ||
|  | 
 | ||
|  |         static void RegisterBeforeAssemblyReloadHandler() | ||
|  |         { | ||
|  |             AssemblyReloadEvents.beforeAssemblyReload += BeforeAssemblyReload; | ||
|  |         } | ||
|  | 
 | ||
|  |         static void RegisterEditorWantsToQuit() | ||
|  |         { | ||
|  |             EditorApplication.wantsToQuit += OnEditorWantsToQuit; | ||
|  |         } | ||
|  | 
 | ||
|  |         static void RegisterEditorQuitting() | ||
|  |         { | ||
|  |             EditorApplication.quitting += OnEditorQuitting; | ||
|  |         } | ||
|  | 
 | ||
|  |         static void UnRegisterDomainUnloadHandler() | ||
|  |         { | ||
|  |             AppDomain.CurrentDomain.DomainUnload -= AppDomainUnload; | ||
|  |         } | ||
|  | 
 | ||
|  |         static void UnRegisterExceptionHandlers() | ||
|  |         { | ||
|  |             AppDomain.CurrentDomain.UnhandledException -= HandleUnhandledException; | ||
|  | 
 | ||
|  |             Application.logMessageReceivedThreaded -= HandleLog; | ||
|  |         } | ||
|  | 
 | ||
|  |         static void UnRegisterApplicationFocusHandlers() | ||
|  |         { | ||
|  |             EditorWindowFocus.OnApplicationActivated -= OnApplicationActivated; | ||
|  | 
 | ||
|  |             EditorWindowFocus.OnApplicationDeactivated -= OnApplicationDeactivated; | ||
|  |         } | ||
|  | 
 | ||
|  |         static void UnRegisterBeforeAssemblyReloadHandler() | ||
|  |         { | ||
|  |             AssemblyReloadEvents.beforeAssemblyReload -= BeforeAssemblyReload; | ||
|  |         } | ||
|  | 
 | ||
|  |         static void UnRegisterEditorWantsToQuit() | ||
|  |         { | ||
|  |             EditorApplication.wantsToQuit -= OnEditorWantsToQuit; | ||
|  |         } | ||
|  | 
 | ||
|  |         static void UnRegisterEditorQuitting() | ||
|  |         { | ||
|  |             EditorApplication.quitting -= OnEditorQuitting; | ||
|  |         } | ||
|  | 
 | ||
|  |         static void AppDomainUnload(object sender, EventArgs e) | ||
|  |         { | ||
|  |             mLog.Debug("AppDomainUnload"); | ||
|  | 
 | ||
|  |             UnRegisterDomainUnloadHandler(); | ||
|  |         } | ||
|  | 
 | ||
|  |         static void HandleUnhandledException(object sender, UnhandledExceptionEventArgs args) | ||
|  |         { | ||
|  |             Exception ex = (Exception)args.ExceptionObject; | ||
|  | 
 | ||
|  |             if (CheckUnityException.IsExitGUIException(ex) || | ||
|  |                 !IsPlasticStackTrace(ex.StackTrace)) | ||
|  |                 throw ex; | ||
|  | 
 | ||
|  |             GUIActionRunner.RunGUIAction(delegate { | ||
|  |                 ExceptionsHandler.HandleException("HandleUnhandledException", ex); | ||
|  |             }); | ||
|  |         } | ||
|  | 
 | ||
|  |         static void HandleLog(string logString, string stackTrace, LogType type) | ||
|  |         { | ||
|  |             if (type != LogType.Exception) | ||
|  |                 return; | ||
|  | 
 | ||
|  |             if (!IsPlasticStackTrace(stackTrace)) | ||
|  |                 return; | ||
|  | 
 | ||
|  |             GUIActionRunner.RunGUIAction(delegate { | ||
|  |                 mLog.ErrorFormat("[HandleLog] Unexpected error: {0}", logString); | ||
|  |                 mLog.DebugFormat("Stack trace: {0}", stackTrace); | ||
|  | 
 | ||
|  |                 string message = logString; | ||
|  |                 if (ExceptionsHandler.DumpStackTrace()) | ||
|  |                     message += Environment.NewLine + stackTrace; | ||
|  | 
 | ||
|  |                 GuiMessage.ShowError(message); | ||
|  |             }); | ||
|  |         } | ||
|  | 
 | ||
|  |         static void OnApplicationActivated() | ||
|  |         { | ||
|  |             mLog.Debug("OnApplicationActivated"); | ||
|  | 
 | ||
|  |             if (UVCSPlugin.Instance.IsEnabled()) | ||
|  |                 UVCSPlugin.Instance.OnApplicationActivated(); | ||
|  | 
 | ||
|  |             if (CloudDrivePlugin.Instance.IsEnabled()) | ||
|  |                 CloudDrivePlugin.Instance.OnApplicationActivated(); | ||
|  |         } | ||
|  | 
 | ||
|  |         static void OnApplicationDeactivated() | ||
|  |         { | ||
|  |             mLog.Debug("OnApplicationDeactivated"); | ||
|  | 
 | ||
|  |             if (UVCSPlugin.Instance.IsEnabled()) | ||
|  |                 UVCSPlugin.Instance.OnApplicationDeactivated(); | ||
|  |         } | ||
|  | 
 | ||
|  |         static void BeforeAssemblyReload() | ||
|  |         { | ||
|  |             mLog.Debug("BeforeAssemblyReload"); | ||
|  | 
 | ||
|  |             UnRegisterBeforeAssemblyReloadHandler(); | ||
|  | 
 | ||
|  |             Shutdown(); | ||
|  |         } | ||
|  | 
 | ||
|  |         static bool OnEditorWantsToQuit() | ||
|  |         { | ||
|  |             mLog.Debug("OnEditorWantsToQuit"); | ||
|  | 
 | ||
|  |             return UVCSPlugin.Instance.OnEditorWantsToQuit() | ||
|  |                 && CloudDrivePlugin.Instance.OnEditorWantsToQuit(); | ||
|  |         } | ||
|  | 
 | ||
|  |         static void OnEditorQuitting() | ||
|  |         { | ||
|  |             mLog.Debug("OnEditorQuitting"); | ||
|  | 
 | ||
|  |             Shutdown(); | ||
|  |         } | ||
|  | 
 | ||
|  |         static void ConfigureLogging() | ||
|  |         { | ||
|  |             try | ||
|  |             { | ||
|  |                 string log4netpath = ToolConfig.GetUnityPlasticLogConfigFile(); | ||
|  | 
 | ||
|  |                 if (!File.Exists(log4netpath)) | ||
|  |                     WriteLogConfiguration.For(log4netpath); | ||
|  | 
 | ||
|  |                 XmlConfigurator.Configure(new FileInfo(log4netpath)); | ||
|  | 
 | ||
|  |                 mLog.DebugFormat("Configured logging in '{0}'", log4netpath); | ||
|  |             } | ||
|  |             catch | ||
|  |             { | ||
|  |                 //it failed configuring the logging info; nothing to do. | ||
|  |             } | ||
|  |         } | ||
|  | 
 | ||
|  |         static void InitLocalization() | ||
|  |         { | ||
|  |             string language = null; | ||
|  |             try | ||
|  |             { | ||
|  |                 language = ClientConfig.Get().GetLanguage(); | ||
|  |             } | ||
|  |             catch | ||
|  |             { | ||
|  |                 language = string.Empty; | ||
|  |             } | ||
|  | 
 | ||
|  |             Localization.Init(language); | ||
|  |             PlasticLocalization.SetLanguage(language); | ||
|  |         } | ||
|  | 
 | ||
|  |         static bool IsPlasticStackTrace(string stackTrace) | ||
|  |         { | ||
|  |             if (stackTrace == null) | ||
|  |                 return false; | ||
|  | 
 | ||
|  |             string[] namespaces = new[] { | ||
|  |                 "Codice.", | ||
|  |                 "GluonGui.", | ||
|  |                 "PlasticGui." | ||
|  |             }; | ||
|  | 
 | ||
|  |             return namespaces.Any(stackTrace.Contains); | ||
|  |         } | ||
|  | 
 | ||
|  |         static bool mIsDomainUnloadHandlerRegistered; | ||
|  |         static bool mIsInitialized; | ||
|  |         static EventSenderScheduler mEventSenderScheduler; | ||
|  | 
 | ||
|  |         static readonly ILog mLog = PlasticApp.GetLogger("PlasticApp"); | ||
|  |     } | ||
|  | } |