@magic-xpa/utils
Version:
magic utils package
390 lines (389 loc) • 42.8 kB
JavaScript
/**
* @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} */
const LogType = {
info: 1,
warning: 2,
error: 3,
};
export { LogType };
LogType[LogType.info] = 'info';
LogType[LogType.warning] = 'warning';
LogType[LogType.error] = 'error';
export class Logger {
constructor() {
this.LogLevel = 0;
this.ShouldBeep = false;
}
/**
* @param {?} value
* @return {?}
*/
static set Instance(value) {
Logger.instance = value;
}
/**
* @return {?}
*/
static get Instance() {
if (Logger.instance === null) {
Logger.instance = new Logger();
}
return Logger.instance;
}
/**
* @param {?} logLevel
* @param {?} internalLogSync
* @param {?} shouldBeep
* @return {?}
*/
Initialize(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 {?}
*/
ShouldLog(logLevel) {
if (arguments.length === 1)
return this.ShouldLog_0(logLevel);
else
return this.ShouldLog_1();
}
/**
* @param {?} logLevel
* @return {?}
*/
ShouldLog_0(logLevel) {
return this.LogLevel === logLevel;
}
/**
* @return {?}
*/
ShouldLog_1() {
return this.LogLevel > Logger_LogLevels.None;
}
/**
* @return {?}
*/
ShouldLogServerRelatedMessages() {
return (this.ShouldLogExtendedServerRelatedMessages() || Logger.Instance.ShouldLog(Logger_LogLevels.Server)) && this.LogLevel !== Logger_LogLevels.Basic;
}
/**
* @return {?}
*/
ShouldLogExtendedServerRelatedMessages() {
return (Logger.Instance.ShouldLog(Logger_LogLevels.ServerMessages) || Logger.Instance.ShouldLog(Logger_LogLevels.Support) || Logger.Instance.ShouldLog(Logger_LogLevels.Development)) && this.LogLevel !== Logger_LogLevels.Basic;
}
/**
* @param {?} msg
* @param {?} openIfNecessary
* @param {?=} logType
* @return {?}
*/
WriteToLog(msg, openIfNecessary, 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);
}
}
}
/**
* @param {?} msg
* @return {?}
*/
WriteServerToLog(msg) {
if (this.ShouldLogServerRelatedMessages()) {
this.WriteToLog(NString.Format("Server, Thread={0}: ", Thread.CurrentThread.ManagedThreadId) + msg, false, LogType.info);
}
}
/**
* @param {?} msg
* @return {?}
*/
WriteServerMessagesToLog(msg) {
if (this.ShouldLogExtendedServerRelatedMessages()) {
this.WriteToLog("Server#: " + msg, false, LogType.info);
}
}
/**
* @param {?} msg
* @param {?} skipLine
* @return {?}
*/
WriteSupportToLog(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);
}
}
}
/**
* @param {?} msg
* @return {?}
*/
WriteGuiToLog(msg) {
if (this.LogLevel >= Logger_LogLevels.Gui && this.LogLevel !== Logger_LogLevels.Basic) {
this.WriteToLog(msg, false, LogType.info);
}
}
/**
* @param {?} msg
* @return {?}
*/
WriteDevToLog(msg) {
if (this.LogLevel >= Logger_LogLevels.Development && this.LogLevel !== Logger_LogLevels.Basic) {
this.WriteToLog("DEV: " + msg, false, LogType.info);
}
}
/**
* @param {?} messageDirection
* @param {?} contextID
* @param {?} sessionCounter
* @param {?} clientID
* @param {?} serverID
* @param {?} responseTime
* @param {?} statusCode
* @param {?} httpHeaders
* @param {?} contentLength
* @return {?}
*/
WriteBasicToLog(messageDirection, contextID, sessionCounter, clientID, serverID, responseTime, statusCode, httpHeaders, contentLength) {
if (this.LogLevel === Logger_LogLevels.Basic) {
/** @type {?} */
let text = httpHeaders;
text = text.trim();
text = NString.Replace(text, "\r\n", "|");
/** @type {?} */
let arg_E4_0 = "RIA,{0}_{1},{2},{3},{4},{5},-,{6},{7},{8},{9},{10},{11}";
/** @type {?} */
let 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 {?} */
let arg_D3_1 = 9;
/** @type {?} */
let arg_D3_2;
arg_D3_2 = statusCode;
expr_3E[arg_D3_1] = arg_D3_2;
expr_3E[10] = text;
expr_3E[11] = contentLength;
/** @type {?} */
let value = NString.Format(arg_E4_0, expr_3E);
console.log(value);
}
}
/**
* @param {?} contextID
* @param {?} sessionCounter
* @param {?} clientID
* @param {?} serverID
* @param {?} ex
* @return {?}
*/
WriteBasicErrorToLog(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);
}
/**
* @param {?} msg
* @return {?}
*/
WriteErrorToLog(msg) {
this.WriteToLog("ERROR: " + msg, true, LogType.error);
}
/**
* @param {?} msgOrEx
* @param {?=} msg
* @return {?}
*/
WriteExceptionToLog(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 {?}
*/
WriteExceptionToLogWithMsg(msg) {
this.WriteToLog("ERROR: " + msg, true, LogType.error);
}
/**
* @param {?} ex
* @return {?}
*/
WriteExceptionToLog_1(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 {?}
*/
WriteExceptionToLog_2(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 {?}
*/
WriteExceptionToLog_3(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 {?}
*/
WriteWarningToLog(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 {?}
*/
WriteWarningToLogWithMsg(msg) {
if (this.LogLevel !== Logger_LogLevels.Basic) {
this.WriteToLog("WARNING: " + msg, true, LogType.warning);
}
}
/**
* @param {?} ex
* @return {?}
*/
WriteWarningToLog_1(ex) {
this.WriteWarningToLogWithMsg(ex.GetType() + " : " + OSEnvironment.EolSeq + ex.StackTrace + OSEnvironment.EolSeq + ex.Message);
}
/**
* @param {?} ex
* @return {?}
*/
WriteWarningToLog_2(ex) {
this.WriteWarningToLogWithMsg(NString.Format("{0}{1}{2}", [
ex.stack, OSEnvironment.EolSeq, ex.message
]));
}
/**
* @param {?} ex
* @param {?} msg
* @return {?}
*/
WriteWarningToLog_3(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 {?}
*/
WriteStackTrace(stackTrace, framesToPrint, traceTitle) {
if (traceTitle === null) {
traceTitle = "Stack trace:";
}
/** @type {?} */
let stringBuilder = new StringBuilder(traceTitle + OSEnvironment.EolSeq);
/** @type {?} */
let frames = stackTrace.GetFrames();
/** @type {?} */
let array = frames;
for (let i = 0; i < array.length; i = i + 1) {
/** @type {?} */
let 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);
}
/**
* @return {?}
*/
Flush() {
}
}
Logger.instance = null;
if (false) {
/** @type {?} */
Logger.instance;
/** @type {?} */
Logger.prototype.LogLevel;
/** @type {?} */
Logger.prototype.ShouldBeep;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTG9nZ2VyLmpzIiwic291cmNlUm9vdCI6Im5nOi8vQG1hZ2ljLXhwYS91dGlscy8iLCJzb3VyY2VzIjpbInNyYy9Mb2dnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLE9BQU8sRUFBQyxnQkFBZ0IsRUFBRSx1QkFBdUIsRUFBQyxNQUFNLFNBQVMsQ0FBQztBQUNsRSxPQUFPLEVBQUMsUUFBUSxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFjLGFBQWEsRUFBRSxNQUFNLEVBQUMsTUFBTSxzQkFBc0IsQ0FBQztBQUM1RyxPQUFPLEVBQUMsYUFBYSxFQUFDLE1BQU0saUJBQWlCLENBQUM7QUFDOUMsT0FBTyxFQUFDLGFBQWEsRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBQzlDLE9BQU8sRUFBQyxZQUFZLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUU1QyxPQUFPLEVBQUMsaUJBQWlCLEVBQUMsTUFBTSxNQUFNLENBQUM7OztJQUlyQyxPQUFRO0lBQ1IsVUFBTztJQUNQLFFBQUs7OztnQkFGTCxJQUFJO2dCQUNKLE9BQU87Z0JBQ1AsS0FBSztBQVFQLE1BQU07SUF1VUo7d0JBclU2QixDQUFDOzBCQUtSLEtBQUs7S0FpVTFCOzs7OztJQS9URCxNQUFNLEtBQUssUUFBUSxDQUFDLEtBQWE7UUFDL0IsTUFBTSxDQUFDLFFBQVEsR0FBRyxLQUFLLENBQUM7S0FDekI7Ozs7SUFFRCxNQUFNLEtBQUssUUFBUTtRQUNqQixFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsUUFBUSxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUM7WUFDN0IsTUFBTSxDQUFDLFFBQVEsR0FBRyxJQUFJLE1BQU0sRUFBRSxDQUFDO1NBQ2hDO1FBQ0QsTUFBTSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUM7S0FDeEI7Ozs7Ozs7SUFPRCxVQUFVLENBQUMsUUFBMEIsRUFBRSxlQUF1QixFQUFFLFVBQW1CO1FBQ2pGLElBQUksQ0FBQzs7WUFFSCxJQUFJLENBQUMsUUFBUSxH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QUFFLENBQUM7O1FBQ3BELElBQUksS0FBSyxHQUFtQixNQUFNLENBQUM7UUFDbkMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQVcsQ0FBQyxFQUFFLENBQUMsR0FBRyxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7O1lBQ3BELElBQUksVUFBVSxHQUFpQixLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDeEMsYUFBYSxHQUFHLGFBQWEsR0FBRyxDQUFDLENBQUM7WUFFbEMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztZQUU1QyxFQUFFLENBQUMsQ0FBQyxhQUFhLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDeEIsYUFBYSxDQUFDLE1BQU0sQ0FBQywrQkFBK0IsQ0FBQyxDQUFDO2dCQUN0RCxLQUFLLENBQUM7YUFDUDtTQUNGO1FBQ0QsSUFBSSxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUMsUUFBUSxFQUFFLEVBQUUsSUFBSSxDQUFDLENBQUM7S0FDakQ7Ozs7SUFLRCxLQUFLO0tBRUo7O2tCQXBVeUIsSUFBSSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7TG9nZ2VyX0xvZ0xldmVscywgTG9nZ2VyX01lc3NhZ2VEaXJlY3Rpb259IGZyb20gXCIuL2VudW1zXCI7XHJcbmltcG9ydCB7RGF0ZVRpbWUsIERlYnVnLCBFeGNlcHRpb24sIE5TdHJpbmcsIFN0YWNrVHJhY2UsIFN0cmluZ0J1aWxkZXIsIFRocmVhZH0gZnJvbSBcIkBtYWdpYy14cGEvbXNjb3JlbGliXCI7XHJcbmltcG9ydCB7T1NFbnZpcm9ubWVudH0gZnJvbSBcIi4vUGxhdGZvcm1VdGlsc1wiO1xyXG5pbXBvcnQge0RhdGVUaW1lVXRpbHN9IGZyb20gXCIuL0RhdGVUaW1lVXRpbHNcIjtcclxuaW1wb3J0IHtYTUxDb25zdGFudHN9IGZyb20gXCIuL1hNTENvbnN0YW50c1wiO1xyXG5pbXBvcnQgKiBhcyBKU1N0YWNrVHJhY2UgZnJvbSAnc3RhY2t0cmFjZS1qcyc7XHJcbmltcG9ydCB7aXNOdWxsT3JVbmRlZmluZWR9IGZyb20gXCJ1dGlsXCI7XHJcbmltcG9ydCBKU1N0YWNrRnJhbWUgPSBKU1N0YWNrVHJhY2UuU3RhY2tGcmFtZTtcclxuXHJcbmV4cG9ydCBlbnVtIExvZ1R5cGUge1xyXG4gIGluZm8gPSAxLFxyXG4gIHdhcm5pbmcsXHJcbiAgZXJyb3JcclxufVxyXG5cclxuXHJcbi8vLyA8c3VtbWFyeT5cclxuLy8vIExvZ2dlciBjbGFzcyB3aWxsIHRha2UgY2FyZSBvZiBjbGllbnQgc2lkZSBsb2dnaW5nIC4gSXQgd2lsbCBjaGVjayBmb3IgdmFyaW91cyBsb2cgbGV2ZWxzIGFuZCBhY2NvcmRpbmdseSB3aWxsIHdyaXRlIG1lc3NhZ2VzIGluIGxvZyBmaWxlLlxyXG4vLy8gPC9zdW1tYXJ5PlxyXG4vL0BkeW5hbWljXHJcbmV4cG9ydCBjbGFzcyBMb2dnZXIge1xyXG4gIHN0YXRpYyBpbnN0YW5jZTogTG9nZ2VyID0gbnVsbDtcclxuICBMb2dMZXZlbDogTG9nZ2VyX0xvZ0xldmVscyA9IDA7IC8vIEludGVybmFsTG9nTGV2ZWxcclxuXHJcbiAgLy8vIDxzdW1tYXJ5PlxyXG4gIC8vLyBXaGlsZSB3cml0aW5nIHRoZSBlcnJvciBtZXNzYWdlcyBpbiB0aGUgZmlsZSBwbGF5IHRoZSBiZWVwLlxyXG4gIC8vLyA8L3N1bW1hcnk+XHJcbiAgU2hvdWxkQmVlcDogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICBzdGF0aWMgc2V0IEluc3RhbmNlKHZhbHVlOiBMb2dnZXIpIHtcclxuICAgIExvZ2dlci5pbnN0YW5jZSA9IHZhbHVlO1xyXG4gIH1cclxuXHJcbiAgc3RhdGljIGdldCBJbnN0YW5jZSgpOiBMb2dnZXIge1xyXG4gICAgaWYgKExvZ2dlci5pbnN0YW5jZSA9PT0gbnVsbCkge1xyXG4gICAgICBMb2dnZXIuaW5zdGFuY2UgPSBuZXcgTG9nZ2VyKCk7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gTG9nZ2VyLmluc3RhbmNlO1xyXG4gIH1cclxuXHJcbi8vLyA8c3VtbWFyeT5cclxuICAvLy8gSW5pdGlhbGl6ZSBsb2dnZXJcclxuICAvLy8gPC9zdW1tYXJ5PlxyXG4gIC8vLyA8cGFyYW0gbmFtZT1cImxvZ0xldmVsXCI+PC9wYXJhbT5cclxuICAvLy8gPHBhcmFtIG5hbWU9XCJpbnRlcm5hbExvZ1N5bmNcIj48L3BhcmFtPlxyXG4gIEluaXRpYWxpemUobG9nTGV2ZWw6IExvZ2dlcl9Mb2dMZXZlbHMsIGludGVybmFsTG9nU3luYzogc3RyaW5nLCBzaG91bGRCZWVwOiBib29sZWFuKTogdm9pZCB7XHJcbiAgICB0cnkge1xyXG4gICAgICAvLyBsZXQgbG9nU3luYzogTG9nU3luY01vZGUgID0gTG9nU3luY01vZGUuU2Vzc2lvbjtcclxuICAgICAgdGhpcy5Mb2dMZXZlbCA9IGxvZ0xldmVsO1xyXG4gICAgICB0aGlzLlNob3VsZEJlZXAgPSBzaG91bGRCZWVwO1xyXG5cclxuICAgICAgLy8gVE9ETzogaW1wbGVtZW50XHJcbi8vICAgU3RyaW5nIHN0ckxvZ1N5bmMgPSBpbnRlcm5hbExvZ1N5bmM7XHJcbi8vICAgaWYgKCFzdHJpbmcuSXNOdWxsT3JFbXB0eShzdHJMb2dTeW5jKSlcclxuLy8ge1xyXG4vLyAgIGlmIChzdHJMb2dTeW5jLlN0YXJ0c1dpdGgoXCJNXCIsIFN0cmluZ0NvbXBhcmlzb24uQ3VycmVudEN1bHR1cmVJZ25vcmVDYXNlKSlcclxuLy8gICBsb2dTeW5jID0gTG9nU3luY01vZGUuTWVzc2FnZTtcclxuLy8gICBlbHNlIGlmIChzdHJMb2dTeW5jLlN0YXJ0c1dpdGgoXCJGXCIsIFN0cmluZ0NvbXBhcmlzb24uQ3VycmVudEN1bHR1cmVJZ25vcmVDYXNlKSlcclxuLy8gICBsb2dTeW5jID0gTG9nU3luY01vZGUuRmx1c2g7XHJcbi8vIH1cclxuLy9cclxuICAgIH1cclxuICAgIGNhdGNoIChlKSB7XHJcbiAgICAgIHRoaXMuV3JpdGVEZXZUb0xvZyhcIkNsaWVudE1hbmFnZXIuaW5pdCgpOiBcIiArIGUuTWVzc2FnZSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvLy8gPHN1bW1hcnk+PC9zdW1tYXJ5PlxyXG4gIC8vLyA8cGFyYW0gbmFtZT1cImxvZ0xldmVsXCI+PC9wYXJhbT5cclxuICAvLy8gPHJldHVybnM+PC9yZXR1cm5zPlxyXG5cclxuICBTaG91bGRMb2cobG9nTGV2ZWw6IExvZ2dlcl9Mb2dMZXZlbHMpOiBib29sZWFuO1xyXG4gIFNob3VsZExvZygpOiBib29sZWFuO1xyXG4gIFNob3VsZExvZyhsb2dMZXZlbD86IExvZ2dlcl9Mb2dMZXZlbHMpOiBib29sZWFuIHtcclxuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAxKVxyXG4gICAgICByZXR1cm4gdGhpcy5TaG91bGRMb2dfMChsb2dMZXZlbCk7XHJcbiAgICBlbHNlXHJcbiAgICAgIHJldHVybiB0aGlzLlNob3VsZExvZ18xKCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIFNob3VsZExvZ18wKGxvZ0xldmVsOiBMb2dnZXJfTG9nTGV2ZWxzKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gdGhpcy5Mb2dMZXZlbCA9PT0gbG9nTGV2ZWw7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIFNob3VsZExvZ18xKCk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIHRoaXMuTG9nTGV2ZWwgPiBMb2dnZXJfTG9nTGV2ZWxzLk5vbmU7XHJcbiAgfVxyXG5cclxuICBTaG91bGRMb2dTZXJ2ZXJSZWxhdGVkTWVzc2FnZXMoKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gKHRoaXMuU2hvdWxkTG9nRXh0ZW5kZWRTZXJ2ZXJSZWxhdGVkTWVzc2FnZXMoKSB8fCBMb2dnZXIuSW5zdGFuY2UuU2hvdWxkTG9nKExvZ2dlcl9Mb2dMZXZlbHMuU2VydmVyKSkgJiYgdGhpcy5Mb2dMZXZlbCAhPT0gTG9nZ2VyX0xvZ0xldmVscy5CYXNpYztcclxuICB9XHJcblxyXG4gIFNob3VsZExvZ0V4dGVuZGVkU2VydmVyUmVsYXRlZE1lc3NhZ2VzKCk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIChMb2dnZXIuSW5zdGFuY2UuU2hvdWxkTG9nKExvZ2dlcl9Mb2dMZXZlbHMuU2VydmVyTWVzc2FnZXMpIHx8IExvZ2dlci5JbnN0YW5jZS5TaG91bGRMb2coTG9nZ2VyX0xvZ0xldmVscy5TdXBwb3J0KSB8fCBMb2dnZXIuSW5zdGFuY2UuU2hvdWxkTG9nKExvZ2dlcl9Mb2dMZXZlbHMuRGV2ZWxvcG1lbnQpKSAmJiB0aGlzLkxvZ0xldmVsICE9PSBMb2dnZXJfTG9nTGV2ZWxzLkJhc2ljO1xyXG4gIH1cclxuXHJcbiAgLy8vIDxzdW1tYXJ5Pjwvc3VtbWFyeT5cclxuICAvLy8gPHBhcmFtIG5hbWU9XCJtc2dcIj48L3BhcmFtPlxyXG4gIC8vLyA8cGFyYW0gbmFtZT1cIm9wZW5JZk5lY2Vzc2FyeVwiPm9wZW4gdGhlIGxvZyBmaWxlIGlmIG5vdCBvcGVuZWQgeWV0PC9wYXJhbT5cclxuXHJcbiAgV3JpdGVUb0xvZyhtc2c6IHN0cmluZywgb3BlbklmTmVjZXNzYXJ5OiBib29sZWFuLCBsb2dUeXBlOiBMb2dUeXBlID0gTG9nVHlwZS5pbmZvKTogdm9pZCB7XHJcblxyXG4gICAgaWYgKHRoaXMuTG9nTGV2ZWwgPiBMb2dnZXJfTG9nTGV2ZWxzLk5vbmUgfHwgb3BlbklmTmVjZXNzYXJ5KSB7XHJcbiAgICAgIG1zZyA9IE5TdHJpbmcuRm9ybWF0KFwiezB9IHsxfVwiLCAodGhpcy5Mb2dMZXZlbCA9PT0gTG9nZ2VyX0xvZ0xldmVscy5CYXNpYykgPyBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCkgOiBEYXRlVGltZVV0aWxzLlRvU3RyaW5nKERhdGVUaW1lLk5vdywgWE1MQ29uc3RhbnRzLkVSUk9SX0xPR19USU1FX0ZPUk1BVCwgdGhpcyksXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgIG1zZyk7XHJcblxyXG4gICAgICBzd2l0Y2ggKGxvZ1R5cGUpIHtcclxuICAgICAgICBjYXNlIExvZ1R5cGUuZXJyb3I6XHJcbiAgICAgICAgICBjb25zb2xlLmVycm9yKG1zZyk7XHJcbiAgICAgICAgICBicmVhaztcclxuICAgICAgICBjYXNlIExvZ1R5cGUud2FybmluZzpcclxuICAgICAgICAgIGNvbnNvbGUud2Fybihtc2cpO1xyXG4gICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgZGVmYXVsdDpcclxuICAgICAgICAgIGNvbnNvbGUubG9nKG1zZyk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8vLyA8c3VtbWFyeT5cclxuICAvLy8gd3JpdGUgYSBzZXJ2ZXIgYWNjZXNzIHRvIHRoZSBsb2dcclxuICAvLy8gPC9zdW1tYXJ5PlxyXG4gIC8vLyA8cGFyYW0gbmFtZT1cIm1zZ1wiPnRoZSBtZXNzYWdlIHRvIHdyaXRlIHRvIHRoZSBsb2c8L3BhcmFtPlxyXG4gIFdyaXRlU2VydmVyVG9Mb2cobXNnOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLlNob3VsZExvZ1NlcnZlclJlbGF0ZWRNZXNzYWdlcygpKSB7XHJcbiAgICAgIHRoaXMuV3JpdGVUb0xvZyhOU3RyaW5nLkZvcm1hdChcIlNlcnZlciwgVGhyZWFkPXswfTogXCIsIFRocmVhZC5DdXJyZW50VGhyZWFkLk1hbmFnZWRUaHJlYWRJZCkgKyBtc2csIGZhbHNlLCBMb2dUeXBlLmluZm8pO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy8vIDxzdW1tYXJ5PlxyXG4gIC8vLyB3cml0ZSBhIHNlcnZlciBhY2Nlc3MgdG8gdGhlIGxvZywgaW5jbHVkaW5nIHRoZSBjb250ZW50XHJcbiAgLy8vIDwvc3VtbWFyeT5cclxuICAvLy8gPHBhcmFtIG5hbWU9XCJtc2dcIj50aGUgbWVzc2FnZSB0byB3cml0ZSB0byB0aGUgbG9nPC9wYXJhbT5cclxuICBXcml0ZVNlcnZlck1lc3NhZ2VzVG9Mb2cobXNnOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLlNob3VsZExvZ0V4dGVuZGVkU2VydmVyUmVsYXRlZE1lc3NhZ2VzKCkpIHtcclxuICAgICAgdGhpcy5Xcml0ZVRvTG9nKFwiU2VydmVyIzogXCIgKyBtc2csIGZhbHNlLCBMb2dUeXBlLmluZm8pO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy8vIDxzdW1tYXJ5PldyaXRlIGEgUUMgbWVzc2FnZSB0byB0aGUgbG9nPC9zdW1tYXJ5PlxyXG4gIC8vLyA8cGFyYW0gbmFtZT1cIm1zZ1wiPnRoZSBtZXNzYWdlIHRvIHdyaXRlIHRvIHRoZSBsb2c8L3BhcmFtPlxyXG4gIFdyaXRlU3VwcG9ydFRvTG9nKG1zZzogc3RyaW5nLCBza2lwTGluZTogYm9vbGVhbik6IHZvaWQge1xyXG5cclxuICAgIGlmICh0aGlzLkxvZ0xldmVsID49IExvZ2dlcl9Mb2dMZXZlbHMuU3VwcG9ydCAmJiB0aGlzLkxvZ0xldmVsICE9PSBMb2dnZXJfTG9nTGV2ZWxzLkJhc2ljKSB7XHJcbiAgICAgIGlmIChza2lwTGluZSkge1xyXG4gICAgICAgIHRoaXMuV3JpdGVUb0xvZyhcIlNVUFBPUlQ6IFwiICsgbXNnLCBmYWxzZSwgTG9nVHlwZS5pbmZvKTtcclxuICAgICAgfVxyXG4gICAgICBlbHNlIHtcclxuICAgICAgICB0aGlzLldyaXRlVG9Mb2coXCJTVVBQT1JUOiBcIiArIG1zZyArIE9TRW52aXJvbm1lbnQuRW9sU2VxICsgXCItLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVwiLCBmYWxzZSwgTG9nVHlwZS5pbmZvKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy8vIDxzdW1tYXJ5PlxyXG4gIC8vLyB3cml0ZSBhIHBlcmZvcm1hbmNlIG1lc3NhZ2UgdG8gdGhlIGxvZ1xyXG4gIC8vLyA8L3N1bW1hcnk+XHJcbiAgLy8vIDxwYXJhbSBuYW1lPVwibXNnXCI+dGhlIG1lc3NhZ2UgdG8gd3JpdGUgdG8gdGhlIGxvZzwvcGFyYW0+XHJcbiAgV3JpdGVHdWlUb0xvZyhtc2c6IHN0cmluZyk6IHZvaWQge1xyXG5cclxuICAgIGlmICh0aGlzLkxvZ0xldmVsID49IExvZ2dlcl9Mb2dMZXZlbHMuR3VpICYmIHRoaXMuTG9nTGV2ZWwgIT09IExvZ2dlcl9Mb2dMZXZlbHMuQmFzaWMpIHtcclxuICAgICAgdGhpcy5Xcml0ZVRvTG9nKG1zZywgZmFsc2UsIExvZ1R5cGUuaW5mbyk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvLy8gPHN1bW1hcnk+XHJcbiAgLy8vIHdyaXRlIGEgZGV2ZWxvcGVyIG1lc3NhZ2UgdG8gdGhlIGxvZ1xyXG4gIC8vLyA8L3N1bW1hcnk+XHJcbiAgLy8vIDxwYXJhbSBuYW1lPVwibXNnXCI+dGhlIG1lc3NhZ2UgdG8gd3JpdGUgdG8gdGhlIGxvZzwvcGFyYW0+XHJcbiAgV3JpdGVEZXZUb0xvZyhtc2c6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuTG9nTGV2ZWwgPj0gTG9nZ2VyX0xvZ0xldmVscy5EZXZlbG9wbWVudCAmJiB0aGlzLkxvZ0xldmVsICE9PSBMb2dnZXJfTG9nTGV2ZWxzLkJhc2ljKSB7XHJcbiAgICAgIHRoaXMuV3JpdGVUb0xvZyhcIkRFVjogXCIgKyBtc2csIGZhbHNlLCBMb2dUeXBlLmluZm8pO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy8vIDxzdW1tYXJ5PlxyXG4gIC8vLyBXcml0ZXMgYSBiYXNpYyBsZXZlbCBlbnRyeSB0byBsb2dcclxuICAvLy8gPC9zdW1tYXJ5PlxyXG4gIC8vLyA8cGFyYW0gbmFtZT1cIm1lc3NhZ2VEaXJlY3Rpb25cIj5tZXNzYWdlIGRpcmVjdGlvbiByZWxhdGl2ZSB0byB0aGUgY3VycmVudCBtb2R1bGUgKFJJQSBjbGllbnQpLiBDYW4gYmUgZWl0aGVyIE1lc3NhZ2VFbnRlcmluZyBvciBNZXNzYWdlTGVhdmluZzwvcGFyYW0+XHJcbiAgLy8vIDxwYXJhbSBuYW1lPVwic3RhdHVzQ29kZVwiPkhUVFAgc3RhdHVzIGNvZGU8L3BhcmFtPlxyXG4gIC8vLyA8cGFyYW0gbmFtZT1cImNvbnRlbnRMZW5ndGhcIj5sZW5ndGggb2YgdGhlIGh0dHAgbWVzc2FnZTwvcGFyYW0+XHJcbiAgLy8vIDxwYXJhbSBuYW1lPVwiaHR0cEhlYWRlcnNcIj5IVFRQIGhlYWRlcnM8L3BhcmFtPlxyXG4gIFdyaXRlQmFzaWNUb0xvZyhtZXNzYWdlRGlyZWN0aW9uOiBMb2dnZXJfTWVzc2FnZURpcmVjdGlvbiwgY29udGV4dElEOiBzdHJpbmcsIHNlc3Npb25Db3VudGVyOiBudW1iZXIsIGNsaWVudElEOiBzdHJpbmcsIHNlcnZlcklEOiBzdHJpbmcsIHJlc3BvbnNlVGltZTogbnVtYmVyLCBzdGF0dXNDb2RlOiBzdHJpbmcsIGh0dHBIZWFkZXJzOiBzdHJpbmcsIGNvbnRlbnRMZW5ndGg6IG51bWJlcik6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuTG9nTGV2ZWwgPT09IExvZ2dlcl9Mb2dMZXZlbHMuQmFzaWMpIHtcclxuICAgICAgbGV0IHRleHQ6IHN0cmluZyA9IGh0dHBIZWFkZXJzO1xyXG4gICAgICB0ZXh0ID0gdGV4dC50cmltKCk7XHJcbiAgICAgIHRleHQgPSBOU3RyaW5nLlJlcGxhY2UodGV4dCwgXCJcXHJcXG5cIiwgXCJ8XCIpO1xyXG4gICAgICBsZXQgYXJnX0U0XzA6IHN0cmluZyA9IFwiUklBLHswfV97MX0sezJ9LHszfSx7NH0sezV9LC0sezZ9LHs3fSx7OH0sezl9LHsxMH0sezExfVwiO1xyXG4gICAgICBsZXQgZXhwcl8zRTogYW55W10gPSBuZXcgQXJyYXk8YW55PigxMik7XHJcblxyXG4gICAgICAvLyBUT0RPIDogbmVlZCB0byBjaGVjayBIb3cgdG8gaGFuZGxlIFByb2Nlc3MgY2xhc3MuXHJcbiAgICAgIC8vIGV4cHJfM0VbMF0gPSBQcm9jZXNzLkdldEN1cnJlbnRQcm9jZXNzKCkuSWQ7XHJcbiAgICAgIGV4cHJfM0VbMV0gPSBUaHJlYWQuQ3VycmVudFRocmVhZC5NYW5hZ2VkVGhyZWFkSWQ7XHJcbiAgICAgIGV4cHJfM0VbMl0gPSBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCk7XHJcbiAgICAgIGV4cHJfM0VbM10gPSAoKG1lc3NhZ2VEaXJlY3Rpb24gPT09IExvZ2dlcl9NZXNzYWdlRGlyZWN0aW9uLk1lc3NhZ2VMZWF2aW5nKSA/IFwiTVNHTFwiIDogXCJNU0dFXCIpO1xyXG4gICAgICBleHByXzNFWzRdID0gY29udGV4dElEO1xyXG4gICAgICBleHByXzNFWzVdID0gc2Vzc2lvbkNvdW50ZXI7XHJcbiAgICAgIGV4cHJfM0VbNl0gPSBjbGllbnRJRDtcclxuICAgICAgZXhwcl8zRVs3XSA9IHNlcnZlcklEO1xyXG4gICAgICBleHByXzNFWzhdID0gKChyZXNwb25zZVRpbWUgIT09IDApID8gcmVzcG9uc2VUaW1lLnRvU3RyaW5nKCkgOiBcIi1cIik7XHJcbiAgICAgIGxldCBhcmdfRDNfMTogbnVtYmVyID0gOTtcclxuICAgICAgbGV0IGFyZ19EM18yOiBhbnk7XHJcbiAgICAgIGFyZ19EM18yID0gc3RhdHVzQ29kZTtcclxuICAgICAgZXhwcl8zRVthcmdfRDNfMV0gPSBhcmdfRDNfMjtcclxuICAgICAgZXhwcl8zRVsxMF0gPSB0ZXh0O1xyXG4gICAgICBleHByXzNFWzExXSA9IGNvbnRlbnRMZW5ndGg7XHJcbiAgICAgIGxldCB2YWx1ZTogc3RyaW5nID0gTlN0cmluZy5Gb3JtYXQoYXJnX0U0XzAsIGV4cHJfM0UpO1xyXG4gICAgICBjb25zb2xlLmxvZyh2YWx1ZSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvLy8gPHN1bW1hcnk+XHJcbiAgLy8vIFdyaXRlcyBhIHJlcXVlc3QgZXhjZXB0aW9uIGJhc2ljIGxldmVsIGVudHJ5IHRvIGxvZ1xyXG4gIC8vLyA8L3N1bW1hcnk+XHJcbiAgLy8vIDxwYXJhbSBuYW1lPVwiY29udGV4dElEXCI+PC9wYXJhbT5cclxuICAvLy8gPHBhcmFtIG5hbWU9XCJzZXNzaW9uQ291bnRlclwiPjwvcGFyYW0+XHJcbiAgLy8vIDxwYXJhbSBuYW1lPVwiY2xpZW50SURcIj48L3BhcmFtPlxyXG4gIC8vLyA8cGFyYW0gbmFtZT1cInNlcnZlcklEXCI+PC9wYXJhbT5cclxuICAvLy8gPHBhcmFtIG5hbWU9XCJleFwiPnRoZSBsb2dnZWQgZXhjZXB0aW9uPC9wYXJhbT5cclxuICBXcml0ZUJhc2ljRXJyb3JUb0xvZyhjb250ZXh0SUQ6IHN0cmluZywgc2Vzc2lvbkNvdW50ZXI6IG51bWJlciwgY2xpZW50SUQ6IHN0cmluZywgc2VydmVySUQ6IHN0cmluZywgZXg6IEV4Y2VwdGlvbik6IHZvaWQge1xyXG4gICAgRGVidWcuQXNzZXJ0KHRoaXMuTG9nTGV2ZWwgPT09IExvZ2dlcl9Mb2dMZXZlbHMuQmFzaWMpO1xyXG5cclxuICAgIC8vIFRPRE8gOiBOZWVkIHRvIGNoZWNrIGhvdyB0byBoYW5kbGUgUHJvY2Vzc1xyXG4gICAgLy8gbGV0IHZhbHVlOiBzdHJpbmcgPSBOU3RyaW5nLkZvcm1hdChcIlJJQSx7MH1fezF9LHsyfSx7M30sezR9LHs1fSwtLHs2fSx7N30sLSwtLC0sezh9IHs5fVwiLCBbXHJcbiAgICAvLyBQcm9jZXNzLkdldEN1cnJlbnRQcm9jZXNzKCkuSWQsIFRocmVhZC5DdXJyZW50VGhyZWFkLk1hbmFnZWRUaHJlYWRJZCwgRGF0ZVRpbWUuVXRjTm93LlRvU3RyaW5nKFwieXl5eS1NTS1kZFRISDptbTpzcy5mZmZmZmZmWlwiKSwgXCJSRVNcIiwgY29udGV4dElELCBzZXNzaW9uQ291bnRlciwgY2xpZW50SUQsIHNlcnZlcklELCBleC5HZXRUeXBlKCksIGV4Lk1lc3NhZ2VcclxuICAgIC8vIF0pO1xyXG4gICAgLy8gTkNvbnNvbGUuV3JpdGVMaW5lKHZhbHVlKTtcclxuICB9XHJcblxyXG4gIC8vLyA8c3VtbWFyeT5cclxuICAvLy8gV3JpdGUgYW4gZXJyb3IgdG8gdGhlIGxvZ1xyXG4gIC8vLyA8L3N1bW1hcnk+XHJcbiAgLy8vIDxwYXJhbSBuYW1lPVwibXNnXCI+dGhlIG1lc3NhZ2UgdG8gd3JpdGUgdG8gdGhlIGxvZzwvcGFyYW0+XHJcbiAgV3JpdGVFcnJvclRvTG9nKG1zZzogc3RyaW5nKTogdm9pZCB7XHJcbiAgICB0aGlzLldyaXRlVG9Mb2coXCJFUlJPUjogXCIgKyBtc2csIHRydWUsIExvZ1R5cGUuZXJyb3IpO1xyXG4gIH1cclxuXHJcbiAgLy8vIDxzdW1tYXJ5PlxyXG4gIC8vLyBXcml0ZSBhbiBpbnRlcm5hbCBlcnJvciB0byB0aGUgbG9nLiBBbHNvIHByaW50cyBzdGFjayB0cmFjZSBhbG9uZyB3aXRoIHRoZSBtZXNzYWdlXHJcbiAgLy8vIDwvc3VtbWFyeT5cclxuICAvLy8gPHBhcmFtIG5hbWU9XCJtc2dcIj50aGUgbWVzc2FnZSB0byB3cml0ZSB0byB0aGUgbG9nPC9wYXJhbT5cclxuICBXcml0ZUV4Y2VwdGlvblRvTG9nKGV4OiBFeGNlcHRpb24pOiB2b2lkO1xyXG4gIFdyaXRlRXhjZXB0aW9uVG9Mb2coZXg6IEVycm9yKTogdm9pZDtcclxuICBXcml0ZUV4Y2VwdGlvblRvTG9nKGV4OiBFeGNlcHRpb24sIG1zZzogc3RyaW5nKTogdm9pZDtcclxuICBXcml0ZUV4Y2VwdGlvblRvTG9nKG1zZ09yRXg6IGFueSwgbXNnPzogc3RyaW5nKTogdm9pZCB7XHJcbiAgICBpZiAobXNnT3JFeCBpbnN0YW5jZW9mIEVycm9yKSB7XHJcbiAgICAgIHRoaXMuV3JpdGVFeGNlcHRpb25Ub0xvZ18yKG1zZ09yRXgsIG1zZyk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAxICYmIChtc2dPckV4ICE9PSBudWxsIHx8IG1zZ09yRXggaW5zdGFuY2VvZiBFeGNlcHRpb24pKSB7XHJcbiAgICAgIHRoaXMuV3JpdGVFeGNlcHRpb25Ub0xvZ18xKG1zZ09yRXgpO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5Xcml0ZUV4Y2VwdGlvblRvTG9nXzMobXNnT3JFeCwgbXNnKTtcclxuICB9XHJcblxyXG4gIFdyaXRlRXhjZXB0aW9uVG9Mb2dXaXRoTXNnKG1zZzogc3RyaW5nKTogdm9pZCB7XHJcbiAgICB0aGlzLldyaXRlVG9Mb2coXCJFUlJPUjogXCIgKyBtc2csIHRydWUsIExvZ1R5cGUuZXJyb3IpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBXcml0ZUV4Y2VwdGlvblRvTG9nXzEoZXg6IEV4Y2VwdGlvbik6IHZvaWQge1xyXG4gICAgdGhpcy5Xcml0ZUV4Y2VwdGlvblRvTG9nV2l0aE1zZyhOU3RyaW5nLkZvcm1hdChcInswfSA6IHsxfXsyfXszfXs0fVwiLCBbXHJcbiAgICAgIGV4LkdldFR5cGUoKSwgT1NFbnZpcm9ubWVudC5Fb2xTZXEsIGV4LlN0YWNrVHJhY2UsIE9TRW52aXJvbm1lbnQuRW9sU2VxLCBleC5NZXNzYWdlXHJcbiAgICBdKSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIFdyaXRlRXhjZXB0aW9uVG9Mb2dfMihleDogRXJyb3IsIG1lc3NhZ2U6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgaWYgKGlzTnVsbE9yVW5kZWZpbmVkKG1lc3NhZ2UpKVxyXG4gICAgICB0aGlzLldyaXRlRXhjZXB0aW9uVG9Mb2dXaXRoTXNnKE5TdHJpbmcuRm9ybWF0KFwiezB9ezF9ezJ9XCIsIFtleC5zdGFjaywgT1NFbnZpcm9ubWVudC5Fb2xTZXEsIGV4Lm1lc3NhZ2VdKSk7XHJcbiAgICBlbHNlXHJcbiAgICAgIHRoaXMuV3JpdGVFeGNlcHRpb25Ub0xvZ1dpdGhNc2coTlN0cmluZy5Gb3JtYXQoXCJ7MH17MX17Mn17NH17NX1cIiwgW21lc3NhZ2UsIE9TRW52aXJvbm1lbnQuRW9sU2VxLCBleC5zdGFjaywgT1NFbnZpcm9ubWVudC5Fb2xTZXEsIGV4Lm1lc3NhZ2VdKSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIFdyaXRlRXhjZXB0aW9uVG9Mb2dfMyhleDogRXhjZXB0aW9uLCBtc2c6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgdGhpcy5Xcml0ZUV4Y2VwdGlvblRvTG9nV2l0aE1zZyhOU3RyaW5nLkZvcm1hdChcInswfSwgezF9IDogezJ9ezN9ezR9ezV9XCIsIFtcclxuICAgICAgZXguR2V0VHlwZSgpLCBtc2csIE9TRW52aXJvbm1lbnQuRW9sU2VxLCBleC5TdGFja1RyYWNlLCBPU0Vudmlyb25tZW50LkVvbFNlcSwgZXguTWVzc2FnZVxyXG4gICAgXSkpO1xyXG4gIH1cclxuXHJcbiAgLy8vIDxzdW1tYXJ5PiB3cml0ZSBhIHdhcm5pbmcgdG8gdGhlIGxvZzwvc3VtbWFyeT5cclxuICAvLy8gPHBhcmFtIG5hbWU9XCJtc2dcIj50aGUgbWVzc2FnZSB0byB3cml0ZSB0byB0aGUgbG9nPC9wYXJhbT5cclxuICBXcml0ZVdhcm5pbmdUb0xvZyhleDogRXhjZXB0aW9uKTogdm9pZDtcclxuICBXcml0ZVdhcm5pbmdUb0xvZyhleDogRXhjZXB0aW9uLCBtc2c6IHN0cmluZyk6IHZvaWQ7XHJcbiAgV3JpdGVXYXJuaW5nVG9Mb2coZXg6IEVycm9yKTogdm9pZDtcclxuICBXcml0ZVdhcm5pbmdUb0xvZyhtc2dPckV4OiBhbnksIG1zZz86IHN0cmluZyk6IHZvaWQge1xyXG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEgJiYgbXNnT3JFeCAhPT0gbnVsbCkge1xyXG4gICAgICBpZiAobXNnT3JFeCBpbnN0YW5jZW9mIEV4Y2VwdGlvbilcclxuICAgICAgICB0aGlzLldyaXRlV2FybmluZ1RvTG9nXzEobXNnT3JFeCk7XHJcbiAgICAgIGVsc2UgaWYgKG1zZ09yRXggaW5zdGFuY2VvZiBFcnJvcilcclxuICAgICAgICB0aGlzLldyaXRlV2FybmluZ1RvTG9nXzIobXNnT3JFeCk7XHJcbiAgICB9XHJcbiAgICBlbHNlXHJcbiAgICAgIHRoaXMuV3JpdGVXYXJuaW5nVG9Mb2dfMyhtc2dPckV4LCBtc2cpO1xyXG4gIH1cclxuXHJcbiAgV3JpdGVXYXJuaW5nVG9Mb2dXaXRoTXNnKG1zZzogc3RyaW5nKTogdm9pZCB7XHJcblxyXG4gICAgaWYgKHRoaXMuTG9nTGV2ZWwgIT09IExvZ2dlcl9Mb2dMZXZlbHMuQmFzaWMpIHtcclxuICAgICAgdGhpcy5Xcml0ZVRvTG9nKFwiV0FSTklORzogXCIgKyBtc2csIHRydWUsIExvZ1R5cGUud2FybmluZyk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIFdyaXRlV2FybmluZ1RvTG9nXzEoZXg6IEV4Y2VwdGlvbik6IHZvaWQge1xyXG4gICAgdGhpcy5Xcml0ZVdhcm5pbmdUb0xvZ1dpdGhNc2coZXguR2V0VHlwZSgpICsgXCIgOiBcIiArIE9TRW52aXJvbm1lbnQuRW9sU2VxICsgZXguU3RhY2tUcmFjZSArIE9TRW52aXJvbm1lbnQuRW9sU2VxICsgZXguTWVzc2FnZSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIFdyaXRlV2FybmluZ1RvTG9nXzIoZXg6IEVycm9yKTogdm9pZCB7XHJcbiAgICB0aGlzLldyaXRlV2FybmluZ1RvTG9nV2l0aE1zZyhOU3RyaW5nLkZvcm1hdChcInswfXsxfXsyfVwiLCBbXHJcbiAgICAgIGV4LnN0YWNrLCBPU0Vudmlyb25tZW50LkVvbFNlcSwgZXgubWVzc2FnZVxyXG4gICAgXSkpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBXcml0ZVdhcm5pbmdUb0xvZ18zKGV4OiBFeGNlcHRpb24sIG1zZzogc3RyaW5nKTogdm9pZCB7XHJcbiAgICB0aGlzLldyaXRlV2FybmluZ1RvTG9nV2l0aE1zZyhOU3RyaW5nLkZvcm1hdChcInswfSwgezF9IDogezJ9ezN9ezR9ezV9XCIsIFtcclxuICAgICAgZXguR2V0VHlwZSgpLCBtc2csIE9TRW52aXJvbm1lbnQuRW9sU2VxLCBleC5TdGFja1RyYWNlLCBPU0Vudmlyb25tZW50LkVvbFNlcSwgZXguTWVzc2FnZVxyXG4gICAgXSkpO1xyXG4gIH1cclxuXHJcbiAgV3JpdGVTdGFja1RyYWNlKHN0YWNrVHJhY2U6IFN0YWNrVHJhY2UsIGZyYW1lc1RvUHJpbnQ6IG51bWJlciwgdHJhY2VUaXRsZTogc3RyaW5nKTogdm9pZCB7XHJcblxyXG4gICAgaWYgKHRyYWNlVGl0bGUgPT09IG51bGwpIHtcclxuICAgICAgdHJhY2VUaXRsZSA9IFwiU3RhY2sgdHJhY2U6XCI7XHJcbiAgICB9XHJcbiAgICBsZXQgc3RyaW5nQnVpbGRlcjogU3RyaW5nQnVpbGRlciA9IG5ldyBTdHJpbmdCdWlsZGVyKHRyYWNlVGl0bGUgKyBPU0Vudmlyb25tZW50LkVvbFNlcSk7XHJcbiAgICBsZXQgZnJhbWVzOiBKU1N0YWNrRnJhbWVbXSA9IHN0YWNrVHJhY2UuR2V0RnJhbWVzKCk7XHJcbiAgICBsZXQgYXJyYXk6IEpTU3RhY2tGcmFtZVtdID0gZnJhbWVzO1xyXG4gICAgZm9yIChsZXQgaTogbnVtYmVyID0gMDsgaSA8IGFycmF5Lmxlbmd0aDsgaSA9IGkgKyAxKSB7XHJcbiAgICAgIGxldCBzdGFja0ZyYW1lOiBKU1N0YWNrRnJhbWUgPSBhcnJheVtpXTtcclxuICAgICAgZnJhbWVzVG9QcmludCA9IGZyYW1lc1RvUHJpbnQgLSAxO1xyXG5cclxuICAgICAgc3RyaW5nQnVpbGRlci5BcHBlbmQoc3RhY2tGcmFtZS50b1N0cmluZygpKTtcclxuXHJcbiAgICAgIGlmIChmcmFtZXNUb1ByaW50ID09PSAwKSB7XHJcbiAgICAgICAgc3RyaW5nQnVpbGRlci5BcHBlbmQoXCJcXHQuLi4gbW9yZSBzdGFjayBmcmFtZXMgLi4uXFxuXCIpO1xyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICB0aGlzLldyaXRlVG9Mb2coc3RyaW5nQnVpbGRlci5Ub1N0cmluZygpLCB0cnVlKTtcclxuICB9XHJcblxyXG4gIC8vLyA8c3VtbWFyeT5cclxuICAvLy8gRmx1c2ggdGhlIGxvZyB3cml0ZXIuXHJcbiAgLy8vIDwvc3VtbWFyeT5cclxuICBGbHVzaCgpOiB2b2lkIHtcclxuXHJcbiAgfVxyXG5cclxuICBjb25zdHJ1Y3RvcigpIHtcclxuICB9XHJcbn1cclxuIl19