UNPKG

@magic-xpa/utils

Version:

magic utils package

573 lines (572 loc) • 49.4 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'; var Logger = /** @class */ (function () { function Logger() { this.LogLevel = 0; 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> /** * @param {?} logLevel * @param {?} internalLogSync * @param {?} shouldBeep * @return {?} */ Logger.prototype.Initialize = /** * @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> /** * @param {?} msg * @param {?} openIfNecessary * @param {?=} logType * @return {?} */ Logger.prototype.WriteToLog = /** * @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> /** * @param {?} msg * @return {?} */ Logger.prototype.WriteServerToLog = /** * @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> /** * @param {?} msg * @return {?} */ Logger.prototype.WriteServerMessagesToLog = /** * @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> /** * @param {?} msg * @param {?} skipLine * @return {?} */ Logger.prototype.WriteSupportToLog = /** * @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> /** * @param {?} msg * @return {?} */ Logger.prototype.WriteGuiToLog = /** * @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> /** * @param {?} msg * @return {?} */ Logger.prototype.WriteDevToLog = /** * @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> /** * @param {?} messageDirection * @param {?} contextID * @param {?} sessionCounter * @param {?} clientID * @param {?} serverID * @param {?} responseTime * @param {?} statusCode * @param {?} httpHeaders * @param {?} contentLength * @return {?} */ Logger.prototype.WriteBasicToLog = /** * @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> /** * @param {?} contextID * @param {?} sessionCounter * @param {?} clientID * @param {?} serverID * @param {?} ex * @return {?} */ Logger.prototype.WriteBasicErrorToLog = /** * @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> /** * @param {?} msg * @return {?} */ Logger.prototype.WriteErrorToLog = /** * @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> /** * @return {?} */ Logger.prototype.Flush = /** * @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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTG9nZ2VyLmpzIiwic291cmNlUm9vdCI6Im5nOi8vQG1hZ2ljLXhwYS91dGlscy8iLCJzb3VyY2VzIjpbInNyYy9Mb2dnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLE9BQU8sRUFBQyxnQkFBZ0IsRUFBRSx1QkFBdUIsRUFBQyxNQUFNLFNBQVMsQ0FBQztBQUNsRSxPQUFPLEVBQUMsUUFBUSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFjLGFBQWEsRUFBRSxNQUFNLEVBQUMsTUFBTSxzQkFBc0IsQ0FBQztBQUM1RyxPQUFPLEVBQUMsYUFBYSxFQUFDLE1BQU0saUJBQWlCLENBQUM7QUFDOUMsT0FBTyxFQUFDLGFBQWEsRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBQzlDLE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUU1QyxPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSxNQUFNLENBQUM7OztJQUlyQyxPQUFRO0lBQ1IsVUFBTztJQUNQLFFBQUs7OztnQkFGTCxJQUFJO2dCQUNKLE9BQU87Z0JBQ1AsS0FBSzs7SUErVUw7d0JBclU2QixDQUFDOzBCQUtSLEtBQUs7S0FpVTFCO0lBL1RELHNCQUFXLGtCQUFROzs7O1FBSW5CO1lBQ0UsRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLFFBQVEsS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDO2dCQUM3QixNQUFNLENBQUMsUUFBUSxHQUFHLElBQUksTUFBTSxFQUFFLENBQUM7YUFDaEM7WUFDRCxNQUFNLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQztTQUN4Qjs7Ozs7UUFURCxVQUFvQixLQUFhO1lBQy9CLE1BQU0sQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDO1NBQ3pCOzs7T0FBQTtJQVNILGFBQWE7SUFDWCxxQkFBcUI7SUFDckIsY0FBYztJQUNkLG1DQUFtQztJQUNuQywwQ0FBMEM7Ozs7Ozs7SUFDMUMsMkJBQVU7Ozs7OztJQUFWLFVBQVcsUUFBMEIsRUFB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QUFHLENBQUMsRUFBRSxDQUFDOztZQUNwRCxJQUFJLFVBQVUsR0FBaUIsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3hDLGFBQWEsR0FBRyxhQUFhLEdBQUcsQ0FBQyxDQUFDO1lBRWxDLGFBQWEsQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUM7WUFFNUMsRUFBRSxDQUFDLENBQUMsYUFBYSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ3hCLGFBQWEsQ0FBQyxNQUFNLENBQUMsK0JBQStCLENBQUMsQ0FBQztnQkFDdEQsS0FBSyxDQUFDO2FBQ1A7U0FDRjtRQUNELElBQUksQ0FBQyxVQUFVLENBQUMsYUFBYSxDQUFDLFFBQVEsRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDO0tBQ2pEO0lBRUQsYUFBYTtJQUNiLHlCQUF5QjtJQUN6QixjQUFjOzs7O0lBQ2Qsc0JBQUs7OztJQUFMO0tBRUM7c0JBcFV5QixJQUFJO2lCQXJCaEM7O1NBb0JhLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0xvZ2dlcl9Mb2dMZXZlbHMsIExvZ2dlcl9NZXNzYWdlRGlyZWN0aW9ufSBmcm9tIFwiLi9lbnVtc1wiO1xyXG5pbXBvcnQge0RhdGVUaW1lLCBEZWJ1ZywgRXhjZXB0aW9uLCBOU3RyaW5nLCBTdGFja1RyYWNlLCBTdHJpbmdCdWlsZGVyLCBUaHJlYWR9IGZyb20gXCJAbWFnaWMteHBhL21zY29yZWxpYlwiO1xyXG5pbXBvcnQge09TRW52aXJvbm1lbnR9IGZyb20gXCIuL1BsYXRmb3JtVXRpbHNcIjtcclxuaW1wb3J0IHtEYXRlVGltZVV0aWxzfSBmcm9tIFwiLi9EYXRlVGltZVV0aWxzXCI7XHJcbmltcG9ydCB7WE1MQ29uc3RhbnRzfSBmcm9tIFwiLi9YTUxDb25zdGFudHNcIjtcclxuaW1wb3J0ICogYXMgSlNTdGFja1RyYWNlIGZyb20gJ3N0YWNrdHJhY2UtanMnO1xyXG5pbXBvcnQge2lzTnVsbE9yVW5kZWZpbmVkfSBmcm9tIFwidXRpbFwiO1xyXG5pbXBvcnQgSlNTdGFja0ZyYW1lID0gSlNTdGFja1RyYWNlLlN0YWNrRnJhbWU7XHJcblxyXG5leHBvcnQgZW51bSBMb2dUeXBlIHtcclxuICBpbmZvID0gMSxcclxuICB3YXJuaW5nLFxyXG4gIGVycm9yXHJcbn1cclxuXHJcblxyXG4vLy8gPHN1bW1hcnk+XHJcbi8vLyBMb2dnZXIgY2xhc3Mgd2lsbCB0YWtlIGNhcmUgb2YgY2xpZW50IHNpZGUgbG9nZ2luZyAuIEl0IHdpbGwgY2hlY2sgZm9yIHZhcmlvdXMgbG9nIGxldmVscyBhbmQgYWNjb3JkaW5nbHkgd2lsbCB3cml0ZSBtZXNzYWdlcyBpbiBsb2cgZmlsZS5cclxuLy8vIDwvc3VtbWFyeT5cclxuLy9AZHluYW1pY1xyXG5leHBvcnQgY2xhc3MgTG9nZ2VyIHtcclxuICBzdGF0aWMgaW5zdGFuY2U6IExvZ2dlciA9IG51bGw7XHJcbiAgTG9nTGV2ZWw6IExvZ2dlcl9Mb2dMZXZlbHMgPSAwOyAvLyBJbnRlcm5hbExvZ0xldmVsXHJcblxyXG4gIC8vLyA8c3VtbWFyeT5cclxuICAvLy8gV2hpbGUgd3JpdGluZyB0aGUgZXJyb3IgbWVzc2FnZXMgaW4gdGhlIGZpbGUgcGxheSB0aGUgYmVlcC5cclxuICAvLy8gPC9zdW1tYXJ5PlxyXG4gIFNob3VsZEJlZXA6IGJvb2xlYW4gPSBmYWxzZTtcclxuXHJcbiAgc3RhdGljIHNldCBJbnN0YW5jZSh2YWx1ZTogTG9nZ2VyKSB7XHJcbiAgICBMb2dnZXIuaW5zdGFuY2UgPSB2YWx1ZTtcclxuICB9XHJcblxyXG4gIHN0YXRpYyBnZXQgSW5zdGFuY2UoKTogTG9nZ2VyIHtcclxuICAgIGlmIChMb2dnZXIuaW5zdGFuY2UgPT09IG51bGwpIHtcclxuICAgICAgTG9nZ2VyLmluc3RhbmNlID0gbmV3IExvZ2dlcigpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIExvZ2dlci5pbnN0YW5jZTtcclxuICB9XHJcblxyXG4vLy8gPHN1bW1hcnk+XHJcbiAgLy8vIEluaXRpYWxpemUgbG9nZ2VyXHJcbiAgLy8vIDwvc3VtbWFyeT5cclxuICAvLy8gPHBhcmFtIG5hbWU9XCJsb2dMZXZlbFwiPjwvcGFyYW0+XHJcbiAgLy8vIDxwYXJhbSBuYW1lPVwiaW50ZXJuYWxMb2dTeW5jXCI+PC9wYXJhbT5cclxuICBJbml0aWFsaXplKGxvZ0xldmVsOiBMb2dnZXJfTG9nTGV2ZWxzLCBpbnRlcm5hbExvZ1N5bmM6IHN0cmluZywgc2hvdWxkQmVlcDogYm9vbGVhbik6IHZvaWQge1xyXG4gICAgdHJ5IHtcclxuICAgICAgLy8gbGV0IGxvZ1N5bmM6IExvZ1N5bmNNb2RlICA9IExvZ1N5bmNNb2RlLlNlc3Npb247XHJcbiAgICAgIHRoaXMuTG9nTGV2ZWwgPSBsb2dMZXZlbDtcclxuICAgICAgdGhpcy5TaG91bGRCZWVwID0gc2hvdWxkQmVlcDtcclxuXHJcbiAgICAgIC8vIFRPRE86IGltcGxlbWVudFxyXG4vLyAgIFN0cmluZyBzdHJMb2dTeW5jID0gaW50ZXJuYWxMb2dTeW5jO1xyXG4vLyAgIGlmICghc3RyaW5nLklzTnVsbE9yRW1wdHkoc3RyTG9nU3luYykpXHJcbi8vIHtcclxuLy8gICBpZiAoc3RyTG9nU3luYy5TdGFydHNXaXRoKFwiTVwiLCBTdHJpbmdDb21wYXJpc29uLkN1cnJlbnRDdWx0dXJlSWdub3JlQ2FzZSkpXHJcbi8vICAgbG9nU3luYyA9IExvZ1N5bmNNb2RlLk1lc3NhZ2U7XHJcbi8vICAgZWxzZSBpZiAoc3RyTG9nU3luYy5TdGFydHNXaXRoKFwiRlwiLCBTdHJpbmdDb21wYXJpc29uLkN1cnJlbnRDdWx0dXJlSWdub3JlQ2FzZSkpXHJcbi8vICAgbG9nU3luYyA9IExvZ1N5bmNNb2RlLkZsdXNoO1xyXG4vLyB9XHJcbi8vXHJcbiAgICB9XHJcbiAgICBjYXRjaCAoZSkge1xyXG4gICAgICB0aGlzLldyaXRlRGV2VG9Mb2coXCJDbGllbnRNYW5hZ2VyLmluaXQoKTogXCIgKyBlLk1lc3NhZ2UpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy8vIDxzdW1tYXJ5Pjwvc3VtbWFyeT5cclxuICAvLy8gPHBhcmFtIG5hbWU9XCJsb2dMZXZlbFwiPjwvcGFyYW0+XHJcbiAgLy8vIDxyZXR1cm5zPjwvcmV0dXJucz5cclxuXHJcbiAgU2hvdWxkTG9nKGxvZ0xldmVsOiBMb2dnZXJfTG9nTGV2ZWxzKTogYm9vbGVhbjtcclxuICBTaG91bGRMb2coKTogYm9vbGVhbjtcclxuICBTaG91bGRMb2cobG9nTGV2ZWw/OiBMb2dnZXJfTG9nTGV2ZWxzKTogYm9vbGVhbiB7XHJcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSlcclxuICAgICAgcmV0dXJuIHRoaXMuU2hvdWxkTG9nXzAobG9nTGV2ZWwpO1xyXG4gICAgZWxzZVxyXG4gICAgICByZXR1cm4gdGhpcy5TaG91bGRMb2dfMSgpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBTaG91bGRMb2dfMChsb2dMZXZlbDogTG9nZ2VyX0xvZ0xldmVscyk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIHRoaXMuTG9nTGV2ZWwgPT09IGxvZ0xldmVsO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBTaG91bGRMb2dfMSgpOiBib29sZWFuIHtcclxuICAgIHJldHVybiB0aGlzLkxvZ0xldmVsID4gTG9nZ2VyX0xvZ0xldmVscy5Ob25lO1xyXG4gIH1cclxuXHJcbiAgU2hvdWxkTG9nU2VydmVyUmVsYXRlZE1lc3NhZ2VzKCk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuICh0aGlzLlNob3VsZExvZ0V4dGVuZGVkU2VydmVyUmVsYXRlZE1lc3NhZ2VzKCkgfHwgTG9nZ2VyLkluc3RhbmNlLlNob3VsZExvZyhMb2dnZXJfTG9nTGV2ZWxzLlNlcnZlcikpICYmIHRoaXMuTG9nTGV2ZWwgIT09IExvZ2dlcl9Mb2dMZXZlbHMuQmFzaWM7XHJcbiAgfVxyXG5cclxuICBTaG91bGRMb2dFeHRlbmRlZFNlcnZlclJlbGF0ZWRNZXNzYWdlcygpOiBib29sZWFuIHtcclxuICAgIHJldHVybiAoTG9nZ2VyLkluc3RhbmNlLlNob3VsZExvZyhMb2dnZXJfTG9nTGV2ZWxzLlNlcnZlck1lc3NhZ2VzKSB8fCBMb2dnZXIuSW5zdGFuY2UuU2hvdWxkTG9nKExvZ2dlcl9Mb2dMZXZlbHMuU3VwcG9ydCkgfHwgTG9nZ2VyLkluc3RhbmNlLlNob3VsZExvZyhMb2dnZXJfTG9nTGV2ZWxzLkRldmVsb3BtZW50KSkgJiYgdGhpcy5Mb2dMZXZlbCAhPT0gTG9nZ2VyX0xvZ0xldmVscy5CYXNpYztcclxuICB9XHJcblxyXG4gIC8vLyA8c3VtbWFyeT48L3N1bW1hcnk+XHJcbiAgLy8vIDxwYXJhbSBuYW1lPVwibXNnXCI+PC9wYXJhbT5cclxuICAvLy8gPHBhcmFtIG5hbWU9XCJvcGVuSWZOZWNlc3NhcnlcIj5vcGVuIHRoZSBsb2cgZmlsZSBpZiBub3Qgb3BlbmVkIHlldDwvcGFyYW0+XHJcblxyXG4gIFdyaXRlVG9Mb2cobXNnOiBzdHJpbmcsIG9wZW5JZk5lY2Vzc2FyeTogYm9vbGVhbiwgbG9nVHlwZTogTG9nVHlwZSA9IExvZ1R5cGUuaW5mbyk6IHZvaWQge1xyXG5cclxuICAgIGlmICh0aGlzLkxvZ0xldmVsID4gTG9nZ2VyX0xvZ0xldmVscy5Ob25lIHx8IG9wZW5JZk5lY2Vzc2FyeSkge1xyXG4gICAgICBtc2cgPSBOU3RyaW5nLkZvcm1hdChcInswfSB7MX1cIiwgKHRoaXMuTG9nTGV2ZWwgPT09IExvZ2dlcl9Mb2dMZXZlbHMuQmFzaWMpID8gbmV3IERhdGUoKS50b0lTT1N0cmluZygpIDogRGF0ZVRpbWVVdGlscy5Ub1N0cmluZyhEYXRlVGltZS5Ob3csIFhNTENvbnN0YW50cy5FUlJPUl9MT0dfVElNRV9GT1JNQVQsIHRoaXMpLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICBtc2cpO1xyXG5cclxuICAgICAgc3dpdGNoIChsb2dUeXBlKSB7XHJcbiAgICAgICAgY2FzZSBMb2dUeXBlLmVycm9yOlxyXG4gICAgICAgICAgY29uc29sZS5lcnJvcihtc2cpO1xyXG4gICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgY2FzZSBMb2dUeXBlLndhcm5pbmc6XHJcbiAgICAgICAgICBjb25zb2xlLndhcm4obXNnKTtcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICBjb25zb2xlLmxvZyhtc2cpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvLy8gPHN1bW1hcnk+XHJcbiAgLy8vIHdyaXRlIGEgc2VydmVyIGFjY2VzcyB0byB0aGUgbG9nXHJcbiAgLy8vIDwvc3VtbWFyeT5cclxuICAvLy8gPHBhcmFtIG5hbWU9XCJtc2dcIj50aGUgbWVzc2FnZSB0byB3cml0ZSB0byB0aGUgbG9nPC9wYXJhbT5cclxuICBXcml0ZVNlcnZlclRvTG9nKG1zZzogc3RyaW5nKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5TaG91bGRMb2dTZXJ2ZXJSZWxhdGVkTWVzc2FnZXMoKSkge1xyXG4gICAgICB0aGlzLldyaXRlVG9Mb2coTlN0cmluZy5Gb3JtYXQoXCJTZXJ2ZXIsIFRocmVhZD17MH06IFwiLCBUaHJlYWQuQ3VycmVudFRocmVhZC5NYW5hZ2VkVGhyZWFkSWQpICsgbXNnLCBmYWxzZSwgTG9nVHlwZS5pbmZvKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8vLyA8c3VtbWFyeT5cclxuICAvLy8gd3JpdGUgYSBzZXJ2ZXIgYWNjZXNzIHRvIHRoZSBsb2csIGluY2x1ZGluZyB0aGUgY29udGVudFxyXG4gIC8vLyA8L3N1bW1hcnk+XHJcbiAgLy8vIDxwYXJhbSBuYW1lPVwibXNnXCI+dGhlIG1lc3NhZ2UgdG8gd3JpdGUgdG8gdGhlIGxvZzwvcGFyYW0+XHJcbiAgV3JpdGVTZXJ2ZXJNZXNzYWdlc1RvTG9nKG1zZzogc3RyaW5nKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5TaG91bGRMb2dFeHRlbmRlZFNlcnZlclJlbGF0ZWRNZXNzYWdlcygpKSB7XHJcbiAgICAgIHRoaXMuV3JpdGVUb0xvZyhcIlNlcnZlciM6IFwiICsgbXNnLCBmYWxzZSwgTG9nVHlwZS5pbmZvKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8vLyA8c3VtbWFyeT5Xcml0ZSBhIFFDIG1lc3NhZ2UgdG8gdGhlIGxvZzwvc3VtbWFyeT5cclxuICAvLy8gPHBhcmFtIG5hbWU9XCJtc2dcIj50aGUgbWVzc2FnZSB0byB3cml0ZSB0byB0aGUgbG9nPC9wYXJhbT5cclxuICBXcml0ZVN1cHBvcnRUb0xvZyhtc2c6IHN0cmluZywgc2tpcExpbmU6IGJvb2xlYW4pOiB2b2lkIHtcclxuXHJcbiAgICBpZiAodGhpcy5Mb2dMZXZlbCA+PSBMb2dnZXJfTG9nTGV2ZWxzLlN1cHBvcnQgJiYgdGhpcy5Mb2dMZXZlbCAhPT0gTG9nZ2VyX0xvZ0xldmVscy5CYXNpYykge1xyXG4gICAgICBpZiAoc2tpcExpbmUpIHtcclxuICAgICAgICB0aGlzLldyaXRlVG9Mb2coXCJTVVBQT1JUOiBcIiArIG1zZywgZmFsc2UsIExvZ1R5cGUuaW5mbyk7XHJcbiAgICAgIH1cclxuICAgICAgZWxzZSB7XHJcbiAgICAgICAgdGhpcy5Xcml0ZVRvTG9nKFwiU1VQUE9SVDogXCIgKyBtc2cgKyBPU0Vudmlyb25tZW50LkVvbFNlcSArIFwiLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cIiwgZmFsc2UsIExvZ1R5cGUuaW5mbyk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8vLyA8c3VtbWFyeT5cclxuICAvLy8gd3JpdGUgYSBwZXJmb3JtYW5jZSBtZXNzYWdlIHRvIHRoZSBsb2dcclxuICAvLy8gPC9zdW1tYXJ5PlxyXG4gIC8vLyA8cGFyYW0gbmFtZT1cIm1zZ1wiPnRoZSBtZXNzYWdlIHRvIHdyaXRlIHRvIHRoZSBsb2c8L3BhcmFtPlxyXG4gIFdyaXRlR3VpVG9Mb2cobXNnOiBzdHJpbmcpOiB2b2lkIHtcclxuXHJcbiAgICBpZiAodGhpcy5Mb2dMZXZlbCA+PSBMb2dnZXJfTG9nTGV2ZWxzLkd1aSAmJiB0aGlzLkxvZ0xldmVsICE9PSBMb2dnZXJfTG9nTGV2ZWxzLkJhc2ljKSB7XHJcbiAgICAgIHRoaXMuV3JpdGVUb0xvZyhtc2csIGZhbHNlLCBMb2dUeXBlLmluZm8pO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy8vIDxzdW1tYXJ5PlxyXG4gIC8vLyB3cml0ZSBhIGRldmVsb3BlciBtZXNzYWdlIHRvIHRoZSBsb2dcclxuICAvLy8gPC9zdW1tYXJ5PlxyXG4gIC8vLyA8cGFyYW0gbmFtZT1cIm1zZ1wiPnRoZSBtZXNzYWdlIHRvIHdyaXRlIHRvIHRoZSBsb2c8L3BhcmFtPlxyXG4gIFdyaXRlRGV2VG9Mb2cobXNnOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLkxvZ0xldmVsID49IExvZ2dlcl9Mb2dMZXZlbHMuRGV2ZWxvcG1lbnQgJiYgdGhpcy5Mb2dMZXZlbCAhPT0gTG9nZ2VyX0xvZ0xldmVscy5CYXNpYykge1xyXG4gICAgICB0aGlzLldyaXRlVG9Mb2coXCJERVY6IFwiICsgbXNnLCBmYWxzZSwgTG9nVHlwZS5pbmZvKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8vLyA8c3VtbWFyeT5cclxuICAvLy8gV3JpdGVzIGEgYmFzaWMgbGV2ZWwgZW50cnkgdG8gbG9nXHJcbiAgLy8vIDwvc3VtbWFyeT5cclxuICAvLy8gPHBhcmFtIG5hbWU9XCJtZXNzYWdlRGlyZWN0aW9uXCI+bWVzc2FnZSBkaXJlY3Rpb24gcmVsYXRpdmUgdG8gdGhlIGN1cnJlbnQgbW9kdWxlIChSSUEgY2xpZW50KS4gQ2FuIGJlIGVpdGhlciBNZXNzYWdlRW50ZXJpbmcgb3IgTWVzc2FnZUxlYXZpbmc8L3BhcmFtPlxyXG4gIC8vLyA8cGFyYW0gbmFtZT1cInN0YXR1c0NvZGVcIj5IVFRQIHN0YXR1cyBjb2RlPC9wYXJhbT5cclxuICAvLy8gPHBhcmFtIG5hbWU9XCJjb250ZW50TGVuZ3RoXCI+bGVuZ3RoIG9mIHRoZSBodHRwIG1lc3NhZ2U8L3BhcmFtPlxyXG4gIC8vLyA8cGFyYW0gbmFtZT1cImh0dHBIZWFkZXJzXCI+SFRUUCBoZWFkZXJzPC9wYXJhbT5cclxuICBXcml0ZUJhc2ljVG9Mb2cobWVzc2FnZURpcmVjdGlvbjogTG9nZ2VyX01lc3NhZ2VEaXJlY3Rpb24sIGNvbnRleHRJRDogc3RyaW5nLCBzZXNzaW9uQ291bnRlcjogbnVtYmVyLCBjbGllbnRJRDogc3RyaW5nLCBzZXJ2ZXJJRDogc3RyaW5nLCByZXNwb25zZVRpbWU6IG51bWJlciwgc3RhdHVzQ29kZTogc3RyaW5nLCBodHRwSGVhZGVyczogc3RyaW5nLCBjb250ZW50TGVuZ3RoOiBudW1iZXIpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLkxvZ0xldmVsID09PSBMb2dnZXJfTG9nTGV2ZWxzLkJhc2ljKSB7XHJcbiAgICAgIGxldCB0ZXh0OiBzdHJpbmcgPSBodHRwSGVhZGVycztcclxuICAgICAgdGV4dCA9IHRleHQudHJpbSgpO1xyXG4gICAgICB0ZXh0ID0gTlN0cmluZy5SZXBsYWNlKHRleHQsIFwiXFxyXFxuXCIsIFwifFwiKTtcclxuICAgICAgbGV0IGFyZ19FNF8wOiBzdHJpbmcgPSBcIlJJQSx7MH1fezF9LHsyfSx7M30sezR9LHs1fSwtLHs2fSx7N30sezh9LHs5fSx7MTB9LHsxMX1cIjtcclxuICAgICAgbGV0IGV4cHJfM0U6IGFueVtdID0gbmV3IEFycmF5PGFueT4oMTIpO1xyXG5cclxuICAgICAgLy8gVE9ETyA6IG5lZWQgdG8gY2hlY2sgSG93IHRvIGhhbmRsZSBQcm9jZXNzIGNsYXNzLlxyXG4gICAgICAvLyBleHByXzNFWzBdID0gUHJvY2Vzcy5HZXRDdXJyZW50UHJvY2VzcygpLklkO1xyXG4gICAgICBleHByXzNFWzFdID0gVGhyZWFkLkN1cnJlbnRUaHJlYWQuTWFuYWdlZFRocmVhZElkO1xyXG4gICAgICBleHByXzNFWzJdID0gbmV3IERhdGUoKS50b0lTT1N0cmluZygpO1xyXG4gICAgICBleHByXzNFWzNdID0gKChtZXNzYWdlRGlyZWN0aW9uID09PSBMb2dnZXJfTWVzc2FnZURpcmVjdGlvbi5NZXNzYWdlTGVhdmluZykgPyBcIk1TR0xcIiA6IFwiTVNHRVwiKTtcclxuICAgICAgZXhwcl8zRVs0XSA9IGNvbnRleHRJRDtcclxuICAgICAgZXhwcl8zRVs1XSA9IHNlc3Npb25Db3VudGVyO1xyXG4gICAgICBleHByXzNFWzZdID0gY2xpZW50SUQ7XHJcbiAgICAgIGV4cHJfM0VbN10gPSBzZXJ2ZXJJRDtcclxuICAgICAgZXhwcl8zRVs4XSA9ICgocmVzcG9uc2VUaW1lICE9PSAwKSA/IHJlc3BvbnNlVGltZS50b1N0cmluZygpIDogXCItXCIpO1xyXG4gICAgICBsZXQgYXJnX0QzXzE6IG51bWJlciA9IDk7XHJcbiAgICAgIGxldCBhcmdfRDNfMjogYW55O1xyXG4gICAgICBhcmdfRDNfMiA9IHN0YXR1c0NvZGU7XHJcbiAgICAgIGV4cHJfM0VbYXJnX0QzXzFdID0gYXJnX0QzXzI7XHJcbiAgICAgIGV4cHJfM0VbMTBdID0gdGV4dDtcclxuICAgICAgZXhwcl8zRVsxMV0gPSBjb250ZW50TGVuZ3RoO1xyXG4gICAgICBsZXQgdmFsdWU6IHN0cmluZyA9IE5TdHJpbmcuRm9ybWF0KGFyZ19FNF8wLCBleHByXzNFKTtcclxuICAgICAgY29uc29sZS5sb2codmFsdWUpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy8vIDxzdW1tYXJ5PlxyXG4gIC8vLyBXcml0ZXMgYSByZXF1ZXN0IGV4Y2VwdGlvbiBiYXNpYyBsZXZlbCBlbnRyeSB0byBsb2dcclxuICAvLy8gPC9zdW1tYXJ5PlxyXG4gIC8vLyA8cGFyYW0gbmFtZT1cImNvbnRleHRJRFwiPjwvcGFyYW0+XHJcbiAgLy8vIDxwYXJhbSBuYW1lPVwic2Vzc2lvbkNvdW50ZXJcIj48L3BhcmFtPlxyXG4gIC8vLyA8cGFyYW0gbmFtZT1cImNsaWVudElEXCI+PC9wYXJhbT5cclxuICAvLy8gPHBhcmFtIG5hbWU9XCJzZXJ2ZXJJRFwiPjwvcGFyYW0+XHJcbiAgLy8vIDxwYXJhbSBuYW1lPVwiZXhcIj50aGUgbG9nZ2VkIGV4Y2VwdGlvbjwvcGFyYW0+XHJcbiAgV3JpdGVCYXNpY0Vycm9yVG9Mb2coY29udGV4dElEOiBzdHJpbmcsIHNlc3Npb25Db3VudGVyOiBudW1iZXIsIGNsaWVudElEOiBzdHJpbmcsIHNlcnZlcklEOiBzdHJpbmcsIGV4OiBFeGNlcHRpb24pOiB2b2lkIHtcclxuICAgIERlYnVnLkFzc2VydCh0aGlzLkxvZ0xldmVsID09PSBMb2dnZXJfTG9nTGV2ZWxzLkJhc2ljKTtcclxuXHJcbiAgICAvLyBUT0RPIDogTmVlZCB0byBjaGVjayBob3cgdG8gaGFuZGxlIFByb2Nlc3NcclxuICAgIC8vIGxldCB2YWx1ZTogc3RyaW5nID0gTlN0cmluZy5Gb3JtYXQoXCJSSUEsezB9X3sxfSx7Mn0sezN9LHs0fSx7NX0sLSx7Nn0sezd9LC0sLSwtLHs4fSB7OX1cIiwgW1xyXG4gICAgLy8gUHJvY2Vzcy5HZXRDdXJyZW50UHJvY2VzcygpLklkLCBUaHJlYWQuQ3VycmVudFRocmVhZC5NYW5hZ2VkVGhyZWFkSWQsIERhdGVUaW1lLlV0Y05vdy5Ub1N0cmluZyhcInl5eXktTU0tZGRUSEg6bW06c3MuZmZmZmZmZlpcIiksIFwiUkVTXCIsIGNvbnRleHRJRCwgc2Vzc2lvbkNvdW50ZXIsIGNsaWVudElELCBzZXJ2ZXJJRCwgZXguR2V0VHlwZSgpLCBleC5NZXNzYWdlXHJcbiAgICAvLyBdKTtcclxuICAgIC8vIE5Db25zb2xlLldyaXRlTGluZSh2YWx1ZSk7XHJcbiAgfVxyXG5cclxuICAvLy8gPHN1bW1hcnk+XHJcbiAgLy8vIFdyaXRlIGFuIGVycm9yIHRvIHRoZSBsb2dcclxuICAvLy8gPC9zdW1tYXJ5PlxyXG4gIC8vLyA8cGFyYW0gbmFtZT1cIm1zZ1wiPnRoZSBtZXNzYWdlIHRvIHdyaXRlIHRvIHRoZSBsb2c8L3BhcmFtPlxyXG4gIFdyaXRlRXJyb3JUb0xvZyhtc2c6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgdGhpcy5Xcml0ZVRvTG9nKFwiRVJST1I6IFwiICsgbXNnLCB0cnVlLCBMb2dUeXBlLmVycm9yKTtcclxuICB9XHJcblxyXG4gIC8vLyA8c3VtbWFyeT5cclxuICAvLy8gV3JpdGUgYW4gaW50ZXJuYWwgZXJyb3IgdG8gdGhlIGxvZy4gQWxzbyBwcmludHMgc3RhY2sgdHJhY2UgYWxvbmcgd2l0aCB0aGUgbWVzc2FnZVxyXG4gIC8vLyA8L3N1bW1hcnk+XHJcbiAgLy8vIDxwYXJhbSBuYW1lPVwibXNnXCI+dGhlIG1lc3NhZ2UgdG8gd3JpdGUgdG8gdGhlIGxvZzwvcGFyYW0+XHJcbiAgV3JpdGVFeGNlcHRpb25Ub0xvZyhleDogRXhjZXB0aW9uKTogdm9pZDtcclxuICBXcml0ZUV4Y2VwdGlvblRvTG9nKGV4OiBFcnJvcik6IHZvaWQ7XHJcbiAgV3JpdGVFeGNlcHRpb25Ub0xvZyhleDogRXhjZXB0aW9uLCBtc2c6IHN0cmluZyk6IHZvaWQ7XHJcbiAgV3JpdGVFeGNlcHRpb25Ub0xvZyhtc2dPckV4OiBhbnksIG1zZz86IHN0cmluZyk6IHZvaWQge1xyXG4gICAgaWYgKG1zZ09yRXggaW5zdGFuY2VvZiBFcnJvcikge1xyXG4gICAgICB0aGlzLldyaXRlRXhjZXB0aW9uVG9Mb2dfMihtc2dPckV4LCBtc2cpO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSAmJiAobXNnT3JFeCAhPT0gbnVsbCB8fCBtc2dPckV4IGluc3RhbmNlb2YgRXhjZXB0aW9uKSkge1xyXG4gICAgICB0aGlzLldyaXRlRXhjZXB0aW9uVG9Mb2dfMShtc2dPckV4KTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuV3JpdGVFeGNlcHRpb25Ub0xvZ18zKG1zZ09yRXgsIG1zZyk7XHJcbiAgfVxyXG5cclxuICBXcml0ZUV4Y2VwdGlvblRvTG9nV2l0aE1zZyhtc2c6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgdGhpcy5Xcml0ZVRvTG9nKFwiRVJST1I6IFwiICsgbXNnLCB0cnVlLCBMb2dUeXBlLmVycm9yKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgV3JpdGVFeGNlcHRpb25Ub0xvZ18xKGV4OiBFeGNlcHRpb24pOiB2b2lkIHtcclxuICAgIHRoaXMuV3JpdGVFeGNlcHRpb25Ub0xvZ1dpdGhNc2coTlN0cmluZy5Gb3JtYXQoXCJ7MH0gOiB7MX17Mn17M317NH1cIiwgW1xyXG4gICAgICBleC5HZXRUeXBlKCksIE9TRW52aXJvbm1lbnQuRW9sU2VxLCBleC5TdGFja1RyYWNlLCBPU0Vudmlyb25tZW50LkVvbFNlcSwgZXguTWVzc2FnZVxyXG4gICAgXSkpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBXcml0ZUV4Y2VwdGlvblRvTG9nXzIoZXg6IEVycm9yLCBtZXNzYWdlOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIGlmIChpc051bGxPclVuZGVmaW5lZChtZXNzYWdlKSlcclxuICAgICAgdGhpcy5Xcml0ZUV4Y2VwdGlvblRvTG9nV2l0aE1zZyhOU3RyaW5nLkZvcm1hdChcInswfXsxfXsyfVwiLCBbZXguc3RhY2ssIE9TRW52aXJvbm1lbnQuRW9sU2VxLCBleC5tZXNzYWdlXSkpO1xyXG4gICAgZWxzZVxyXG4gICAgICB0aGlzLldyaXRlRXhjZXB0aW9uVG9Mb2dXaXRoTXNnKE5TdHJpbmcuRm9ybWF0KFwiezB9ezF9ezJ9ezR9ezV9XCIsIFttZXNzYWdlLCBPU0Vudmlyb25tZW50LkVvbFNlcSwgZXguc3RhY2ssIE9TRW52aXJvbm1lbnQuRW9sU2VxLCBleC5tZXNzYWdlXSkpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBXcml0ZUV4Y2VwdGlvblRvTG9nXzMoZXg6IEV4Y2VwdGlvbiwgbXNnOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIHRoaXMuV3JpdGVFeGNlcHRpb25Ub0xvZ1dpdGhNc2coTlN0cmluZy5Gb3JtYXQoXCJ7MH0sIHsxfSA6IHsyfXszfXs0fXs1fVwiLCBbXHJcbiAgICAgIGV4LkdldFR5cGUoKSwgbXNnLCBPU0Vudmlyb25tZW50LkVvbFNlcSwgZXguU3RhY2tUcmFjZSwgT1NFbnZpcm9ubWVudC5Fb2xTZXEsIGV4Lk1lc3NhZ2VcclxuICAgIF0pKTtcclxuICB9XHJcblxyXG4gIC8vLyA8c3VtbWFyeT4gd3JpdGUgYSB3YXJuaW5nIHRvIHRoZSBsb2c8L3N1bW1hcnk+XHJcbiAgLy8vIDxwYXJhbSBuYW1lPVwibXNnXCI+dGhlIG1lc3NhZ2UgdG8gd3JpdGUgdG8gdGhlIGxvZzwvcGFyYW0+XHJcbiAgV3JpdGVXYXJuaW5nVG9Mb2coZXg6IEV4Y2VwdGlvbik6IHZvaWQ7XHJcbiAgV3JpdGVXYXJuaW5nVG9Mb2coZXg6IEV4Y2VwdGlvbiwgbXNnOiBzdHJpbmcpOiB2b2lkO1xyXG4gIFdyaXRlV2FybmluZ1RvTG9nKGV4OiBFcnJvcik6IHZvaWQ7XHJcbiAgV3JpdGVXYXJuaW5nVG9Mb2cobXNnT3JFeDogYW55LCBtc2c/OiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAxICYmIG1zZ09yRXggIT09IG51bGwpIHtcclxuICAgICAgaWYgKG1zZ09yRXggaW5zdGFuY2VvZiBFeGNlcHRpb24pXHJcbiAgICAgICAgdGhpcy5Xcml0ZVdhcm5pbmdUb0xvZ18xKG1zZ09yRXgpO1xyXG4gICAgICBlbHNlIGlmIChtc2dPckV4IGluc3RhbmNlb2YgRXJyb3IpXHJcbiAgICAgICAgdGhpcy5Xcml0ZVdhcm5pbmdUb0xvZ18yKG1zZ09yRXgpO1xyXG4gICAgfVxyXG4gICAgZWxzZVxyXG4gICAgICB0aGlzLldyaXRlV2FybmluZ1RvTG9nXzMobXNnT3JFeCwgbXNnKTtcclxuICB9XHJcblxyXG4gIFdyaXRlV2FybmluZ1RvTG9nV2l0aE1zZyhtc2c6IHN0cmluZyk6IHZvaWQge1xyXG5cclxuICAgIGlmICh0aGlzLkxvZ0xldmVsICE9PSBMb2dnZXJfTG9nTGV2ZWxzLkJhc2ljKSB7XHJcbiAgICAgIHRoaXMuV3JpdGVUb0xvZyhcIldBUk5JTkc6IFwiICsgbXNnLCB0cnVlLCBMb2dUeXBlLndhcm5pbmcpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBXcml0ZVdhcm5pbmdUb0xvZ18xKGV4OiBFeGNlcHRpb24pOiB2b2lkIHtcclxuICAgIHRoaXMuV3JpdGVXYXJuaW5nVG9Mb2dXaXRoTXNnKGV4LkdldFR5cGUoKSArIFwiIDogXCIgKyBPU0Vudmlyb25tZW50LkVvbFNlcSArIGV4LlN0YWNrVHJhY2UgKyBPU0Vudmlyb25tZW50LkVvbFNlcSArIGV4Lk1lc3NhZ2UpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBXcml0ZVdhcm5pbmdUb0xvZ18yKGV4OiBFcnJvcik6IHZvaWQge1xyXG4gICAgdGhpcy5Xcml0ZVdhcm5pbmdUb0xvZ1dpdGhNc2coTlN0cmluZy5Gb3JtYXQoXCJ7MH17MX17Mn1cIiwgW1xyXG4gICAgICBleC5zdGFjaywgT1NFbnZpcm9ubWVudC5Fb2xTZXEsIGV4Lm1lc3NhZ2VcclxuICAgIF0pKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgV3JpdGVXYXJuaW5nVG9Mb2dfMyhleDogRXhjZXB0aW9uLCBtc2c6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgdGhpcy5Xcml0ZVdhcm5pbmdUb0xvZ1dpdGhNc2coTlN0cmluZy5Gb3JtYXQoXCJ7MH0sIHsxfSA6IHsyfXszfXs0fXs1fVwiLCBbXHJcbiAgICAgIGV4LkdldFR5cGUoKSwgbXNnLCBPU0Vudmlyb25tZW50LkVvbFNlcSwgZXguU3RhY2tUcmFjZSwgT1NFbnZpcm9ubWVudC5Fb2xTZXEsIGV4Lk1lc3NhZ2VcclxuICAgIF0pKTtcclxuICB9XHJcblxyXG4gIFdyaXRlU3RhY2tUcmFjZShzdGFja1RyYWNlOiBTdGFja1RyYWNlLCBmcmFtZXNUb1ByaW50OiBudW1iZXIsIHRyYWNlVGl0bGU6IHN0cmluZyk6IHZvaWQge1xyXG5cclxuICAgIGlmICh0cmFjZVRpdGxlID09PSBudWxsKSB7XHJcbiAgICAgIHRyYWNlVGl0bGUgPSBcIlN0YWNrIHRyYWNlOlwiO1xyXG4gICAgfVxyXG4gICAgbGV0IHN0cmluZ0J1aWxkZXI6IFN0cmluZ0J1aWxkZXIgPSBuZXcgU3RyaW5nQnVpbGRlcih0cmFjZVRpdGxlICsgT1NFbnZpcm9ubWVudC5Fb2xTZXEpO1xyXG4gICAgbGV0IGZyYW1lczogSlNTdGFja0ZyYW1lW10gPSBzdGFja1RyYWNlLkdldEZyYW1lcygpO1xyXG4gICAgbGV0IGFycmF5OiBKU1N0YWNrRnJhbWVbXSA9IGZyYW1lcztcclxuICAgIGZvciAobGV0IGk6IG51bWJlciA9IDA7IGkgPCBhcnJheS5sZW5ndGg7IGkgPSBpICsgMSkge1xyXG4gICAgICBsZXQgc3RhY2tGcmFtZTogSlNTdGFja0ZyYW1lID0gYXJyYXlbaV07XHJcbiAgICAgIGZyYW1lc1RvUHJpbnQgPSBmcmFtZXNUb1ByaW50IC0gMTtcclxuXHJcbiAgICAgIHN0cmluZ0J1aWxkZXIuQXBwZW5kKHN0YWNrRnJhbWUudG9TdHJpbmcoKSk7XHJcblxyXG4gICAgICBpZiAoZnJhbWVzVG9QcmludCA9PT0gMCkge1xyXG4gICAgICAgIHN0cmluZ0J1aWxkZXIuQXBwZW5kKFwiXFx0Li4uIG1vcmUgc3RhY2sgZnJhbWVzIC4uLlxcblwiKTtcclxuICAgICAgICBicmVhaztcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgdGhpcy5Xcml0ZVRvTG9nKHN0cmluZ0J1aWxkZXIuVG9TdHJpbmcoKSwgdHJ1ZSk7XHJcbiAgfVxyXG5cclxuICAvLy8gPHN1bW1hcnk+XHJcbiAgLy8vIEZsdXNoIHRoZSBsb2cgd3JpdGVyLlxyXG4gIC8vLyA8L3N1bW1hcnk+XHJcbiAgRmx1c2goKTogdm9pZCB7XHJcblxyXG4gIH1cclxuXHJcbiAgY29uc3RydWN0b3IoKSB7XHJcbiAgfVxyXG59XHJcbiJdfQ==