UNPKG

@magic-xpa/utils

Version:

magic utils package

686 lines • 54.7 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ import { Logger_LogLevels, Logger_MessageDirection } from "./enums"; import { DateTime, Debug, Exception, NString, StringBuilder, Thread } from "@magic-xpa/mscorelib"; import { OSEnvironment } from "./PlatformUtils"; import { DateTimeUtils } from "./DateTimeUtils"; import { XMLConstants } from "./XMLConstants"; import { isNullOrUndefined } from "util"; /** @enum {number} */ var LogType = { info: 1, warning: 2, error: 3, }; export { LogType }; LogType[LogType.info] = 'info'; LogType[LogType.warning] = 'warning'; LogType[LogType.error] = 'error'; /// <summary> /// Logger class will take care of client side logging . It will check for various log levels and accordingly will write messages in log file. /// </summary> //@dynamic var Logger = /** @class */ (function () { function Logger() { this.LogLevel = 0; // InternalLogLevel /// <summary> /// While writing the error messages in the file play the beep. /// </summary> this.ShouldBeep = false; } Object.defineProperty(Logger, "Instance", { get: /** * @return {?} */ function () { if (Logger.instance === null) { Logger.instance = new Logger(); } return Logger.instance; }, set: /** * @param {?} value * @return {?} */ function (value) { Logger.instance = value; }, enumerable: true, configurable: true }); /// <summary> /// Initialize logger /// </summary> /// <param name="logLevel"></param> /// <param name="internalLogSync"></param> /// <summary> /// Initialize logger /// </summary> /// <param name="logLevel"></param> /// <param name="internalLogSync"></param> /** * @param {?} logLevel * @param {?} internalLogSync * @param {?} shouldBeep * @return {?} */ Logger.prototype.Initialize = /// <summary> /// Initialize logger /// </summary> /// <param name="logLevel"></param> /// <param name="internalLogSync"></param> /** * @param {?} logLevel * @param {?} internalLogSync * @param {?} shouldBeep * @return {?} */ function (logLevel, internalLogSync, shouldBeep) { try { // let logSync: LogSyncMode = LogSyncMode.Session; this.LogLevel = logLevel; this.ShouldBeep = shouldBeep; // TODO: implement // String strLogSync = internalLogSync; // if (!string.IsNullOrEmpty(strLogSync)) // { // if (strLogSync.StartsWith("M", StringComparison.CurrentCultureIgnoreCase)) // logSync = LogSyncMode.Message; // else if (strLogSync.StartsWith("F", StringComparison.CurrentCultureIgnoreCase)) // logSync = LogSyncMode.Flush; // } // } catch (e) { this.WriteDevToLog("ClientManager.init(): " + e.Message); } }; /** * @param {?=} logLevel * @return {?} */ Logger.prototype.ShouldLog = /** * @param {?=} logLevel * @return {?} */ function (logLevel) { if (arguments.length === 1) return this.ShouldLog_0(logLevel); else return this.ShouldLog_1(); }; /** * @param {?} logLevel * @return {?} */ Logger.prototype.ShouldLog_0 = /** * @param {?} logLevel * @return {?} */ function (logLevel) { return this.LogLevel === logLevel; }; /** * @return {?} */ Logger.prototype.ShouldLog_1 = /** * @return {?} */ function () { return this.LogLevel > Logger_LogLevels.None; }; /** * @return {?} */ Logger.prototype.ShouldLogServerRelatedMessages = /** * @return {?} */ function () { return (this.ShouldLogExtendedServerRelatedMessages() || Logger.Instance.ShouldLog(Logger_LogLevels.Server)) && this.LogLevel !== Logger_LogLevels.Basic; }; /** * @return {?} */ Logger.prototype.ShouldLogExtendedServerRelatedMessages = /** * @return {?} */ function () { return (Logger.Instance.ShouldLog(Logger_LogLevels.ServerMessages) || Logger.Instance.ShouldLog(Logger_LogLevels.Support) || Logger.Instance.ShouldLog(Logger_LogLevels.Development)) && this.LogLevel !== Logger_LogLevels.Basic; }; /// <summary></summary> /// <param name="msg"></param> /// <param name="openIfNecessary">open the log file if not opened yet</param> /// <summary></summary> /// <param name="msg"></param> /// <param name="openIfNecessary">open the log file if not opened yet</param> /** * @param {?} msg * @param {?} openIfNecessary * @param {?=} logType * @return {?} */ Logger.prototype.WriteToLog = /// <summary></summary> /// <param name="msg"></param> /// <param name="openIfNecessary">open the log file if not opened yet</param> /** * @param {?} msg * @param {?} openIfNecessary * @param {?=} logType * @return {?} */ function (msg, openIfNecessary, logType) { if (logType === void 0) { logType = LogType.info; } if (this.LogLevel > Logger_LogLevels.None || openIfNecessary) { msg = NString.Format("{0} {1}", (this.LogLevel === Logger_LogLevels.Basic) ? new Date().toISOString() : DateTimeUtils.ToString(DateTime.Now, XMLConstants.ERROR_LOG_TIME_FORMAT, this), msg); switch (logType) { case LogType.error: console.error(msg); break; case LogType.warning: console.warn(msg); break; default: console.log(msg); } } }; /// <summary> /// write a server access to the log /// </summary> /// <param name="msg">the message to write to the log</param> /// <summary> /// write a server access to the log /// </summary> /// <param name="msg">the message to write to the log</param> /** * @param {?} msg * @return {?} */ Logger.prototype.WriteServerToLog = /// <summary> /// write a server access to the log /// </summary> /// <param name="msg">the message to write to the log</param> /** * @param {?} msg * @return {?} */ function (msg) { if (this.ShouldLogServerRelatedMessages()) { this.WriteToLog(NString.Format("Server, Thread={0}: ", Thread.CurrentThread.ManagedThreadId) + msg, false, LogType.info); } }; /// <summary> /// write a server access to the log, including the content /// </summary> /// <param name="msg">the message to write to the log</param> /// <summary> /// write a server access to the log, including the content /// </summary> /// <param name="msg">the message to write to the log</param> /** * @param {?} msg * @return {?} */ Logger.prototype.WriteServerMessagesToLog = /// <summary> /// write a server access to the log, including the content /// </summary> /// <param name="msg">the message to write to the log</param> /** * @param {?} msg * @return {?} */ function (msg) { if (this.ShouldLogExtendedServerRelatedMessages()) { this.WriteToLog("Server#: " + msg, false, LogType.info); } }; /// <summary>Write a QC message to the log</summary> /// <param name="msg">the message to write to the log</param> /// <summary>Write a QC message to the log</summary> /// <param name="msg">the message to write to the log</param> /** * @param {?} msg * @param {?} skipLine * @return {?} */ Logger.prototype.WriteSupportToLog = /// <summary>Write a QC message to the log</summary> /// <param name="msg">the message to write to the log</param> /** * @param {?} msg * @param {?} skipLine * @return {?} */ function (msg, skipLine) { if (this.LogLevel >= Logger_LogLevels.Support && this.LogLevel !== Logger_LogLevels.Basic) { if (skipLine) { this.WriteToLog("SUPPORT: " + msg, false, LogType.info); } else { this.WriteToLog("SUPPORT: " + msg + OSEnvironment.EolSeq + "-----------------------------------------------------------------------------------------------------------", false, LogType.info); } } }; /// <summary> /// write a performance message to the log /// </summary> /// <param name="msg">the message to write to the log</param> /// <summary> /// write a performance message to the log /// </summary> /// <param name="msg">the message to write to the log</param> /** * @param {?} msg * @return {?} */ Logger.prototype.WriteGuiToLog = /// <summary> /// write a performance message to the log /// </summary> /// <param name="msg">the message to write to the log</param> /** * @param {?} msg * @return {?} */ function (msg) { if (this.LogLevel >= Logger_LogLevels.Gui && this.LogLevel !== Logger_LogLevels.Basic) { this.WriteToLog(msg, false, LogType.info); } }; /// <summary> /// write a developer message to the log /// </summary> /// <param name="msg">the message to write to the log</param> /// <summary> /// write a developer message to the log /// </summary> /// <param name="msg">the message to write to the log</param> /** * @param {?} msg * @return {?} */ Logger.prototype.WriteDevToLog = /// <summary> /// write a developer message to the log /// </summary> /// <param name="msg">the message to write to the log</param> /** * @param {?} msg * @return {?} */ function (msg) { if (this.LogLevel >= Logger_LogLevels.Development && this.LogLevel !== Logger_LogLevels.Basic) { this.WriteToLog("DEV: " + msg, false, LogType.info); } }; /// <summary> /// Writes a basic level entry to log /// </summary> /// <param name="messageDirection">message direction relative to the current module (RIA client). Can be either MessageEntering or MessageLeaving</param> /// <param name="statusCode">HTTP status code</param> /// <param name="contentLength">length of the http message</param> /// <param name="httpHeaders">HTTP headers</param> /// <summary> /// Writes a basic level entry to log /// </summary> /// <param name="messageDirection">message direction relative to the current module (RIA client). Can be either MessageEntering or MessageLeaving</param> /// <param name="statusCode">HTTP status code</param> /// <param name="contentLength">length of the http message</param> /// <param name="httpHeaders">HTTP headers</param> /** * @param {?} messageDirection * @param {?} contextID * @param {?} sessionCounter * @param {?} clientID * @param {?} serverID * @param {?} responseTime * @param {?} statusCode * @param {?} httpHeaders * @param {?} contentLength * @return {?} */ Logger.prototype.WriteBasicToLog = /// <summary> /// Writes a basic level entry to log /// </summary> /// <param name="messageDirection">message direction relative to the current module (RIA client). Can be either MessageEntering or MessageLeaving</param> /// <param name="statusCode">HTTP status code</param> /// <param name="contentLength">length of the http message</param> /// <param name="httpHeaders">HTTP headers</param> /** * @param {?} messageDirection * @param {?} contextID * @param {?} sessionCounter * @param {?} clientID * @param {?} serverID * @param {?} responseTime * @param {?} statusCode * @param {?} httpHeaders * @param {?} contentLength * @return {?} */ function (messageDirection, contextID, sessionCounter, clientID, serverID, responseTime, statusCode, httpHeaders, contentLength) { if (this.LogLevel === Logger_LogLevels.Basic) { /** @type {?} */ var text = httpHeaders; text = text.trim(); text = NString.Replace(text, "\r\n", "|"); /** @type {?} */ var arg_E4_0 = "RIA,{0}_{1},{2},{3},{4},{5},-,{6},{7},{8},{9},{10},{11}"; /** @type {?} */ var expr_3E = new Array(12); // TODO : need to check How to handle Process class. // expr_3E[0] = Process.GetCurrentProcess().Id; expr_3E[1] = Thread.CurrentThread.ManagedThreadId; expr_3E[2] = new Date().toISOString(); expr_3E[3] = ((messageDirection === Logger_MessageDirection.MessageLeaving) ? "MSGL" : "MSGE"); expr_3E[4] = contextID; expr_3E[5] = sessionCounter; expr_3E[6] = clientID; expr_3E[7] = serverID; expr_3E[8] = ((responseTime !== 0) ? responseTime.toString() : "-"); /** @type {?} */ var arg_D3_1 = 9; /** @type {?} */ var arg_D3_2 = void 0; arg_D3_2 = statusCode; expr_3E[arg_D3_1] = arg_D3_2; expr_3E[10] = text; expr_3E[11] = contentLength; /** @type {?} */ var value = NString.Format(arg_E4_0, expr_3E); console.log(value); } }; /// <summary> /// Writes a request exception basic level entry to log /// </summary> /// <param name="contextID"></param> /// <param name="sessionCounter"></param> /// <param name="clientID"></param> /// <param name="serverID"></param> /// <param name="ex">the logged exception</param> /// <summary> /// Writes a request exception basic level entry to log /// </summary> /// <param name="contextID"></param> /// <param name="sessionCounter"></param> /// <param name="clientID"></param> /// <param name="serverID"></param> /// <param name="ex">the logged exception</param> /** * @param {?} contextID * @param {?} sessionCounter * @param {?} clientID * @param {?} serverID * @param {?} ex * @return {?} */ Logger.prototype.WriteBasicErrorToLog = /// <summary> /// Writes a request exception basic level entry to log /// </summary> /// <param name="contextID"></param> /// <param name="sessionCounter"></param> /// <param name="clientID"></param> /// <param name="serverID"></param> /// <param name="ex">the logged exception</param> /** * @param {?} contextID * @param {?} sessionCounter * @param {?} clientID * @param {?} serverID * @param {?} ex * @return {?} */ function (contextID, sessionCounter, clientID, serverID, ex) { Debug.Assert(this.LogLevel === Logger_LogLevels.Basic); // TODO : Need to check how to handle Process // let value: string = NString.Format("RIA,{0}_{1},{2},{3},{4},{5},-,{6},{7},-,-,-,{8} {9}", [ // Process.GetCurrentProcess().Id, Thread.CurrentThread.ManagedThreadId, DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ"), "RES", contextID, sessionCounter, clientID, serverID, ex.GetType(), ex.Message // ]); // NConsole.WriteLine(value); }; /// <summary> /// Write an error to the log /// </summary> /// <param name="msg">the message to write to the log</param> /// <summary> /// Write an error to the log /// </summary> /// <param name="msg">the message to write to the log</param> /** * @param {?} msg * @return {?} */ Logger.prototype.WriteErrorToLog = /// <summary> /// Write an error to the log /// </summary> /// <param name="msg">the message to write to the log</param> /** * @param {?} msg * @return {?} */ function (msg) { this.WriteToLog("ERROR: " + msg, true, LogType.error); }; /** * @param {?} msgOrEx * @param {?=} msg * @return {?} */ Logger.prototype.WriteExceptionToLog = /** * @param {?} msgOrEx * @param {?=} msg * @return {?} */ function (msgOrEx, msg) { if (msgOrEx instanceof Error) { this.WriteExceptionToLog_2(msgOrEx, msg); return; } if (arguments.length === 1 && (msgOrEx !== null || msgOrEx instanceof Exception)) { this.WriteExceptionToLog_1(msgOrEx); return; } this.WriteExceptionToLog_3(msgOrEx, msg); }; /** * @param {?} msg * @return {?} */ Logger.prototype.WriteExceptionToLogWithMsg = /** * @param {?} msg * @return {?} */ function (msg) { this.WriteToLog("ERROR: " + msg, true, LogType.error); }; /** * @param {?} ex * @return {?} */ Logger.prototype.WriteExceptionToLog_1 = /** * @param {?} ex * @return {?} */ function (ex) { this.WriteExceptionToLogWithMsg(NString.Format("{0} : {1}{2}{3}{4}", [ ex.GetType(), OSEnvironment.EolSeq, ex.StackTrace, OSEnvironment.EolSeq, ex.Message ])); }; /** * @param {?} ex * @param {?} message * @return {?} */ Logger.prototype.WriteExceptionToLog_2 = /** * @param {?} ex * @param {?} message * @return {?} */ function (ex, message) { if (isNullOrUndefined(message)) this.WriteExceptionToLogWithMsg(NString.Format("{0}{1}{2}", [ex.stack, OSEnvironment.EolSeq, ex.message])); else this.WriteExceptionToLogWithMsg(NString.Format("{0}{1}{2}{4}{5}", [message, OSEnvironment.EolSeq, ex.stack, OSEnvironment.EolSeq, ex.message])); }; /** * @param {?} ex * @param {?} msg * @return {?} */ Logger.prototype.WriteExceptionToLog_3 = /** * @param {?} ex * @param {?} msg * @return {?} */ function (ex, msg) { this.WriteExceptionToLogWithMsg(NString.Format("{0}, {1} : {2}{3}{4}{5}", [ ex.GetType(), msg, OSEnvironment.EolSeq, ex.StackTrace, OSEnvironment.EolSeq, ex.Message ])); }; /** * @param {?} msgOrEx * @param {?=} msg * @return {?} */ Logger.prototype.WriteWarningToLog = /** * @param {?} msgOrEx * @param {?=} msg * @return {?} */ function (msgOrEx, msg) { if (arguments.length === 1 && msgOrEx !== null) { if (msgOrEx instanceof Exception) this.WriteWarningToLog_1(msgOrEx); else if (msgOrEx instanceof Error) this.WriteWarningToLog_2(msgOrEx); } else this.WriteWarningToLog_3(msgOrEx, msg); }; /** * @param {?} msg * @return {?} */ Logger.prototype.WriteWarningToLogWithMsg = /** * @param {?} msg * @return {?} */ function (msg) { if (this.LogLevel !== Logger_LogLevels.Basic) { this.WriteToLog("WARNING: " + msg, true, LogType.warning); } }; /** * @param {?} ex * @return {?} */ Logger.prototype.WriteWarningToLog_1 = /** * @param {?} ex * @return {?} */ function (ex) { this.WriteWarningToLogWithMsg(ex.GetType() + " : " + OSEnvironment.EolSeq + ex.StackTrace + OSEnvironment.EolSeq + ex.Message); }; /** * @param {?} ex * @return {?} */ Logger.prototype.WriteWarningToLog_2 = /** * @param {?} ex * @return {?} */ function (ex) { this.WriteWarningToLogWithMsg(NString.Format("{0}{1}{2}", [ ex.stack, OSEnvironment.EolSeq, ex.message ])); }; /** * @param {?} ex * @param {?} msg * @return {?} */ Logger.prototype.WriteWarningToLog_3 = /** * @param {?} ex * @param {?} msg * @return {?} */ function (ex, msg) { this.WriteWarningToLogWithMsg(NString.Format("{0}, {1} : {2}{3}{4}{5}", [ ex.GetType(), msg, OSEnvironment.EolSeq, ex.StackTrace, OSEnvironment.EolSeq, ex.Message ])); }; /** * @param {?} stackTrace * @param {?} framesToPrint * @param {?} traceTitle * @return {?} */ Logger.prototype.WriteStackTrace = /** * @param {?} stackTrace * @param {?} framesToPrint * @param {?} traceTitle * @return {?} */ function (stackTrace, framesToPrint, traceTitle) { if (traceTitle === null) { traceTitle = "Stack trace:"; } /** @type {?} */ var stringBuilder = new StringBuilder(traceTitle + OSEnvironment.EolSeq); /** @type {?} */ var frames = stackTrace.GetFrames(); /** @type {?} */ var array = frames; for (var i = 0; i < array.length; i = i + 1) { /** @type {?} */ var stackFrame = array[i]; framesToPrint = framesToPrint - 1; stringBuilder.Append(stackFrame.toString()); if (framesToPrint === 0) { stringBuilder.Append("\t... more stack frames ...\n"); break; } } this.WriteToLog(stringBuilder.ToString(), true); }; /// <summary> /// Flush the log writer. /// </summary> /// <summary> /// Flush the log writer. /// </summary> /** * @return {?} */ Logger.prototype.Flush = /// <summary> /// Flush the log writer. /// </summary> /** * @return {?} */ function () { }; Logger.instance = null; return Logger; }()); export { Logger }; if (false) { /** @type {?} */ Logger.instance; /** @type {?} */ Logger.prototype.LogLevel; /** @type {?} */ Logger.prototype.ShouldBeep; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTG9nZ2VyLmpzIiwic291cmNlUm9vdCI6Im5nOi8vQG1hZ2ljLXhwYS91dGlscy8iLCJzb3VyY2VzIjpbInNyYy9Mb2dnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLE9BQU8sRUFBQyxnQkFBZ0IsRUFBRSx1QkFBdUIsRUFBQyxNQUFNLFNBQVMsQ0FBQztBQUNsRSxPQUFPLEVBQUMsUUFBUSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFjLGFBQWEsRUFBRSxNQUFNLEVBQUMsTUFBTSxzQkFBc0IsQ0FBQztBQUM1RyxPQUFPLEVBQUMsYUFBYSxFQUFDLE1BQU0saUJBQWlCLENBQUM7QUFDOUMsT0FBTyxFQUFDLGFBQWEsRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBQzlDLE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUU1QyxPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSxNQUFNLENBQUM7OztJQUlyQyxPQUFRO0lBQ1IsVUFBTztJQUNQLFFBQUs7Ozs7Ozs7Ozs7QUFRUDtJQXVVRTtRQXJVQSxhQUFRLEdBQXFCLENBQUMsQ0FBQyxDQUFDLG1CQUFtQjtRQUVuRCxhQUFhO1FBQ2IsK0RBQStEO1FBQy9ELGNBQWM7UUFDZCxlQUFVLEdBQVksS0FBSyxDQUFDO0lBaVU1QixDQUFDO0lBL1RELHNCQUFXLGtCQUFROzs7O1FBSW5CO1lBQ0UsRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLFFBQVEsS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDO2dCQUM3QixNQUFNLENBQUMsUUFBUSxHQUFHLElBQUksTUFBTSxFQUFFLENBQUM7WUFDakMsQ0FBQztZQUNELE1BQU0sQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDO1FBQ3pCLENBQUM7Ozs7O1FBVEQsVUFBb0IsS0FBYTtZQUMvQixNQUFNLENBQUMsUUFBUSxHQUFHLEtBQUssQ0FBQztRQUMxQixDQUFDOzs7T0FBQTtJQVNILGFBQWE7SUFDWCxxQkFBcUI7SUFDckIs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QUFDLGFBQWEsQ0FBQyxRQUFRLEVBQUUsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUNsRCxDQUFDO0lBRUQsYUFBYTtJQUNiLHlCQUF5QjtJQUN6QixjQUFjOzs7Ozs7O0lBQ2Qsc0JBQUs7Ozs7Ozs7SUFBTDtJQUVBLENBQUM7SUFwVU0sZUFBUSxHQUFXLElBQUksQ0FBQztJQXdVakMsYUFBQztDQUFBLEFBelVELElBeVVDO1NBelVZLE1BQU07OztJQUNqQixnQkFBK0I7O0lBQy9CLDBCQUErQjs7SUFLL0IsNEJBQTRCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtMb2dnZXJfTG9nTGV2ZWxzLCBMb2dnZXJfTWVzc2FnZURpcmVjdGlvbn0gZnJvbSBcIi4vZW51bXNcIjtcclxuaW1wb3J0IHtEYXRlVGltZSwgRGVidWcsIEV4Y2VwdGlvbiwgTlN0cmluZywgU3RhY2tUcmFjZSwgU3RyaW5nQnVpbGRlciwgVGhyZWFkfSBmcm9tIFwiQG1hZ2ljLXhwYS9tc2NvcmVsaWJcIjtcclxuaW1wb3J0IHtPU0Vudmlyb25tZW50fSBmcm9tIFwiLi9QbGF0Zm9ybVV0aWxzXCI7XHJcbmltcG9ydCB7RGF0ZVRpbWVVdGlsc30gZnJvbSBcIi4vRGF0ZVRpbWVVdGlsc1wiO1xyXG5pbXBvcnQge1hNTENvbnN0YW50c30gZnJvbSBcIi4vWE1MQ29uc3RhbnRzXCI7XHJcbmltcG9ydCAqIGFzIEpTU3RhY2tUcmFjZSBmcm9tICdzdGFja3RyYWNlLWpzJztcclxuaW1wb3J0IHtpc051bGxPclVuZGVmaW5lZH0gZnJvbSBcInV0aWxcIjtcclxuaW1wb3J0IEpTU3RhY2tGcmFtZSA9IEpTU3RhY2tUcmFjZS5TdGFja0ZyYW1lO1xyXG5cclxuZXhwb3J0IGVudW0gTG9nVHlwZSB7XHJcbiAgaW5mbyA9IDEsXHJcbiAgd2FybmluZyxcclxuICBlcnJvclxyXG59XHJcblxyXG5cclxuLy8vIDxzdW1tYXJ5PlxyXG4vLy8gTG9nZ2VyIGNsYXNzIHdpbGwgdGFrZSBjYXJlIG9mIGNsaWVudCBzaWRlIGxvZ2dpbmcgLiBJdCB3aWxsIGNoZWNrIGZvciB2YXJpb3VzIGxvZyBsZXZlbHMgYW5kIGFjY29yZGluZ2x5IHdpbGwgd3JpdGUgbWVzc2FnZXMgaW4gbG9nIGZpbGUuXHJcbi8vLyA8L3N1bW1hcnk+XHJcbi8vQGR5bmFtaWNcclxuZXhwb3J0IGNsYXNzIExvZ2dlciB7XHJcbiAgc3RhdGljIGluc3RhbmNlOiBMb2dnZXIgPSBudWxsO1xyXG4gIExvZ0xldmVsOiBMb2dnZXJfTG9nTGV2ZWxzID0gMDsgLy8gSW50ZXJuYWxMb2dMZXZlbFxyXG5cclxuICAvLy8gPHN1bW1hcnk+XHJcbiAgLy8vIFdoaWxlIHdyaXRpbmcgdGhlIGVycm9yIG1lc3NhZ2VzIGluIHRoZSBmaWxlIHBsYXkgdGhlIGJlZXAuXHJcbiAgLy8vIDwvc3VtbWFyeT5cclxuICBTaG91bGRCZWVwOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gIHN0YXRpYyBzZXQgSW5zdGFuY2UodmFsdWU6IExvZ2dlcikge1xyXG4gICAgTG9nZ2VyLmluc3RhbmNlID0gdmFsdWU7XHJcbiAgfVxyXG5cclxuICBzdGF0aWMgZ2V0IEluc3RhbmNlKCk6IExvZ2dlciB7XHJcbiAgICBpZiAoTG9nZ2VyLmluc3RhbmNlID09PSBudWxsKSB7XHJcbiAgICAgIExvZ2dlci5pbnN0YW5jZSA9IG5ldyBMb2dnZXIoKTtcclxuICAgIH1cclxuICAgIHJldHVybiBMb2dnZXIuaW5zdGFuY2U7XHJcbiAgfVxyXG5cclxuLy8vIDxzdW1tYXJ5PlxyXG4gIC8vLyBJbml0aWFsaXplIGxvZ2dlclxyXG4gIC8vLyA8L3N1bW1hcnk+XHJcbiAgLy8vIDxwYXJhbSBuYW1lPVwibG9nTGV2ZWxcIj48L3BhcmFtPlxyXG4gIC8vLyA8cGFyYW0gbmFtZT1cImludGVybmFsTG9nU3luY1wiPjwvcGFyYW0+XHJcbiAgSW5pdGlhbGl6ZShsb2dMZXZlbDogTG9nZ2VyX0xvZ0xldmVscywgaW50ZXJuYWxMb2dTeW5jOiBzdHJpbmcsIHNob3VsZEJlZXA6IGJvb2xlYW4pOiB2b2lkIHtcclxuICAgIHRyeSB7XHJcbiAgICAgIC8vIGxldCBsb2dTeW5jOiBMb2dTeW5jTW9kZSAgPSBMb2dTeW5jTW9kZS5TZXNzaW9uO1xyXG4gICAgICB0aGlzLkxvZ0xldmVsID0gbG9nTGV2ZWw7XHJcbiAgICAgIHRoaXMuU2hvdWxkQmVlcCA9IHNob3VsZEJlZXA7XHJcblxyXG4gICAgICAvLyBUT0RPOiBpbXBsZW1lbnRcclxuLy8gICBTdHJpbmcgc3RyTG9nU3luYyA9IGludGVybmFsTG9nU3luYztcclxuLy8gICBpZiAoIXN0cmluZy5Jc051bGxPckVtcHR5KHN0ckxvZ1N5bmMpKVxyXG4vLyB7XHJcbi8vICAgaWYgKHN0ckxvZ1N5bmMuU3RhcnRzV2l0aChcIk1cIiwgU3RyaW5nQ29tcGFyaXNvbi5DdXJyZW50Q3VsdHVyZUlnbm9yZUNhc2UpKVxyXG4vLyAgIGxvZ1N5bmMgPSBMb2dTeW5jTW9kZS5NZXNzYWdlO1xyXG4vLyAgIGVsc2UgaWYgKHN0ckxvZ1N5bmMuU3RhcnRzV2l0aChcIkZcIiwgU3RyaW5nQ29tcGFyaXNvbi5DdXJyZW50Q3VsdHVyZUlnbm9yZUNhc2UpKVxyXG4vLyAgIGxvZ1N5bmMgPSBMb2dTeW5jTW9kZS5GbHVzaDtcclxuLy8gfVxyXG4vL1xyXG4gICAgfVxyXG4gICAgY2F0Y2ggKGUpIHtcclxuICAgICAgdGhpcy5Xcml0ZURldlRvTG9nKFwiQ2xpZW50TWFuYWdlci5pbml0KCk6IFwiICsgZS5NZXNzYWdlKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8vLyA8c3VtbWFyeT48L3N1bW1hcnk+XHJcbiAgLy8vIDxwYXJhbSBuYW1lPVwibG9nTGV2ZWxcIj48L3BhcmFtPlxyXG4gIC8vLyA8cmV0dXJucz48L3JldHVybnM+XHJcblxyXG4gIFNob3VsZExvZyhsb2dMZXZlbDogTG9nZ2VyX0xvZ0xldmVscyk6IGJvb2xlYW47XHJcbiAgU2hvdWxkTG9nKCk6IGJvb2xlYW47XHJcbiAgU2hvdWxkTG9nKGxvZ0xldmVsPzogTG9nZ2VyX0xvZ0xldmVscyk6IGJvb2xlYW4ge1xyXG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEpXHJcbiAgICAgIHJldHVybiB0aGlzLlNob3VsZExvZ18wKGxvZ0xldmVsKTtcclxuICAgIGVsc2VcclxuICAgICAgcmV0dXJuIHRoaXMuU2hvdWxkTG9nXzEoKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgU2hvdWxkTG9nXzAobG9nTGV2ZWw6IExvZ2dlcl9Mb2dMZXZlbHMpOiBib29sZWFuIHtcclxuICAgIHJldHVybiB0aGlzLkxvZ0xldmVsID09PSBsb2dMZXZlbDtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgU2hvdWxkTG9nXzEoKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gdGhpcy5Mb2dMZXZlbCA+IExvZ2dlcl9Mb2dMZXZlbHMuTm9uZTtcclxuICB9XHJcblxyXG4gIFNob3VsZExvZ1NlcnZlclJlbGF0ZWRNZXNzYWdlcygpOiBib29sZWFuIHtcclxuICAgIHJldHVybiAodGhpcy5TaG91bGRMb2dFeHRlbmRlZFNlcnZlclJlbGF0ZWRNZXNzYWdlcygpIHx8IExvZ2dlci5JbnN0YW5jZS5TaG91bGRMb2coTG9nZ2VyX0xvZ0xldmVscy5TZXJ2ZXIpKSAmJiB0aGlzLkxvZ0xldmVsICE9PSBMb2dnZXJfTG9nTGV2ZWxzLkJhc2ljO1xyXG4gIH1cclxuXHJcbiAgU2hvdWxkTG9nRXh0ZW5kZWRTZXJ2ZXJSZWxhdGVkTWVzc2FnZXMoKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gKExvZ2dlci5JbnN0YW5jZS5TaG91bGRMb2coTG9nZ2VyX0xvZ0xldmVscy5TZXJ2ZXJNZXNzYWdlcykgfHwgTG9nZ2VyLkluc3RhbmNlLlNob3VsZExvZyhMb2dnZXJfTG9nTGV2ZWxzLlN1cHBvcnQpIHx8IExvZ2dlci5JbnN0YW5jZS5TaG91bGRMb2coTG9nZ2VyX0xvZ0xldmVscy5EZXZlbG9wbWVudCkpICYmIHRoaXMuTG9nTGV2ZWwgIT09IExvZ2dlcl9Mb2dMZXZlbHMuQmFzaWM7XHJcbiAgfVxyXG5cclxuICAvLy8gPHN1bW1hcnk+PC9zdW1tYXJ5PlxyXG4gIC8vLyA8cGFyYW0gbmFtZT1cIm1zZ1wiPjwvcGFyYW0+XHJcbiAgLy8vIDxwYXJhbSBuYW1lPVwib3BlbklmTmVjZXNzYXJ5XCI+b3BlbiB0aGUgbG9nIGZpbGUgaWYgbm90IG9wZW5lZCB5ZXQ8L3BhcmFtPlxyXG5cclxuICBXcml0ZVRvTG9nKG1zZzogc3RyaW5nLCBvcGVuSWZOZWNlc3Nhcnk6IGJvb2xlYW4sIGxvZ1R5cGU6IExvZ1R5cGUgPSBMb2dUeXBlLmluZm8pOiB2b2lkIHtcclxuXHJcbiAgICBpZiAodGhpcy5Mb2dMZXZlbCA+IExvZ2dlcl9Mb2dMZXZlbHMuTm9uZSB8fCBvcGVuSWZOZWNlc3NhcnkpIHtcclxuICAgICAgbXNnID0gTlN0cmluZy5Gb3JtYXQoXCJ7MH0gezF9XCIsICh0aGlzLkxvZ0xldmVsID09PSBMb2dnZXJfTG9nTGV2ZWxzLkJhc2ljKSA/IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSA6IERhdGVUaW1lVXRpbHMuVG9TdHJpbmcoRGF0ZVRpbWUuTm93LCBYTUxDb25zdGFudHMuRVJST1JfTE9HX1RJTUVfRk9STUFULCB0aGlzKSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgbXNnKTtcclxuXHJcbiAgICAgIHN3aXRjaCAobG9nVHlwZSkge1xyXG4gICAgICAgIGNhc2UgTG9nVHlwZS5lcnJvcjpcclxuICAgICAgICAgIGNvbnNvbGUuZXJyb3IobXNnKTtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIGNhc2UgTG9nVHlwZS53YXJuaW5nOlxyXG4gICAgICAgICAgY29uc29sZS53YXJuKG1zZyk7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICBkZWZhdWx0OlxyXG4gICAgICAgICAgY29uc29sZS5sb2cobXNnKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy8vIDxzdW1tYXJ5PlxyXG4gIC8vLyB3cml0ZSBhIHNlcnZlciBhY2Nlc3MgdG8gdGhlIGxvZ1xyXG4gIC8vLyA8L3N1bW1hcnk+XHJcbiAgLy8vIDxwYXJhbSBuYW1lPVwibXNnXCI+dGhlIG1lc3NhZ2UgdG8gd3JpdGUgdG8gdGhlIGxvZzwvcGFyYW0+XHJcbiAgV3JpdGVTZXJ2ZXJUb0xvZyhtc2c6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuU2hvdWxkTG9nU2VydmVyUmVsYXRlZE1lc3NhZ2VzKCkpIHtcclxuICAgICAgdGhpcy5Xcml0ZVRvTG9nKE5TdHJpbmcuRm9ybWF0KFwiU2VydmVyLCBUaHJlYWQ9ezB9OiBcIiwgVGhyZWFkLkN1cnJlbnRUaHJlYWQuTWFuYWdlZFRocmVhZElkKSArIG1zZywgZmFsc2UsIExvZ1R5cGUuaW5mbyk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvLy8gPHN1bW1hcnk+XHJcbiAgLy8vIHdyaXRlIGEgc2VydmVyIGFjY2VzcyB0byB0aGUgbG9nLCBpbmNsdWRpbmcgdGhlIGNvbnRlbnRcclxuICAvLy8gPC9zdW1tYXJ5PlxyXG4gIC8vLyA8cGFyYW0gbmFtZT1cIm1zZ1wiPnRoZSBtZXNzYWdlIHRvIHdyaXRlIHRvIHRoZSBsb2c8L3BhcmFtPlxyXG4gIFdyaXRlU2VydmVyTWVzc2FnZXNUb0xvZyhtc2c6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuU2hvdWxkTG9nRXh0ZW5kZWRTZXJ2ZXJSZWxhdGVkTWVzc2FnZXMoKSkge1xyXG4gICAgICB0aGlzLldyaXRlVG9Mb2coXCJTZXJ2ZXIjOiBcIiArIG1zZywgZmFsc2UsIExvZ1R5cGUuaW5mbyk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvLy8gPHN1bW1hcnk+V3JpdGUgYSBRQyBtZXNzYWdlIHRvIHRoZSBsb2c8L3N1bW1hcnk+XHJcbiAgLy8vIDxwYXJhbSBuYW1lPVwibXNnXCI+dGhlIG1lc3NhZ2UgdG8gd3JpdGUgdG8gdGhlIGxvZzwvcGFyYW0+XHJcbiAgV3JpdGVTdXBwb3J0VG9Mb2cobXNnOiBzdHJpbmcsIHNraXBMaW5lOiBib29sZWFuKTogdm9pZCB7XHJcblxyXG4gICAgaWYgKHRoaXMuTG9nTGV2ZWwgPj0gTG9nZ2VyX0xvZ0xldmVscy5TdXBwb3J0ICYmIHRoaXMuTG9nTGV2ZWwgIT09IExvZ2dlcl9Mb2dMZXZlbHMuQmFzaWMpIHtcclxuICAgICAgaWYgKHNraXBMaW5lKSB7XHJcbiAgICAgICAgdGhpcy5Xcml0ZVRvTG9nKFwiU1VQUE9SVDogXCIgKyBtc2csIGZhbHNlLCBMb2dUeXBlLmluZm8pO1xyXG4gICAgICB9XHJcbiAgICAgIGVsc2Uge1xyXG4gICAgICAgIHRoaXMuV3JpdGVUb0xvZyhcIlNVUFBPUlQ6IFwiICsgbXNnICsgT1NFbnZpcm9ubWVudC5Fb2xTZXEgKyBcIi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXCIsIGZhbHNlLCBMb2dUeXBlLmluZm8pO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvLy8gPHN1bW1hcnk+XHJcbiAgLy8vIHdyaXRlIGEgcGVyZm9ybWFuY2UgbWVzc2FnZSB0byB0aGUgbG9nXHJcbiAgLy8vIDwvc3VtbWFyeT5cclxuICAvLy8gPHBhcmFtIG5hbWU9XCJtc2dcIj50aGUgbWVzc2FnZSB0byB3cml0ZSB0byB0aGUgbG9nPC9wYXJhbT5cclxuICBXcml0ZUd1aVRvTG9nKG1zZzogc3RyaW5nKTogdm9pZCB7XHJcblxyXG4gICAgaWYgKHRoaXMuTG9nTGV2ZWwgPj0gTG9nZ2VyX0xvZ0xldmVscy5HdWkgJiYgdGhpcy5Mb2dMZXZlbCAhPT0gTG9nZ2VyX0xvZ0xldmVscy5CYXNpYykge1xyXG4gICAgICB0aGlzLldyaXRlVG9Mb2cobXNnLCBmYWxzZSwgTG9nVHlwZS5pbmZvKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8vLyA8c3VtbWFyeT5cclxuICAvLy8gd3JpdGUgYSBkZXZlbG9wZXIgbWVzc2FnZSB0byB0aGUgbG9nXHJcbiAgLy8vIDwvc3VtbWFyeT5cclxuICAvLy8gPHBhcmFtIG5hbWU9XCJtc2dcIj50aGUgbWVzc2FnZSB0byB3cml0ZSB0byB0aGUgbG9nPC9wYXJhbT5cclxuICBXcml0ZURldlRvTG9nKG1zZzogc3RyaW5nKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5Mb2dMZXZlbCA+PSBMb2dnZXJfTG9nTGV2ZWxzLkRldmVsb3BtZW50ICYmIHRoaXMuTG9nTGV2ZWwgIT09IExvZ2dlcl9Mb2dMZXZlbHMuQmFzaWMpIHtcclxuICAgICAgdGhpcy5Xcml0ZVRvTG9nKFwiREVWOiBcIiArIG1zZywgZmFsc2UsIExvZ1R5cGUuaW5mbyk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvLy8gPHN1bW1hcnk+XHJcbiAgLy8vIFdyaXRlcyBhIGJhc2ljIGxldmVsIGVudHJ5IHRvIGxvZ1xyXG4gIC8vLyA8L3N1bW1hcnk+XHJcbiAgLy8vIDxwYXJhbSBuYW1lPVwibWVzc2FnZURpcmVjdGlvblwiPm1lc3NhZ2UgZGlyZWN0aW9uIHJlbGF0aXZlIHRvIHRoZSBjdXJyZW50IG1vZHVsZSAoUklBIGNsaWVudCkuIENhbiBiZSBlaXRoZXIgTWVzc2FnZUVudGVyaW5nIG9yIE1lc3NhZ2VMZWF2aW5nPC9wYXJhbT5cclxuICAvLy8gPHBhcmFtIG5hbWU9XCJzdGF0dXNDb2RlXCI+SFRUUCBzdGF0dXMgY29kZTwvcGFyYW0+XHJcbiAgLy8vIDxwYXJhbSBuYW1lPVwiY29udGVudExlbmd0aFwiPmxlbmd0aCBvZiB0aGUgaHR0cCBtZXNzYWdlPC9wYXJhbT5cclxuICAvLy8gPHBhcmFtIG5hbWU9XCJodHRwSGVhZGVyc1wiPkhUVFAgaGVhZGVyczwvcGFyYW0+XHJcbiAgV3JpdGVCYXNpY1RvTG9nKG1lc3NhZ2VEaXJlY3Rpb246IExvZ2dlcl9NZXNzYWdlRGlyZWN0aW9uLCBjb250ZXh0SUQ6IHN0cmluZywgc2Vzc2lvbkNvdW50ZXI6IG51bWJlciwgY2xpZW50SUQ6IHN0cmluZywgc2VydmVySUQ6IHN0cmluZywgcmVzcG9uc2VUaW1lOiBudW1iZXIsIHN0YXR1c0NvZGU6IHN0cmluZywgaHR0cEhlYWRlcnM6IHN0cmluZywgY29udGVudExlbmd0aDogbnVtYmVyKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5Mb2dMZXZlbCA9PT0gTG9nZ2VyX0xvZ0xldmVscy5CYXNpYykge1xyXG4gICAgICBsZXQgdGV4dDogc3RyaW5nID0gaHR0cEhlYWRlcnM7XHJcbiAgICAgIHRleHQgPSB0ZXh0LnRyaW0oKTtcclxuICAgICAgdGV4dCA9IE5TdHJpbmcuUmVwbGFjZSh0ZXh0LCBcIlxcclxcblwiLCBcInxcIik7XHJcbiAgICAgIGxldCBhcmdfRTRfMDogc3RyaW5nID0gXCJSSUEsezB9X3sxfSx7Mn0sezN9LHs0fSx7NX0sLSx7Nn0sezd9LHs4fSx7OX0sezEwfSx7MTF9XCI7XHJcbiAgICAgIGxldCBleHByXzNFOiBhbnlbXSA9IG5ldyBBcnJheTxhbnk+KDEyKTtcclxuXHJcbiAgICAgIC8vIFRPRE8gOiBuZWVkIHRvIGNoZWNrIEhvdyB0byBoYW5kbGUgUHJvY2VzcyBjbGFzcy5cclxuICAgICAgLy8gZXhwcl8zRVswXSA9IFByb2Nlc3MuR2V0Q3VycmVudFByb2Nlc3MoKS5JZDtcclxuICAgICAgZXhwcl8zRVsxXSA9IFRocmVhZC5DdXJyZW50VGhyZWFkLk1hbmFnZWRUaHJlYWRJZDtcclxuICAgICAgZXhwcl8zRVsyXSA9IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKTtcclxuICAgICAgZXhwcl8zRVszXSA9ICgobWVzc2FnZURpcmVjdGlvbiA9PT0gTG9nZ2VyX01lc3NhZ2VEaXJlY3Rpb24uTWVzc2FnZUxlYXZpbmcpID8gXCJNU0dMXCIgOiBcIk1TR0VcIik7XHJcbiAgICAgIGV4cHJfM0VbNF0gPSBjb250ZXh0SUQ7XHJcbiAgICAgIGV4cHJfM0VbNV0gPSBzZXNzaW9uQ291bnRlcjtcclxuICAgICAgZXhwcl8zRVs2XSA9IGNsaWVudElEO1xyXG4gICAgICBleHByXzNFWzddID0gc2VydmVySUQ7XHJcbiAgICAgIGV4cHJfM0VbOF0gPSAoKHJlc3BvbnNlVGltZSAhPT0gMCkgPyByZXNwb25zZVRpbWUudG9TdHJpbmcoKSA6IFwiLVwiKTtcclxuICAgICAgbGV0IGFyZ19EM18xOiBudW1iZXIgPSA5O1xyXG4gICAgICBsZXQgYXJnX0QzXzI6IGFueTtcclxuICAgICAgYXJnX0QzXzIgPSBzdGF0dXNDb2RlO1xyXG4gICAgICBleHByXzNFW2FyZ19EM18xXSA9IGFyZ19EM18yO1xyXG4gICAgICBleHByXzNFWzEwXSA9IHRleHQ7XHJcbiAgICAgIGV4cHJfM0VbMTFdID0gY29udGVudExlbmd0aDtcclxuICAgICAgbGV0IHZhbHVlOiBzdHJpbmcgPSBOU3RyaW5nLkZvcm1hdChhcmdfRTRfMCwgZXhwcl8zRSk7XHJcbiAgICAgIGNvbnNvbGUubG9nKHZhbHVlKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8vLyA8c3VtbWFyeT5cclxuICAvLy8gV3JpdGVzIGEgcmVxdWVzdCBleGNlcHRpb24gYmFzaWMgbGV2ZWwgZW50cnkgdG8gbG9nXHJcbiAgLy8vIDwvc3VtbWFyeT5cclxuICAvLy8gPHBhcmFtIG5hbWU9XCJjb250ZXh0SURcIj48L3BhcmFtPlxyXG4gIC8vLyA8cGFyYW0gbmFtZT1cInNlc3Npb25Db3VudGVyXCI+PC9wYXJhbT5cclxuICAvLy8gPHBhcmFtIG5hbWU9XCJjbGllbnRJRFwiPjwvcGFyYW0+XHJcbiAgLy8vIDxwYXJhbSBuYW1lPVwic2VydmVySURcIj48L3BhcmFtPlxyXG4gIC8vLyA8cGFyYW0gbmFtZT1cImV4XCI+dGhlIGxvZ2dlZCBleGNlcHRpb248L3BhcmFtPlxyXG4gIFdyaXRlQmFzaWNFcnJvclRvTG9nKGNvbnRleHRJRDogc3RyaW5nLCBzZXNzaW9uQ291bnRlcjogbnVtYmVyLCBjbGllbnRJRDogc3RyaW5nLCBzZXJ2ZXJJRDogc3RyaW5nLCBleDogRXhjZXB0aW9uKTogdm9pZCB7XHJcbiAgICBEZWJ1Zy5Bc3NlcnQodGhpcy5Mb2dMZXZlbCA9PT0gTG9nZ2VyX0xvZ0xldmVscy5CYXNpYyk7XHJcblxyXG4gICAgLy8gVE9ETyA6IE5lZWQgdG8gY2hlY2sgaG93IHRvIGhhbmRsZSBQcm9jZXNzXHJcbiAgICAvLyBsZXQgdmFsdWU6IHN0cmluZyA9IE5TdHJpbmcuRm9ybWF0KFwiUklBLHswfV97MX0sezJ9LHszfSx7NH0sezV9LC0sezZ9LHs3fSwtLC0sLSx7OH0gezl9XCIsIFtcclxuICAgIC8vIFByb2Nlc3MuR2V0Q3VycmVudFByb2Nlc3MoKS5JZCwgVGhyZWFkLkN1cnJlbnRUaHJlYWQuTWFuYWdlZFRocmVhZElkLCBEYXRlVGltZS5VdGNOb3cuVG9TdHJpbmcoXCJ5eXl5LU1NLWRkVEhIOm1tOnNzLmZmZmZmZmZaXCIpLCBcIlJFU1wiLCBjb250ZXh0SUQsIHNlc3Npb25Db3VudGVyLCBjbGllbnRJRCwgc2VydmVySUQsIGV4LkdldFR5cGUoKSwgZXguTWVzc2FnZVxyXG4gICAgLy8gXSk7XHJcbiAgICAvLyBOQ29uc29sZS5Xcml0ZUxpbmUodmFsdWUpO1xyXG4gIH1cclxuXHJcbiAgLy8vIDxzdW1tYXJ5PlxyXG4gIC8vLyBXcml0ZSBhbiBlcnJvciB0byB0aGUgbG9nXHJcbiAgLy8vIDwvc3VtbWFyeT5cclxuICAvLy8gPHBhcmFtIG5hbWU9XCJtc2dcIj50aGUgbWVzc2FnZSB0byB3cml0ZSB0byB0aGUgbG9nPC9wYXJhbT5cclxuICBXcml0ZUVycm9yVG9Mb2cobXNnOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIHRoaXMuV3JpdGVUb0xvZyhcIkVSUk9SOiBcIiArIG1zZywgdHJ1ZSwgTG9nVHlwZS5lcnJvcik7XHJcbiAgfVxyXG5cclxuICAvLy8gPHN1bW1hcnk+XHJcbiAgLy8vIFdyaXRlIGFuIGludGVybmFsIGVycm9yIHRvIHRoZSBsb2cuIEFsc28gcHJpbnRzIHN0YWNrIHRyYWNlIGFsb25nIHdpdGggdGhlIG1lc3NhZ2VcclxuICAvLy8gPC9zdW1tYXJ5PlxyXG4gIC8vLyA8cGFyYW0gbmFtZT1cIm1zZ1wiPnRoZSBtZXNzYWdlIHRvIHdyaXRlIHRvIHRoZSBsb2c8L3BhcmFtPlxyXG4gIFdyaXRlRXhjZXB0aW9uVG9Mb2coZXg6IEV4Y2VwdGlvbik6IHZvaWQ7XHJcbiAgV3JpdGVFeGNlcHRpb25Ub0xvZyhleDogRXJyb3IpOiB2b2lkO1xyXG4gIFdyaXRlRXhjZXB0aW9uVG9Mb2coZXg6IEV4Y2VwdGlvbiwgbXNnOiBzdHJpbmcpOiB2b2lkO1xyXG4gIFdyaXRlRXhjZXB0aW9uVG9Mb2cobXNnT3JFeDogYW55LCBtc2c/OiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIGlmIChtc2dPckV4IGluc3RhbmNlb2YgRXJyb3IpIHtcclxuICAgICAgdGhpcy5Xcml0ZUV4Y2VwdGlvblRvTG9nXzIobXNnT3JFeCwgbXNnKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEgJiYgKG1zZ09yRXggIT09IG51bGwgfHwgbXNnT3JFeCBpbnN0YW5jZW9mIEV4Y2VwdGlvbikpIHtcclxuICAgICAgdGhpcy5Xcml0ZUV4Y2VwdGlvblRvTG9nXzEobXNnT3JFeCk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLldyaXRlRXhjZXB0aW9uVG9Mb2dfMyhtc2dPckV4LCBtc2cpO1xyXG4gIH1cclxuXHJcbiAgV3Jpd