import * as __WEBPACK_EXTERNAL_MODULE_sdp__ from "sdp"; /******/ var __webpack_modules__ = ({ /***/ "./src/AFK/AFKController.ts": /*!**********************************!*\ !*** ./src/AFK/AFKController.ts ***! \**********************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "AFKController": () => (/* binding */ AFKController) /* harmony export */ }); /* harmony import */ var _Config_Config__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Config/Config */ "./src/Config/Config.ts"); /* harmony import */ var _Logger_Logger__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../Logger/Logger */ "./src/Logger/Logger.ts"); /* harmony import */ var _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Util/EventEmitter */ "./src/Util/EventEmitter.ts"); // Copyright Epic Games, Inc. All Rights Reserved. class AFKController { constructor(config, pixelStreaming, onDismissAfk) { // time out logic details this.closeTimeout = 10; this.active = false; this.countdownActive = false; this.warnTimer = undefined; this.countDown = 0; this.countDownTimer = undefined; this.config = config; this.pixelStreaming = pixelStreaming; this.onDismissAfk = onDismissAfk; this.onAFKTimedOutCallback = () => { console.log('AFK timed out, did you want to override this callback?'); }; } /** * The methods that occur when an afk event listener is clicked */ onAfkClick() { clearInterval(this.countDownTimer); if (this.active || this.countdownActive) { this.startAfkWarningTimer(); this.pixelStreaming.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_0__.AfkWarningDeactivateEvent()); } } /** * Start the warning timer if a timeout is set greater that 0 seconds */ startAfkWarningTimer() { if (this.config.getNumericSettingValue(_Config_Config__WEBPACK_IMPORTED_MODULE_1__.NumericParameters.AFKTimeoutSecs) > 0 && this.config.isFlagEnabled(_Config_Config__WEBPACK_IMPORTED_MODULE_1__.Flags.AFKDetection)) { this.active = true; } else { this.active = false; } this.resetAfkWarningTimer(); } /** * Stop the afk warning timer */ stopAfkWarningTimer() { this.active = false; this.countdownActive = false; clearTimeout(this.warnTimer); clearInterval(this.countDownTimer); } /** * Pause the timer which when elapsed will warn the user they are inactive. */ pauseAfkWarningTimer() { this.active = false; } /** * If the user interacts then reset the warning timer. */ resetAfkWarningTimer() { if (this.active && this.config.isFlagEnabled(_Config_Config__WEBPACK_IMPORTED_MODULE_1__.Flags.AFKDetection)) { clearTimeout(this.warnTimer); this.warnTimer = setTimeout(() => this.activateAfkEvent(), this.config.getNumericSettingValue(_Config_Config__WEBPACK_IMPORTED_MODULE_1__.NumericParameters.AFKTimeoutSecs) * 1000); } } /** * Show the AFK overlay and begin the countDown */ activateAfkEvent() { // Pause the timer while the user is looking at the inactivity warning overlay this.pauseAfkWarningTimer(); // instantiate a new overlay this.pixelStreaming.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_0__.AfkWarningActivateEvent({ countDown: this.countDown, dismissAfk: this.onDismissAfk })); // update our countDown timer and overlay contents this.countDown = this.closeTimeout; this.countdownActive = true; this.pixelStreaming.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_0__.AfkWarningUpdateEvent({ countDown: this.countDown })); // if we are in locked mouse exit pointerlock if (!this.config.isFlagEnabled(_Config_Config__WEBPACK_IMPORTED_MODULE_1__.Flags.HoveringMouseMode)) { // minor hack to alleviate ios not supporting pointerlock if (document.exitPointerLock) { document.exitPointerLock(); } } // reset our countDown interval accordingly this.countDownTimer = setInterval(() => { this.countDown--; if (this.countDown == 0) { // The user failed to click so hide the overlay and disconnect them. this.pixelStreaming.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_0__.AfkTimedOutEvent()); this.onAFKTimedOutCallback(); _Logger_Logger__WEBPACK_IMPORTED_MODULE_2__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_2__.Logger.GetStackTrace(), 'You have been disconnected due to inactivity'); // switch off the afk feature as stream has closed this.stopAfkWarningTimer(); } else { this.pixelStreaming.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_0__.AfkWarningUpdateEvent({ countDown: this.countDown })); } }, 1000); } } /***/ }), /***/ "./src/Config/Config.ts": /*!******************************!*\ !*** ./src/Config/Config.ts ***! \******************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "Config": () => (/* binding */ Config), /* harmony export */ "ControlSchemeType": () => (/* binding */ ControlSchemeType), /* harmony export */ "Flags": () => (/* binding */ Flags), /* harmony export */ "NumericParameters": () => (/* binding */ NumericParameters), /* harmony export */ "OptionParameters": () => (/* binding */ OptionParameters), /* harmony export */ "TextParameters": () => (/* binding */ TextParameters) /* harmony export */ }); /* harmony import */ var _Logger_Logger__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../Logger/Logger */ "./src/Logger/Logger.ts"); /* harmony import */ var _SettingFlag__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./SettingFlag */ "./src/Config/SettingFlag.ts"); /* harmony import */ var _SettingNumber__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./SettingNumber */ "./src/Config/SettingNumber.ts"); /* harmony import */ var _SettingText__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./SettingText */ "./src/Config/SettingText.ts"); /* harmony import */ var _SettingOption__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./SettingOption */ "./src/Config/SettingOption.ts"); /* harmony import */ var _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../Util/EventEmitter */ "./src/Util/EventEmitter.ts"); // Copyright Epic Games, Inc. All Rights Reserved. /** * A collection of flags that can be toggled and are core to all Pixel Streaming experiences. * These are used in the `Config.Flags` map. */ class Flags { } Flags.AutoConnect = 'AutoConnect'; Flags.AutoPlayVideo = 'AutoPlayVideo'; Flags.AFKDetection = 'TimeoutIfIdle'; Flags.BrowserSendOffer = 'OfferToReceive'; Flags.HoveringMouseMode = 'HoveringMouse'; Flags.ForceMonoAudio = 'ForceMonoAudio'; Flags.ForceTURN = 'ForceTURN'; Flags.FakeMouseWithTouches = 'FakeMouseWithTouches'; Flags.IsQualityController = 'ControlsQuality'; Flags.MatchViewportResolution = 'MatchViewportRes'; Flags.StartVideoMuted = 'StartVideoMuted'; Flags.SuppressBrowserKeys = 'SuppressBrowserKeys'; Flags.UseMic = 'UseMic'; Flags.KeyboardInput = 'KeyboardInput'; Flags.MouseInput = 'MouseInput'; Flags.TouchInput = 'TouchInput'; Flags.GamepadInput = 'GamepadInput'; Flags.XRControllerInput = 'XRControllerInput'; Flags.WaitForStreamer = "WaitForStreamer"; const isFlagId = (id) => Object.getOwnPropertyNames(Flags).some((name) => Flags[name] === id); /** * A collection of numeric parameters that are core to all Pixel Streaming experiences. * */ class NumericParameters { } NumericParameters.AFKTimeoutSecs = 'AFKTimeout'; NumericParameters.MinQP = 'MinQP'; NumericParameters.MaxQP = 'MaxQP'; NumericParameters.WebRTCFPS = 'WebRTCFPS'; NumericParameters.WebRTCMinBitrate = 'WebRTCMinBitrate'; NumericParameters.WebRTCMaxBitrate = 'WebRTCMaxBitrate'; NumericParameters.MaxReconnectAttempts = 'MaxReconnectAttempts'; NumericParameters.StreamerAutoJoinInterval = 'StreamerAutoJoinInterval'; const isNumericId = (id) => Object.getOwnPropertyNames(NumericParameters).some((name) => NumericParameters[name] === id); /** * A collection of textual parameters that are core to all Pixel Streaming experiences. * */ class TextParameters { } TextParameters.SignallingServerUrl = 'ss'; const isTextId = (id) => Object.getOwnPropertyNames(TextParameters).some((name) => TextParameters[name] === id); /** * A collection of enum based parameters that are core to all Pixel Streaming experiences. * */ class OptionParameters { } OptionParameters.PreferredCodec = 'PreferredCodec'; OptionParameters.StreamerId = 'StreamerId'; const isOptionId = (id) => Object.getOwnPropertyNames(OptionParameters).some((name) => OptionParameters[name] === id); class Config { // ------------ Settings ----------------- constructor(config = {}) { /* A map of flags that can be toggled - options that can be set in the application - e.g. Use Mic? */ this.flags = new Map(); /* A map of numerical settings - options that can be in the application - e.g. MinBitrate */ this.numericParameters = new Map(); /* A map of text settings - e.g. signalling server url */ this.textParameters = new Map(); /* A map of enum based settings - e.g. preferred codec */ this.optionParameters = new Map(); const { initialSettings, useUrlParams } = config; this._useUrlParams = !!useUrlParams; this.populateDefaultSettings(this._useUrlParams); if (initialSettings) { this.setSettings(initialSettings); } } /** * True if reading configuration initial values from URL parameters, and * persisting changes in URL when changed. */ get useUrlParams() { return this._useUrlParams; } /** * Populate the default settings for a Pixel Streaming application */ populateDefaultSettings(useUrlParams) { /** * Text Parameters */ this.textParameters.set(TextParameters.SignallingServerUrl, new _SettingText__WEBPACK_IMPORTED_MODULE_0__.SettingText(TextParameters.SignallingServerUrl, 'Signalling url', 'Url of the signalling server', (location.protocol === 'https:' ? 'wss://' : 'ws://') + window.location.hostname + // for readability, we omit the port if it's 80 (window.location.port === '80' || window.location.port === '' ? '' : `:${window.location.port}`), useUrlParams)); this.optionParameters.set(OptionParameters.StreamerId, new _SettingOption__WEBPACK_IMPORTED_MODULE_1__.SettingOption(OptionParameters.StreamerId, 'Streamer ID', 'The ID of the streamer to stream.', '', [], useUrlParams)); /** * Enum Parameters */ this.optionParameters.set(OptionParameters.PreferredCodec, new _SettingOption__WEBPACK_IMPORTED_MODULE_1__.SettingOption(OptionParameters.PreferredCodec, 'Preferred Codec', 'The preferred codec to be used during codec negotiation', 'H264 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f', (function () { const browserSupportedCodecs = []; // Try get the info needed from the RTCRtpReceiver. This is only available on chrome if (!RTCRtpReceiver.getCapabilities) { browserSupportedCodecs.push('Only available on Chrome'); return browserSupportedCodecs; } const matcher = /(VP\d|H26\d|AV1).*/; const codecs = RTCRtpReceiver.getCapabilities('video').codecs; codecs.forEach((codec) => { const str = codec.mimeType.split('/')[1] + ' ' + (codec.sdpFmtpLine || ''); const match = matcher.exec(str); if (match !== null) { browserSupportedCodecs.push(str); } }); return browserSupportedCodecs; })(), useUrlParams)); /** * Boolean parameters */ this.flags.set(Flags.AutoConnect, new _SettingFlag__WEBPACK_IMPORTED_MODULE_2__.SettingFlag(Flags.AutoConnect, 'Auto connect to stream', 'Whether we should attempt to auto connect to the signalling server or show a click to start prompt.', false, useUrlParams)); this.flags.set(Flags.AutoPlayVideo, new _SettingFlag__WEBPACK_IMPORTED_MODULE_2__.SettingFlag(Flags.AutoPlayVideo, 'Auto play video', 'When video is ready automatically start playing it as opposed to showing a play button.', true, useUrlParams)); this.flags.set(Flags.BrowserSendOffer, new _SettingFlag__WEBPACK_IMPORTED_MODULE_2__.SettingFlag(Flags.BrowserSendOffer, 'Browser send offer', 'Browser will initiate the WebRTC handshake by sending the offer to the streamer', false, useUrlParams)); this.flags.set(Flags.UseMic, new _SettingFlag__WEBPACK_IMPORTED_MODULE_2__.SettingFlag(Flags.UseMic, 'Use microphone', 'Make browser request microphone access and open an input audio track.', false, useUrlParams)); this.flags.set(Flags.StartVideoMuted, new _SettingFlag__WEBPACK_IMPORTED_MODULE_2__.SettingFlag(Flags.StartVideoMuted, 'Start video muted', 'Video will start muted if true.', false, useUrlParams)); this.flags.set(Flags.SuppressBrowserKeys, new _SettingFlag__WEBPACK_IMPORTED_MODULE_2__.SettingFlag(Flags.SuppressBrowserKeys, 'Suppress browser keys', 'Suppress certain browser keys that we use in UE, for example F5 to show shader complexity instead of refresh the page.', true, useUrlParams)); this.flags.set(Flags.IsQualityController, new _SettingFlag__WEBPACK_IMPORTED_MODULE_2__.SettingFlag(Flags.IsQualityController, 'Is quality controller?', 'True if this peer controls stream quality', true, useUrlParams)); this.flags.set(Flags.ForceMonoAudio, new _SettingFlag__WEBPACK_IMPORTED_MODULE_2__.SettingFlag(Flags.ForceMonoAudio, 'Force mono audio', 'Force browser to request mono audio in the SDP', false, useUrlParams)); this.flags.set(Flags.ForceTURN, new _SettingFlag__WEBPACK_IMPORTED_MODULE_2__.SettingFlag(Flags.ForceTURN, 'Force TURN', 'Only generate TURN/Relayed ICE candidates.', false, useUrlParams)); this.flags.set(Flags.AFKDetection, new _SettingFlag__WEBPACK_IMPORTED_MODULE_2__.SettingFlag(Flags.AFKDetection, 'AFK if idle', 'Timeout the experience if user is AFK for a period.', false, useUrlParams)); this.flags.set(Flags.MatchViewportResolution, new _SettingFlag__WEBPACK_IMPORTED_MODULE_2__.SettingFlag(Flags.MatchViewportResolution, 'Match viewport resolution', 'Pixel Streaming will be instructed to dynamically resize the video stream to match the size of the video element.', false, useUrlParams)); this.flags.set(Flags.HoveringMouseMode, new _SettingFlag__WEBPACK_IMPORTED_MODULE_2__.SettingFlag(Flags.HoveringMouseMode, 'Control Scheme: Locked Mouse', 'Either locked mouse, where the pointer is consumed by the video and locked to it, or hovering mouse, where the mouse is not consumed.', false, useUrlParams, (isHoveringMouse, setting) => { setting.label = `Control Scheme: ${isHoveringMouse ? 'Hovering' : 'Locked'} Mouse`; })); this.flags.set(Flags.FakeMouseWithTouches, new _SettingFlag__WEBPACK_IMPORTED_MODULE_2__.SettingFlag(Flags.FakeMouseWithTouches, 'Fake mouse with touches', 'A single finger touch is converted into a mouse event. This allows a non-touch application to be controlled partially via a touch device.', false, useUrlParams)); this.flags.set(Flags.KeyboardInput, new _SettingFlag__WEBPACK_IMPORTED_MODULE_2__.SettingFlag(Flags.KeyboardInput, 'Keyboard input', 'If enabled, send keyboard events to streamer', true, useUrlParams)); this.flags.set(Flags.MouseInput, new _SettingFlag__WEBPACK_IMPORTED_MODULE_2__.SettingFlag(Flags.MouseInput, 'Mouse input', 'If enabled, send mouse events to streamer', true, useUrlParams)); this.flags.set(Flags.TouchInput, new _SettingFlag__WEBPACK_IMPORTED_MODULE_2__.SettingFlag(Flags.TouchInput, 'Touch input', 'If enabled, send touch events to streamer', true, useUrlParams)); this.flags.set(Flags.GamepadInput, new _SettingFlag__WEBPACK_IMPORTED_MODULE_2__.SettingFlag(Flags.GamepadInput, 'Gamepad input', 'If enabled, send gamepad events to streamer', true, useUrlParams)); this.flags.set(Flags.XRControllerInput, new _SettingFlag__WEBPACK_IMPORTED_MODULE_2__.SettingFlag(Flags.XRControllerInput, 'XR controller input', 'If enabled, send XR controller events to streamer', true, useUrlParams)); this.flags.set(Flags.WaitForStreamer, new _SettingFlag__WEBPACK_IMPORTED_MODULE_2__.SettingFlag(Flags.WaitForStreamer, 'Wait for streamer', 'Will continue trying to connect to the first streamer available.', true, useUrlParams)); /** * Numeric parameters */ this.numericParameters.set(NumericParameters.AFKTimeoutSecs, new _SettingNumber__WEBPACK_IMPORTED_MODULE_3__.SettingNumber(NumericParameters.AFKTimeoutSecs, 'AFK timeout', 'The time (in seconds) it takes for the application to time out if AFK timeout is enabled.', 0 /*min*/, 600 /*max*/, 120 /*value*/, useUrlParams)); this.numericParameters.set(NumericParameters.MaxReconnectAttempts, new _SettingNumber__WEBPACK_IMPORTED_MODULE_3__.SettingNumber(NumericParameters.MaxReconnectAttempts, 'Max Reconnects', 'Maximum number of reconnects the application will attempt when a streamer disconnects.', 0 /*min*/, 999 /*max*/, 3 /*value*/, useUrlParams)); this.numericParameters.set(NumericParameters.MinQP, new _SettingNumber__WEBPACK_IMPORTED_MODULE_3__.SettingNumber(NumericParameters.MinQP, 'Min QP', 'The lower bound for the quantization parameter (QP) of the encoder. 0 = Best quality, 51 = worst quality.', 0 /*min*/, 51 /*max*/, 0 /*value*/, useUrlParams)); this.numericParameters.set(NumericParameters.MaxQP, new _SettingNumber__WEBPACK_IMPORTED_MODULE_3__.SettingNumber(NumericParameters.MaxQP, 'Max QP', 'The upper bound for the quantization parameter (QP) of the encoder. 0 = Best quality, 51 = worst quality.', 0 /*min*/, 51 /*max*/, 51 /*value*/, useUrlParams)); this.numericParameters.set(NumericParameters.WebRTCFPS, new _SettingNumber__WEBPACK_IMPORTED_MODULE_3__.SettingNumber(NumericParameters.WebRTCFPS, 'Max FPS', 'The maximum FPS that WebRTC will try to transmit frames at.', 1 /*min*/, 999 /*max*/, 60 /*value*/, useUrlParams)); this.numericParameters.set(NumericParameters.WebRTCMinBitrate, new _SettingNumber__WEBPACK_IMPORTED_MODULE_3__.SettingNumber(NumericParameters.WebRTCMinBitrate, 'Min Bitrate (kbps)', 'The minimum bitrate that WebRTC should use.', 0 /*min*/, 500000 /*max*/, 0 /*value*/, useUrlParams)); this.numericParameters.set(NumericParameters.WebRTCMaxBitrate, new _SettingNumber__WEBPACK_IMPORTED_MODULE_3__.SettingNumber(NumericParameters.WebRTCMaxBitrate, 'Max Bitrate (kbps)', 'The maximum bitrate that WebRTC should use.', 0 /*min*/, 500000 /*max*/, 0 /*value*/, useUrlParams)); this.numericParameters.set(NumericParameters.StreamerAutoJoinInterval, new _SettingNumber__WEBPACK_IMPORTED_MODULE_3__.SettingNumber(NumericParameters.StreamerAutoJoinInterval, 'Streamer Auto Join Interval (ms)', 'Delay between retries when waiting for an available streamer.', 500 /*min*/, 900000 /*max*/, 3000 /*value*/, useUrlParams)); } /** * Add a callback to fire when the numeric setting is toggled. * @param id The id of the flag. * @param onChangedListener The callback to fire when the numeric value changes. */ _addOnNumericSettingChangedListener(id, onChangedListener) { if (this.numericParameters.has(id)) { this.numericParameters .get(id) .addOnChangedListener(onChangedListener); } } _addOnOptionSettingChangedListener(id, onChangedListener) { if (this.optionParameters.has(id)) { this.optionParameters .get(id) .addOnChangedListener(onChangedListener); } } /** * @param id The id of the numeric setting we are interested in getting a value for. * @returns The numeric value stored in the parameter with the passed id. */ getNumericSettingValue(id) { if (this.numericParameters.has(id)) { return this.numericParameters.get(id).number; } else { throw new Error(`There is no numeric setting with the id of ${id}`); } } /** * @param id The id of the text setting we are interested in getting a value for. * @returns The text value stored in the parameter with the passed id. */ getTextSettingValue(id) { if (this.textParameters.has(id)) { return this.textParameters.get(id).value; } else { throw new Error(`There is no numeric setting with the id of ${id}`); } } /** * Set number in the setting. * @param id The id of the numeric setting we are interested in. * @param value The numeric value to set. */ setNumericSetting(id, value) { if (this.numericParameters.has(id)) { this.numericParameters.get(id).number = value; } else { throw new Error(`There is no numeric setting with the id of ${id}`); } } /** * Add a callback to fire when the flag is toggled. * @param id The id of the flag. * @param onChangeListener The callback to fire when the value changes. */ _addOnSettingChangedListener(id, onChangeListener) { if (this.flags.has(id)) { this.flags.get(id).onChange = onChangeListener; } } /** * Add a callback to fire when the text is changed. * @param id The id of the flag. * @param onChangeListener The callback to fire when the value changes. */ _addOnTextSettingChangedListener(id, onChangeListener) { if (this.textParameters.has(id)) { this.textParameters.get(id).onChange = onChangeListener; } } /** * Get the option which has the given id. * @param id The id of the option. * @returns The SettingOption object matching id */ getSettingOption(id) { return this.optionParameters.get(id); } /** * Get the value of the configuration flag which has the given id. * @param id The unique id for the flag. * @returns True if the flag is enabled. */ isFlagEnabled(id) { return this.flags.get(id).flag; } /** * Set flag to be enabled/disabled. * @param id The id of the flag to toggle. * @param flagEnabled True if the flag should be enabled. */ setFlagEnabled(id, flagEnabled) { if (!this.flags.has(id)) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_4__.Logger.Warning(_Logger_Logger__WEBPACK_IMPORTED_MODULE_4__.Logger.GetStackTrace(), `Cannot toggle flag called ${id} - it does not exist in the Config.flags map.`); } else { this.flags.get(id).flag = flagEnabled; } } /** * Set the text setting. * @param id The id of the setting * @param settingValue The value to set in the setting. */ setTextSetting(id, settingValue) { if (!this.textParameters.has(id)) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_4__.Logger.Warning(_Logger_Logger__WEBPACK_IMPORTED_MODULE_4__.Logger.GetStackTrace(), `Cannot set text setting called ${id} - it does not exist in the Config.textParameters map.`); } else { this.textParameters.get(id).text = settingValue; } } /** * Set the option setting list of options. * @param id The id of the setting * @param settingOptions The values the setting could take */ setOptionSettingOptions(id, settingOptions) { if (!this.optionParameters.has(id)) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_4__.Logger.Warning(_Logger_Logger__WEBPACK_IMPORTED_MODULE_4__.Logger.GetStackTrace(), `Cannot set text setting called ${id} - it does not exist in the Config.optionParameters map.`); } else { this.optionParameters.get(id).options = settingOptions; } } /** * Set option enum settings selected option. * @param id The id of the setting * @param settingOptions The value to select out of all the options */ setOptionSettingValue(id, settingValue) { if (!this.optionParameters.has(id)) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_4__.Logger.Warning(_Logger_Logger__WEBPACK_IMPORTED_MODULE_4__.Logger.GetStackTrace(), `Cannot set text setting called ${id} - it does not exist in the Config.enumParameters map.`); } else { this.optionParameters.get(id).selected = settingValue; } } /** * Set the label for the flag. * @param id The id of the flag. * @param label The new label to use for the flag. */ setFlagLabel(id, label) { if (!this.flags.has(id)) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_4__.Logger.Warning(_Logger_Logger__WEBPACK_IMPORTED_MODULE_4__.Logger.GetStackTrace(), `Cannot set label for flag called ${id} - it does not exist in the Config.flags map.`); } else { this.flags.get(id).label = label; } } /** * Set a subset of all settings in one function call. * * @param settings A (partial) list of settings to set */ setSettings(settings) { for (const key of Object.keys(settings)) { if (isFlagId(key)) { this.setFlagEnabled(key, settings[key]); } else if (isNumericId(key)) { this.setNumericSetting(key, settings[key]); } else if (isTextId(key)) { this.setTextSetting(key, settings[key]); } else if (isOptionId(key)) { this.setOptionSettingValue(key, settings[key]); } } } /** * Get all settings * @returns All setting values as an object with setting ids as keys */ getSettings() { const settings = {}; for (const [key, value] of this.flags.entries()) { settings[key] = value.flag; } for (const [key, value] of this.numericParameters.entries()) { settings[key] = value.number; } for (const [key, value] of this.textParameters.entries()) { settings[key] = value.text; } for (const [key, value] of this.optionParameters.entries()) { settings[key] = value.selected; } return settings; } /** * Get all Flag settings as an array. * @returns All SettingFlag objects */ getFlags() { return Array.from(this.flags.values()); } /** * Get all Text settings as an array. * @returns All SettingText objects */ getTextSettings() { return Array.from(this.textParameters.values()); } /** * Get all Number settings as an array. * @returns All SettingNumber objects */ getNumericSettings() { return Array.from(this.numericParameters.values()); } /** * Get all Option settings as an array. * @returns All SettingOption objects */ getOptionSettings() { return Array.from(this.optionParameters.values()); } /** * Emit events when settings change. * @param eventEmitter */ _registerOnChangeEvents(eventEmitter) { for (const key of this.flags.keys()) { const flag = this.flags.get(key); if (flag) { flag.onChangeEmit = (newValue) => eventEmitter.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_5__.SettingsChangedEvent({ id: flag.id, type: 'flag', value: newValue, target: flag })); } } for (const key of this.numericParameters.keys()) { const number = this.numericParameters.get(key); if (number) { number.onChangeEmit = (newValue) => eventEmitter.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_5__.SettingsChangedEvent({ id: number.id, type: 'number', value: newValue, target: number })); } } for (const key of this.textParameters.keys()) { const text = this.textParameters.get(key); if (text) { text.onChangeEmit = (newValue) => eventEmitter.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_5__.SettingsChangedEvent({ id: text.id, type: 'text', value: newValue, target: text })); } } for (const key of this.optionParameters.keys()) { const option = this.optionParameters.get(key); if (option) { option.onChangeEmit = (newValue) => eventEmitter.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_5__.SettingsChangedEvent({ id: option.id, type: 'option', value: newValue, target: option })); } } } } /** * The enum associated with the mouse being locked or hovering */ var ControlSchemeType; (function (ControlSchemeType) { ControlSchemeType[ControlSchemeType["LockedMouse"] = 0] = "LockedMouse"; ControlSchemeType[ControlSchemeType["HoveringMouse"] = 1] = "HoveringMouse"; })(ControlSchemeType || (ControlSchemeType = {})); /***/ }), /***/ "./src/Config/SettingBase.ts": /*!***********************************!*\ !*** ./src/Config/SettingBase.ts ***! \***********************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "SettingBase": () => (/* binding */ SettingBase) /* harmony export */ }); // Copyright Epic Games, Inc. All Rights Reserved. /** * Base class for a setting that has a text label and an arbitrary setting value it stores. */ class SettingBase { constructor(id, label, description, defaultSettingValue, // eslint-disable-next-line @typescript-eslint/no-empty-function defaultOnChangeListener = () => { }) { this.onChange = defaultOnChangeListener; this.onChangeEmit = () => { /* Do nothing, to be overridden. */ }; this.id = id; this.description = description; this.label = label; this.value = defaultSettingValue; } /** * Set the label text for the setting. * @param label setting label. */ set label(inLabel) { this._label = inLabel; this.onChangeEmit(this._value); } /** * @returns The label text for the setting. */ get label() { return this._label; } /** * @return The setting's value. */ get value() { return this._value; } /** * Update the setting's stored value. * @param inValue The new value for the setting. */ set value(inValue) { this._value = inValue; this.onChange(this._value, this); this.onChangeEmit(this._value); } } /***/ }), /***/ "./src/Config/SettingFlag.ts": /*!***********************************!*\ !*** ./src/Config/SettingFlag.ts ***! \***********************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "SettingFlag": () => (/* binding */ SettingFlag) /* harmony export */ }); /* harmony import */ var _SettingBase__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./SettingBase */ "./src/Config/SettingBase.ts"); // Copyright Epic Games, Inc. All Rights Reserved. /** * A boolean flag setting object with a text label. */ class SettingFlag extends _SettingBase__WEBPACK_IMPORTED_MODULE_0__.SettingBase { constructor(id, label, description, defaultFlagValue, useUrlParams, // eslint-disable-next-line @typescript-eslint/no-empty-function defaultOnChangeListener = () => { }) { super(id, label, description, defaultFlagValue, defaultOnChangeListener); const urlParams = new URLSearchParams(window.location.search); if (!useUrlParams || !urlParams.has(this.id)) { this.flag = defaultFlagValue; } else { // parse flag from url parameters const urlParamFlag = this.getUrlParamFlag(); this.flag = urlParamFlag; } this.useUrlParams = useUrlParams; } /** * Parse the flag value from the url parameters. * @returns True if the url parameters contains /?id, but False if /?id=false */ getUrlParamFlag() { const urlParams = new URLSearchParams(window.location.search); if (urlParams.has(this.id)) { if (urlParams.get(this.id) === 'false' || urlParams.get(this.id) === 'False') { return false; } return true; } return false; } /** * Persist the setting value in URL. */ updateURLParams() { if (this.useUrlParams) { // set url params const urlParams = new URLSearchParams(window.location.search); if (this.flag === true) { urlParams.set(this.id, 'true'); } else { urlParams.set(this.id, 'false'); } window.history.replaceState({}, '', urlParams.toString() !== '' ? `${location.pathname}?${urlParams}` : `${location.pathname}`); } } /** * Enables this flag. */ enable() { this.flag = true; } /** * @return The setting's value. */ get flag() { return !!this.value; } /** * Update the setting's stored value. * @param inValue The new value for the setting. */ set flag(inValue) { this.value = inValue; } } /***/ }), /***/ "./src/Config/SettingNumber.ts": /*!*************************************!*\ !*** ./src/Config/SettingNumber.ts ***! \*************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "SettingNumber": () => (/* binding */ SettingNumber) /* harmony export */ }); /* harmony import */ var _SettingBase__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./SettingBase */ "./src/Config/SettingBase.ts"); // Copyright Epic Games, Inc. All Rights Reserved. /** * A number setting object with a text label. Min and max limit the range of allowed values. */ class SettingNumber extends _SettingBase__WEBPACK_IMPORTED_MODULE_0__.SettingBase { constructor(id, label, description, min, max, defaultNumber, useUrlParams, // eslint-disable-next-line @typescript-eslint/no-empty-function defaultOnChangeListener = () => { }) { super(id, label, description, defaultNumber, defaultOnChangeListener); this._min = min; this._max = max; // attempt to read the number from the url params const urlParams = new URLSearchParams(window.location.search); if (!useUrlParams || !urlParams.has(this.id)) { this.number = defaultNumber; } else { const parsedValue = Number.parseInt(urlParams.get(this.id)); this.number = Number.isNaN(parsedValue) ? defaultNumber : parsedValue; } this.useUrlParams = useUrlParams; } /** * Persist the setting value in URL. */ updateURLParams() { if (this.useUrlParams) { // set url params like ?id=number const urlParams = new URLSearchParams(window.location.search); urlParams.set(this.id, this.number.toString()); window.history.replaceState({}, '', urlParams.toString() !== '' ? `${location.pathname}?${urlParams}` : `${location.pathname}`); } } /** * Set the number value (will be clamped within range). */ set number(newNumber) { this.value = this.clamp(newNumber); } /** * @returns The number stored. */ get number() { return this.value; } /** * Clamps a number between the min and max values (inclusive). * @param inNumber The number to clamp. * @returns The clamped number. */ clamp(inNumber) { return Math.max(Math.min(this._max, inNumber), this._min); } /** * Returns the minimum value * @returns The minimum value */ get min() { return this._min; } /** * Returns the maximum value * @returns The maximum value */ get max() { return this._max; } /** * Add a change listener to the number object. */ addOnChangedListener(onChangedFunc) { this.onChange = onChangedFunc; } } /***/ }), /***/ "./src/Config/SettingOption.ts": /*!*************************************!*\ !*** ./src/Config/SettingOption.ts ***! \*************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "SettingOption": () => (/* binding */ SettingOption) /* harmony export */ }); /* harmony import */ var _SettingBase__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./SettingBase */ "./src/Config/SettingBase.ts"); // Copyright Epic Games, Inc. All Rights Reserved. /** * An Option setting object with a text label. Allows you to specify an array of options and select one of them. */ class SettingOption extends _SettingBase__WEBPACK_IMPORTED_MODULE_0__.SettingBase { constructor(id, label, description, defaultTextValue, options, useUrlParams, // eslint-disable-next-line @typescript-eslint/no-empty-function defaultOnChangeListener = () => { }) { super(id, label, description, [defaultTextValue, defaultTextValue], defaultOnChangeListener); this.options = options; const urlParams = new URLSearchParams(window.location.search); const stringToMatch = useUrlParams && urlParams.has(this.id) ? this.getUrlParamText() : defaultTextValue; this.selected = stringToMatch; this.useUrlParams = useUrlParams; } /** * Parse the text value from the url parameters. * @returns The text value parsed from the url if the url parameters contains /?id=value, but empty string if just /?id or no url param found. */ getUrlParamText() { var _a; const urlParams = new URLSearchParams(window.location.search); if (urlParams.has(this.id)) { return (_a = urlParams.get(this.id)) !== null && _a !== void 0 ? _a : ''; } return ''; } /** * Persist the setting value in URL. */ updateURLParams() { if (this.useUrlParams) { // set url params const urlParams = new URLSearchParams(window.location.search); urlParams.set(this.id, this.selected); window.history.replaceState({}, '', urlParams.toString() !== '' ? `${location.pathname}?${urlParams}` : `${location.pathname}`); } } /** * Add a change listener to the select element. */ addOnChangedListener(onChangedFunc) { this.onChange = onChangedFunc; } /** * @returns All available options as an array */ get options() { return this._options; } /** * Set options * @param values Array of options */ set options(values) { this._options = values; this.onChangeEmit(this.selected); } /** * @returns Selected option as a string */ get selected() { return this.value; } /** * Set selected option if it matches one of the available options * @param value Selected option */ set selected(value) { if(!value) { return; } // A user may not specify the full possible value so we instead use the closest match. // eg ?xxx=H264 would select 'H264 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f' let filteredList = this.options.filter((option) => option.indexOf(value) !== -1); if (filteredList.length) { this.value = filteredList[0]; return; } // A user has specified a codec with a fmtp string but this codec + fmtp line isn't available. // in that case, just use the codec filteredList = this.options.filter((option) => option.indexOf(value.split(' ')[0]) !== -1); if (filteredList.length) { this.value = filteredList[0]; return; } } } /***/ }), /***/ "./src/Config/SettingText.ts": /*!***********************************!*\ !*** ./src/Config/SettingText.ts ***! \***********************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "SettingText": () => (/* binding */ SettingText) /* harmony export */ }); /* harmony import */ var _SettingBase__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./SettingBase */ "./src/Config/SettingBase.ts"); // Copyright Epic Games, Inc. All Rights Reserved. /** * A text setting object with a text label. */ class SettingText extends _SettingBase__WEBPACK_IMPORTED_MODULE_0__.SettingBase { constructor(id, label, description, defaultTextValue, useUrlParams, // eslint-disable-next-line @typescript-eslint/no-empty-function defaultOnChangeListener = () => { }) { super(id, label, description, defaultTextValue, defaultOnChangeListener); const urlParams = new URLSearchParams(window.location.search); if (!useUrlParams || !urlParams.has(this.id)) { this.text = defaultTextValue; } else { // parse flag from url parameters const urlParamFlag = this.getUrlParamText(); this.text = urlParamFlag; } this.useUrlParams = useUrlParams; } /** * Parse the text value from the url parameters. * @returns The text value parsed from the url if the url parameters contains /?id=value, but empty string if just /?id or no url param found. */ getUrlParamText() { var _a; const urlParams = new URLSearchParams(window.location.search); if (urlParams.has(this.id)) { return (_a = urlParams.get(this.id)) !== null && _a !== void 0 ? _a : ''; } return ''; } /** * Persist the setting value in URL. */ updateURLParams() { if (this.useUrlParams) { // set url params const urlParams = new URLSearchParams(window.location.search); urlParams.set(this.id, this.text); window.history.replaceState({}, '', urlParams.toString() !== '' ? `${location.pathname}?${urlParams}` : `${location.pathname}`); } } /** * @return The setting's value. */ get text() { return this.value; } /** * Update the setting's stored value. * @param inValue The new value for the setting. */ set text(inValue) { this.value = inValue; } } /***/ }), /***/ "./src/DataChannel/DataChannelController.ts": /*!**************************************************!*\ !*** ./src/DataChannel/DataChannelController.ts ***! \**************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "DataChannelController": () => (/* binding */ DataChannelController) /* harmony export */ }); /* harmony import */ var _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Logger/Logger */ "./src/Logger/Logger.ts"); // Copyright Epic Games, Inc. All Rights Reserved. /** * Handles the Sending and Receiving of messages to the UE Instance via the Data Channel */ class DataChannelController { constructor() { this.isReceivingFreezeFrame = false; } /** * return the current state of a datachannel controller instance * @returns the current DataChannelController instance */ getDataChannelInstance() { return this; } /** * To Create and Set up a Data Channel * @param peerConnection - The RTC Peer Connection * @param label - Label of the Data Channel * @param datachannelOptions - Optional RTC DataChannel options */ createDataChannel(peerConnection, label, datachannelOptions) { this.peerConnection = peerConnection; this.label = label; this.datachannelOptions = datachannelOptions; if (datachannelOptions == null) { this.datachannelOptions = {}; this.datachannelOptions.ordered = true; } this.dataChannel = this.peerConnection.createDataChannel(this.label, this.datachannelOptions); this.setupDataChannel(); } setupDataChannel() { //We Want an Array Buffer not a blob this.dataChannel.binaryType = 'arraybuffer'; this.dataChannel.onopen = (ev) => this.handleOnOpen(ev); this.dataChannel.onclose = (ev) => this.handleOnClose(ev); this.dataChannel.onmessage = (ev) => this.handleOnMessage(ev); this.dataChannel.onerror = (ev) => this.handleOnError(ev); } /** * Handles when the Data Channel is opened */ handleOnOpen(ev) { var _a; _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), `Data Channel (${this.label}) opened.`, 7); this.onOpen((_a = this.dataChannel) === null || _a === void 0 ? void 0 : _a.label, ev); } /** * Handles when the Data Channel is closed */ handleOnClose(ev) { var _a; _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), `Data Channel (${this.label}) closed.`, 7); this.onClose((_a = this.dataChannel) === null || _a === void 0 ? void 0 : _a.label, ev); } /** * Handles when a message is received * @param event - Message Event */ handleOnMessage(event) { // Higher log level to prevent log spam with messages received _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), `Data Channel (${this.label}) message: ${event}`, 8); } /** * Handles when an error is thrown * @param event - Error Event */ handleOnError(event) { var _a; _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), `Data Channel (${this.label}) error: ${event}`, 7); this.onError((_a = this.dataChannel) === null || _a === void 0 ? void 0 : _a.label, event); } /** * Override to register onOpen handler * @param label Data channel label ("datachannel", "send-datachannel", "recv-datachannel") * @param ev event */ // eslint-disable-next-line @typescript-eslint/no-unused-vars onOpen(label, ev) { // empty default implementation } /** * Override to register onClose handler * @param label Data channel label ("datachannel", "send-datachannel", "recv-datachannel") * @param ev event */ // eslint-disable-next-line @typescript-eslint/no-unused-vars onClose(label, ev) { // empty default implementation } /** * Override to register onError handler * @param label Data channel label ("datachannel", "send-datachannel", "recv-datachannel") * @param ev event */ // eslint-disable-next-line @typescript-eslint/no-unused-vars onError(label, ev) { // empty default implementation } } /***/ }), /***/ "./src/DataChannel/DataChannelLatencyTestController.ts": /*!*************************************************************!*\ !*** ./src/DataChannel/DataChannelLatencyTestController.ts ***! \*************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "DataChannelLatencyTestController": () => (/* binding */ DataChannelLatencyTestController) /* harmony export */ }); /* harmony import */ var _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Logger/Logger */ "./src/Logger/Logger.ts"); /* harmony import */ var _DataChannelLatencyTestResults__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./DataChannelLatencyTestResults */ "./src/DataChannel/DataChannelLatencyTestResults.ts"); // Copyright Epic Games, Inc. All Rights Reserved. class DataChannelLatencyTestController { constructor(sink, callback) { this.sink = sink; this.callback = callback; this.records = new Map(); this.seq = 0; } start(config) { if (this.isRunning()) { return false; } this.startTime = Date.now(); this.records.clear(); this.interval = setInterval((() => { if (Date.now() - this.startTime >= config.duration) { this.stop(); } else { this.sendRequest(config.requestSize, config.responseSize); } }).bind(this), Math.floor(1000 / config.rps)); return true; } stop() { if (this.interval) { clearInterval(this.interval); this.interval = undefined; this.callback(this.produceResult()); } } produceResult() { const resultRecords = new Map(this.records); return { records: resultRecords, dataChannelRtt: Math.ceil(Array.from(this.records.values()).reduce((acc, next) => { return acc + (next.playerReceivedTimestamp - next.playerSentTimestamp); }, 0) / this.records.size), playerToStreamerTime: Math.ceil(Array.from(this.records.values()).reduce((acc, next) => { return acc + (next.streamerReceivedTimestamp - next.playerSentTimestamp); }, 0) / this.records.size), streamerToPlayerTime: Math.ceil(Array.from(this.records.values()).reduce((acc, next) => { return acc + (next.playerReceivedTimestamp - next.streamerSentTimestamp); }, 0) / this.records.size), exportLatencyAsCSV: () => { let csv = "Timestamp;RTT;PlayerToStreamer;StreamerToPlayer;\n"; resultRecords.forEach((record) => { csv += record.playerSentTimestamp + ";"; csv += (record.playerReceivedTimestamp - record.playerSentTimestamp) + ";"; csv += (record.streamerReceivedTimestamp - record.playerSentTimestamp) + ";"; csv += (record.playerReceivedTimestamp - record.streamerSentTimestamp) + ";"; csv += "\n"; }); return csv; } }; } isRunning() { return !!this.interval; } receive(response) { if (!this.isRunning()) { return; } if (!response) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Error(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), "Undefined response from server"); return; } let record = this.records.get(response.Seq); if (record) { record.update(response); } } sendRequest(requestSize, responseSize) { let request = this.createRequest(requestSize, responseSize); let record = new _DataChannelLatencyTestResults__WEBPACK_IMPORTED_MODULE_1__.DataChannelLatencyTestRecord(request); this.records.set(record.seq, record); this.sink(request); } createRequest(requestSize, responseSize) { return { Seq: this.seq++, FillResponseSize: responseSize, Filler: requestSize ? "A".repeat(requestSize) : "" }; } } /***/ }), /***/ "./src/DataChannel/DataChannelLatencyTestResults.ts": /*!**********************************************************!*\ !*** ./src/DataChannel/DataChannelLatencyTestResults.ts ***! \**********************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "DataChannelLatencyTestRecord": () => (/* binding */ DataChannelLatencyTestRecord) /* harmony export */ }); // Copyright Epic Games, Inc. All Rights Reserved. class DataChannelLatencyTestRecord { constructor(request) { this.seq = request.Seq; this.playerSentTimestamp = Date.now(); this.requestFillerSize = request.Filler ? request.Filler.length : 0; } update(response) { this.playerReceivedTimestamp = Date.now(); this.streamerReceivedTimestamp = response.ReceivedTimestamp; this.streamerSentTimestamp = response.SentTimestamp; this.responseFillerSize = response.Filler ? response.Filler.length : 0; } } /***/ }), /***/ "./src/DataChannel/DataChannelSender.ts": /*!**********************************************!*\ !*** ./src/DataChannel/DataChannelSender.ts ***! \**********************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "DataChannelSender": () => (/* binding */ DataChannelSender) /* harmony export */ }); /* harmony import */ var _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Logger/Logger */ "./src/Logger/Logger.ts"); // Copyright Epic Games, Inc. All Rights Reserved. /** * A class for sending data channel messages */ class DataChannelSender { /** * @param dataChannelProvider - Data channel object type */ constructor(dataChannelProvider) { this.dataChannelProvider = dataChannelProvider; } canSend() { return (this.dataChannelProvider.getDataChannelInstance().dataChannel !== undefined && this.dataChannelProvider.getDataChannelInstance().dataChannel .readyState == 'open'); } /** * Send Data over the Data channel to the UE Instance * @param data - Message Data Array Buffer */ sendData(data) { // reset the afk inactivity const dataChannelInstance = this.dataChannelProvider.getDataChannelInstance(); if (dataChannelInstance.dataChannel.readyState == 'open') { dataChannelInstance.dataChannel.send(data); _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), `Message Sent: ${new Uint8Array(data)}`, 6); this.resetAfkWarningTimerOnDataSend(); } else { _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Error(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), `Message Failed: ${new Uint8Array(data)}`); } } /** * An override method for resetting the Afk warning timer when data is sent over the data channel */ resetAfkWarningTimerOnDataSend() { // Base Functionality: Do Nothing } } /***/ }), /***/ "./src/DataChannel/InitialSettings.ts": /*!********************************************!*\ !*** ./src/DataChannel/InitialSettings.ts ***! \********************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "EncoderSettings": () => (/* binding */ EncoderSettings), /* harmony export */ "InitialSettings": () => (/* binding */ InitialSettings), /* harmony export */ "PixelStreamingSettings": () => (/* binding */ PixelStreamingSettings), /* harmony export */ "WebRTCSettings": () => (/* binding */ WebRTCSettings) /* harmony export */ }); // Copyright Epic Games, Inc. All Rights Reserved. /** * Latency Test Results Data */ class InitialSettings { constructor() { this.PixelStreamingSettings = new PixelStreamingSettings(); this.EncoderSettings = new EncoderSettings(); this.WebRTCSettings = new WebRTCSettings(); } /** * Checks for compatibility with the FPS and MaxFPS stats between 4.27 and 5 */ ueCompatible() { if (this.WebRTCSettings.MaxFPS != null) { this.WebRTCSettings.FPS = this.WebRTCSettings.MaxFPS; } } } /** * A class for handling Pixel Streaming details */ class PixelStreamingSettings { } /** * A class for handling encoder stats */ class EncoderSettings { } /** * A class for handling web rtc stats */ class WebRTCSettings { } /***/ }), /***/ "./src/DataChannel/LatencyTestResults.ts": /*!***********************************************!*\ !*** ./src/DataChannel/LatencyTestResults.ts ***! \***********************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "LatencyTestResults": () => (/* binding */ LatencyTestResults) /* harmony export */ }); /* harmony import */ var _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Logger/Logger */ "./src/Logger/Logger.ts"); // Copyright Epic Games, Inc. All Rights Reserved. /** * Latency Test Results Data */ class LatencyTestResults { constructor() { //Fields Set from the latency payload regardless of version this.ReceiptTimeMs = null; this.TransmissionTimeMs = null; //Fields Set from the latency payload from 4.27.2 this.PreCaptureTimeMs = null; this.PostCaptureTimeMs = null; this.PreEncodeTimeMs = null; this.PostEncodeTimeMs = null; //Fields Set from the latency payload from 5.0 this.EncodeMs = null; this.CaptureToSendMs = null; //Fields Set when processed this.testStartTimeMs = 0; this.browserReceiptTimeMs = 0; //Fields set from calculations this.latencyExcludingDecode = 0; this.testDuration = 0; //ueLatency: number = 0; this.networkLatency = 0; this.browserSendLatency = 0; this.frameDisplayDeltaTimeMs = 0; this.endToEndLatency = 0; //uePixelStreamLatency: number = 0; this.encodeLatency = 0; } /** * Sets the Delta Time Milliseconds * @param DeltaTimeMs - Delta Time Milliseconds */ setFrameDisplayDeltaTime(DeltaTimeMs) { if (this.frameDisplayDeltaTimeMs == 0) { this.frameDisplayDeltaTimeMs = Math.round(DeltaTimeMs); } } /** * Process the encoder times and set them */ processFields() { if (this.EncodeMs == null && (this.PreEncodeTimeMs != null || this.PostEncodeTimeMs != null)) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), `Setting Encode Ms \n ${this.PostEncodeTimeMs} \n ${this.PreEncodeTimeMs}`, 6); this.EncodeMs = this.PostEncodeTimeMs - this.PreEncodeTimeMs; } if (this.CaptureToSendMs == null && (this.PreCaptureTimeMs != null || this.PostCaptureTimeMs != null)) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), `Setting CaptureToSendMs Ms \n ${this.PostCaptureTimeMs} \n ${this.PreCaptureTimeMs}`, 6); this.CaptureToSendMs = this.PostCaptureTimeMs - this.PreCaptureTimeMs; } } } /***/ }), /***/ "./src/FreezeFrame/FreezeFrame.ts": /*!****************************************!*\ !*** ./src/FreezeFrame/FreezeFrame.ts ***! \****************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "FreezeFrame": () => (/* binding */ FreezeFrame) /* harmony export */ }); // Copyright Epic Games, Inc. All Rights Reserved. /** * A class for managing the freeze frame object */ class FreezeFrame { /** * Construct a freeze frame * @param rootDiv the div that a freeze frame element will be injected into */ constructor(rootDiv) { this.freezeFrameHeight = 0; this.freezeFrameWidth = 0; this.rootDiv = rootDiv; // create the overlay this.rootElement = document.createElement('div'); this.rootElement.id = 'freezeFrame'; this.rootElement.style.display = 'none'; this.rootElement.style.pointerEvents = 'none'; this.rootElement.style.position = 'absolute'; this.rootElement.style.zIndex = '20'; // create the image place holder this.imageElement = document.createElement('img'); this.imageElement.style.position = 'absolute'; // append the image into the root element and append the element to the root div this.rootElement.appendChild(this.imageElement); this.rootDiv.appendChild(this.rootElement); } /** * Set the freeze frame element for showing */ setElementForShow() { this.rootElement.style.display = 'block'; } /** * Set the freeze frame element for hiding */ setElementForHide() { this.rootElement.style.display = 'none'; } /** * Update the freeze frames image source * @param jpeg - the freeze frame image as a byte array data */ updateImageElementSource(jpeg) { const base64 = btoa(jpeg.reduce((data, byte) => data + String.fromCharCode(byte), '')); this.imageElement.src = 'data:image/jpeg;base64,' + base64; } /** * Set the dimensions for the freeze frame from the element and resize it */ setDimensionsFromElementAndResize() { this.freezeFrameHeight = this.imageElement.naturalHeight; this.freezeFrameWidth = this.imageElement.naturalWidth; this.resize(); } /** * Resize a freeze frame element */ resize() { if (this.freezeFrameWidth !== 0 && this.freezeFrameHeight !== 0) { let displayWidth = 0; let displayHeight = 0; let displayTop = 0; let displayLeft = 0; const parentAspectRatio = this.rootDiv.clientWidth / this.rootDiv.clientHeight; const videoAspectRatio = this.freezeFrameWidth / this.freezeFrameHeight; if (parentAspectRatio < videoAspectRatio) { displayWidth = this.rootDiv.clientWidth; displayHeight = Math.floor(this.rootDiv.clientWidth / videoAspectRatio); displayTop = Math.floor((this.rootDiv.clientHeight - displayHeight) * 0.5); displayLeft = 0; } else { displayWidth = Math.floor(this.rootDiv.clientHeight * videoAspectRatio); displayHeight = this.rootDiv.clientHeight; displayTop = 0; displayLeft = Math.floor((this.rootDiv.clientWidth - displayWidth) * 0.5); } this.rootElement.style.width = this.rootDiv.offsetWidth + 'px'; this.rootElement.style.height = this.rootDiv.offsetHeight + 'px'; this.rootElement.style.left = 0 + 'px'; this.rootElement.style.top = 0 + 'px'; this.imageElement.style.width = displayWidth + 'px'; this.imageElement.style.height = displayHeight + 'px'; this.imageElement.style.left = displayLeft + 'px'; this.imageElement.style.top = displayTop + 'px'; } } } /***/ }), /***/ "./src/FreezeFrame/FreezeFrameController.ts": /*!**************************************************!*\ !*** ./src/FreezeFrame/FreezeFrameController.ts ***! \**************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "FreezeFrameController": () => (/* binding */ FreezeFrameController) /* harmony export */ }); /* harmony import */ var _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Logger/Logger */ "./src/Logger/Logger.ts"); /* harmony import */ var _FreezeFrame__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./FreezeFrame */ "./src/FreezeFrame/FreezeFrame.ts"); // Copyright Epic Games, Inc. All Rights Reserved. /** * A class for controlling freeze frame functionality */ class FreezeFrameController { /** * Construct a freeze frame controller * @param rootDiv - the div that a freeze frame element will be injected into */ constructor(rootDiv) { this.receiving = false; this.size = 0; this.jpeg = undefined; this.valid = false; this.freezeFrameDelay = 50; this.freezeFrame = new _FreezeFrame__WEBPACK_IMPORTED_MODULE_0__.FreezeFrame(rootDiv); } /** * Show the freeze frame if it is valid */ showFreezeFrame() { if (this.valid) { this.freezeFrame.setElementForShow(); } } /** * Hide the freeze frame and set the validity to false */ hideFreezeFrame() { this.valid = false; this.freezeFrame.setElementForHide(); } /** * Update the freeze frames image source and load it * @param jpeg - the freeze frame image as a byte array data * @param onLoadCallBack - a call back for managing if the play overlay needs to be shown or not */ updateFreezeFrameAndShow(jpeg, onLoadCallBack) { this.freezeFrame.updateImageElementSource(jpeg); this.freezeFrame.imageElement.onload = () => { this.freezeFrame.setDimensionsFromElementAndResize(); onLoadCallBack(); }; } /** * Process the new freeze frame image and update it * @param view - the freeze frame image as a byte array data * @param onLoadCallBack - a call back for managing if the play overlay needs to be shown or not */ processFreezeFrameMessage(view, onLoadCallBack) { // Reset freeze frame if we got a freeze frame message and we are not "receiving" yet. if (!this.receiving) { this.receiving = true; this.valid = false; this.size = 0; this.jpeg = undefined; } // Extract total size of freeze frame (across all chunks) this.size = new DataView(view.slice(1, 5).buffer).getInt32(0, true); // Get the jpeg part of the payload const jpegBytes = view.slice(1 + 4); // Append to existing jpeg that holds the freeze frame if (this.jpeg) { const jpeg = new Uint8Array(this.jpeg.length + jpegBytes.length); jpeg.set(this.jpeg, 0); jpeg.set(jpegBytes, this.jpeg.length); this.jpeg = jpeg; } // No existing freeze frame jpeg, make one else { this.jpeg = jpegBytes; this.receiving = true; _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.GetStackTrace(), `received first chunk of freeze frame: ${this.jpeg.length}/${this.size}`, 6); } // Finished receiving freeze frame, we can show it now if (this.jpeg.length === this.size) { this.receiving = false; this.valid = true; _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.GetStackTrace(), `received complete freeze frame ${this.size}`, 6); this.updateFreezeFrameAndShow(this.jpeg, onLoadCallBack); } // We received more data than the freeze frame payload message indicate (this is an error) else if (this.jpeg.length > this.size) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Error(_Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.GetStackTrace(), `received bigger freeze frame than advertised: ${this.jpeg.length}/${this.size}`); this.jpeg = undefined; this.receiving = false; } } } /***/ }), /***/ "./src/Inputs/FakeTouchController.ts": /*!*******************************************!*\ !*** ./src/Inputs/FakeTouchController.ts ***! \*******************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "FakeTouchController": () => (/* binding */ FakeTouchController), /* harmony export */ "FakeTouchFinger": () => (/* binding */ FakeTouchFinger) /* harmony export */ }); /* harmony import */ var _MouseButtons__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./MouseButtons */ "./src/Inputs/MouseButtons.ts"); /* harmony import */ var _Util_EventListenerTracker__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Util/EventListenerTracker */ "./src/Util/EventListenerTracker.ts"); // Copyright Epic Games, Inc. All Rights Reserved. /** * Allows for the usage of fake touch events and implements ITouchController * @param dataChannelController - The controller for the Data channel * @param videoElementParent - The video player DOM element */ class FakeTouchController { /** * @param toStreamerMessagesProvider - Stream message instance * @param videoElementProvider - Video element instance * @param coordinateConverter - A coordinate converter instance */ constructor(toStreamerMessagesProvider, videoElementProvider, coordinateConverter) { // Utility for keeping track of event handlers and unregistering them this.touchEventListenerTracker = new _Util_EventListenerTracker__WEBPACK_IMPORTED_MODULE_0__.EventListenerTracker(); this.toStreamerMessagesProvider = toStreamerMessagesProvider; this.videoElementProvider = videoElementProvider; this.coordinateConverter = coordinateConverter; const ontouchstart = (ev) => this.onTouchStart(ev); const ontouchend = (ev) => this.onTouchEnd(ev); const ontouchmove = (ev) => this.onTouchMove(ev); document.addEventListener('touchstart', ontouchstart, { passive: false }); document.addEventListener('touchend', ontouchend, { passive: false }); document.addEventListener('touchmove', ontouchmove, { passive: false }); this.touchEventListenerTracker.addUnregisterCallback(() => document.removeEventListener('touchstart', ontouchstart)); this.touchEventListenerTracker.addUnregisterCallback(() => document.removeEventListener('touchend', ontouchend)); this.touchEventListenerTracker.addUnregisterCallback(() => document.removeEventListener('touchmove', ontouchmove)); } /** * Unregister all touch events */ unregisterTouchEvents() { this.touchEventListenerTracker.unregisterAll(); } /** * Sets the video Element Parent Client Rect numbers for this class * @param videoElementParentClientRect - a html ElementParentClientRect object */ setVideoElementParentClientRect(videoElementParentClientRect) { this.videoElementParentClientRect = videoElementParentClientRect; } /** * When a touch event begins * @param touch - the activating touch event */ onTouchStart(touch) { if (!this.videoElementProvider.isVideoReady()) { return; } if (this.fakeTouchFinger == null) { const first_touch = touch.changedTouches[0]; this.fakeTouchFinger = new FakeTouchFinger(first_touch.identifier, first_touch.clientX - this.videoElementParentClientRect.left, first_touch.clientY - this.videoElementParentClientRect.top); const videoElementParent = this.videoElementProvider.getVideoParentElement(); const mouseEvent = new MouseEvent('mouseenter', first_touch); videoElementParent.dispatchEvent(mouseEvent); const coord = this.coordinateConverter.normalizeAndQuantizeUnsigned(this.fakeTouchFinger.x, this.fakeTouchFinger.y); const toStreamerHandlers = this.toStreamerMessagesProvider.toStreamerHandlers; toStreamerHandlers.get('MouseDown')([ _MouseButtons__WEBPACK_IMPORTED_MODULE_1__.MouseButton.mainButton, coord.x, coord.y ]); } touch.preventDefault(); } /** * When a touch event ends * @param touchEvent - the activating touch event */ onTouchEnd(touchEvent) { if (!this.videoElementProvider.isVideoReady()) { return; } const videoElementParent = this.videoElementProvider.getVideoParentElement(); const toStreamerHandlers = this.toStreamerMessagesProvider.toStreamerHandlers; for (let t = 0; t < touchEvent.changedTouches.length; t++) { const touch = touchEvent.changedTouches[t]; if (touch.identifier === this.fakeTouchFinger.id) { const x = touch.clientX - this.videoElementParentClientRect.left; const y = touch.clientY - this.videoElementParentClientRect.top; const coord = this.coordinateConverter.normalizeAndQuantizeUnsigned(x, y); toStreamerHandlers.get('MouseUp')([ _MouseButtons__WEBPACK_IMPORTED_MODULE_1__.MouseButton.mainButton, coord.x, coord.y ]); const mouseEvent = new MouseEvent('mouseleave', touch); videoElementParent.dispatchEvent(mouseEvent); this.fakeTouchFinger = null; break; } } touchEvent.preventDefault(); } /** * On a Move touch event * @param touchEvent - the activating touch event */ onTouchMove(touchEvent) { if (!this.videoElementProvider.isVideoReady()) { return; } const toStreamerHandlers = this.toStreamerMessagesProvider.toStreamerHandlers; for (let t = 0; t < touchEvent.touches.length; t++) { const touch = touchEvent.touches[t]; if (touch.identifier === this.fakeTouchFinger.id) { const x = touch.clientX - this.videoElementParentClientRect.left; const y = touch.clientY - this.videoElementParentClientRect.top; const coord = this.coordinateConverter.normalizeAndQuantizeUnsigned(x, y); const delta = this.coordinateConverter.normalizeAndQuantizeSigned(x - this.fakeTouchFinger.x, y - this.fakeTouchFinger.y); toStreamerHandlers.get('MouseMove')([ coord.x, coord.y, delta.x, delta.y ]); this.fakeTouchFinger.x = x; this.fakeTouchFinger.y = y; break; } } touchEvent.preventDefault(); } } /** * The interface for finger position mapping */ class FakeTouchFinger { /** * @param id - the button id * @param x - the x axis value * @param y - the y axis value */ constructor(id, x, y) { this.id = id; this.x = x; this.y = y; } } /***/ }), /***/ "./src/Inputs/GamepadController.ts": /*!*****************************************!*\ !*** ./src/Inputs/GamepadController.ts ***! \*****************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "GamePadController": () => (/* binding */ GamePadController), /* harmony export */ "gamepadLayout": () => (/* binding */ gamepadLayout) /* harmony export */ }); /* harmony import */ var _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Logger/Logger */ "./src/Logger/Logger.ts"); /* harmony import */ var _Util_EventListenerTracker__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Util/EventListenerTracker */ "./src/Util/EventListenerTracker.ts"); // Copyright Epic Games, Inc. All Rights Reserved. /** * The class that handles the functionality of gamepads and controllers */ class GamePadController { /** * @param toStreamerMessagesProvider - Stream message instance */ constructor(toStreamerMessagesProvider) { // Utility for keeping track of event handlers and unregistering them this.gamePadEventListenerTracker = new _Util_EventListenerTracker__WEBPACK_IMPORTED_MODULE_0__.EventListenerTracker(); this.toStreamerMessagesProvider = toStreamerMessagesProvider; this.requestAnimationFrame = (window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.requestAnimationFrame).bind(window); const browserWindow = window; if ('GamepadEvent' in browserWindow) { const onGamePadConnected = (ev) => this.gamePadConnectHandler(ev); const onGamePadDisconnected = (ev) => this.gamePadDisconnectHandler(ev); window.addEventListener('gamepadconnected', onGamePadConnected); window.addEventListener('gamepaddisconnected', onGamePadDisconnected); this.gamePadEventListenerTracker.addUnregisterCallback(() => window.removeEventListener('gamepadconnected', onGamePadConnected)); this.gamePadEventListenerTracker.addUnregisterCallback(() => window.removeEventListener('gamepaddisconnected', onGamePadDisconnected)); } else if ('WebKitGamepadEvent' in browserWindow) { const onWebkitGamePadConnected = (ev) => this.gamePadConnectHandler(ev); const onWebkitGamePadDisconnected = (ev) => this.gamePadDisconnectHandler(ev); window.addEventListener('webkitgamepadconnected', onWebkitGamePadConnected); window.addEventListener('webkitgamepaddisconnected', onWebkitGamePadDisconnected); this.gamePadEventListenerTracker.addUnregisterCallback(() => window.removeEventListener('webkitgamepadconnected', onWebkitGamePadConnected)); this.gamePadEventListenerTracker.addUnregisterCallback(() => window.removeEventListener('webkitgamepaddisconnected', onWebkitGamePadDisconnected)); } this.controllers = []; if (navigator.getGamepads) { for (const gamepad of navigator.getGamepads()) { if (gamepad) { this.gamePadConnectHandler(new GamepadEvent('gamepadconnected', { gamepad })); } } } } /** * Unregisters all event handlers */ unregisterGamePadEvents() { this.gamePadEventListenerTracker.unregisterAll(); for (const controller of this.controllers) { if (controller.id !== undefined) { this.onGamepadDisconnected(controller.id); } } this.controllers = []; this.onGamepadConnected = () => { }; this.onGamepadDisconnected = () => { }; } /** * Connects the gamepad handler * @param gamePadEvent - the activating gamepad event */ gamePadConnectHandler(gamePadEvent) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.GetStackTrace(), 'Gamepad connect handler', 6); const gamepad = gamePadEvent.gamepad; const temp = { currentState: gamepad, prevState: gamepad, id: undefined }; this.controllers.push(temp); this.controllers[gamepad.index].currentState = gamepad; this.controllers[gamepad.index].prevState = gamepad; _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.GetStackTrace(), 'gamepad: ' + gamepad.id + ' connected', 6); window.requestAnimationFrame(() => this.updateStatus()); this.onGamepadConnected(); } /** * Disconnects the gamepad handler * @param gamePadEvent - the activating gamepad event */ gamePadDisconnectHandler(gamePadEvent) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.GetStackTrace(), 'Gamepad disconnect handler', 6); _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.GetStackTrace(), 'gamepad: ' + gamePadEvent.gamepad.id + ' disconnected', 6); const deletedController = this.controllers[gamePadEvent.gamepad.index]; delete this.controllers[gamePadEvent.gamepad.index]; this.controllers = this.controllers.filter((controller) => controller !== undefined); this.onGamepadDisconnected(deletedController.id); } /** * Scan for connected gamepads */ scanGamePads() { const gamepads = navigator.getGamepads ? navigator.getGamepads() : navigator.webkitGetGamepads ? navigator.webkitGetGamepads() : []; for (let i = 0; i < gamepads.length; i++) { if (gamepads[i] && gamepads[i].index in this.controllers) { this.controllers[gamepads[i].index].currentState = gamepads[i]; } } } /** * Updates the status of the gamepad and sends the inputs */ updateStatus() { this.scanGamePads(); const toStreamerHandlers = this.toStreamerMessagesProvider.toStreamerHandlers; // Iterate over multiple controllers in the case the multiple gamepads are connected for (const controller of this.controllers) { // If we haven't received an id (possible if using an older version of UE), return to original functionality const controllerIndex = (controller.id === undefined) ? this.controllers.indexOf(controller) : controller.id; const currentState = controller.currentState; for (let i = 0; i < controller.currentState.buttons.length; i++) { const currentButton = controller.currentState.buttons[i]; const previousButton = controller.prevState.buttons[i]; if (currentButton.pressed) { // press if (i == gamepadLayout.LeftTrigger) { // UEs left analog has a button index of 5 toStreamerHandlers.get('GamepadAnalog')([ controllerIndex, 5, currentButton.value ]); } else if (i == gamepadLayout.RightTrigger) { // UEs right analog has a button index of 6 toStreamerHandlers.get('GamepadAnalog')([ controllerIndex, 6, currentButton.value ]); } else { toStreamerHandlers.get('GamepadButtonPressed')([ controllerIndex, i, previousButton.pressed ? 1 : 0 ]); } } else if (!currentButton.pressed && previousButton.pressed) { // release if (i == gamepadLayout.LeftTrigger) { // UEs left analog has a button index of 5 toStreamerHandlers.get('GamepadAnalog')([ controllerIndex, 5, 0 ]); } else if (i == gamepadLayout.RightTrigger) { // UEs right analog has a button index of 6 toStreamerHandlers.get('GamepadAnalog')([ controllerIndex, 6, 0 ]); } else { toStreamerHandlers.get('GamepadButtonReleased')([ controllerIndex, i ]); } } } // Iterate over gamepad axes (we will increment in lots of 2 as there is 2 axes per stick) for (let i = 0; i < currentState.axes.length; i += 2) { // Horizontal axes are even numbered const x = parseFloat(currentState.axes[i].toFixed(4)); // Vertical axes are odd numbered // https://w3c.github.io/gamepad/#remapping Gamepad browser side standard mapping has positive down, negative up. This is downright disgusting. So we fix it. const y = -parseFloat(currentState.axes[i + 1].toFixed(4)); // UE's analog axes follow the same order as the browsers, but start at index 1 so we will offset as such toStreamerHandlers.get('GamepadAnalog')([ controllerIndex, i + 1, x ]); // Horizontal axes, only offset by 1 toStreamerHandlers.get('GamepadAnalog')([ controllerIndex, i + 2, y ]); // Vertical axes, offset by two (1 to match UEs axes convention and then another 1 for the vertical axes) } this.controllers[controllerIndex].prevState = currentState; } if (this.controllers.length > 0) { this.requestAnimationFrame(() => this.updateStatus()); } } onGamepadResponseReceived(gamepadId) { for (const controller of this.controllers) { if (controller.id === undefined) { controller.id = gamepadId; break; } } } /** * Event to send the gamepadconnected message to the application */ onGamepadConnected() { // Default Functionality: Do Nothing } /** * Event to send the gamepaddisconnected message to the application */ // eslint-disable-next-line @typescript-eslint/no-unused-vars onGamepadDisconnected(controllerIdx) { // Default Functionality: Do Nothing } } /** * Gamepad layout codes enum */ var gamepadLayout; (function (gamepadLayout) { gamepadLayout[gamepadLayout["RightClusterBottomButton"] = 0] = "RightClusterBottomButton"; gamepadLayout[gamepadLayout["RightClusterRightButton"] = 1] = "RightClusterRightButton"; gamepadLayout[gamepadLayout["RightClusterLeftButton"] = 2] = "RightClusterLeftButton"; gamepadLayout[gamepadLayout["RightClusterTopButton"] = 3] = "RightClusterTopButton"; gamepadLayout[gamepadLayout["LeftShoulder"] = 4] = "LeftShoulder"; gamepadLayout[gamepadLayout["RightShoulder"] = 5] = "RightShoulder"; gamepadLayout[gamepadLayout["LeftTrigger"] = 6] = "LeftTrigger"; gamepadLayout[gamepadLayout["RightTrigger"] = 7] = "RightTrigger"; gamepadLayout[gamepadLayout["SelectOrBack"] = 8] = "SelectOrBack"; gamepadLayout[gamepadLayout["StartOrForward"] = 9] = "StartOrForward"; gamepadLayout[gamepadLayout["LeftAnalogPress"] = 10] = "LeftAnalogPress"; gamepadLayout[gamepadLayout["RightAnalogPress"] = 11] = "RightAnalogPress"; gamepadLayout[gamepadLayout["LeftClusterTopButton"] = 12] = "LeftClusterTopButton"; gamepadLayout[gamepadLayout["LeftClusterBottomButton"] = 13] = "LeftClusterBottomButton"; gamepadLayout[gamepadLayout["LeftClusterLeftButton"] = 14] = "LeftClusterLeftButton"; gamepadLayout[gamepadLayout["LeftClusterRightButton"] = 15] = "LeftClusterRightButton"; gamepadLayout[gamepadLayout["CentreButton"] = 16] = "CentreButton"; // Axes gamepadLayout[gamepadLayout["LeftStickHorizontal"] = 0] = "LeftStickHorizontal"; gamepadLayout[gamepadLayout["LeftStickVertical"] = 1] = "LeftStickVertical"; gamepadLayout[gamepadLayout["RightStickHorizontal"] = 2] = "RightStickHorizontal"; gamepadLayout[gamepadLayout["RightStickVertical"] = 3] = "RightStickVertical"; })(gamepadLayout || (gamepadLayout = {})); /***/ }), /***/ "./src/Inputs/HoveringMouseEvents.ts": /*!*******************************************!*\ !*** ./src/Inputs/HoveringMouseEvents.ts ***! \*******************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "HoveringMouseEvents": () => (/* binding */ HoveringMouseEvents) /* harmony export */ }); /* harmony import */ var _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Logger/Logger */ "./src/Logger/Logger.ts"); // Copyright Epic Games, Inc. All Rights Reserved. /** * Video Player mouse Hover handler */ class HoveringMouseEvents { /** * @param mouseController - Mouse Controller instance */ constructor(mouseController) { this.mouseController = mouseController; } /** * Unregister event handlers */ unregisterMouseEvents() { // empty for HoveringMouseEvents implementation } /** * Handle the mouse move event, sends the mouse data to the UE Instance * @param mouseEvent - Mouse Event */ updateMouseMovePosition(mouseEvent) { if (!this.mouseController.videoElementProvider.isVideoReady()) { return; } _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), 'MouseMove', 6); const coord = this.mouseController.coordinateConverter.normalizeAndQuantizeUnsigned(mouseEvent.offsetX, mouseEvent.offsetY); const delta = this.mouseController.coordinateConverter.normalizeAndQuantizeSigned(mouseEvent.movementX, mouseEvent.movementY); const toStreamerHandlers = this.mouseController.toStreamerMessagesProvider.toStreamerHandlers; toStreamerHandlers.get('MouseMove')([ coord.x, coord.y, delta.x, delta.y ]); mouseEvent.preventDefault(); } /** * Handle the mouse Down event, sends the mouse data to the UE Instance * @param mouseEvent - Mouse Event */ handleMouseDown(mouseEvent) { if (!this.mouseController.videoElementProvider.isVideoReady()) { return; } _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), 'onMouse Down', 6); const coord = this.mouseController.coordinateConverter.normalizeAndQuantizeUnsigned(mouseEvent.offsetX, mouseEvent.offsetY); const toStreamerHandlers = this.mouseController.toStreamerMessagesProvider.toStreamerHandlers; toStreamerHandlers.get('MouseDown')([ mouseEvent.button, coord.x, coord.y ]); mouseEvent.preventDefault(); } /** * Handle the mouse Up event, sends the mouse data to the UE Instance * @param mouseEvent - Mouse Event */ handleMouseUp(mouseEvent) { if (!this.mouseController.videoElementProvider.isVideoReady()) { return; } _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), 'onMouse Up', 6); const coord = this.mouseController.coordinateConverter.normalizeAndQuantizeUnsigned(mouseEvent.offsetX, mouseEvent.offsetY); const toStreamerHandlers = this.mouseController.toStreamerMessagesProvider.toStreamerHandlers; toStreamerHandlers.get('MouseUp')([ mouseEvent.button, coord.x, coord.y ]); mouseEvent.preventDefault(); } /** * Consumes the mouse context event. The UE instance has no equivalent and doesn't need to be informed. * @param mouseEvent - Mouse Event */ handleContextMenu(mouseEvent) { if (!this.mouseController.videoElementProvider.isVideoReady()) { return; } mouseEvent.preventDefault(); } /** * Handle the mouse wheel event, sends the mouse wheel data to the UE Instance * @param wheelEvent - Mouse Event */ handleMouseWheel(wheelEvent) { if (!this.mouseController.videoElementProvider.isVideoReady()) { return; } const coord = this.mouseController.coordinateConverter.normalizeAndQuantizeUnsigned(wheelEvent.offsetX, wheelEvent.offsetY); const toStreamerHandlers = this.mouseController.toStreamerMessagesProvider.toStreamerHandlers; toStreamerHandlers.get('MouseWheel')([ wheelEvent.wheelDelta, coord.x, coord.y ]); wheelEvent.preventDefault(); } /** * Handle the mouse double click event, sends the mouse data to the UE Instance * @param mouseEvent - Mouse Event */ handleMouseDouble(mouseEvent) { if (!this.mouseController.videoElementProvider.isVideoReady()) { return; } const coord = this.mouseController.coordinateConverter.normalizeAndQuantizeUnsigned(mouseEvent.offsetX, mouseEvent.offsetY); const toStreamerHandlers = this.mouseController.toStreamerMessagesProvider.toStreamerHandlers; toStreamerHandlers.get('MouseDouble')([ mouseEvent.button, coord.x, coord.y ]); } /** * Handle the press mouse buttons event, sends the mouse data to the UE Instance * @param mouseEvent - Mouse Event */ handlePressMouseButtons(mouseEvent) { if (!this.mouseController.videoElementProvider.isVideoReady()) { return; } _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), 'onMouse press', 6); this.mouseController.pressMouseButtons(mouseEvent.buttons, mouseEvent.offsetX, mouseEvent.offsetY); } /** * Handle the release mouse buttons event, sends the mouse data to the UE Instance * @param mouseEvent - Mouse Event */ handleReleaseMouseButtons(mouseEvent) { if (!this.mouseController.videoElementProvider.isVideoReady()) { return; } _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), 'onMouse release', 6); this.mouseController.releaseMouseButtons(mouseEvent.buttons, mouseEvent.offsetX, mouseEvent.offsetY); } } /***/ }), /***/ "./src/Inputs/InputClassesFactory.ts": /*!*******************************************!*\ !*** ./src/Inputs/InputClassesFactory.ts ***! \*******************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "ActiveKeys": () => (/* binding */ ActiveKeys), /* harmony export */ "InputClassesFactory": () => (/* binding */ InputClassesFactory) /* harmony export */ }); /* harmony import */ var _FakeTouchController__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./FakeTouchController */ "./src/Inputs/FakeTouchController.ts"); /* harmony import */ var _KeyboardController__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./KeyboardController */ "./src/Inputs/KeyboardController.ts"); /* harmony import */ var _MouseController__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./MouseController */ "./src/Inputs/MouseController.ts"); /* harmony import */ var _TouchController__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./TouchController */ "./src/Inputs/TouchController.ts"); /* harmony import */ var _GamepadController__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./GamepadController */ "./src/Inputs/GamepadController.ts"); /* harmony import */ var _Config_Config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../Config/Config */ "./src/Config/Config.ts"); /* harmony import */ var _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Logger/Logger */ "./src/Logger/Logger.ts"); // Copyright Epic Games, Inc. All Rights Reserved. /** * Class for making and setting up input class types */ class InputClassesFactory { /** * @param toStreamerMessagesProvider - Stream message instance * @param videoElementProvider - Video Player instance * @param coordinateConverter - A coordinateConverter instance */ constructor(toStreamerMessagesProvider, videoElementProvider, coordinateConverter) { this.activeKeys = new ActiveKeys(); this.toStreamerMessagesProvider = toStreamerMessagesProvider; this.videoElementProvider = videoElementProvider; this.coordinateConverter = coordinateConverter; } /** * Registers browser key events. */ registerKeyBoard(config) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), 'Register Keyboard Events', 7); const keyboardController = new _KeyboardController__WEBPACK_IMPORTED_MODULE_1__.KeyboardController(this.toStreamerMessagesProvider, config, this.activeKeys); keyboardController.registerKeyBoardEvents(); return keyboardController; } /** * register mouse events based on a control type * @param controlScheme - if the mouse is either hovering or locked */ registerMouse(controlScheme) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), 'Register Mouse Events', 7); const mouseController = new _MouseController__WEBPACK_IMPORTED_MODULE_2__.MouseController(this.toStreamerMessagesProvider, this.videoElementProvider, this.coordinateConverter, this.activeKeys); switch (controlScheme) { case _Config_Config__WEBPACK_IMPORTED_MODULE_3__.ControlSchemeType.LockedMouse: mouseController.registerLockedMouseEvents(mouseController); break; case _Config_Config__WEBPACK_IMPORTED_MODULE_3__.ControlSchemeType.HoveringMouse: mouseController.registerHoveringMouseEvents(mouseController); break; default: _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Info(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), 'unknown Control Scheme Type Defaulting to Locked Mouse Events'); mouseController.registerLockedMouseEvents(mouseController); break; } return mouseController; } /** * register touch events * @param fakeMouseTouch - the faked mouse touch event */ registerTouch(fakeMouseTouch, videoElementParentClientRect) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), 'Registering Touch', 6); if (fakeMouseTouch) { const fakeTouchController = new _FakeTouchController__WEBPACK_IMPORTED_MODULE_4__.FakeTouchController(this.toStreamerMessagesProvider, this.videoElementProvider, this.coordinateConverter); fakeTouchController.setVideoElementParentClientRect(videoElementParentClientRect); return fakeTouchController; } else { return new _TouchController__WEBPACK_IMPORTED_MODULE_5__.TouchController(this.toStreamerMessagesProvider, this.videoElementProvider, this.coordinateConverter); } } /** * registers a gamepad */ registerGamePad() { _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), 'Register Game Pad', 7); const gamePadController = new _GamepadController__WEBPACK_IMPORTED_MODULE_6__.GamePadController(this.toStreamerMessagesProvider); return gamePadController; } } /** * A class that keeps track of current active keys */ class ActiveKeys { constructor() { this.activeKeys = []; this.activeKeys = []; } /** * Get the current array of active keys * @returns - an array of active keys */ getActiveKeys() { return this.activeKeys; } } /***/ }), /***/ "./src/Inputs/KeyboardController.ts": /*!******************************************!*\ !*** ./src/Inputs/KeyboardController.ts ***! \******************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "KeyboardController": () => (/* binding */ KeyboardController) /* harmony export */ }); /* harmony import */ var _SpecialKeyCodes__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./SpecialKeyCodes */ "./src/Inputs/SpecialKeyCodes.ts"); /* harmony import */ var _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Logger/Logger */ "./src/Logger/Logger.ts"); /* harmony import */ var _Config_Config__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../Config/Config */ "./src/Config/Config.ts"); /* harmony import */ var _Util_EventListenerTracker__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Util/EventListenerTracker */ "./src/Util/EventListenerTracker.ts"); // Copyright Epic Games, Inc. All Rights Reserved. /** * Handles the Keyboard Inputs for the document */ class KeyboardController { /** * @param toStreamerMessagesProvider Stream message provider class object * @param config The applications configuration. We're interested in the suppress browser keys option * @param activeKeysProvider Active keys provider class object */ constructor(toStreamerMessagesProvider, config, activeKeysProvider) { // Utility for keeping track of event handlers and unregistering them this.keyboardEventListenerTracker = new _Util_EventListenerTracker__WEBPACK_IMPORTED_MODULE_0__.EventListenerTracker(); /* * New browser APIs have moved away from KeyboardEvent.keyCode to KeyboardEvent.Code. * For details see: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode#constants_for_keycode_value * We still use old KeyboardEvent.keyCode integers in the UE C++ side, so we need a way to map the new * string-based KeyboardEvent.Code to the old integers. */ this.CodeToKeyCode = { Escape: 27, Digit0: 48, Digit1: 49, Digit2: 50, Digit3: 51, Digit4: 52, Digit5: 53, Digit6: 54, Digit7: 55, Digit8: 56, Digit9: 57, Minus: 173, Equal: 187, Backspace: 8, Tab: 9, KeyQ: 81, KeyW: 87, KeyE: 69, KeyR: 82, KeyT: 84, KeyY: 89, KeyU: 85, KeyI: 73, KeyO: 79, KeyP: 80, BracketLeft: 219, BracketRight: 221, Enter: 13, ControlLeft: 17, KeyA: 65, KeyS: 83, KeyD: 68, KeyF: 70, KeyG: 71, KeyH: 72, KeyJ: 74, KeyK: 75, KeyL: 76, Semicolon: 186, Quote: 222, Backquote: 192, ShiftLeft: 16, Backslash: 220, KeyZ: 90, KeyX: 88, KeyC: 67, KeyV: 86, KeyB: 66, KeyN: 78, KeyM: 77, Comma: 188, Period: 190, Slash: 191, ShiftRight: 253, AltLeft: 18, Space: 32, CapsLock: 20, F1: 112, F2: 113, F3: 114, F4: 115, F5: 116, F6: 117, F7: 118, F8: 119, F9: 120, F10: 121, F11: 122, F12: 123, Pause: 19, ScrollLock: 145, NumpadDivide: 111, NumpadMultiply: 106, NumpadSubtract: 109, NumpadAdd: 107, NumpadDecimal: 110, Numpad9: 105, Numpad8: 104, Numpad7: 103, Numpad6: 102, Numpad5: 101, Numpad4: 100, Numpad3: 99, Numpad2: 98, Numpad1: 97, Numpad0: 96, NumLock: 144, ControlRight: 254, AltRight: 255, Home: 36, End: 35, ArrowUp: 38, ArrowLeft: 37, ArrowRight: 39, ArrowDown: 40, PageUp: 33, PageDown: 34, Insert: 45, Delete: 46, ContextMenu: 93 }; this.toStreamerMessagesProvider = toStreamerMessagesProvider; this.config = config; this.activeKeysProvider = activeKeysProvider; } /** * Registers document keyboard events with the controller */ registerKeyBoardEvents() { const keyDownHandler = (ev) => this.handleOnKeyDown(ev); const keyUpHandler = (ev) => this.handleOnKeyUp(ev); const keyPressHandler = (ev) => this.handleOnKeyPress(ev); document.addEventListener("keydown", keyDownHandler); document.addEventListener("keyup", keyUpHandler); //This has been deprecated as at Jun 13 2021 document.addEventListener("keypress", keyPressHandler); this.keyboardEventListenerTracker.addUnregisterCallback(() => document.removeEventListener("keydown", keyDownHandler)); this.keyboardEventListenerTracker.addUnregisterCallback(() => document.removeEventListener("keyup", keyUpHandler)); this.keyboardEventListenerTracker.addUnregisterCallback(() => document.removeEventListener("keypress", keyPressHandler)); } /** * Unregisters document keyboard events */ unregisterKeyBoardEvents() { this.keyboardEventListenerTracker.unregisterAll(); } /** * Handles When a key is down * @param keyboardEvent - Keyboard event */ handleOnKeyDown(keyboardEvent) { const keyCode = this.getKeycode(keyboardEvent); if (!keyCode) { return; } _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.GetStackTrace(), `key down ${keyCode}, repeat = ${keyboardEvent.repeat}`, 6); const toStreamerHandlers = this.toStreamerMessagesProvider.toStreamerHandlers; toStreamerHandlers.get('KeyDown')([ this.getKeycode(keyboardEvent), keyboardEvent.repeat ? 1 : 0 ]); const activeKeys = this.activeKeysProvider.getActiveKeys(); activeKeys.push(keyCode); // Backspace is not considered a keypress in JavaScript but we need it // to be so characters may be deleted in a UE text entry field. if (keyCode === _SpecialKeyCodes__WEBPACK_IMPORTED_MODULE_2__.SpecialKeyCodes.backSpace) { document.dispatchEvent(new KeyboardEvent('keypress', { charCode: _SpecialKeyCodes__WEBPACK_IMPORTED_MODULE_2__.SpecialKeyCodes.backSpace })); } if (this.config.isFlagEnabled(_Config_Config__WEBPACK_IMPORTED_MODULE_3__.Flags.SuppressBrowserKeys) && this.isKeyCodeBrowserKey(keyCode)) { keyboardEvent.preventDefault(); } } /** * handles when a key is up * @param keyboardEvent - Keyboard event */ handleOnKeyUp(keyboardEvent) { const keyCode = this.getKeycode(keyboardEvent); if (!keyCode) { return; } _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.GetStackTrace(), `key up ${keyCode}`, 6); const toStreamerHandlers = this.toStreamerMessagesProvider.toStreamerHandlers; toStreamerHandlers.get('KeyUp')([keyCode]); if (this.config.isFlagEnabled(_Config_Config__WEBPACK_IMPORTED_MODULE_3__.Flags.SuppressBrowserKeys) && this.isKeyCodeBrowserKey(keyCode)) { keyboardEvent.preventDefault(); } } /** * Handles when a key is press * @param keyboard - Keyboard Event */ handleOnKeyPress(keyboard) { if (!('charCode' in keyboard)) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Warning(_Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.GetStackTrace(), 'KeyboardEvent.charCode is deprecated in this browser, cannot send key press.'); return; } const charCode = keyboard.charCode; _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.GetStackTrace(), `key press ${charCode}`, 6); const toStreamerHandlers = this.toStreamerMessagesProvider.toStreamerHandlers; toStreamerHandlers.get('KeyPress')([charCode]); } /** * Gets the Keycode of the Key pressed * @param keyboardEvent - Key board Event * @returns - the key code of the Key */ getKeycode(keyboardEvent) { // If we don't have keyCode property because browser API is deprecated then use KeyboardEvent.code instead. // See: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode#constants_for_keycode_value if (!('keyCode' in keyboardEvent)) { // Convert KeyboardEvent.code string into integer-based key code for backwards compatibility reasons. const event = keyboardEvent; if (event.code in this.CodeToKeyCode) { return this.CodeToKeyCode[event.code]; } else { _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Warning(_Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.GetStackTrace(), `Keyboard code of ${event.code} is not supported in our mapping, ignoring this key.`); return null; } } // If we made it here KeyboardEvent.keyCode is still supported so we can safely use it. if (keyboardEvent.keyCode === _SpecialKeyCodes__WEBPACK_IMPORTED_MODULE_2__.SpecialKeyCodes.shift && keyboardEvent.code === 'ShiftRight') { return _SpecialKeyCodes__WEBPACK_IMPORTED_MODULE_2__.SpecialKeyCodes.rightShift; } else if (keyboardEvent.keyCode === _SpecialKeyCodes__WEBPACK_IMPORTED_MODULE_2__.SpecialKeyCodes.control && keyboardEvent.code === 'ControlRight') { return _SpecialKeyCodes__WEBPACK_IMPORTED_MODULE_2__.SpecialKeyCodes.rightControl; } else if (keyboardEvent.keyCode === _SpecialKeyCodes__WEBPACK_IMPORTED_MODULE_2__.SpecialKeyCodes.alt && keyboardEvent.code === 'AltRight') { return _SpecialKeyCodes__WEBPACK_IMPORTED_MODULE_2__.SpecialKeyCodes.rightAlt; } else { return keyboardEvent.keyCode; } } /** * Browser keys do not have a charCode so we only need to test keyCode. * @param keyCode - the browser keycode number */ isKeyCodeBrowserKey(keyCode) { // Function keys or tab key are considered "browser keys" that we may wish to suppress by preventing them being process by browser. return (keyCode >= 112 && keyCode <= 123) || keyCode === 9; } } /***/ }), /***/ "./src/Inputs/LockedMouseEvents.ts": /*!*****************************************!*\ !*** ./src/Inputs/LockedMouseEvents.ts ***! \*****************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "LockedMouseEvents": () => (/* binding */ LockedMouseEvents) /* harmony export */ }); /* harmony import */ var _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Logger/Logger */ "./src/Logger/Logger.ts"); /* harmony import */ var _Util_EventListenerTracker__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Util/EventListenerTracker */ "./src/Util/EventListenerTracker.ts"); // Copyright Epic Games, Inc. All Rights Reserved. /** * Handle the mouse locked events */ class LockedMouseEvents { /** * @param videoElementProvider - Video Player instance * @param mouseController - Mouse controller instance * @param activeKeysProvider - Active keys provider instance * @param playerStyleAttributesProvider - Player style attributes instance */ constructor(videoElementProvider, mouseController, activeKeysProvider) { this.x = 0; this.y = 0; this.updateMouseMovePositionEvent = (mouseEvent) => { this.updateMouseMovePosition(mouseEvent); }; // Utility for keeping track of event handlers and unregistering them this.mouseEventListenerTracker = new _Util_EventListenerTracker__WEBPACK_IMPORTED_MODULE_0__.EventListenerTracker(); this.videoElementProvider = videoElementProvider; this.mouseController = mouseController; this.activeKeysProvider = activeKeysProvider; const videoElementParent = this.videoElementProvider.getVideoParentElement(); this.x = videoElementParent.getBoundingClientRect().width / 2; this.y = videoElementParent.getBoundingClientRect().height / 2; this.coord = this.mouseController.coordinateConverter.normalizeAndQuantizeUnsigned(this.x, this.y); } /** * Unregisters all event handlers */ unregisterMouseEvents() { this.mouseEventListenerTracker.unregisterAll(); } /** * Handle when the locked state Changed */ lockStateChange() { const videoElementParent = this.videoElementProvider.getVideoParentElement(); const toStreamerHandlers = this.mouseController.toStreamerMessagesProvider.toStreamerHandlers; if (document.pointerLockElement === videoElementParent || document.mozPointerLockElement === videoElementParent) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.GetStackTrace(), 'Pointer locked', 6); document.addEventListener('mousemove', this.updateMouseMovePositionEvent, false); this.mouseEventListenerTracker.addUnregisterCallback(() => document.removeEventListener('mousemove', this.updateMouseMovePositionEvent, false)); } else { _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.GetStackTrace(), 'The pointer lock status is now unlocked', 6); // !a new arrow function must not be used here as it will be counted as a new function that cannot be removed document.removeEventListener('mousemove', this.updateMouseMovePositionEvent, false); // If mouse loses focus, send a key up for all of the currently held-down keys // This is necessary as when the mouse loses focus, the windows stops listening for events and as such // the keyup listener won't get fired let activeKeys = this.activeKeysProvider.getActiveKeys(); const setKeys = new Set(activeKeys); const newKeysIterable = []; setKeys.forEach((setKey) => { newKeysIterable[setKey]; }); newKeysIterable.forEach((uniqueKeycode) => { toStreamerHandlers.get('KeyUp')([uniqueKeycode]); }); // Reset the active keys back to nothing activeKeys = []; } } /** * Handle the mouse move event, sends the mouse data to the UE Instance * @param mouseEvent - Mouse Event */ updateMouseMovePosition(mouseEvent) { if (!this.videoElementProvider.isVideoReady()) { return; } const toStreamerHandlers = this.mouseController.toStreamerMessagesProvider.toStreamerHandlers; const styleWidth = this.videoElementProvider.getVideoParentElement().clientWidth; const styleHeight = this.videoElementProvider.getVideoParentElement().clientHeight; this.x += mouseEvent.movementX; this.y += mouseEvent.movementY; if (this.x > styleWidth) { this.x -= styleWidth; } if (this.y > styleHeight) { this.y -= styleHeight; } if (this.x < 0) { this.x = styleWidth + this.x; } if (this.y < 0) { this.y = styleHeight - this.y; } this.coord = this.mouseController.coordinateConverter.normalizeAndQuantizeUnsigned(this.x, this.y); const delta = this.mouseController.coordinateConverter.normalizeAndQuantizeSigned(mouseEvent.movementX, mouseEvent.movementY); toStreamerHandlers.get('MouseMove')([ this.coord.x, this.coord.y, delta.x, delta.y ]); } /** * Handle the mouse Down event, sends the mouse data to the UE Instance * @param mouseEvent - Mouse Event */ handleMouseDown(mouseEvent) { if (!this.videoElementProvider.isVideoReady()) { return; } const toStreamerHandlers = this.mouseController.toStreamerMessagesProvider.toStreamerHandlers; toStreamerHandlers.get('MouseDown')([ mouseEvent.button, // We use the store value of this.coord as opposed to the mouseEvent.x/y as the mouseEvent location // uses the system cursor location which hasn't moved this.coord.x, this.coord.y ]); } /** * Handle the mouse Up event, sends the mouse data to the UE Instance * @param mouseEvent - Mouse Event */ handleMouseUp(mouseEvent) { if (!this.videoElementProvider.isVideoReady()) { return; } const toStreamerHandlers = this.mouseController.toStreamerMessagesProvider.toStreamerHandlers; toStreamerHandlers.get('MouseUp')([ mouseEvent.button, // We use the store value of this.coord as opposed to the mouseEvent.x/y as the mouseEvent location // uses the system cursor location which hasn't moved this.coord.x, this.coord.y ]); } /** * Handle the mouse wheel event, sends the mouse wheel data to the UE Instance * @param wheelEvent - Mouse Event */ handleMouseWheel(wheelEvent) { if (!this.videoElementProvider.isVideoReady()) { return; } const toStreamerHandlers = this.mouseController.toStreamerMessagesProvider.toStreamerHandlers; toStreamerHandlers.get('MouseWheel')([ wheelEvent.wheelDelta, // We use the store value of this.coord as opposed to the mouseEvent.x/y as the mouseEvent location // uses the system cursor location which hasn't moved this.coord.x, this.coord.y ]); } /** * Handle the mouse double click event, sends the mouse data to the UE Instance * @param mouseEvent - Mouse Event */ handleMouseDouble(mouseEvent) { if (!this.videoElementProvider.isVideoReady()) { return; } const toStreamerHandlers = this.mouseController.toStreamerMessagesProvider.toStreamerHandlers; toStreamerHandlers.get('MouseDouble')([ mouseEvent.button, // We use the store value of this.coord as opposed to the mouseEvent.x/y as the mouseEvent location // uses the system cursor location which hasn't moved this.coord.x, this.coord.y ]); } /** * Handle the press mouse buttons event, sends the mouse data to the UE Instance * @param mouseEvent - Mouse Event */ handlePressMouseButtons(mouseEvent) { if (!this.videoElementProvider.isVideoReady()) { return; } this.mouseController.pressMouseButtons(mouseEvent.buttons, this.x, this.y); } /** * Handle the release mouse buttons event, sends the mouse data to the UE Instance * @param mouseEvent - Mouse Event */ handleReleaseMouseButtons(mouseEvent) { if (!this.videoElementProvider.isVideoReady()) { return; } this.mouseController.releaseMouseButtons(mouseEvent.buttons, this.x, this.y); } } /***/ }), /***/ "./src/Inputs/MouseButtons.ts": /*!************************************!*\ !*** ./src/Inputs/MouseButtons.ts ***! \************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "MouseButton": () => (/* binding */ MouseButton), /* harmony export */ "MouseButtonsMask": () => (/* binding */ MouseButtonsMask) /* harmony export */ }); // Copyright Epic Games, Inc. All Rights Reserved. /** * Mouse Button Data * {@link https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button} */ class MouseButton { } MouseButton.mainButton = 0; // Left button. MouseButton.auxiliaryButton = 1; // Wheel button. MouseButton.secondaryButton = 2; // Right button. MouseButton.fourthButton = 3; // Browser Back button. MouseButton.fifthButton = 4; // Browser Forward button. /** * Mouse Button Mask Data * {@link https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/buttons} */ class MouseButtonsMask { } MouseButtonsMask.primaryButton = 1; // Left button. MouseButtonsMask.secondaryButton = 2; // Right button. MouseButtonsMask.auxiliaryButton = 4; // Wheel button. MouseButtonsMask.fourthButton = 8; // Browser Back button. MouseButtonsMask.fifthButton = 16; // Browser Forward button. /***/ }), /***/ "./src/Inputs/MouseController.ts": /*!***************************************!*\ !*** ./src/Inputs/MouseController.ts ***! \***************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "MouseController": () => (/* binding */ MouseController) /* harmony export */ }); /* harmony import */ var _MouseButtons__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./MouseButtons */ "./src/Inputs/MouseButtons.ts"); /* harmony import */ var _Logger_Logger__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../Logger/Logger */ "./src/Logger/Logger.ts"); /* harmony import */ var _LockedMouseEvents__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./LockedMouseEvents */ "./src/Inputs/LockedMouseEvents.ts"); /* harmony import */ var _HoveringMouseEvents__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./HoveringMouseEvents */ "./src/Inputs/HoveringMouseEvents.ts"); /* harmony import */ var _Util_EventListenerTracker__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Util/EventListenerTracker */ "./src/Util/EventListenerTracker.ts"); // Copyright Epic Games, Inc. All Rights Reserved. /** * Handles the Mouse Inputs for the document */ class MouseController { /** * @param toStreamerMessagesProvider - Stream message instance * @param videoElementProvider - Video Player instance * @param normalizeAndQuantize - A normalize and quantize instance */ constructor(toStreamerMessagesProvider, videoElementProvider, coordinateConverter, activeKeysProvider) { // Utility for keeping track of event handlers and unregistering them this.mouseEventListenerTracker = new _Util_EventListenerTracker__WEBPACK_IMPORTED_MODULE_0__.EventListenerTracker(); this.toStreamerMessagesProvider = toStreamerMessagesProvider; this.coordinateConverter = coordinateConverter; this.videoElementProvider = videoElementProvider; this.activeKeysProvider = activeKeysProvider; this.registerMouseEnterAndLeaveEvents(); } /** * Clears all the click events on the current video element parent div */ unregisterMouseEvents() { this.mouseEventListenerTracker.unregisterAll(); } /** * Register a locked mouse class * @param mouseController - a mouse controller instance * @param playerStyleAttributesProvider - a player style attributes instance */ registerLockedMouseEvents(mouseController) { const videoElementParent = this.videoElementProvider.getVideoParentElement(); const lockedMouseEvents = new _LockedMouseEvents__WEBPACK_IMPORTED_MODULE_1__.LockedMouseEvents(this.videoElementProvider, mouseController, this.activeKeysProvider); videoElementParent.requestPointerLock = videoElementParent.requestPointerLock || videoElementParent.mozRequestPointerLock; document.exitPointerLock = document.exitPointerLock || document.mozExitPointerLock; // minor hack to alleviate ios not supporting pointerlock if (videoElementParent.requestPointerLock) { const onclick = () => { videoElementParent.requestPointerLock(); }; videoElementParent.addEventListener('click', onclick); this.mouseEventListenerTracker.addUnregisterCallback(() => videoElementParent.removeEventListener('click', onclick)); } const lockStateChangeListener = () => lockedMouseEvents.lockStateChange(); document.addEventListener('pointerlockchange', lockStateChangeListener, false); document.addEventListener('mozpointerlockchange', lockStateChangeListener, false); this.mouseEventListenerTracker.addUnregisterCallback(() => document.removeEventListener('pointerlockchange', lockStateChangeListener, false)); this.mouseEventListenerTracker.addUnregisterCallback(() => document.removeEventListener('mozpointerlockchange', lockStateChangeListener, false)); const onmousedown = (mouseEvent) => lockedMouseEvents.handleMouseDown(mouseEvent); const onmouseup = (mouseEvent) => lockedMouseEvents.handleMouseUp(mouseEvent); const onwheel = (wheelEvent) => lockedMouseEvents.handleMouseWheel(wheelEvent); const ondblclick = (mouseEvent) => lockedMouseEvents.handleMouseDouble(mouseEvent); videoElementParent.addEventListener('mousedown', onmousedown); videoElementParent.addEventListener('mouseup', onmouseup); videoElementParent.addEventListener('wheel', onwheel); videoElementParent.addEventListener('dblclick', ondblclick); this.mouseEventListenerTracker.addUnregisterCallback(() => videoElementParent.removeEventListener('mousedown', onmousedown)); this.mouseEventListenerTracker.addUnregisterCallback(() => videoElementParent.removeEventListener('mouseup', onmouseup)); this.mouseEventListenerTracker.addUnregisterCallback(() => videoElementParent.removeEventListener('wheel', onwheel)); this.mouseEventListenerTracker.addUnregisterCallback(() => videoElementParent.removeEventListener('dblclick', ondblclick)); this.mouseEventListenerTracker.addUnregisterCallback(() => lockedMouseEvents.unregisterMouseEvents()); this.mouseEventListenerTracker.addUnregisterCallback(() => { if (document.exitPointerLock && (document.pointerLockElement === videoElementParent || document.mozPointerLockElement === videoElementParent)) { document.exitPointerLock(); } }); } /** * Register a hovering mouse class * @param mouseController - A mouse controller object */ registerHoveringMouseEvents(mouseController) { const videoElementParent = this.videoElementProvider.getVideoParentElement(); const hoveringMouseEvents = new _HoveringMouseEvents__WEBPACK_IMPORTED_MODULE_2__.HoveringMouseEvents(mouseController); const onmousemove = (mouseEvent) => hoveringMouseEvents.updateMouseMovePosition(mouseEvent); const onmousedown = (mouseEvent) => hoveringMouseEvents.handleMouseDown(mouseEvent); const onmouseup = (mouseEvent) => hoveringMouseEvents.handleMouseUp(mouseEvent); const oncontextmenu = (mouseEvent) => hoveringMouseEvents.handleContextMenu(mouseEvent); const onwheel = (wheelEvent) => hoveringMouseEvents.handleMouseWheel(wheelEvent); const ondblclick = (mouseEvent) => hoveringMouseEvents.handleMouseDouble(mouseEvent); videoElementParent.addEventListener('mousemove', onmousemove); videoElementParent.addEventListener('mousedown', onmousedown); videoElementParent.addEventListener('mouseup', onmouseup); videoElementParent.addEventListener('contextmenu', oncontextmenu); videoElementParent.addEventListener('wheel', onwheel); videoElementParent.addEventListener('dblclick', ondblclick); this.mouseEventListenerTracker.addUnregisterCallback(() => videoElementParent.removeEventListener('mousemove', onmousemove)); this.mouseEventListenerTracker.addUnregisterCallback(() => videoElementParent.removeEventListener('mousedown', onmousedown)); this.mouseEventListenerTracker.addUnregisterCallback(() => videoElementParent.removeEventListener('mouseup', onmouseup)); this.mouseEventListenerTracker.addUnregisterCallback(() => videoElementParent.removeEventListener('contextmenu', oncontextmenu)); this.mouseEventListenerTracker.addUnregisterCallback(() => videoElementParent.removeEventListener('wheel', onwheel)); this.mouseEventListenerTracker.addUnregisterCallback(() => videoElementParent.removeEventListener('dblclick', ondblclick)); this.mouseEventListenerTracker.addUnregisterCallback(() => hoveringMouseEvents.unregisterMouseEvents()); } /** * Set the mouse enter and mouse leave events */ registerMouseEnterAndLeaveEvents() { const videoElementParent = this.videoElementProvider.getVideoParentElement(); // Handle when the Mouse has entered the element const onmouseenter = (event) => { if (!this.videoElementProvider.isVideoReady()) { return; } _Logger_Logger__WEBPACK_IMPORTED_MODULE_3__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_3__.Logger.GetStackTrace(), 'Mouse Entered', 6); this.sendMouseEnter(); this.pressMouseButtons(event.buttons, event.x, event.y); }; // Handles when the mouse has left the element const onmouseleave = (event) => { if (!this.videoElementProvider.isVideoReady()) { return; } _Logger_Logger__WEBPACK_IMPORTED_MODULE_3__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_3__.Logger.GetStackTrace(), 'Mouse Left', 6); this.sendMouseLeave(); this.releaseMouseButtons(event.buttons, event.x, event.y); }; videoElementParent.addEventListener('mouseenter', onmouseenter); videoElementParent.addEventListener('mouseleave', onmouseleave); this.mouseEventListenerTracker.addUnregisterCallback(() => videoElementParent.removeEventListener('mouseenter', onmouseenter)); this.mouseEventListenerTracker.addUnregisterCallback(() => videoElementParent.removeEventListener('mouseleave', onmouseleave)); } /** * Handle when a mouse button is released * @param buttons - Mouse Button * @param X - Mouse pointer X coordinate * @param Y - Mouse pointer Y coordinate */ releaseMouseButtons(buttons, X, Y) { const coord = this.coordinateConverter.normalizeAndQuantizeUnsigned(X, Y); if (buttons & _MouseButtons__WEBPACK_IMPORTED_MODULE_4__.MouseButtonsMask.primaryButton) { this.sendMouseUp(_MouseButtons__WEBPACK_IMPORTED_MODULE_4__.MouseButton.mainButton, coord.x, coord.y); } if (buttons & _MouseButtons__WEBPACK_IMPORTED_MODULE_4__.MouseButtonsMask.secondaryButton) { this.sendMouseUp(_MouseButtons__WEBPACK_IMPORTED_MODULE_4__.MouseButton.secondaryButton, coord.x, coord.y); } if (buttons & _MouseButtons__WEBPACK_IMPORTED_MODULE_4__.MouseButtonsMask.auxiliaryButton) { this.sendMouseUp(_MouseButtons__WEBPACK_IMPORTED_MODULE_4__.MouseButton.auxiliaryButton, coord.x, coord.y); } if (buttons & _MouseButtons__WEBPACK_IMPORTED_MODULE_4__.MouseButtonsMask.fourthButton) { this.sendMouseUp(_MouseButtons__WEBPACK_IMPORTED_MODULE_4__.MouseButton.fourthButton, coord.x, coord.y); } if (buttons & _MouseButtons__WEBPACK_IMPORTED_MODULE_4__.MouseButtonsMask.fifthButton) { this.sendMouseUp(_MouseButtons__WEBPACK_IMPORTED_MODULE_4__.MouseButton.fifthButton, coord.x, coord.y); } } /** * Handle when a mouse button is pressed * @param buttons - Mouse Button * @param X - Mouse pointer X coordinate * @param Y - Mouse pointer Y coordinate */ pressMouseButtons(buttons, X, Y) { if (!this.videoElementProvider.isVideoReady()) { return; } const coord = this.coordinateConverter.normalizeAndQuantizeUnsigned(X, Y); if (buttons & _MouseButtons__WEBPACK_IMPORTED_MODULE_4__.MouseButtonsMask.primaryButton) { this.sendMouseDown(_MouseButtons__WEBPACK_IMPORTED_MODULE_4__.MouseButton.mainButton, coord.x, coord.y); } if (buttons & _MouseButtons__WEBPACK_IMPORTED_MODULE_4__.MouseButtonsMask.secondaryButton) { this.sendMouseDown(_MouseButtons__WEBPACK_IMPORTED_MODULE_4__.MouseButton.secondaryButton, coord.x, coord.y); } if (buttons & _MouseButtons__WEBPACK_IMPORTED_MODULE_4__.MouseButtonsMask.auxiliaryButton) { this.sendMouseDown(_MouseButtons__WEBPACK_IMPORTED_MODULE_4__.MouseButton.auxiliaryButton, coord.x, coord.y); } if (buttons & _MouseButtons__WEBPACK_IMPORTED_MODULE_4__.MouseButtonsMask.fourthButton) { this.sendMouseDown(_MouseButtons__WEBPACK_IMPORTED_MODULE_4__.MouseButton.fourthButton, coord.x, coord.y); } if (buttons & _MouseButtons__WEBPACK_IMPORTED_MODULE_4__.MouseButtonsMask.fifthButton) { this.sendMouseDown(_MouseButtons__WEBPACK_IMPORTED_MODULE_4__.MouseButton.fifthButton, coord.x, coord.y); } } /** * Handles mouse enter */ sendMouseEnter() { if (!this.videoElementProvider.isVideoReady()) { return; } const toStreamerHandlers = this.toStreamerMessagesProvider.toStreamerHandlers; toStreamerHandlers.get('MouseEnter')(); } /** * Handles mouse Leave */ sendMouseLeave() { if (!this.videoElementProvider.isVideoReady()) { return; } const toStreamerHandlers = this.toStreamerMessagesProvider.toStreamerHandlers; toStreamerHandlers.get('MouseLeave')(); } /** * Handles when a mouse button is pressed down * @param button - Mouse Button Pressed * @param X - Mouse X Coordinate * @param Y - Mouse Y Coordinate */ sendMouseDown(button, X, Y) { if (!this.videoElementProvider.isVideoReady()) { return; } _Logger_Logger__WEBPACK_IMPORTED_MODULE_3__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_3__.Logger.GetStackTrace(), `mouse button ${button} down at (${X}, ${Y})`, 6); const toStreamerHandlers = this.toStreamerMessagesProvider.toStreamerHandlers; toStreamerHandlers.get('MouseDown')([button, X, Y]); } /** * Handles when a mouse button is pressed up * @param button - Mouse Button Pressed * @param X - Mouse X Coordinate * @param Y - Mouse Y Coordinate */ sendMouseUp(button, X, Y) { if (!this.videoElementProvider.isVideoReady()) { return; } _Logger_Logger__WEBPACK_IMPORTED_MODULE_3__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_3__.Logger.GetStackTrace(), `mouse button ${button} up at (${X}, ${Y})`, 6); const coord = this.coordinateConverter.normalizeAndQuantizeUnsigned(X, Y); const toStreamerHandlers = this.toStreamerMessagesProvider.toStreamerHandlers; toStreamerHandlers.get('MouseUp')([button, coord.x, coord.y]); } } /***/ }), /***/ "./src/Inputs/SpecialKeyCodes.ts": /*!***************************************!*\ !*** ./src/Inputs/SpecialKeyCodes.ts ***! \***************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "SpecialKeyCodes": () => (/* binding */ SpecialKeyCodes) /* harmony export */ }); // Copyright Epic Games, Inc. All Rights Reserved. /** * Registers the Special Key codes * Must be kept in sync with JavaScriptKeyCodeToFKey C++ array. * The index of the entry in the array is the special key code given below. */ class SpecialKeyCodes { } SpecialKeyCodes.backSpace = 8; SpecialKeyCodes.shift = 16; SpecialKeyCodes.control = 17; SpecialKeyCodes.alt = 18; SpecialKeyCodes.rightShift = 253; SpecialKeyCodes.rightControl = 254; SpecialKeyCodes.rightAlt = 255; /***/ }), /***/ "./src/Inputs/TouchController.ts": /*!***************************************!*\ !*** ./src/Inputs/TouchController.ts ***! \***************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "TouchController": () => (/* binding */ TouchController) /* harmony export */ }); /* harmony import */ var _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Logger/Logger */ "./src/Logger/Logger.ts"); /* harmony import */ var _Util_EventListenerTracker__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Util/EventListenerTracker */ "./src/Util/EventListenerTracker.ts"); // Copyright Epic Games, Inc. All Rights Reserved. /** * Handles the Touch input Events */ class TouchController { /** * @param toStreamerMessagesProvider - Stream message instance * @param videoElementProvider - Video Player instance * @param coordinateConverter - A coordinate converter instance */ constructor(toStreamerMessagesProvider, videoElementProvider, coordinateConverter) { this.fingers = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]; this.fingerIds = new Map(); this.maxByteValue = 255; // Utility for keeping track of event handlers and unregistering them this.touchEventListenerTracker = new _Util_EventListenerTracker__WEBPACK_IMPORTED_MODULE_0__.EventListenerTracker(); this.toStreamerMessagesProvider = toStreamerMessagesProvider; this.videoElementProvider = videoElementProvider; this.coordinateConverter = coordinateConverter; this.videoElementParent = videoElementProvider.getVideoElement(); const ontouchstart = (ev) => this.onTouchStart(ev); const ontouchend = (ev) => this.onTouchEnd(ev); const ontouchmove = (ev) => this.onTouchMove(ev); this.videoElementParent.addEventListener('touchstart', ontouchstart); this.videoElementParent.addEventListener('touchend', ontouchend); this.videoElementParent.addEventListener('touchmove', ontouchmove); this.touchEventListenerTracker.addUnregisterCallback(() => this.videoElementParent.removeEventListener('touchstart', ontouchstart)); this.touchEventListenerTracker.addUnregisterCallback(() => this.videoElementParent.removeEventListener('touchend', ontouchend)); this.touchEventListenerTracker.addUnregisterCallback(() => this.videoElementParent.removeEventListener('touchmove', ontouchmove)); _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.GetStackTrace(), 'Touch Events Registered', 6); // is this strictly necessary? const preventOnTouchMove = (event) => { event.preventDefault(); }; document.addEventListener('touchmove', preventOnTouchMove); this.touchEventListenerTracker.addUnregisterCallback(() => document.removeEventListener('touchmove', preventOnTouchMove)); } /** * Unregister all touch events */ unregisterTouchEvents() { this.touchEventListenerTracker.unregisterAll(); } /** * Remember a touch command * @param touch - the touch command */ rememberTouch(touch) { const finger = this.fingers.pop(); if (finger === undefined) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.GetStackTrace(), 'exhausted touch identifiers', 6); } this.fingerIds.set(touch.identifier, finger); } /** * Forgets a touch command * @param touch - the touch command */ forgetTouch(touch) { this.fingers.push(this.fingerIds.get(touch.identifier)); // Sort array back into descending order. This means if finger '1' were to lift after finger '0', we would ensure that 0 will be the first index to pop this.fingers.sort(function (a, b) { return b - a; }); this.fingerIds.delete(touch.identifier); } /** * When a touch event starts * @param touchEvent - the touch event being intercepted */ onTouchStart(touchEvent) { if (!this.videoElementProvider.isVideoReady()) { return; } for (let t = 0; t < touchEvent.changedTouches.length; t++) { this.rememberTouch(touchEvent.changedTouches[t]); } _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.GetStackTrace(), 'touch start', 6); this.emitTouchData('TouchStart', touchEvent.changedTouches); touchEvent.preventDefault(); } /** * When a touch event ends * @param touchEvent - the touch event being intercepted */ onTouchEnd(touchEvent) { if (!this.videoElementProvider.isVideoReady()) { return; } _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.GetStackTrace(), 'touch end', 6); this.emitTouchData('TouchEnd', touchEvent.changedTouches); // Re-cycle unique identifiers previously assigned to each touch. for (let t = 0; t < touchEvent.changedTouches.length; t++) { this.forgetTouch(touchEvent.changedTouches[t]); } touchEvent.preventDefault(); } /** * when a moving touch event occurs * @param touchEvent - the touch event being intercepted */ onTouchMove(touchEvent) { if (!this.videoElementProvider.isVideoReady()) { return; } _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.GetStackTrace(), 'touch move', 6); this.emitTouchData('TouchMove', touchEvent.touches); touchEvent.preventDefault(); } emitTouchData(type, touches) { if (!this.videoElementProvider.isVideoReady()) { return; } const offset = this.videoElementProvider.getVideoParentElement().getBoundingClientRect(); const toStreamerHandlers = this.toStreamerMessagesProvider.toStreamerHandlers; for (let t = 0; t < touches.length; t++) { const numTouches = 1; // the number of touches to be sent this message const touch = touches[t]; const x = touch.clientX - offset.left; const y = touch.clientY - offset.top; _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.GetStackTrace(), `F${this.fingerIds.get(touch.identifier)}=(${x}, ${y})`, 6); const coord = this.coordinateConverter.normalizeAndQuantizeUnsigned(x, y); switch (type) { case 'TouchStart': toStreamerHandlers.get('TouchStart')([ numTouches, coord.x, coord.y, this.fingerIds.get(touch.identifier), this.maxByteValue * touch.force, coord.inRange ? 1 : 0 ]); break; case 'TouchEnd': toStreamerHandlers.get('TouchEnd')([ numTouches, coord.x, coord.y, this.fingerIds.get(touch.identifier), this.maxByteValue * touch.force, coord.inRange ? 1 : 0 ]); break; case 'TouchMove': toStreamerHandlers.get('TouchMove')([ numTouches, coord.x, coord.y, this.fingerIds.get(touch.identifier), this.maxByteValue * touch.force, coord.inRange ? 1 : 0 ]); break; } } } } /***/ }), /***/ "./src/Inputs/XRGamepadController.ts": /*!*******************************************!*\ !*** ./src/Inputs/XRGamepadController.ts ***! \*******************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "XRGamepadController": () => (/* binding */ XRGamepadController) /* harmony export */ }); /* harmony import */ var _Util_WebXRUtils__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Util/WebXRUtils */ "./src/Util/WebXRUtils.ts"); // Copyright Epic Games, Inc. All Rights Reserved. /** * The class that handles the functionality of xrgamepads and controllers */ class XRGamepadController { /** * @param toStreamerMessagesProvider - Stream message instance */ constructor(toStreamerMessagesProvider) { this.toStreamerMessagesProvider = toStreamerMessagesProvider; this.controllers = []; } updateStatus(source, frame, refSpace) { if (source.gamepad) { const gamepadPose = frame.getPose(source.gripSpace, refSpace); if (!gamepadPose) { return; } let system = 0; if (source.profiles.includes('htc-vive')) { system = 1; } else if (source.profiles.includes('oculus-touch')) { system = 2; } // TODO (william.belcher): Add other profiles (Quest, Microsoft Mixed Reality, etc) this.toStreamerMessagesProvider.toStreamerHandlers.get('XRSystem')([ system ]); // Default: AnyHand (2) let handedness = 2; switch (source.handedness) { case 'left': handedness = 0; break; case 'right': handedness = 1; break; } // Send controller transform const matrix = gamepadPose.transform.matrix; const mat = []; for (let i = 0; i < 16; i++) { mat[i] = new Float32Array([matrix[i]])[0]; } // prettier-ignore this.toStreamerMessagesProvider.toStreamerHandlers.get('XRControllerTransform')([ mat[0], mat[4], mat[8], mat[12], mat[1], mat[5], mat[9], mat[13], mat[2], mat[6], mat[10], mat[14], mat[3], mat[7], mat[11], mat[15], handedness ]); // Handle controller buttons and axes if (this.controllers[handedness] === undefined) { this.controllers[handedness] = { prevState: undefined, currentState: undefined, id: undefined }; this.controllers[handedness].prevState = _Util_WebXRUtils__WEBPACK_IMPORTED_MODULE_0__.WebXRUtils.deepCopyGamepad(source.gamepad); } this.controllers[handedness].currentState = _Util_WebXRUtils__WEBPACK_IMPORTED_MODULE_0__.WebXRUtils.deepCopyGamepad(source.gamepad); const controller = this.controllers[handedness]; const currState = controller.currentState; const prevState = controller.prevState; // Iterate over buttons for (let i = 0; i < currState.buttons.length; i++) { const currButton = currState.buttons[i]; const prevButton = prevState.buttons[i]; if (currButton.pressed) { // press this.toStreamerMessagesProvider.toStreamerHandlers.get('XRButtonPressed')([handedness, i, prevButton.pressed ? 1 : 0]); } else if (!currButton.pressed && prevButton.pressed) { this.toStreamerMessagesProvider.toStreamerHandlers.get('XRButtonReleased')([handedness, i, 0]); } if (currButton.touched && !currButton.pressed) { // press this.toStreamerMessagesProvider.toStreamerHandlers.get('XRButtonPressed')([handedness, 3, prevButton.touched ? 1 : 0]); } else if (!currButton.touched && prevButton.touched) { this.toStreamerMessagesProvider.toStreamerHandlers.get('XRButtonReleased')([handedness, 3, 0]); } } // Iterate over gamepad axes for (let i = 0; i < currState.axes.length; i++) { this.toStreamerMessagesProvider.toStreamerHandlers.get('XRAnalog')([handedness, i, currState.axes[i]]); } this.controllers[handedness].prevState = currState; } } } /***/ }), /***/ "./src/Logger/Logger.ts": /*!******************************!*\ !*** ./src/Logger/Logger.ts ***! \******************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "Logger": () => (/* binding */ Logger) /* harmony export */ }); // Copyright Epic Games, Inc. All Rights Reserved. class Logger { /** * Captures the stack and returns it * @returns the current stack */ static GetStackTrace() { const error = new Error(); let formattedStack = 'No Stack Available for this browser'; // format the error if (error.stack) { formattedStack = error.stack.toString().replace(/Error/g, ''); } return formattedStack; } /** * Set the log verbosity level */ static SetLoggerVerbosity(verboseLogLevel) { if (this.verboseLogLevel != null) { this.verboseLogLevel = verboseLogLevel; } } /** * The standard logging output * @param stack - the stack trace * @param message - the message to be logged * @param verbosity - the verbosity level */ static Log(stack, message, verbosity) { if (verbosity > this.verboseLogLevel) { return; } const returnString = `Level: Log\nMsg: ${message}\nCaller: ${stack}`; console.log(returnString); } /** * The standard logging output * @param stack - the stack trace * @param message - the message to be logged * @param verbosity - the verbosity level */ static Info(stack, message, verbosity) { if (verbosity > this.verboseLogLevel) { return; } const returnString = `Level: Info\nMsg: ${message}`; console.info(returnString); } /** * The standard logging output * @param stack - the stack trace * @param message - the message to be logged */ static Error(stack, message) { const returnString = `Level: Error\nMsg: ${message}\nCaller: ${stack}`; console.error(returnString); } /** * The standard logging output * @param stack - the stack trace * @param message - the message to be logged */ static Warning(stack, message) { const returnString = `Level: Warning\nCaller: ${stack}\nMsg: ${message}`; console.warn(returnString); } } Logger.verboseLogLevel = 5; /***/ }), /***/ "./src/PeerConnectionController/AggregatedStats.ts": /*!*********************************************************!*\ !*** ./src/PeerConnectionController/AggregatedStats.ts ***! \*********************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "AggregatedStats": () => (/* binding */ AggregatedStats) /* harmony export */ }); /* harmony import */ var _InboundRTPStats__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./InboundRTPStats */ "./src/PeerConnectionController/InboundRTPStats.ts"); /* harmony import */ var _DataChannelStats__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./DataChannelStats */ "./src/PeerConnectionController/DataChannelStats.ts"); /* harmony import */ var _CandidateStat__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./CandidateStat */ "./src/PeerConnectionController/CandidateStat.ts"); /* harmony import */ var _CandidatePairStats__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./CandidatePairStats */ "./src/PeerConnectionController/CandidatePairStats.ts"); /* harmony import */ var _OutBoundRTPStats__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./OutBoundRTPStats */ "./src/PeerConnectionController/OutBoundRTPStats.ts"); /* harmony import */ var _SessionStats__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./SessionStats */ "./src/PeerConnectionController/SessionStats.ts"); /* harmony import */ var _StreamStats__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./StreamStats */ "./src/PeerConnectionController/StreamStats.ts"); /* harmony import */ var _Logger_Logger__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../Logger/Logger */ "./src/Logger/Logger.ts"); // Copyright Epic Games, Inc. All Rights Reserved. class AggregatedStats { constructor() { this.inboundVideoStats = new _InboundRTPStats__WEBPACK_IMPORTED_MODULE_0__.InboundVideoStats(); this.inboundAudioStats = new _InboundRTPStats__WEBPACK_IMPORTED_MODULE_0__.InboundAudioStats(); this.candidatePair = new _CandidatePairStats__WEBPACK_IMPORTED_MODULE_1__.CandidatePairStats(); this.DataChannelStats = new _DataChannelStats__WEBPACK_IMPORTED_MODULE_2__.DataChannelStats(); this.outBoundVideoStats = new _OutBoundRTPStats__WEBPACK_IMPORTED_MODULE_3__.OutBoundVideoStats(); this.sessionStats = new _SessionStats__WEBPACK_IMPORTED_MODULE_4__.SessionStats(); this.streamStats = new _StreamStats__WEBPACK_IMPORTED_MODULE_5__.StreamStats(); this.codecs = new Map(); } /** * Gather all the information from the RTC Peer Connection Report * @param rtcStatsReport - RTC Stats Report */ processStats(rtcStatsReport) { this.localCandidates = new Array(); this.remoteCandidates = new Array(); rtcStatsReport.forEach((stat) => { const type = stat.type; switch (type) { case 'candidate-pair': this.handleCandidatePair(stat); break; case 'certificate': break; case 'codec': this.handleCodec(stat); break; case 'data-channel': this.handleDataChannel(stat); break; case 'inbound-rtp': this.handleInBoundRTP(stat); break; case 'local-candidate': this.handleLocalCandidate(stat); break; case 'media-source': break; case 'media-playout': break; case 'outbound-rtp': break; case 'peer-connection': break; case 'remote-candidate': this.handleRemoteCandidate(stat); break; case 'remote-inbound-rtp': break; case 'remote-outbound-rtp': this.handleRemoteOutBound(stat); break; case 'track': this.handleTrack(stat); break; case 'transport': break; case 'stream': this.handleStream(stat); break; default: _Logger_Logger__WEBPACK_IMPORTED_MODULE_6__.Logger.Error(_Logger_Logger__WEBPACK_IMPORTED_MODULE_6__.Logger.GetStackTrace(), 'unhandled Stat Type'); _Logger_Logger__WEBPACK_IMPORTED_MODULE_6__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_6__.Logger.GetStackTrace(), stat); break; } }); } /** * Process stream stats data from webrtc * * @param stat - the stats coming in from webrtc */ handleStream(stat) { this.streamStats = stat; } /** * Process the Ice Candidate Pair Data * @param stat - the stats coming in from ice candidates */ handleCandidatePair(stat) { this.candidatePair.bytesReceived = stat.bytesReceived; this.candidatePair.bytesSent = stat.bytesSent; this.candidatePair.localCandidateId = stat.localCandidateId; this.candidatePair.remoteCandidateId = stat.remoteCandidateId; this.candidatePair.nominated = stat.nominated; this.candidatePair.readable = stat.readable; this.candidatePair.selected = stat.selected; this.candidatePair.writable = stat.writable; this.candidatePair.state = stat.state; this.candidatePair.currentRoundTripTime = stat.currentRoundTripTime; } /** * Process the Data Channel Data * @param stat - the stats coming in from the data channel */ handleDataChannel(stat) { this.DataChannelStats.bytesReceived = stat.bytesReceived; this.DataChannelStats.bytesSent = stat.bytesSent; this.DataChannelStats.dataChannelIdentifier = stat.dataChannelIdentifier; this.DataChannelStats.id = stat.id; this.DataChannelStats.label = stat.label; this.DataChannelStats.messagesReceived = stat.messagesReceived; this.DataChannelStats.messagesSent = stat.messagesSent; this.DataChannelStats.protocol = stat.protocol; this.DataChannelStats.state = stat.state; this.DataChannelStats.timestamp = stat.timestamp; } /** * Process the Local Ice Candidate Data * @param stat - local stats */ handleLocalCandidate(stat) { const localCandidate = new _CandidateStat__WEBPACK_IMPORTED_MODULE_7__.CandidateStat(); localCandidate.label = 'local-candidate'; localCandidate.address = stat.address; localCandidate.port = stat.port; localCandidate.protocol = stat.protocol; localCandidate.candidateType = stat.candidateType; localCandidate.id = stat.id; this.localCandidates.push(localCandidate); } /** * Process the Remote Ice Candidate Data * @param stat - ice candidate stats */ handleRemoteCandidate(stat) { const RemoteCandidate = new _CandidateStat__WEBPACK_IMPORTED_MODULE_7__.CandidateStat(); RemoteCandidate.label = 'local-candidate'; RemoteCandidate.address = stat.address; RemoteCandidate.port = stat.port; RemoteCandidate.protocol = stat.protocol; RemoteCandidate.id = stat.id; RemoteCandidate.candidateType = stat.candidateType; this.remoteCandidates.push(RemoteCandidate); } /** * Process the Inbound RTP Audio and Video Data * @param stat - inbound rtp stats */ handleInBoundRTP(stat) { switch (stat.kind) { case 'video': // Need to convert to unknown first to remove an error around // InboundVideoStats having the bitrate member which isn't found on // the InboundRTPStats this.inboundVideoStats = stat; if (this.lastVideoStats != undefined) { this.inboundVideoStats.bitrate = (8 * (this.inboundVideoStats.bytesReceived - this.lastVideoStats.bytesReceived)) / (this.inboundVideoStats.timestamp - this.lastVideoStats.timestamp); this.inboundVideoStats.bitrate = Math.floor(this.inboundVideoStats.bitrate); } this.lastVideoStats = Object.assign({}, this.inboundVideoStats); break; case 'audio': // Need to convert to unknown first to remove an error around // InboundAudioStats having the bitrate member which isn't found on // the InboundRTPStats this.inboundAudioStats = stat; if (this.lastAudioStats != undefined) { this.inboundAudioStats.bitrate = (8 * (this.inboundAudioStats.bytesReceived - this.lastAudioStats.bytesReceived)) / (this.inboundAudioStats.timestamp - this.lastAudioStats.timestamp); this.inboundAudioStats.bitrate = Math.floor(this.inboundAudioStats.bitrate); } this.lastAudioStats = Object.assign({}, this.inboundAudioStats); break; default: _Logger_Logger__WEBPACK_IMPORTED_MODULE_6__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_6__.Logger.GetStackTrace(), 'Kind is not handled'); break; } } /** * Process the outbound RTP Audio and Video Data * @param stat - remote outbound stats */ handleRemoteOutBound(stat) { switch (stat.kind) { case 'video': this.outBoundVideoStats.bytesSent = stat.bytesSent; this.outBoundVideoStats.id = stat.id; this.outBoundVideoStats.localId = stat.localId; this.outBoundVideoStats.packetsSent = stat.packetsSent; this.outBoundVideoStats.remoteTimestamp = stat.remoteTimestamp; this.outBoundVideoStats.timestamp = stat.timestamp; break; case 'audio': break; default: break; } } /** * Process the Inbound Video Track Data * @param stat - video track stats */ handleTrack(stat) { // we only want to extract stats from the video track if (stat.type === 'track' && (stat.trackIdentifier === 'video_label' || stat.kind === 'video')) { this.inboundVideoStats.framesDropped = stat.framesDropped; this.inboundVideoStats.framesReceived = stat.framesReceived; this.inboundVideoStats.frameHeight = stat.frameHeight; this.inboundVideoStats.frameWidth = stat.frameWidth; } } handleCodec(stat) { const codecId = stat.id; const codecType = `${stat.mimeType .replace('video/', '') .replace('audio/', '')}${stat.sdpFmtpLine ? ` ${stat.sdpFmtpLine}` : ''}`; this.codecs.set(codecId, codecType); } handleSessionStatistics(videoStartTime, inputController, videoEncoderAvgQP) { const deltaTime = Date.now() - videoStartTime; this.sessionStats.runTime = new Date(deltaTime) .toISOString() .substr(11, 8) .toString(); const controlsStreamInput = inputController === null ? 'Not sent yet' : inputController ? 'true' : 'false'; this.sessionStats.controlsStreamInput = controlsStreamInput; this.sessionStats.videoEncoderAvgQP = videoEncoderAvgQP; } /** * Check if a value coming in from our stats is actually a number * @param value - the number to be checked */ isNumber(value) { return typeof value === 'number' && isFinite(value); } } /***/ }), /***/ "./src/PeerConnectionController/CandidatePairStats.ts": /*!************************************************************!*\ !*** ./src/PeerConnectionController/CandidatePairStats.ts ***! \************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "CandidatePairStats": () => (/* binding */ CandidatePairStats) /* harmony export */ }); // Copyright Epic Games, Inc. All Rights Reserved. /** * ICE Candidate Pair Stats collected from the RTC Stats Report */ class CandidatePairStats { } /***/ }), /***/ "./src/PeerConnectionController/CandidateStat.ts": /*!*******************************************************!*\ !*** ./src/PeerConnectionController/CandidateStat.ts ***! \*******************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "CandidateStat": () => (/* binding */ CandidateStat) /* harmony export */ }); // Copyright Epic Games, Inc. All Rights Reserved. /** * ICE Candidate Stat collected from the RTC Stats Report */ class CandidateStat { } /***/ }), /***/ "./src/PeerConnectionController/DataChannelStats.ts": /*!**********************************************************!*\ !*** ./src/PeerConnectionController/DataChannelStats.ts ***! \**********************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "DataChannelStats": () => (/* binding */ DataChannelStats) /* harmony export */ }); // Copyright Epic Games, Inc. All Rights Reserved. /** * Data Channel Stats collected from the RTC Stats Report */ class DataChannelStats { } /***/ }), /***/ "./src/PeerConnectionController/InboundRTPStats.ts": /*!*********************************************************!*\ !*** ./src/PeerConnectionController/InboundRTPStats.ts ***! \*********************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "InboundAudioStats": () => (/* binding */ InboundAudioStats), /* harmony export */ "InboundRTPStats": () => (/* binding */ InboundRTPStats), /* harmony export */ "InboundVideoStats": () => (/* binding */ InboundVideoStats) /* harmony export */ }); // Copyright Epic Games, Inc. All Rights Reserved. /** * Inbound Audio Stats collected from the RTC Stats Report */ class InboundAudioStats { } /** * Inbound Video Stats collected from the RTC Stats Report */ class InboundVideoStats { } /** * Inbound Stats collected from the RTC Stats Report */ class InboundRTPStats { } /***/ }), /***/ "./src/PeerConnectionController/OutBoundRTPStats.ts": /*!**********************************************************!*\ !*** ./src/PeerConnectionController/OutBoundRTPStats.ts ***! \**********************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "OutBoundRTPStats": () => (/* binding */ OutBoundRTPStats), /* harmony export */ "OutBoundVideoStats": () => (/* binding */ OutBoundVideoStats) /* harmony export */ }); // Copyright Epic Games, Inc. All Rights Reserved. /** * Outbound Video Stats collected from the RTC Stats Report */ class OutBoundVideoStats { } /** * Outbound Stats collected from the RTC Stats Report */ class OutBoundRTPStats { } /***/ }), /***/ "./src/PeerConnectionController/PeerConnectionController.ts": /*!******************************************************************!*\ !*** ./src/PeerConnectionController/PeerConnectionController.ts ***! \******************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "PeerConnectionController": () => (/* binding */ PeerConnectionController) /* harmony export */ }); /* harmony import */ var _Logger_Logger__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../Logger/Logger */ "./src/Logger/Logger.ts"); /* harmony import */ var _Config_Config__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Config/Config */ "./src/Config/Config.ts"); /* harmony import */ var _AggregatedStats__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./AggregatedStats */ "./src/PeerConnectionController/AggregatedStats.ts"); /* harmony import */ var sdp__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! sdp */ "sdp"); /* harmony import */ var _Util_RTCUtils__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../Util/RTCUtils */ "./src/Util/RTCUtils.ts"); // Copyright Epic Games, Inc. All Rights Reserved. var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; /** * Handles the Peer Connection */ class PeerConnectionController { /** * Create a new RTC Peer Connection client * @param options - Peer connection Options * @param config - The config for our PS experience. */ constructor(options, config, preferredCodec) { this.config = config; this.createPeerConnection(options, preferredCodec); } createPeerConnection(options, preferredCodec) { // Set the ICE transport to relay if TURN enabled if (this.config.isFlagEnabled(_Config_Config__WEBPACK_IMPORTED_MODULE_1__.Flags.ForceTURN)) { options.iceTransportPolicy = 'relay'; _Logger_Logger__WEBPACK_IMPORTED_MODULE_2__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_2__.Logger.GetStackTrace(), 'Forcing TURN usage by setting ICE Transport Policy in peer connection config.'); } // build a new peer connection with the options this.peerConnection = new RTCPeerConnection(options); this.peerConnection.onsignalingstatechange = (ev) => this.handleSignalStateChange(ev); this.peerConnection.oniceconnectionstatechange = (ev) => this.handleIceConnectionStateChange(ev); this.peerConnection.onicegatheringstatechange = (ev) => this.handleIceGatheringStateChange(ev); this.peerConnection.ontrack = (ev) => this.handleOnTrack(ev); this.peerConnection.onicecandidate = (ev) => this.handleIceCandidate(ev); this.peerConnection.ondatachannel = (ev) => this.handleDataChannel(ev); this.aggregatedStats = new _AggregatedStats__WEBPACK_IMPORTED_MODULE_3__.AggregatedStats(); this.preferredCodec = preferredCodec; this.updateCodecSelection = true; } /** * Create an offer for the Web RTC handshake and send the offer to the signaling server via websocket * @param offerOptions - RTC Offer Options */ createOffer(offerOptions, config) { return __awaiter(this, void 0, void 0, function* () { _Logger_Logger__WEBPACK_IMPORTED_MODULE_2__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_2__.Logger.GetStackTrace(), 'Create Offer', 6); const isLocalhostConnection = location.hostname === 'localhost' || location.hostname === '127.0.0.1'; const isHttpsConnection = location.protocol === 'https:'; let useMic = config.isFlagEnabled(_Config_Config__WEBPACK_IMPORTED_MODULE_1__.Flags.UseMic); if (useMic && !(isLocalhostConnection || isHttpsConnection)) { useMic = false; _Logger_Logger__WEBPACK_IMPORTED_MODULE_2__.Logger.Error(_Logger_Logger__WEBPACK_IMPORTED_MODULE_2__.Logger.GetStackTrace(), 'Microphone access in the browser will not work if you are not on HTTPS or localhost. Disabling mic access.'); _Logger_Logger__WEBPACK_IMPORTED_MODULE_2__.Logger.Error(_Logger_Logger__WEBPACK_IMPORTED_MODULE_2__.Logger.GetStackTrace(), "For testing you can enable HTTP microphone access Chrome by visiting chrome://flags/ and enabling 'unsafely-treat-insecure-origin-as-secure'"); } this.setupTransceiversAsync(useMic).finally(() => { var _a; (_a = this.peerConnection) === null || _a === void 0 ? void 0 : _a.createOffer(offerOptions).then((offer) => { var _a; this.showTextOverlayConnecting(); offer.sdp = this.mungeSDP(offer.sdp, useMic); (_a = this.peerConnection) === null || _a === void 0 ? void 0 : _a.setLocalDescription(offer); this.onSendWebRTCOffer(offer); }).catch(() => { this.showTextOverlaySetupFailure(); }); }); }); } /** * */ receiveOffer(offer, config) { var _a; return __awaiter(this, void 0, void 0, function* () { _Logger_Logger__WEBPACK_IMPORTED_MODULE_2__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_2__.Logger.GetStackTrace(), 'Receive Offer', 6); (_a = this.peerConnection) === null || _a === void 0 ? void 0 : _a.setRemoteDescription(offer).then(() => { const isLocalhostConnection = location.hostname === 'localhost' || location.hostname === '127.0.0.1'; const isHttpsConnection = location.protocol === 'https:'; let useMic = config.isFlagEnabled(_Config_Config__WEBPACK_IMPORTED_MODULE_1__.Flags.UseMic); if (useMic && !(isLocalhostConnection || isHttpsConnection)) { useMic = false; _Logger_Logger__WEBPACK_IMPORTED_MODULE_2__.Logger.Error(_Logger_Logger__WEBPACK_IMPORTED_MODULE_2__.Logger.GetStackTrace(), 'Microphone access in the browser will not work if you are not on HTTPS or localhost. Disabling mic access.'); _Logger_Logger__WEBPACK_IMPORTED_MODULE_2__.Logger.Error(_Logger_Logger__WEBPACK_IMPORTED_MODULE_2__.Logger.GetStackTrace(), "For testing you can enable HTTP microphone access Chrome by visiting chrome://flags/ and enabling 'unsafely-treat-insecure-origin-as-secure'"); } this.setupTransceiversAsync(useMic).finally(() => { var _a; (_a = this.peerConnection) === null || _a === void 0 ? void 0 : _a.createAnswer().then((Answer) => { var _a; Answer.sdp = this.mungeSDP(Answer.sdp, useMic); return (_a = this.peerConnection) === null || _a === void 0 ? void 0 : _a.setLocalDescription(Answer); }).then(() => { var _a; this.onSendWebRTCAnswer((_a = this.peerConnection) === null || _a === void 0 ? void 0 : _a.currentLocalDescription); }).catch(() => { _Logger_Logger__WEBPACK_IMPORTED_MODULE_2__.Logger.Error(_Logger_Logger__WEBPACK_IMPORTED_MODULE_2__.Logger.GetStackTrace(), 'createAnswer() failed'); }); }); }); // Ugly syntax, but this achieves the intersection of the browser supported list and the UE supported list this.config.setOptionSettingOptions(_Config_Config__WEBPACK_IMPORTED_MODULE_1__.OptionParameters.PreferredCodec, this.parseAvailableCodecs(offer).filter((value) => this.config .getSettingOption(_Config_Config__WEBPACK_IMPORTED_MODULE_1__.OptionParameters.PreferredCodec) .options.includes(value))); }); } /** * Set the Remote Descriptor from the signaling server to the RTC Peer Connection * @param answer - RTC Session Descriptor from the Signaling Server */ receiveAnswer(answer) { var _a; (_a = this.peerConnection) === null || _a === void 0 ? void 0 : _a.setRemoteDescription(answer); // Ugly syntax, but this achieves the intersection of the browser supported list and the UE supported list this.config.setOptionSettingOptions(_Config_Config__WEBPACK_IMPORTED_MODULE_1__.OptionParameters.PreferredCodec, this.parseAvailableCodecs(answer).filter((value) => this.config .getSettingOption(_Config_Config__WEBPACK_IMPORTED_MODULE_1__.OptionParameters.PreferredCodec) .options.includes(value))); } /** * Generate Aggregated Stats and then fire a onVideo Stats event */ generateStats() { var _a; (_a = this.peerConnection) === null || _a === void 0 ? void 0 : _a.getStats(null).then((StatsData) => { this.aggregatedStats.processStats(StatsData); this.onVideoStats(this.aggregatedStats); // Update the preferred codec selection based on what was actually negotiated if (this.updateCodecSelection) { this.config.setOptionSettingValue(_Config_Config__WEBPACK_IMPORTED_MODULE_1__.OptionParameters.PreferredCodec, this.aggregatedStats.codecs.get(this.aggregatedStats.inboundVideoStats.codecId)); } }); } /** * Close The Peer Connection */ close() { if (this.peerConnection) { this.peerConnection.close(); this.peerConnection = null; } } /** * Modify the Session Descriptor * @param sdp - Session Descriptor as a string * @param useMic - Is the microphone in use * @returns A modified Session Descriptor */ mungeSDP(sdp, useMic) { let mungedSDP = sdp.replace(/(a=fmtp:\d+ .*level-asymmetry-allowed=.*)\r\n/gm, '$1;x-google-start-bitrate=10000;x-google-max-bitrate=100000\r\n'); // set max bitrate to highest bitrate Opus supports let audioSDP = 'maxaveragebitrate=510000;'; if (useMic) { // set the max capture rate to 48khz (so we can send high quality audio from mic) audioSDP += 'sprop-maxcapturerate=48000;'; } // Force mono or stereo based on whether ?forceMono was passed or not audioSDP += this.config.isFlagEnabled(_Config_Config__WEBPACK_IMPORTED_MODULE_1__.Flags.ForceMonoAudio) ? 'stereo=0;' : 'stereo=1;'; // enable in-band forward error correction for opus audio audioSDP += 'useinbandfec=1'; // We use the line 'useinbandfec=1' (which Opus uses) to set our Opus specific audio parameters. mungedSDP = mungedSDP.replace('useinbandfec=1', audioSDP); return mungedSDP; } /** * When a Ice Candidate is received add to the RTC Peer Connection * @param iceCandidate - RTC Ice Candidate from the Signaling Server */ handleOnIce(iceCandidate) { var _a; _Logger_Logger__WEBPACK_IMPORTED_MODULE_2__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_2__.Logger.GetStackTrace(), 'peerconnection handleOnIce', 6); // // if forcing TURN, reject any candidates not relay if (this.config.isFlagEnabled(_Config_Config__WEBPACK_IMPORTED_MODULE_1__.Flags.ForceTURN)) { // check if no relay address is found, if so, we are assuming it means no TURN server if (iceCandidate.candidate.indexOf('relay') < 0) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_2__.Logger.Info(_Logger_Logger__WEBPACK_IMPORTED_MODULE_2__.Logger.GetStackTrace(), `Dropping candidate because it was not TURN relay. | Type= ${iceCandidate.type} | Protocol= ${iceCandidate.protocol} | Address=${iceCandidate.address} | Port=${iceCandidate.port} |`, 6); return; } } (_a = this.peerConnection) === null || _a === void 0 ? void 0 : _a.addIceCandidate(iceCandidate); } /** * When the RTC Peer Connection Signaling server state Changes * @param state - Signaling Server State Change Event */ handleSignalStateChange(state) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_2__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_2__.Logger.GetStackTrace(), 'signaling state change: ' + state, 6); } /** * Handle when the Ice Connection State Changes * @param state - Ice Connection State */ handleIceConnectionStateChange(state) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_2__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_2__.Logger.GetStackTrace(), 'ice connection state change: ' + state, 6); this.onIceConnectionStateChange(state); } /** * Handle when the Ice Gathering State Changes * @param state - Ice Gathering State Change */ handleIceGatheringStateChange(state) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_2__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_2__.Logger.GetStackTrace(), 'ice gathering state change: ' + JSON.stringify(state), 6); } /** * Activates the onTrack method * @param event - The webRtc track event */ handleOnTrack(event) { this.onTrack(event); } /** * Activates the onPeerIceCandidate * @param event - The peer ice candidate */ handleIceCandidate(event) { this.onPeerIceCandidate(event); } /** * Activates the onDataChannel * @param event - The peer's data channel */ handleDataChannel(event) { this.onDataChannel(event); } /** * An override method for onTrack for use outside of the PeerConnectionController * @param trackEvent - The webRtc track event */ // eslint-disable-next-line @typescript-eslint/no-unused-vars onTrack(trackEvent) { // Default Functionality: Do Nothing } /** * An override method for onIceConnectionStateChange for use outside of the PeerConnectionController * @param event - The webRtc iceconnectionstatechange event */ // eslint-disable-next-line @typescript-eslint/no-unused-vars onIceConnectionStateChange(event) { // Default Functionality: Do Nothing } /** * An override method for onPeerIceCandidate for use outside of the PeerConnectionController * @param peerConnectionIceEvent - The peer ice candidate */ // eslint-disable-next-line @typescript-eslint/no-unused-vars onPeerIceCandidate(peerConnectionIceEvent) { // Default Functionality: Do Nothing } /** * An override method for onDataChannel for use outside of the PeerConnectionController * @param datachannelEvent - The peer's data channel */ // eslint-disable-next-line @typescript-eslint/no-unused-vars onDataChannel(datachannelEvent) { // Default Functionality: Do Nothing } /** * Setup tracks on the RTC Peer Connection * @param useMic - is mic in use */ setupTransceiversAsync(useMic) { var _a, _b, _c, _d, _e, _f, _g, _h, _j; return __awaiter(this, void 0, void 0, function* () { const hasTransceivers = ((_a = this.peerConnection) === null || _a === void 0 ? void 0 : _a.getTransceivers().length) > 0; // Setup a transceiver for getting UE video (_b = this.peerConnection) === null || _b === void 0 ? void 0 : _b.addTransceiver('video', { direction: 'recvonly' }); // We can only set preferrec codec on Chrome if (RTCRtpReceiver.getCapabilities && this.preferredCodec != '') { for (const transceiver of (_d = (_c = this.peerConnection) === null || _c === void 0 ? void 0 : _c.getTransceivers()) !== null && _d !== void 0 ? _d : []) { if (transceiver && transceiver.receiver && transceiver.receiver.track && transceiver.receiver.track.kind === 'video' && // As of 06/2023, FireFox has added RTCRtpReceiver.getCapabilities, but hasn't added the ability to set codec preferences transceiver.setCodecPreferences) { const preferredRTPCodec = this.preferredCodec.split(' '); const codecs = [ { mimeType: 'video/' + preferredRTPCodec[0] /* Name */, clockRate: 90000, sdpFmtpLine: preferredRTPCodec[1] /* sdpFmtpLine */ ? preferredRTPCodec[1] : '' } ]; this.config .getSettingOption(_Config_Config__WEBPACK_IMPORTED_MODULE_1__.OptionParameters.PreferredCodec) .options.filter((option) => { // Remove the preferred codec from the list of possible codecs as we've set it already return option != this.preferredCodec; }) .forEach((option) => { // Ammend the rest of the browsers supported codecs const altCodec = option.split(' '); codecs.push({ mimeType: 'video/' + altCodec[0] /* Name */, clockRate: 90000, sdpFmtpLine: altCodec[1] /* sdpFmtpLine */ ? altCodec[1] : '' }); }); for (const codec of codecs) { if (codec.sdpFmtpLine === '') { // We can't dynamically add members to the codec, so instead remove the field if it's empty delete codec.sdpFmtpLine; } } transceiver.setCodecPreferences(codecs); } } } // Setup a transceiver for sending mic audio to UE and receiving audio from UE if (!useMic) { (_e = this.peerConnection) === null || _e === void 0 ? void 0 : _e.addTransceiver('audio', { direction: 'recvonly' }); } else { // set the audio options based on mic usage const audioOptions = { autoGainControl: false, channelCount: 1, echoCancellation: false, latency: 0, noiseSuppression: false, sampleRate: 48000, sampleSize: 16, volume: 1.0 }; // set the media send options const mediaSendOptions = { video: false, audio: audioOptions }; // Note using mic on android chrome requires SSL or chrome://flags/ "unsafely-treat-insecure-origin-as-secure" const stream = yield navigator.mediaDevices.getUserMedia(mediaSendOptions); if (stream) { if (hasTransceivers) { for (const transceiver of (_g = (_f = this.peerConnection) === null || _f === void 0 ? void 0 : _f.getTransceivers()) !== null && _g !== void 0 ? _g : []) { if (_Util_RTCUtils__WEBPACK_IMPORTED_MODULE_4__.RTCUtils.canTransceiverReceiveAudio(transceiver)) { for (const track of stream.getTracks()) { if (track.kind && track.kind == 'audio') { transceiver.sender.replaceTrack(track); transceiver.direction = 'sendrecv'; } } } } } else { for (const track of stream.getTracks()) { if (track.kind && track.kind == 'audio') { (_h = this.peerConnection) === null || _h === void 0 ? void 0 : _h.addTransceiver(track, { direction: 'sendrecv' }); } } } } else { (_j = this.peerConnection) === null || _j === void 0 ? void 0 : _j.addTransceiver('audio', { direction: 'recvonly' }); } } }); } /** * And override event for when the video stats are fired * @param event - Aggregated Stats */ // eslint-disable-next-line @typescript-eslint/no-unused-vars onVideoStats(event) { // Default Functionality: Do Nothing } /** * Event to send the RTC offer to the Signaling server * @param offer - RTC Offer */ // eslint-disable-next-line @typescript-eslint/no-unused-vars onSendWebRTCOffer(offer) { // Default Functionality: Do Nothing } /** * Event to send the RTC Answer to the Signaling server * @param answer - RTC Answer */ // eslint-disable-next-line @typescript-eslint/no-unused-vars onSendWebRTCAnswer(answer) { // Default Functionality: Do Nothing } /** * An override for showing the Peer connection connecting Overlay */ showTextOverlayConnecting() { // Default Functionality: Do Nothing } /** * An override for showing the Peer connection Failed overlay */ showTextOverlaySetupFailure() { // Default Functionality: Do Nothing } parseAvailableCodecs(rtcSessionDescription) { // No point in updating the available codecs if on FF if (!RTCRtpReceiver.getCapabilities) return ['Only available on Chrome']; const ueSupportedCodecs = []; const sections = (0,sdp__WEBPACK_IMPORTED_MODULE_0__.splitSections)(rtcSessionDescription.sdp); // discard the session information as we only want media related info sections.shift(); sections.forEach((mediaSection) => { const { codecs } = (0,sdp__WEBPACK_IMPORTED_MODULE_0__.parseRtpParameters)(mediaSection); // Filter only for VPX / H26X / AV1 const matcher = /(VP\d|H26\d|AV1).*/; codecs.forEach((c) => { const str = c.name + ' ' + Object.keys(c.parameters || {}) .map((p) => p + '=' + c.parameters[p]) .join(';'); const match = matcher.exec(str); if (match !== null) { if (c.name == 'VP9') { // UE answers don't specify profile but we know we want profile 0 c.parameters = { 'profile-id': '0' }; } const codecStr = c.name + ' ' + Object.keys(c.parameters || {}) .map((p) => p + '=' + c.parameters[p]) .join(';'); ueSupportedCodecs.push(codecStr); } }); }); return ueSupportedCodecs; } } /***/ }), /***/ "./src/PeerConnectionController/SessionStats.ts": /*!******************************************************!*\ !*** ./src/PeerConnectionController/SessionStats.ts ***! \******************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "SessionStats": () => (/* binding */ SessionStats) /* harmony export */ }); // Copyright Epic Games, Inc. All Rights Reserved. /** * Session statistics */ class SessionStats { } /***/ }), /***/ "./src/PeerConnectionController/StreamStats.ts": /*!*****************************************************!*\ !*** ./src/PeerConnectionController/StreamStats.ts ***! \*****************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "StreamStats": () => (/* binding */ StreamStats) /* harmony export */ }); // Copyright Epic Games, Inc. All Rights Reserved. /** * Class to hold the stream stats data coming in from webRtc */ class StreamStats { } /***/ }), /***/ "./src/PixelStreaming/PixelStreaming.ts": /*!**********************************************!*\ !*** ./src/PixelStreaming/PixelStreaming.ts ***! \**********************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "PixelStreaming": () => (/* binding */ PixelStreaming) /* harmony export */ }); /* harmony import */ var _Config_Config__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../Config/Config */ "./src/Config/Config.ts"); /* harmony import */ var _WebRtcPlayer_WebRtcPlayerController__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../WebRtcPlayer/WebRtcPlayerController */ "./src/WebRtcPlayer/WebRtcPlayerController.ts"); /* harmony import */ var _Logger_Logger__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../Logger/Logger */ "./src/Logger/Logger.ts"); /* harmony import */ var _UI_OnScreenKeyboard__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../UI/OnScreenKeyboard */ "./src/UI/OnScreenKeyboard.ts"); /* harmony import */ var _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Util/EventEmitter */ "./src/Util/EventEmitter.ts"); /* harmony import */ var _WebXR_WebXRController__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../WebXR/WebXRController */ "./src/WebXR/WebXRController.ts"); /* harmony import */ var _UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../UeInstanceMessage/StreamMessageController */ "./src/UeInstanceMessage/StreamMessageController.ts"); /* harmony import */ var _DataChannel_DataChannelLatencyTestController__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../DataChannel/DataChannelLatencyTestController */ "./src/DataChannel/DataChannelLatencyTestController.ts"); /* harmony import */ var _Util_RTCUtils__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../Util/RTCUtils */ "./src/Util/RTCUtils.ts"); // Copyright Epic Games, Inc. All Rights Reserved. /** * The key class for the browser side of a Pixel Streaming application, it includes: * WebRTC handling, XR support, input handling, and emitters for lifetime and state change events. * Users are encouraged to use this class as is, through composition, or extend it. In any case, * this will likely be the core of your Pixel Streaming experience in terms of functionality. */ class PixelStreaming { /** * @param config - A newly instantiated config object * @param overrides - Parameters to override default behaviour * returns the base Pixel streaming object */ constructor(config, overrides) { this.allowConsoleCommands = false; this.config = config; if (overrides === null || overrides === void 0 ? void 0 : overrides.videoElementParent) { this._videoElementParent = overrides.videoElementParent; } this._eventEmitter = new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_0__.EventEmitter(); this.configureSettings(); // setup WebRTC this.setWebRtcPlayerController(new _WebRtcPlayer_WebRtcPlayerController__WEBPACK_IMPORTED_MODULE_1__.WebRtcPlayerController(this.config, this)); // Onscreen keyboard this.onScreenKeyboardHelper = new _UI_OnScreenKeyboard__WEBPACK_IMPORTED_MODULE_2__.OnScreenKeyboard(this.videoElementParent); this.onScreenKeyboardHelper.unquantizeAndDenormalizeUnsigned = (x, y) => this._webRtcController.requestUnquantizedAndDenormalizeUnsigned(x, y); this._activateOnScreenKeyboard = (command) => this.onScreenKeyboardHelper.showOnScreenKeyboard(command); this._webXrController = new _WebXR_WebXRController__WEBPACK_IMPORTED_MODULE_3__.WebXRController(this._webRtcController); } /** * Gets the element that contains the video stream element. */ get videoElementParent() { if (!this._videoElementParent) { this._videoElementParent = document.createElement('div'); this._videoElementParent.id = 'videoElementParent'; } return this._videoElementParent; } /** * Configure the settings with on change listeners and any additional per experience settings. */ configureSettings() { this.config._addOnSettingChangedListener(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.Flags.IsQualityController, (wantsQualityController) => { // If the setting has been set to true (either programatically or the user has flicked the toggle) // and we aren't currently quality controller, send the request if (wantsQualityController === true && !this._webRtcController.isQualityController) { this._webRtcController.sendRequestQualityControlOwnership(); } }); this.config._addOnSettingChangedListener(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.Flags.AFKDetection, (isAFKEnabled) => { this._webRtcController.setAfkEnabled(isAFKEnabled); }); this.config._addOnSettingChangedListener(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.Flags.MatchViewportResolution, () => { this._webRtcController.videoPlayer.updateVideoStreamSize(); }); this.config._addOnSettingChangedListener(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.Flags.HoveringMouseMode, (isHoveringMouse) => { this.config.setFlagLabel(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.Flags.HoveringMouseMode, `Control Scheme: ${isHoveringMouse ? 'Hovering' : 'Locked'} Mouse`); this._webRtcController.setMouseInputEnabled(this.config.isFlagEnabled(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.Flags.MouseInput)); }); // user input this.config._addOnSettingChangedListener(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.Flags.KeyboardInput, (isEnabled) => { this._webRtcController.setKeyboardInputEnabled(isEnabled); }); this.config._addOnSettingChangedListener(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.Flags.MouseInput, (isEnabled) => { this._webRtcController.setMouseInputEnabled(isEnabled); }); this.config._addOnSettingChangedListener(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.Flags.TouchInput, (isEnabled) => { this._webRtcController.setTouchInputEnabled(isEnabled); }); this.config._addOnSettingChangedListener(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.Flags.GamepadInput, (isEnabled) => { this._webRtcController.setGamePadInputEnabled(isEnabled); }); // encoder settings this.config._addOnNumericSettingChangedListener(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.NumericParameters.MinQP, (newValue) => { _Logger_Logger__WEBPACK_IMPORTED_MODULE_5__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_5__.Logger.GetStackTrace(), '-------- Sending MinQP --------', 7); this._webRtcController.sendEncoderMinQP(newValue); _Logger_Logger__WEBPACK_IMPORTED_MODULE_5__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_5__.Logger.GetStackTrace(), '-------------------------------------------', 7); }); this.config._addOnNumericSettingChangedListener(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.NumericParameters.MaxQP, (newValue) => { _Logger_Logger__WEBPACK_IMPORTED_MODULE_5__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_5__.Logger.GetStackTrace(), '-------- Sending encoder settings --------', 7); this._webRtcController.sendEncoderMaxQP(newValue); _Logger_Logger__WEBPACK_IMPORTED_MODULE_5__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_5__.Logger.GetStackTrace(), '-------------------------------------------', 7); }); // WebRTC settings this.config._addOnNumericSettingChangedListener(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.NumericParameters.WebRTCMinBitrate, (newValue) => { _Logger_Logger__WEBPACK_IMPORTED_MODULE_5__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_5__.Logger.GetStackTrace(), '-------- Sending web rtc settings --------', 7); this._webRtcController.sendWebRTCMinBitrate(newValue * 1000 /* kbps to bps */); _Logger_Logger__WEBPACK_IMPORTED_MODULE_5__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_5__.Logger.GetStackTrace(), '-------------------------------------------', 7); }); this.config._addOnNumericSettingChangedListener(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.NumericParameters.WebRTCMaxBitrate, (newValue) => { _Logger_Logger__WEBPACK_IMPORTED_MODULE_5__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_5__.Logger.GetStackTrace(), '-------- Sending web rtc settings --------', 7); this._webRtcController.sendWebRTCMaxBitrate(newValue * 1000 /* kbps to bps */); _Logger_Logger__WEBPACK_IMPORTED_MODULE_5__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_5__.Logger.GetStackTrace(), '-------------------------------------------', 7); }); this.config._addOnNumericSettingChangedListener(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.NumericParameters.WebRTCFPS, (newValue) => { _Logger_Logger__WEBPACK_IMPORTED_MODULE_5__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_5__.Logger.GetStackTrace(), '-------- Sending web rtc settings --------', 7); this._webRtcController.sendWebRTCFps(newValue); _Logger_Logger__WEBPACK_IMPORTED_MODULE_5__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_5__.Logger.GetStackTrace(), '-------------------------------------------', 7); }); this.config._addOnOptionSettingChangedListener(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.OptionParameters.PreferredCodec, (newValue) => { if (this._webRtcController) { this._webRtcController.setPreferredCodec(newValue); } }); this.config._registerOnChangeEvents(this._eventEmitter); } /** * Activate the on screen keyboard when receiving the command from the streamer * @param command - the keyboard command */ // eslint-disable-next-line @typescript-eslint/no-unused-vars _activateOnScreenKeyboard(command) { throw new Error('Method not implemented.'); } /** * Set the input control ownership * @param inputControlOwnership - does the user have input control ownership */ _onInputControlOwnership(inputControlOwnership) { this._inputController = inputControlOwnership; } /** * Instantiate the WebRTCPlayerController interface to provide WebRTCPlayerController functionality within this class and set up anything that requires it * @param webRtcPlayerController - a WebRtcPlayerController controller instance */ setWebRtcPlayerController(webRtcPlayerController) { this._webRtcController = webRtcPlayerController; this._webRtcController.setPreferredCodec(this.config.getSettingOption(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.OptionParameters.PreferredCodec) .selected); this._webRtcController.resizePlayerStyle(); // connect if auto connect flag is enabled this.checkForAutoConnect(); } /** * Connect to signaling server. */ connect() { this._eventEmitter.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_0__.StreamPreConnectEvent()); this._webRtcController.connectToSignallingServer(); } /** * Reconnects to the signaling server. If connection is up, disconnects first * before establishing a new connection */ reconnect() { this._eventEmitter.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_0__.StreamReconnectEvent()); this._webRtcController.tryReconnect("Reconnecting..."); } /** * Disconnect from the signaling server and close open peer connections. */ disconnect() { this._eventEmitter.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_0__.StreamPreDisconnectEvent()); this._webRtcController.close(); } /** * Play the stream. Can be called only after a peer connection has been established. */ play() { this._onStreamLoading(); this._webRtcController.playStream(); } /** * Auto connect if AutoConnect flag is enabled */ checkForAutoConnect() { // set up if the auto play will be used or regular click to start if (this.config.isFlagEnabled(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.Flags.AutoConnect)) { // if autoplaying show an info overlay while while waiting for the connection to begin this._onWebRtcAutoConnect(); this._webRtcController.connectToSignallingServer(); } } /** * Will unmute the microphone track which is sent to Unreal Engine. * By default, will only unmute an existing mic track. * * @param forceEnable Can be used for cases when this object wasn't initialized with a mic track. * If this parameter is true, the connection will be restarted with a microphone. * Warning: this takes some time, as a full renegotiation and reconnection will happen. */ unmuteMicrophone(forceEnable = false) { // If there's an existing mic track, we just set muted state if (this.config.isFlagEnabled('UseMic')) { this.setMicrophoneMuted(false); return; } // If there's no pre-existing mic track, and caller is ok with full reset, we enable and reset if (forceEnable) { this.config.setFlagEnabled("UseMic", true); this.reconnect(); return; } // If we prefer not to force a reconnection, just warn the user that this operation didn't happen _Logger_Logger__WEBPACK_IMPORTED_MODULE_5__.Logger.Warning(_Logger_Logger__WEBPACK_IMPORTED_MODULE_5__.Logger.GetStackTrace(), 'Trying to unmute mic, but PixelStreaming was initialized with no microphone track. Call with forceEnable == true to re-connect with a mic track.'); } muteMicrophone() { if (this.config.isFlagEnabled('UseMic')) { this.setMicrophoneMuted(true); return; } // If there wasn't a mic track, just let user know there's nothing to mute _Logger_Logger__WEBPACK_IMPORTED_MODULE_5__.Logger.Info(_Logger_Logger__WEBPACK_IMPORTED_MODULE_5__.Logger.GetStackTrace(), 'Trying to mute mic, but PixelStreaming has no microphone track, so sending sound is already disabled.'); } setMicrophoneMuted(mute) { var _a, _b, _c, _d; for (const transceiver of (_d = (_c = (_b = (_a = this._webRtcController) === null || _a === void 0 ? void 0 : _a.peerConnectionController) === null || _b === void 0 ? void 0 : _b.peerConnection) === null || _c === void 0 ? void 0 : _c.getTransceivers()) !== null && _d !== void 0 ? _d : []) { if (_Util_RTCUtils__WEBPACK_IMPORTED_MODULE_6__.RTCUtils.canTransceiverSendAudio(transceiver)) { transceiver.sender.track.enabled = !mute; } } } /** * Emit an event on auto connecting */ _onWebRtcAutoConnect() { this._eventEmitter.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_0__.WebRtcAutoConnectEvent()); } /** * Set up functionality to happen when receiving a webRTC answer */ _onWebRtcSdp() { this._eventEmitter.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_0__.WebRtcSdpEvent()); } /** * Emits a StreamLoading event */ _onStreamLoading() { this._eventEmitter.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_0__.StreamLoadingEvent()); } /** * Event fired when the video is disconnected - emits given eventString or an override * message from webRtcController if one has been set * @param eventString - a string describing why the connection closed * @param allowClickToReconnect - true if we want to allow the user to retry the connection with a click */ _onDisconnect(eventString, allowClickToReconnect) { this._eventEmitter.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_0__.WebRtcDisconnectedEvent({ eventString: eventString, allowClickToReconnect: allowClickToReconnect })); } /** * Handles when Web Rtc is connecting */ _onWebRtcConnecting() { this._eventEmitter.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_0__.WebRtcConnectingEvent()); } /** * Handles when Web Rtc has connected */ _onWebRtcConnected() { this._eventEmitter.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_0__.WebRtcConnectedEvent()); } /** * Handles when Web Rtc fails to connect */ _onWebRtcFailed() { this._eventEmitter.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_0__.WebRtcFailedEvent()); } /** * Handle when the Video has been Initialized */ _onVideoInitialized() { this._eventEmitter.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_0__.VideoInitializedEvent()); this._videoStartTime = Date.now(); } /** * Set up functionality to happen when receiving latency test results * @param latency - latency test results object */ _onLatencyTestResult(latencyTimings) { this._eventEmitter.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_0__.LatencyTestResultEvent({ latencyTimings })); } _onDataChannelLatencyTestResponse(response) { this._eventEmitter.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_0__.DataChannelLatencyTestResponseEvent({ response })); } /** * Set up functionality to happen when receiving video statistics * @param videoStats - video statistics as a aggregate stats object */ _onVideoStats(videoStats) { // Duration if (!this._videoStartTime || this._videoStartTime === undefined) { this._videoStartTime = Date.now(); } videoStats.handleSessionStatistics(this._videoStartTime, this._inputController, this._webRtcController.videoAvgQp); this._eventEmitter.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_0__.StatsReceivedEvent({ aggregatedStats: videoStats })); } /** * Set up functionality to happen when calculating the average video encoder qp * @param QP - the quality number of the stream */ _onVideoEncoderAvgQP(QP) { this._eventEmitter.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_0__.VideoEncoderAvgQPEvent({ avgQP: QP })); } /** * Set up functionality to happen when receiving and handling initial settings for the UE app * @param settings - initial UE app settings */ _onInitialSettings(settings) { var _a; this._eventEmitter.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_0__.InitialSettingsEvent({ settings })); if (settings.PixelStreamingSettings) { this.allowConsoleCommands = (_a = settings.PixelStreamingSettings.AllowPixelStreamingCommands) !== null && _a !== void 0 ? _a : false; if (this.allowConsoleCommands === false) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_5__.Logger.Info(_Logger_Logger__WEBPACK_IMPORTED_MODULE_5__.Logger.GetStackTrace(), '-AllowPixelStreamingCommands=false, sending arbitrary console commands from browser to UE is disabled.'); } } const useUrlParams = this.config.useUrlParams; const urlParams = new URLSearchParams(window.location.search); if (settings.EncoderSettings) { this.config.setNumericSetting(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.NumericParameters.MinQP, // If a setting is set in the URL, make sure we respect that value as opposed to what the application sends us (useUrlParams && urlParams.has(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.NumericParameters.MinQP)) ? Number.parseInt(urlParams.get(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.NumericParameters.MinQP)) : settings.EncoderSettings.MinQP); this.config.setNumericSetting(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.NumericParameters.MaxQP, (useUrlParams && urlParams.has(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.NumericParameters.MaxQP)) ? Number.parseInt(urlParams.get(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.NumericParameters.MaxQP)) : settings.EncoderSettings.MaxQP); } if (settings.WebRTCSettings) { this.config.setNumericSetting(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.NumericParameters.WebRTCMinBitrate, (useUrlParams && urlParams.has(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.NumericParameters.WebRTCMinBitrate)) ? Number.parseInt(urlParams.get(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.NumericParameters.WebRTCMinBitrate)) : settings.WebRTCSettings.MinBitrate / 1000 /* bps to kbps */); this.config.setNumericSetting(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.NumericParameters.WebRTCMaxBitrate, (useUrlParams && urlParams.has(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.NumericParameters.WebRTCMaxBitrate)) ? Number.parseInt(urlParams.get(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.NumericParameters.WebRTCMaxBitrate)) : settings.WebRTCSettings.MaxBitrate / 1000 /* bps to kbps */); this.config.setNumericSetting(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.NumericParameters.WebRTCFPS, (useUrlParams && urlParams.has(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.NumericParameters.WebRTCFPS)) ? Number.parseInt(urlParams.get(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.NumericParameters.WebRTCFPS)) : settings.WebRTCSettings.FPS); } } /** * Set up functionality to happen when setting quality control ownership of a stream * @param hasQualityOwnership - does this user have quality ownership of the stream true / false */ _onQualityControlOwnership(hasQualityOwnership) { this.config.setFlagEnabled(_Config_Config__WEBPACK_IMPORTED_MODULE_4__.Flags.IsQualityController, hasQualityOwnership); } _onPlayerCount(playerCount) { this._eventEmitter.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_0__.PlayerCountEvent({ count: playerCount })); } /** * Request a connection latency test. * NOTE: There are plans to refactor all request* functions. Expect changes if you use this! * @returns */ requestLatencyTest() { if (!this._webRtcController.videoPlayer.isVideoReady()) { return false; } this._webRtcController.sendLatencyTest(); return true; } /** * Request a data channel latency test. * NOTE: There are plans to refactor all request* functions. Expect changes if you use this! */ requestDataChannelLatencyTest(config) { if (!this._webRtcController.videoPlayer.isVideoReady()) { return false; } if (!this._dataChannelLatencyTestController) { this._dataChannelLatencyTestController = new _DataChannel_DataChannelLatencyTestController__WEBPACK_IMPORTED_MODULE_7__.DataChannelLatencyTestController(this._webRtcController.sendDataChannelLatencyTest.bind(this._webRtcController), (result) => { this._eventEmitter.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_0__.DataChannelLatencyTestResultEvent({ result })); }); this.addEventListener("dataChannelLatencyTestResponse", ({ data: { response } }) => { this._dataChannelLatencyTestController.receive(response); }); } return this._dataChannelLatencyTestController.start(config); } /** * Request for the UE application to show FPS counter. * NOTE: There are plans to refactor all request* functions. Expect changes if you use this! * @returns */ requestShowFps() { if (!this._webRtcController.videoPlayer.isVideoReady()) { return false; } this._webRtcController.sendShowFps(); return true; } /** * Request for a new IFrame from the UE application. * NOTE: There are plans to refactor all request* functions. Expect changes if you use this! * @returns */ requestIframe() { if (!this._webRtcController.videoPlayer.isVideoReady()) { return false; } this._webRtcController.sendIframeRequest(); return true; } /** * Send data to UE application. The data will be run through JSON.stringify() so e.g. strings * and any serializable plain JSON objects with no recurrence can be sent. * @returns true if succeeded, false if rejected */ emitUIInteraction(descriptor) { if (!this._webRtcController.videoPlayer.isVideoReady()) { return false; } this._webRtcController.emitUIInteraction(descriptor); return true; } /** * Send a command to UE application. Blocks ConsoleCommand descriptors unless UE * has signaled that it allows console commands. * @returns true if succeeded, false if rejected */ emitCommand(descriptor) { if (!this._webRtcController.videoPlayer.isVideoReady()) { return false; } if (!this.allowConsoleCommands && 'ConsoleCommand' in descriptor) { return false; } this._webRtcController.emitCommand(descriptor); return true; } /** * Send a console command to UE application. Only allowed if UE has signaled that it allows * console commands. * @returns true if succeeded, false if rejected */ emitConsoleCommand(command) { if (!this.allowConsoleCommands || !this._webRtcController.videoPlayer.isVideoReady()) { return false; } this._webRtcController.emitConsoleCommand(command); return true; } /** * Add a UE -> browser response event listener * @param name - The name of the response handler * @param listener - The method to be activated when a message is received */ addResponseEventListener(name, listener) { this._webRtcController.responseController.addResponseEventListener(name, listener); } /** * Remove a UE -> browser response event listener * @param name - The name of the response handler */ removeResponseEventListener(name) { this._webRtcController.responseController.removeResponseEventListener(name); } /** * Dispatch a new event. * @param e event * @returns */ dispatchEvent(e) { return this._eventEmitter.dispatchEvent(e); } /** * Register an event handler. * @param type event name * @param listener event handler function */ addEventListener(type, listener) { this._eventEmitter.addEventListener(type, listener); } /** * Remove an event handler. * @param type event name * @param listener event handler function */ removeEventListener(type, listener) { this._eventEmitter.removeEventListener(type, listener); } /** * Enable/disable XR mode. */ toggleXR() { this.webXrController.xrClicked(); } /** * Pass in a function to generate a signalling server URL. * This function is useful if you need to programmatically construct your signalling server URL. * @param signallingUrlBuilderFunc A function that generates a signalling server url. */ setSignallingUrlBuilder(signallingUrlBuilderFunc) { this._webRtcController.signallingUrlBuilder = signallingUrlBuilderFunc; } /** * Public getter for the websocket controller. Access to this property allows you to send * custom websocket messages. */ get webSocketController() { return this._webRtcController.webSocketController; } /** * Public getter for the webXrController controller. Used for all XR features. */ get webXrController() { return this._webXrController; } registerMessageHandler(name, direction, handler) { if (direction === _UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_8__.MessageDirection.FromStreamer && typeof handler === 'undefined') { _Logger_Logger__WEBPACK_IMPORTED_MODULE_5__.Logger.Warning(_Logger_Logger__WEBPACK_IMPORTED_MODULE_5__.Logger.GetStackTrace(), `Unable to register an undefined handler for ${name}`); return; } if (direction === _UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_8__.MessageDirection.ToStreamer && typeof handler === 'undefined') { this._webRtcController.streamMessageController.registerMessageHandler(direction, name, (data) => this._webRtcController.sendMessageController.sendMessageToStreamer(name, data)); } else { this._webRtcController.streamMessageController.registerMessageHandler(direction, name, (data) => handler(data)); } } get toStreamerHandlers() { return this._webRtcController.streamMessageController.toStreamerHandlers; } isReconnecting() { return this._webRtcController.isReconnecting; } } /***/ }), /***/ "./src/UI/OnScreenKeyboard.ts": /*!************************************!*\ !*** ./src/UI/OnScreenKeyboard.ts ***! \************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "OnScreenKeyboard": () => (/* binding */ OnScreenKeyboard) /* harmony export */ }); // Copyright Epic Games, Inc. All Rights Reserved. /** * Class for handling on screen keyboard usage */ class OnScreenKeyboard { /** * * @param videoElementParent The div element the video player is injected into */ constructor(videoElementParent) { this.editTextButton = null; this.hiddenInput = null; if ('ontouchstart' in document.documentElement) { this.createOnScreenKeyboardHelpers(videoElementParent); } } /** * An override for unquantizeAndDenormalizeUnsigned * @param x the x axis point * @param y the y axis point * @returns unquantizeAndDenormalizeUnsigned object */ // eslint-disable-next-line @typescript-eslint/no-unused-vars unquantizeAndDenormalizeUnsigned(x, y) { return null; } /** * Creates on screen keyboard helpers * @param videoElementParent The div element the video player i injected into */ createOnScreenKeyboardHelpers(videoElementParent) { if (!this.hiddenInput) { this.hiddenInput = document.createElement('input'); this.hiddenInput.id = 'hiddenInput'; this.hiddenInput.maxLength = 0; videoElementParent.appendChild(this.hiddenInput); } if (!this.editTextButton) { this.editTextButton = document.createElement('button'); this.editTextButton.id = 'editTextButton'; this.editTextButton.innerHTML = 'edit text'; videoElementParent.appendChild(this.editTextButton); // Hide the 'edit text' button. this.editTextButton.classList.add('hiddenState'); this.editTextButton.addEventListener('touchend', (event) => { // Show the on-screen keyboard. this.hiddenInput.focus(); event.preventDefault(); }); } } /** * Shows the on screen keyboard * @param command the command received via the data channel containing keyboard positions */ showOnScreenKeyboard(command) { if (command.showOnScreenKeyboard) { // Show the 'edit text' button. this.editTextButton.classList.remove('hiddenState'); // Place the 'edit text' button near the UE input widget. const pos = this.unquantizeAndDenormalizeUnsigned(command.x, command.y); this.editTextButton.style.top = pos.y.toString() + 'px'; this.editTextButton.style.left = (pos.x - 40).toString() + 'px'; } else { // Hide the 'edit text' button. this.editTextButton.classList.add('hiddenState'); // Hide the on-screen keyboard. this.hiddenInput.blur(); } } } /***/ }), /***/ "./src/UeInstanceMessage/ResponseController.ts": /*!*****************************************************!*\ !*** ./src/UeInstanceMessage/ResponseController.ts ***! \*****************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "ResponseController": () => (/* binding */ ResponseController) /* harmony export */ }); /* harmony import */ var _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Logger/Logger */ "./src/Logger/Logger.ts"); // Copyright Epic Games, Inc. All Rights Reserved. class ResponseController { constructor() { this.responseEventListeners = new Map(); } /** * Add a response event listener to the response map * @param name - The name of the response * @param listener - The method to be activated when the response is selected */ addResponseEventListener(name, listener) { this.responseEventListeners.set(name, listener); } /** * Remove a response event listener to the response map * @param name - The name of the response */ removeResponseEventListener(name) { this.responseEventListeners.delete(name); } /** * Handle a response when receiving one form the streamer * @param message - Data received from the data channel with the command in question */ onResponse(message) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), 'DataChannelReceiveMessageType.Response', 6); const responses = new TextDecoder('utf-16').decode(message.slice(1)); _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), responses, 6); this.responseEventListeners.forEach((listener) => { listener(responses); }); } } /***/ }), /***/ "./src/UeInstanceMessage/SendMessageController.ts": /*!********************************************************!*\ !*** ./src/UeInstanceMessage/SendMessageController.ts ***! \********************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "SendMessageController": () => (/* binding */ SendMessageController) /* harmony export */ }); /* harmony import */ var _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Logger/Logger */ "./src/Logger/Logger.ts"); // Copyright Epic Games, Inc. All Rights Reserved. class SendMessageController { /** * @param dataChannelSender - Data channel instance * @param toStreamerMessagesMapProvider - Stream Messages instance */ constructor(dataChannelSender, toStreamerMessagesMapProvider) { this.dataChannelSender = dataChannelSender; this.toStreamerMessagesMapProvider = toStreamerMessagesMapProvider; } /** * Send a message to the streamer through the data channel * @param messageType - the type of message we are sending * @param messageData - the message data we are sending over the data channel * @returns - nil */ sendMessageToStreamer(messageType, messageData) { if (messageData === undefined) { messageData = []; } const toStreamerMessages = this.toStreamerMessagesMapProvider.toStreamerMessages; const messageFormat = toStreamerMessages.get(messageType); if (messageFormat === undefined) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Error(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), `Attempted to send a message to the streamer with message type: ${messageType}, but the frontend hasn't been configured to send such a message. Check you've added the message type in your cpp`); return; } if (messageFormat.structure && messageData && messageFormat.structure.length !== messageData.length) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Error(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), `Provided message data doesn't match expected layout. Expected [ ${messageFormat.structure.map((element) => { switch (element) { case 'uint8': case 'uint16': case 'int16': case 'float': case 'double': return 'number'; case 'string': return 'string'; } }).toString()} ] but received [ ${messageData.map((element) => typeof element).toString()} ]`); return; } let byteLength = 0; const textEncoder = new TextEncoder(); // One loop to calculate the length in bytes of all of the provided data messageData.forEach((element, idx) => { const type = messageFormat.structure[idx]; switch (type) { case 'uint8': byteLength += 1; break; case 'uint16': byteLength += 2; break; case 'int16': byteLength += 2; break; case 'float': byteLength += 4; break; case 'double': byteLength += 8; break; case 'string': // 2 bytes for string length byteLength += 2; // 2 bytes per characters byteLength += 2 * textEncoder.encode(element).length; break; } }); const data = new DataView(new ArrayBuffer(byteLength + 1)); data.setUint8(0, messageFormat.id); let byteOffset = 1; messageData.forEach((element, idx) => { const type = messageFormat.structure[idx]; switch (type) { case 'uint8': data.setUint8(byteOffset, element); byteOffset += 1; break; case 'uint16': data.setUint16(byteOffset, element, true); byteOffset += 2; break; case 'int16': data.setInt16(byteOffset, element, true); byteOffset += 2; break; case 'float': data.setFloat32(byteOffset, element, true); byteOffset += 4; break; case 'double': data.setFloat64(byteOffset, element, true); byteOffset += 8; break; case 'string': data.setUint16(byteOffset, element.length, true); byteOffset += 2; for (let i = 0; i < element.length; i++) { data.setUint16(byteOffset, element.charCodeAt(i), true); byteOffset += 2; } break; } }); if (!this.dataChannelSender.canSend()) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Info(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), `Data channel cannot send yet, skipping sending message: ${messageType} - ${new Uint8Array(data.buffer)}`); return; } this.dataChannelSender.sendData(data.buffer); } } /***/ }), /***/ "./src/UeInstanceMessage/StreamMessageController.ts": /*!**********************************************************!*\ !*** ./src/UeInstanceMessage/StreamMessageController.ts ***! \**********************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "MessageDirection": () => (/* binding */ MessageDirection), /* harmony export */ "StreamMessageController": () => (/* binding */ StreamMessageController), /* harmony export */ "ToStreamerMessage": () => (/* binding */ ToStreamerMessage) /* harmony export */ }); /* harmony import */ var _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Logger/Logger */ "./src/Logger/Logger.ts"); // Copyright Epic Games, Inc. All Rights Reserved. class ToStreamerMessage { } class StreamMessageController { constructor() { this.toStreamerHandlers = new Map(); this.fromStreamerHandlers = new Map(); this.toStreamerMessages = new Map(); this.fromStreamerMessages = new Map(); } /** * Populate the Default message protocol */ populateDefaultProtocol() { /* * Control Messages. Range = 0..49. */ this.toStreamerMessages.set('IFrameRequest', { id: 0, structure: [] }); this.toStreamerMessages.set('RequestQualityControl', { id: 1, structure: [] }); this.toStreamerMessages.set('FpsRequest', { id: 2, structure: [] }); this.toStreamerMessages.set('AverageBitrateRequest', { id: 3, structure: [] }); this.toStreamerMessages.set('StartStreaming', { id: 4, structure: [] }); this.toStreamerMessages.set('StopStreaming', { id: 5, structure: [] }); this.toStreamerMessages.set('LatencyTest', { id: 6, structure: ['string'] }); this.toStreamerMessages.set('RequestInitialSettings', { id: 7, structure: [] }); this.toStreamerMessages.set('TestEcho', { id: 8, structure: [] }); this.toStreamerMessages.set('DataChannelLatencyTest', { id: 9, structure: [] }); /* * Input Messages. Range = 50..89. */ // Generic Input Messages. Range = 50..59. this.toStreamerMessages.set('UIInteraction', { id: 50, structure: ['string'] }); this.toStreamerMessages.set('Command', { id: 51, structure: ['string'] }); // Keyboard Input Message. Range = 60..69. this.toStreamerMessages.set('KeyDown', { id: 60, // keyCode isRepeat structure: ['uint8', 'uint8'] }); this.toStreamerMessages.set('KeyUp', { id: 61, // keyCode structure: ['uint8'] }); this.toStreamerMessages.set('KeyPress', { id: 62, // charcode structure: ['uint16'] }); // Mouse Input Messages. Range = 70..79. this.toStreamerMessages.set('MouseEnter', { id: 70, structure: [] }); this.toStreamerMessages.set('MouseLeave', { id: 71, structure: [] }); this.toStreamerMessages.set('MouseDown', { id: 72, // button x y structure: ['uint8', 'uint16', 'uint16'] }); this.toStreamerMessages.set('MouseUp', { id: 73, // button x y structure: ['uint8', 'uint16', 'uint16'] }); this.toStreamerMessages.set('MouseMove', { id: 74, // x y deltaX deltaY structure: ['uint16', 'uint16', 'int16', 'int16'] }); this.toStreamerMessages.set('MouseWheel', { id: 75, // delta x y structure: ['int16', 'uint16', 'uint16'] }); this.toStreamerMessages.set('MouseDouble', { id: 76, // button x y structure: ['uint8', 'uint16', 'uint16'] }); // Touch Input Messages. Range = 80..89. this.toStreamerMessages.set('TouchStart', { id: 80, // numtouches(1) x y idx force valid structure: ['uint8', 'uint16', 'uint16', 'uint8', 'uint8', 'uint8'] }); this.toStreamerMessages.set('TouchEnd', { id: 81, // numtouches(1) x y idx force valid structure: ['uint8', 'uint16', 'uint16', 'uint8', 'uint8', 'uint8'] }); this.toStreamerMessages.set('TouchMove', { id: 82, // numtouches(1) x y idx force valid structure: ['uint8', 'uint16', 'uint16', 'uint8', 'uint8', 'uint8'] }); // Gamepad Input Messages. Range = 90..99 this.toStreamerMessages.set('GamepadConnected', { id: 93, structure: [] }); this.toStreamerMessages.set('GamepadButtonPressed', { id: 90, // ctrlerId button isRepeat structure: ['uint8', 'uint8', 'uint8'] }); this.toStreamerMessages.set('GamepadButtonReleased', { id: 91, // ctrlerId button isRepeat(0) structure: ['uint8', 'uint8', 'uint8'] }); this.toStreamerMessages.set('GamepadAnalog', { id: 92, // ctrlerId button analogValue structure: ['uint8', 'uint8', 'double'] }); this.toStreamerMessages.set('GamepadDisconnected', { id: 94, // ctrlerId structure: ['uint8'] }); this.fromStreamerMessages.set(0, 'QualityControlOwnership'); this.fromStreamerMessages.set(1, 'Response'); this.fromStreamerMessages.set(2, 'Command'); this.fromStreamerMessages.set(3, 'FreezeFrame'); this.fromStreamerMessages.set(4, 'UnfreezeFrame'); this.fromStreamerMessages.set(5, 'VideoEncoderAvgQP'); this.fromStreamerMessages.set(6, 'LatencyTest'); this.fromStreamerMessages.set(7, 'InitialSettings'); this.fromStreamerMessages.set(8, 'FileExtension'); this.fromStreamerMessages.set(9, 'FileMimeType'); this.fromStreamerMessages.set(10, 'FileContents'); this.fromStreamerMessages.set(11, 'TestEcho'); this.fromStreamerMessages.set(12, 'InputControlOwnership'); this.fromStreamerMessages.set(13, 'GamepadResponse'); this.fromStreamerMessages.set(14, 'DataChannelLatencyTest'); this.fromStreamerMessages.set(255, 'Protocol'); } /** * Register a message handler * @param messageDirection - the direction of the message; toStreamer or fromStreamer * @param messageType - the type of the message * @param messageHandler - the function or method to be executed when this handler is called */ registerMessageHandler(messageDirection, messageType, messageHandler) { switch (messageDirection) { case MessageDirection.ToStreamer: this.toStreamerHandlers.set(messageType, messageHandler); break; case MessageDirection.FromStreamer: this.fromStreamerHandlers.set(messageType, messageHandler); break; default: _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), `Unknown message direction ${messageDirection}`); } } } /** * The enum for message directions */ var MessageDirection; (function (MessageDirection) { MessageDirection[MessageDirection["ToStreamer"] = 0] = "ToStreamer"; MessageDirection[MessageDirection["FromStreamer"] = 1] = "FromStreamer"; })(MessageDirection || (MessageDirection = {})); /***/ }), /***/ "./src/UeInstanceMessage/ToStreamerMessagesController.ts": /*!***************************************************************!*\ !*** ./src/UeInstanceMessage/ToStreamerMessagesController.ts ***! \***************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "ToStreamerMessagesController": () => (/* binding */ ToStreamerMessagesController) /* harmony export */ }); // Copyright Epic Games, Inc. All Rights Reserved. class ToStreamerMessagesController { /** * @param sendMessageController - Stream message controller instance */ constructor(sendMessageController) { this.sendMessageController = sendMessageController; } /** * Send Request to Take Quality Control to the UE Instance */ SendRequestQualityControl() { this.sendMessageController.sendMessageToStreamer('RequestQualityControl'); } /** * Send Max FPS Request to the UE Instance */ SendMaxFpsRequest() { this.sendMessageController.sendMessageToStreamer('FpsRequest'); } /** * Send Average Bitrate Request to the UE Instance */ SendAverageBitrateRequest() { this.sendMessageController.sendMessageToStreamer('AverageBitrateRequest'); } /** * Send a Start Streaming Message to the UE Instance */ SendStartStreaming() { this.sendMessageController.sendMessageToStreamer('StartStreaming'); } /** * Send a Stop Streaming Message to the UE Instance */ SendStopStreaming() { this.sendMessageController.sendMessageToStreamer('StopStreaming'); } /** * Send a Request Initial Settings to the UE Instance */ SendRequestInitialSettings() { this.sendMessageController.sendMessageToStreamer('RequestInitialSettings'); } } /***/ }), /***/ "./src/Util/CoordinateConverter.ts": /*!*****************************************!*\ !*** ./src/Util/CoordinateConverter.ts ***! \*****************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "CoordinateConverter": () => (/* binding */ CoordinateConverter), /* harmony export */ "NormalizedQuantizedSignedCoord": () => (/* binding */ NormalizedQuantizedSignedCoord), /* harmony export */ "NormalizedQuantizedUnsignedCoord": () => (/* binding */ NormalizedQuantizedUnsignedCoord), /* harmony export */ "UnquantizedDenormalizedUnsignedCoord": () => (/* binding */ UnquantizedDenormalizedUnsignedCoord) /* harmony export */ }); /* harmony import */ var _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Logger/Logger */ "./src/Logger/Logger.ts"); // Copyright Epic Games, Inc. All Rights Reserved. /** * Converts coordinates from element relative coordinates to values normalized within the value range of a short (and back again) */ class CoordinateConverter { /** * @param videoElementProvider - the div element that the video player will be injected into */ constructor(videoElementProvider) { this.videoElementProvider = videoElementProvider; this.normalizeAndQuantizeUnsignedFunc = () => { throw new Error('Normalize and quantize unsigned, method not implemented.'); }; this.normalizeAndQuantizeSignedFunc = () => { throw new Error('Normalize and unquantize signed, method not implemented.'); }; this.denormalizeAndUnquantizeUnsignedFunc = () => { throw new Error('Denormalize and unquantize unsigned, method not implemented.'); }; } /** * The surface method for setterNormalizeAndQuantizeUnsigned * @param x - x axis point * @param y - y axis point */ normalizeAndQuantizeUnsigned(x, y) { return this.normalizeAndQuantizeUnsignedFunc(x, y); } /** * The surface method for setterUnquantizeAndDenormalizeUnsigned * @param x - x axis point * @param y - y axis point */ unquantizeAndDenormalizeUnsigned(x, y) { return this.denormalizeAndUnquantizeUnsignedFunc(x, y); } /** * The surface method for setterNormalizeAndQuantizeSigned * @param x - x axis point * @param y - y axis point */ normalizeAndQuantizeSigned(x, y) { return this.normalizeAndQuantizeSignedFunc(x, y); } /** * set up the Normalize And Quantize methods based on the aspect ratio and the video player ratio */ setupNormalizeAndQuantize() { this.videoElementParent = this.videoElementProvider.getVideoParentElement(); this.videoElement = this.videoElementProvider.getVideoElement(); if (this.videoElementParent && this.videoElement) { const playerAspectRatio = this.videoElementParent.clientHeight / this.videoElementParent.clientWidth; const videoAspectRatio = this.videoElement.videoHeight / this.videoElement.videoWidth; if (playerAspectRatio > videoAspectRatio) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), 'Setup Normalize and Quantize for playerAspectRatio > videoAspectRatio', 6); this.ratio = playerAspectRatio / videoAspectRatio; this.normalizeAndQuantizeUnsignedFunc = (x, y) => this.normalizeAndQuantizeUnsignedPlayerBigger(x, y); this.normalizeAndQuantizeSignedFunc = (x, y) => this.normalizeAndQuantizeSignedPlayerBigger(x, y); this.denormalizeAndUnquantizeUnsignedFunc = (x, y) => this.denormalizeAndUnquantizeUnsignedPlayerBigger(x, y); } else { _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), 'Setup Normalize and Quantize for playerAspectRatio <= videoAspectRatio', 6); this.ratio = videoAspectRatio / playerAspectRatio; this.normalizeAndQuantizeUnsignedFunc = (x, y) => this.normalizeAndQuantizeUnsignedPlayerSmaller(x, y); this.normalizeAndQuantizeSignedFunc = (x, y) => this.normalizeAndQuantizeSignedPlayerSmaller(x, y); this.denormalizeAndUnquantizeUnsignedFunc = (x, y) => this.denormalizeAndUnquantizeUnsignedPlayerSmaller(x, y); } } } /** * normalizeAndQuantizeUnsigned for playerAspectRatio > videoAspectRatio * @param x - x axis point * @param y - y axis point */ normalizeAndQuantizeUnsignedPlayerBigger(x, y) { const normalizedX = x / this.videoElementParent.clientWidth; const normalizedY = this.ratio * (y / this.videoElementParent.clientHeight - 0.5) + 0.5; if (normalizedX < 0.0 || normalizedX > 1.0 || normalizedY < 0.0 || normalizedY > 1.0) { return new NormalizedQuantizedUnsignedCoord(false, 65535, 65535); } else { return new NormalizedQuantizedUnsignedCoord(true, normalizedX * 65536, normalizedY * 65536); } } /** * unquantizeAndDenormalizeUnsigned for playerAspectRatio > videoAspectRatio * @param x - x axis point * @param y - y axis point */ denormalizeAndUnquantizeUnsignedPlayerBigger(x, y) { const normalizedX = x / 65536; const normalizedY = (y / 65536 - 0.5) / this.ratio + 0.5; return new UnquantizedDenormalizedUnsignedCoord(normalizedX * this.videoElementParent.clientWidth, normalizedY * this.videoElementParent.clientHeight); } /** * normalizeAndQuantizeSigned for playerAspectRatio > videoAspectRatio * @param x - x axis point * @param y - y axis point */ normalizeAndQuantizeSignedPlayerBigger(x, y) { const normalizedX = x / (0.5 * this.videoElementParent.clientWidth); const normalizedY = (this.ratio * y) / (0.5 * this.videoElementParent.clientHeight); return new NormalizedQuantizedSignedCoord(normalizedX * 32767, normalizedY * 32767); } /** * normalizeAndQuantizeUnsigned for playerAspectRatio <= videoAspectRatio * @param x - x axis point * @param y - y axis point */ normalizeAndQuantizeUnsignedPlayerSmaller(x, y) { const normalizedX = this.ratio * (x / this.videoElementParent.clientWidth - 0.5) + 0.5; const normalizedY = y / this.videoElementParent.clientHeight; if (normalizedX < 0.0 || normalizedX > 1.0 || normalizedY < 0.0 || normalizedY > 1.0) { return new NormalizedQuantizedUnsignedCoord(false, 65535, 65535); } else { return new NormalizedQuantizedUnsignedCoord(true, normalizedX * 65536, normalizedY * 65536); } } /** * unquantizeAndDenormalizeUnsigned for playerAspectRatio <= videoAspectRatio * @param x - x axis point * @param y - y axis point */ denormalizeAndUnquantizeUnsignedPlayerSmaller(x, y) { const normalizedX = (x / 65536 - 0.5) / this.ratio + 0.5; const normalizedY = y / 65536; return new UnquantizedDenormalizedUnsignedCoord(normalizedX * this.videoElementParent.clientWidth, normalizedY * this.videoElementParent.clientHeight); } /** * normalizeAndQuantizeSigned for playerAspectRatio <= videoAspectRatio * @param x - x axis point * @param y - y axis point */ normalizeAndQuantizeSignedPlayerSmaller(x, y) { const normalizedX = (this.ratio * x) / (0.5 * this.videoElementParent.clientWidth); const normalizedY = y / (0.5 * this.videoElementParent.clientHeight); return new NormalizedQuantizedSignedCoord(normalizedX * 32767, normalizedY * 32767); } } /** * A class for NormalizeAndQuantizeUnsigned objects */ class NormalizedQuantizedUnsignedCoord { constructor(inRange, x, y) { this.inRange = inRange; this.x = x; this.y = y; } } /** * A class for UnquantizedAndDenormalizeUnsigned objects */ class UnquantizedDenormalizedUnsignedCoord { constructor(x, y) { this.x = x; this.y = y; } } /** * A class for NormalizedQuantizedSignedCoord objects */ class NormalizedQuantizedSignedCoord { constructor(x, y) { this.x = x; this.y = y; } } /***/ }), /***/ "./src/Util/EventEmitter.ts": /*!**********************************!*\ !*** ./src/Util/EventEmitter.ts ***! \**********************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "AfkTimedOutEvent": () => (/* binding */ AfkTimedOutEvent), /* harmony export */ "AfkWarningActivateEvent": () => (/* binding */ AfkWarningActivateEvent), /* harmony export */ "AfkWarningDeactivateEvent": () => (/* binding */ AfkWarningDeactivateEvent), /* harmony export */ "AfkWarningUpdateEvent": () => (/* binding */ AfkWarningUpdateEvent), /* harmony export */ "DataChannelCloseEvent": () => (/* binding */ DataChannelCloseEvent), /* harmony export */ "DataChannelErrorEvent": () => (/* binding */ DataChannelErrorEvent), /* harmony export */ "DataChannelLatencyTestResponseEvent": () => (/* binding */ DataChannelLatencyTestResponseEvent), /* harmony export */ "DataChannelLatencyTestResultEvent": () => (/* binding */ DataChannelLatencyTestResultEvent), /* harmony export */ "DataChannelOpenEvent": () => (/* binding */ DataChannelOpenEvent), /* harmony export */ "EventEmitter": () => (/* binding */ EventEmitter), /* harmony export */ "HideFreezeFrameEvent": () => (/* binding */ HideFreezeFrameEvent), /* harmony export */ "InitialSettingsEvent": () => (/* binding */ InitialSettingsEvent), /* harmony export */ "LatencyTestResultEvent": () => (/* binding */ LatencyTestResultEvent), /* harmony export */ "LoadFreezeFrameEvent": () => (/* binding */ LoadFreezeFrameEvent), /* harmony export */ "PlayStreamErrorEvent": () => (/* binding */ PlayStreamErrorEvent), /* harmony export */ "PlayStreamEvent": () => (/* binding */ PlayStreamEvent), /* harmony export */ "PlayStreamRejectedEvent": () => (/* binding */ PlayStreamRejectedEvent), /* harmony export */ "PlayerCountEvent": () => (/* binding */ PlayerCountEvent), /* harmony export */ "SettingsChangedEvent": () => (/* binding */ SettingsChangedEvent), /* harmony export */ "StatsReceivedEvent": () => (/* binding */ StatsReceivedEvent), /* harmony export */ "StreamLoadingEvent": () => (/* binding */ StreamLoadingEvent), /* harmony export */ "StreamPreConnectEvent": () => (/* binding */ StreamPreConnectEvent), /* harmony export */ "StreamPreDisconnectEvent": () => (/* binding */ StreamPreDisconnectEvent), /* harmony export */ "StreamReconnectEvent": () => (/* binding */ StreamReconnectEvent), /* harmony export */ "StreamerListMessageEvent": () => (/* binding */ StreamerListMessageEvent), /* harmony export */ "VideoEncoderAvgQPEvent": () => (/* binding */ VideoEncoderAvgQPEvent), /* harmony export */ "VideoInitializedEvent": () => (/* binding */ VideoInitializedEvent), /* harmony export */ "WebRtcAutoConnectEvent": () => (/* binding */ WebRtcAutoConnectEvent), /* harmony export */ "WebRtcConnectedEvent": () => (/* binding */ WebRtcConnectedEvent), /* harmony export */ "WebRtcConnectingEvent": () => (/* binding */ WebRtcConnectingEvent), /* harmony export */ "WebRtcDisconnectedEvent": () => (/* binding */ WebRtcDisconnectedEvent), /* harmony export */ "WebRtcFailedEvent": () => (/* binding */ WebRtcFailedEvent), /* harmony export */ "WebRtcSdpEvent": () => (/* binding */ WebRtcSdpEvent), /* harmony export */ "XrFrameEvent": () => (/* binding */ XrFrameEvent), /* harmony export */ "XrSessionEndedEvent": () => (/* binding */ XrSessionEndedEvent), /* harmony export */ "XrSessionStartedEvent": () => (/* binding */ XrSessionStartedEvent) /* harmony export */ }); /** * An event that is emitted when AFK disconnect is about to happen. * Can be cancelled by calling the callback function provided as part of the event. */ class AfkWarningActivateEvent extends Event { constructor(data) { super('afkWarningActivate'); this.data = data; } } /** * An event that is emitted when the AFK disconnect countdown is updated. */ class AfkWarningUpdateEvent extends Event { constructor(data) { super('afkWarningUpdate'); this.data = data; } } /** * An event that is emitted when AFK warning is deactivated. */ class AfkWarningDeactivateEvent extends Event { constructor() { super('afkWarningDeactivate'); } } /** * An event that is emitted when AFK countdown reaches 0 and the user is disconnected. */ class AfkTimedOutEvent extends Event { constructor() { super('afkTimedOut'); } } /** * An event that is emitted when we receive new video quality value. */ class VideoEncoderAvgQPEvent extends Event { constructor(data) { super('videoEncoderAvgQP'); this.data = data; } } /** * An event that is emitted after a WebRtc connection has been negotiated. */ class WebRtcSdpEvent extends Event { constructor() { super('webRtcSdp'); } } /** * An event that is emitted when auto connecting. */ class WebRtcAutoConnectEvent extends Event { constructor() { super('webRtcAutoConnect'); } } /** * An event that is emitted when sending a WebRtc offer. */ class WebRtcConnectingEvent extends Event { constructor() { super('webRtcConnecting'); } } /** * An event that is emitted when WebRtc connection has been established. */ class WebRtcConnectedEvent extends Event { constructor() { super('webRtcConnected'); } } /** * An event that is emitted if WebRtc connection has failed. */ class WebRtcFailedEvent extends Event { constructor() { super('webRtcFailed'); } } /** * An event that is emitted if WebRtc connection is disconnected. */ class WebRtcDisconnectedEvent extends Event { constructor(data) { super('webRtcDisconnected'); this.data = data; } } /** * An event that is emitted when RTCDataChannel is opened. */ class DataChannelOpenEvent extends Event { constructor(data) { super('dataChannelOpen'); this.data = data; } } /** * An event that is emitted when RTCDataChannel is closed. */ class DataChannelCloseEvent extends Event { constructor(data) { super('dataChannelClose'); this.data = data; } } /** * An event that is emitted on RTCDataChannel errors. */ class DataChannelErrorEvent extends Event { constructor(data) { super('dataChannelError'); this.data = data; } } /** * An event that is emitted when the video stream has been initialized. */ class VideoInitializedEvent extends Event { constructor() { super('videoInitialized'); } } /** * An event that is emitted when video stream loading starts. */ class StreamLoadingEvent extends Event { constructor() { super('streamLoading'); } } /** * An event that is emitted when video stream loading has finished. */ class StreamPreConnectEvent extends Event { constructor() { super('streamConnect'); } } /** * An event that is emitted when video stream has stopped. */ class StreamPreDisconnectEvent extends Event { constructor() { super('streamDisconnect'); } } /** * An event that is emitted when video stream is reconnecting. */ class StreamReconnectEvent extends Event { constructor() { super('streamReconnect'); } } /** * An event that is emitted if there are errors loading the video stream. */ class PlayStreamErrorEvent extends Event { constructor(data) { super('playStreamError'); this.data = data; } } /** * An event that is emitted before trying to start video playback. */ class PlayStreamEvent extends Event { constructor() { super('playStream'); } } /** * An event that is emitted if the browser rejects video playback. Can happen for example if * video auto-play without user interaction is refused by the browser. */ class PlayStreamRejectedEvent extends Event { constructor(data) { super('playStreamRejected'); this.data = data; } } /** * An event that is emitted when receiving a full FreezeFrame image from UE. */ class LoadFreezeFrameEvent extends Event { constructor(data) { super('loadFreezeFrame'); this.data = data; } } /** * An event that is emitted when receiving UnfreezeFrame message from UE and video playback is about to be resumed. */ class HideFreezeFrameEvent extends Event { constructor() { super('hideFreezeFrame'); } } /** * An event that is emitted when receiving WebRTC statistics. */ class StatsReceivedEvent extends Event { constructor(data) { super('statsReceived'); this.data = data; } } /** * An event that is emitted when streamer list changes. */ class StreamerListMessageEvent extends Event { constructor(data) { super('streamerListMessage'); this.data = data; } } /** * An event that is emitted when receiving latency test results. */ class LatencyTestResultEvent extends Event { constructor(data) { super('latencyTestResult'); this.data = data; } } /** * An event that is emitted when receiving data channel latency test response from server. * This event is handled by DataChannelLatencyTestController */ class DataChannelLatencyTestResponseEvent extends Event { constructor(data) { super('dataChannelLatencyTestResponse'); this.data = data; } } /** * An event that is emitted when data channel latency test results are ready. */ class DataChannelLatencyTestResultEvent extends Event { constructor(data) { super('dataChannelLatencyTestResult'); this.data = data; } } /** * An event that is emitted when receiving initial settings from UE. */ class InitialSettingsEvent extends Event { constructor(data) { super('initialSettings'); this.data = data; } } /** * An event that is emitted when PixelStreaming settings change. */ class SettingsChangedEvent extends Event { constructor(data) { super('settingsChanged'); this.data = data; } } /** * Event emitted when an XR Session starts */ class XrSessionStartedEvent extends Event { constructor() { super('xrSessionStarted'); } } /** * Event emitted when an XR Session ends */ class XrSessionEndedEvent extends Event { constructor() { super('xrSessionEnded'); } } /** * Event emitted when an XR Frame is complete */ class XrFrameEvent extends Event { constructor(data) { super('xrFrame'); this.data = data; } } /** * An event that is emitted when receiving a player count from the signalling server */ class PlayerCountEvent extends Event { constructor(data) { super('playerCount'); this.data = data; } } class EventEmitter extends EventTarget { /** * Dispatch a new event. * @param e event * @returns */ dispatchEvent(e) { return super.dispatchEvent(e); } /** * Register an event handler. * @param type event name * @param listener event handler function */ addEventListener(type, listener) { super.addEventListener(type, listener); } /** * Remove an event handler. * @param type event name * @param listener event handler function */ removeEventListener(type, listener) { super.removeEventListener(type, listener); } } /***/ }), /***/ "./src/Util/EventListenerTracker.ts": /*!******************************************!*\ !*** ./src/Util/EventListenerTracker.ts ***! \******************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "EventListenerTracker": () => (/* binding */ EventListenerTracker) /* harmony export */ }); // Copyright Epic Games, Inc. All Rights Reserved. class EventListenerTracker { constructor() { this.unregisterCallbacks = []; } /** * Add a new callback that is executed when unregisterAll is called. * @param callback */ addUnregisterCallback(callback) { this.unregisterCallbacks.push(callback); } /** * Execute all callbacks and clear the list. */ unregisterAll() { for (const callback of this.unregisterCallbacks) { callback(); } this.unregisterCallbacks = []; } } /***/ }), /***/ "./src/Util/FileUtil.ts": /*!******************************!*\ !*** ./src/Util/FileUtil.ts ***! \******************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "FileTemplate": () => (/* binding */ FileTemplate), /* harmony export */ "FileUtil": () => (/* binding */ FileUtil) /* harmony export */ }); /* harmony import */ var _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Logger/Logger */ "./src/Logger/Logger.ts"); // Copyright Epic Games, Inc. All Rights Reserved. /** * Utility function for populate file information from byte buffers. */ class FileUtil { /** * Processes a files extension when received over data channel * @param view - the file extension data */ static setExtensionFromBytes(view, file) { // Reset file if we got a file message and we are not "receiving" it yet if (!file.receiving) { file.mimetype = ''; file.extension = ''; file.receiving = true; file.valid = false; file.size = 0; file.data = []; file.timestampStart = new Date().getTime(); _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), 'Received first chunk of file', 6); } const extensionAsString = new TextDecoder('utf-16').decode(view.slice(1)); _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), extensionAsString, 6); file.extension = extensionAsString; } /** * Processes a files mime type when received over data channel * @param view - the file mime type data */ static setMimeTypeFromBytes(view, file) { // Reset file if we got a file message and we are not "receiving" it yet if (!file.receiving) { file.mimetype = ''; file.extension = ''; file.receiving = true; file.valid = false; file.size = 0; file.data = []; file.timestampStart = new Date().getTime(); _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), 'Received first chunk of file', 6); } const mimeAsString = new TextDecoder('utf-16').decode(view.slice(1)); _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), mimeAsString, 6); file.mimetype = mimeAsString; } /** * Processes a files contents when received over data channel * @param view - the file contents data */ static setContentsFromBytes(view, file) { // If we haven't received the initial setup instructions, return if (!file.receiving) return; // Extract the total size of the file (across all chunks) file.size = Math.ceil(new DataView(view.slice(1, 5).buffer).getInt32(0, true) / 16379 /* The maximum number of payload bits per message*/); // Get the file part of the payload const fileBytes = view.slice(1 + 4); // Append to existing data that holds the file file.data.push(fileBytes); // Uncomment for debug _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), `Received file chunk: ${file.data.length}/${file.size}`, 6); if (file.data.length === file.size) { file.receiving = false; file.valid = true; _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), 'Received complete file', 6); const transferDuration = new Date().getTime() - file.timestampStart; const transferBitrate = Math.round((file.size * 16 * 1024) / transferDuration); _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), `Average transfer bitrate: ${transferBitrate}kb/s over ${transferDuration / 1000} seconds`, 6); // File reconstruction /** * Example code to reconstruct the file * * This code reconstructs the received data into the original file based on the mime type and extension provided and then downloads the reconstructed file */ const received = new Blob(file.data, { type: file.mimetype }); const a = document.createElement('a'); a.setAttribute('href', URL.createObjectURL(received)); a.setAttribute('download', `transfer.${file.extension}`); document.body.append(a); // if you are so inclined to make it auto-download, do something like: a.click(); a.remove(); } else if (file.data.length > file.size) { file.receiving = false; _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Error(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), `Received bigger file than advertised: ${file.data.length}/${file.size}`); } } } /** * A class that represents a template for a downloaded file */ class FileTemplate { constructor() { this.mimetype = ''; this.extension = ''; this.receiving = false; this.size = 0; this.data = []; this.valid = false; } } /***/ }), /***/ "./src/Util/RTCUtils.ts": /*!******************************!*\ !*** ./src/Util/RTCUtils.ts ***! \******************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "RTCUtils": () => (/* binding */ RTCUtils) /* harmony export */ }); class RTCUtils { static isVideoTransciever(transceiver) { return this.canTransceiverReceiveVideo(transceiver) || this.canTransceiverSendVideo(transceiver); } static canTransceiverReceiveVideo(transceiver) { return !!transceiver && (transceiver.direction === 'sendrecv' || transceiver.direction === 'recvonly') && transceiver.receiver && transceiver.receiver.track && transceiver.receiver.track.kind === 'video'; } static canTransceiverSendVideo(transceiver) { return !!transceiver && (transceiver.direction === 'sendrecv' || transceiver.direction === 'sendonly') && transceiver.sender && transceiver.sender.track && transceiver.sender.track.kind === 'video'; } static isAudioTransciever(transceiver) { return this.canTransceiverReceiveAudio(transceiver) || this.canTransceiverSendAudio(transceiver); } static canTransceiverReceiveAudio(transceiver) { return !!transceiver && (transceiver.direction === 'sendrecv' || transceiver.direction === 'recvonly') && transceiver.receiver && transceiver.receiver.track && transceiver.receiver.track.kind === 'audio'; } static canTransceiverSendAudio(transceiver) { return !!transceiver && (transceiver.direction === 'sendrecv' || transceiver.direction === 'sendonly') && transceiver.sender && transceiver.sender.track && transceiver.sender.track.kind === 'audio'; } } /***/ }), /***/ "./src/Util/WebGLUtils.ts": /*!********************************!*\ !*** ./src/Util/WebGLUtils.ts ***! \********************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "WebGLUtils": () => (/* binding */ WebGLUtils) /* harmony export */ }); // Copyright Epic Games, Inc. All Rights Reserved. class WebGLUtils { static vertexShader() { return ` attribute vec2 a_position; attribute vec2 a_texCoord; // input uniform vec2 u_resolution; uniform vec4 u_offset; // varying vec2 v_texCoord; void main() { // convert the rectangle from pixels to 0.0 to 1.0 vec2 zeroToOne = a_position / u_resolution; // convert from 0->1 to 0->2 vec2 zeroToTwo = zeroToOne * 2.0; // convert from 0->2 to -1->+1 (clipspace) vec2 clipSpace = zeroToTwo - 1.0; gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1); // pass the texCoord to the fragment shader // The GPU will interpolate this value between points. v_texCoord = (a_texCoord * u_offset.xy) + u_offset.zw; } `; } static fragmentShader() { return ` precision mediump float; // our texture uniform sampler2D u_image; // the texCoords passed in from the vertex shader. varying vec2 v_texCoord; void main() { gl_FragColor = texture2D(u_image, v_texCoord); } `; } } /***/ }), /***/ "./src/Util/WebXRUtils.ts": /*!********************************!*\ !*** ./src/Util/WebXRUtils.ts ***! \********************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "WebXRUtils": () => (/* binding */ WebXRUtils) /* harmony export */ }); // Copyright Epic Games, Inc. All Rights Reserved. class WebXRUtils { /** * Deep copies a gamepad's values by first converting it to a JSON object and then back to a gamepad * * @param gamepad the original gamepad * @returns a new gamepad object, populated with the original gamepads values */ static deepCopyGamepad(gamepad) { return JSON.parse(JSON.stringify({ buttons: gamepad.buttons.map((b) => JSON.parse(JSON.stringify({ pressed: b.pressed, touched: b.touched }))), axes: gamepad.axes })); } } /***/ }), /***/ "./src/VideoPlayer/StreamController.ts": /*!*********************************************!*\ !*** ./src/VideoPlayer/StreamController.ts ***! \*********************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "StreamController": () => (/* binding */ StreamController) /* harmony export */ }); /* harmony import */ var _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Logger/Logger */ "./src/Logger/Logger.ts"); // Copyright Epic Games, Inc. All Rights Reserved. /** * Video Player Controller handles the creation of the video HTML element and all handlers */ class StreamController { /** * @param videoElementProvider Video Player instance */ constructor(videoElementProvider) { this.videoElementProvider = videoElementProvider; this.audioElement = document.createElement('Audio'); this.videoElementProvider.setAudioElement(this.audioElement); } /** * Handles when the Peer connection has a track event * @param rtcTrackEvent - RTC Track Event */ handleOnTrack(rtcTrackEvent) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), 'handleOnTrack ' + JSON.stringify(rtcTrackEvent.streams), 6); const videoElement = this.videoElementProvider.getVideoElement(); if (rtcTrackEvent.track) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), 'Got track - ' + rtcTrackEvent.track.kind + ' id=' + rtcTrackEvent.track.id + ' readyState=' + rtcTrackEvent.track.readyState, 6); } if (rtcTrackEvent.track.kind == 'audio') { this.CreateAudioTrack(rtcTrackEvent.streams[0]); return; } else if (rtcTrackEvent.track.kind == 'video' && videoElement.srcObject !== rtcTrackEvent.streams[0]) { videoElement.srcObject = rtcTrackEvent.streams[0]; _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), 'Set video source from video track ontrack.'); return; } } /** * Creates the audio device when receiving an RTCTrackEvent with the kind of "audio" * @param audioMediaStream - Audio Media stream track */ CreateAudioTrack(audioMediaStream) { const videoElement = this.videoElementProvider.getVideoElement(); // do nothing the video has the same media stream as the audio track we have here (they are linked) if (videoElement.srcObject == audioMediaStream) { return; } // video element has some other media stream that is not associated with this audio track else if (videoElement.srcObject && videoElement.srcObject !== audioMediaStream) { // create a new audio element this.audioElement.srcObject = audioMediaStream; _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), 'Created new audio element to play separate audio stream.'); } } } /***/ }), /***/ "./src/VideoPlayer/VideoPlayer.ts": /*!****************************************!*\ !*** ./src/VideoPlayer/VideoPlayer.ts ***! \****************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "VideoPlayer": () => (/* binding */ VideoPlayer) /* harmony export */ }); /* harmony import */ var _Config_Config__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Config/Config */ "./src/Config/Config.ts"); /* harmony import */ var _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Logger/Logger */ "./src/Logger/Logger.ts"); // Copyright Epic Games, Inc. All Rights Reserved. /** * The video player html element */ class VideoPlayer { /** * @param videoElementParent the html div the the video player will be injected into * @param config the applications configuration. We're interested in the startVideoMuted flag */ constructor(videoElementParent, config) { this.lastTimeResized = new Date().getTime(); this.videoElement = document.createElement('video'); this.config = config; this.videoElement.id = 'streamingVideo'; this.videoElement.disablePictureInPicture = true; // this.videoElement.playsInline = true; this.videoElement.style.width = '100%'; this.videoElement.style.height = '100%'; this.videoElement.style.position = 'absolute'; this.videoElement.style.pointerEvents = 'all'; videoElementParent.appendChild(this.videoElement); this.onResizePlayerCallback = () => { console.log('Resolution changed, restyling player, did you forget to override this function?'); }; this.onMatchViewportResolutionCallback = () => { console.log('Resolution changed and match viewport resolution is turned on, did you forget to override this function?'); }; // set play for video (and audio) this.videoElement.onclick = () => { if (this.audioElement != undefined && this.audioElement.paused) { this.audioElement.play(); } if (this.videoElement.paused) { this.videoElement.play(); } }; this.videoElement.onloadedmetadata = () => { this.onVideoInitialized(); }; // set resize events to the windows if it is resized or its orientation is changed window.addEventListener('resize', () => this.resizePlayerStyle(), true); window.addEventListener('orientationchange', () => this.onOrientationChange()); } setAudioElement(audioElement) { this.audioElement = audioElement; } /** * Sets up the video element with any application config and plays the video element. * @returns A promise for if playing the video was successful or not. */ play() { this.videoElement.muted = this.config.isFlagEnabled(_Config_Config__WEBPACK_IMPORTED_MODULE_0__.Flags.StartVideoMuted); this.videoElement.autoplay = this.config.isFlagEnabled(_Config_Config__WEBPACK_IMPORTED_MODULE_0__.Flags.AutoPlayVideo); return this.videoElement.play(); } /** * @returns True if the video element is paused. */ isPaused() { return this.videoElement.paused; } /** * @returns - whether the video element is playing. */ isVideoReady() { return (this.videoElement.readyState !== undefined && this.videoElement.readyState > 0); } /** * @returns True if the video element has a valid video source (srcObject). */ hasVideoSource() { return (this.videoElement.srcObject !== undefined && this.videoElement.srcObject !== null); } /** * Get the current context of the html video element * @returns - the current context of the video element */ getVideoElement() { return this.videoElement; } /** * Get the current context of the html video elements parent * @returns - the current context of the video elements parent */ getVideoParentElement() { return this.videoElement.parentElement; } /** * Set the Video Elements src object tracks to enable * @param enabled - Enable Tracks on the Src Object */ setVideoEnabled(enabled) { // this is a temporary hack until type scripts video element is updated to reflect the need for tracks on a html video element const videoElement = this.videoElement; videoElement.srcObject .getTracks() .forEach((track) => (track.enabled = enabled)); } /** * An override for when the video has been initialized with a srcObject */ onVideoInitialized() { // Default Functionality: Do Nothing } /** * On the orientation change of a window clear the timeout */ onOrientationChange() { clearTimeout(this.orientationChangeTimeout); this.orientationChangeTimeout = window.setTimeout(() => { this.resizePlayerStyle(); }, 500); } /** * Resizes the player style based on the window height and width * @returns - nil if requirements are satisfied */ resizePlayerStyle() { const videoElementParent = this.getVideoParentElement(); if (!videoElementParent) { return; } this.updateVideoStreamSize(); if (videoElementParent.classList.contains('fixed-size')) { this.onResizePlayerCallback(); return; } // controls for resizing the player this.resizePlayerStyleToFillParentElement(); this.onResizePlayerCallback(); } /** * Resizes the player element to fill the parent element */ resizePlayerStyleToFillParentElement() { const videoElementParent = this.getVideoParentElement(); //Video is not initialized yet so set videoElementParent to size of parent element const styleWidth = '100%'; const styleHeight = '100%'; const styleTop = 0; const styleLeft = 0; videoElementParent.setAttribute('style', 'top: ' + styleTop + 'px; left: ' + styleLeft + 'px; width: ' + styleWidth + '; height: ' + styleHeight + '; cursor: default;'); } updateVideoStreamSize() { if (!this.config.isFlagEnabled(_Config_Config__WEBPACK_IMPORTED_MODULE_0__.Flags.MatchViewportResolution)) { return; } const now = new Date().getTime(); if (now - this.lastTimeResized > 300) { const videoElementParent = this.getVideoParentElement(); if (!videoElementParent) { return; } this.onMatchViewportResolutionCallback(videoElementParent.clientWidth, videoElementParent.clientHeight); this.lastTimeResized = new Date().getTime(); } else { _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.GetStackTrace(), 'Resizing too often - skipping', 6); clearTimeout(this.resizeTimeoutHandle); this.resizeTimeoutHandle = window.setTimeout(() => this.updateVideoStreamSize(), 100); } } } /***/ }), /***/ "./src/WebRtcPlayer/WebRtcPlayerController.ts": /*!****************************************************!*\ !*** ./src/WebRtcPlayer/WebRtcPlayerController.ts ***! \****************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "WebRtcPlayerController": () => (/* binding */ WebRtcPlayerController) /* harmony export */ }); /* harmony import */ var _WebSockets_WebSocketController__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ../WebSockets/WebSocketController */ "./src/WebSockets/WebSocketController.ts"); /* harmony import */ var _VideoPlayer_StreamController__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../VideoPlayer/StreamController */ "./src/VideoPlayer/StreamController.ts"); /* harmony import */ var _FreezeFrame_FreezeFrameController__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../FreezeFrame/FreezeFrameController */ "./src/FreezeFrame/FreezeFrameController.ts"); /* harmony import */ var _AFK_AFKController__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../AFK/AFKController */ "./src/AFK/AFKController.ts"); /* harmony import */ var _DataChannel_DataChannelController__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../DataChannel/DataChannelController */ "./src/DataChannel/DataChannelController.ts"); /* harmony import */ var _PeerConnectionController_PeerConnectionController__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ../PeerConnectionController/PeerConnectionController */ "./src/PeerConnectionController/PeerConnectionController.ts"); /* harmony import */ var _Config_Config__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ../Config/Config */ "./src/Config/Config.ts"); /* harmony import */ var _DataChannel_InitialSettings__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ../DataChannel/InitialSettings */ "./src/DataChannel/InitialSettings.ts"); /* harmony import */ var _DataChannel_LatencyTestResults__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ../DataChannel/LatencyTestResults */ "./src/DataChannel/LatencyTestResults.ts"); /* harmony import */ var _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ../Logger/Logger */ "./src/Logger/Logger.ts"); /* harmony import */ var _Util_FileUtil__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Util/FileUtil */ "./src/Util/FileUtil.ts"); /* harmony import */ var _Inputs_InputClassesFactory__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ../Inputs/InputClassesFactory */ "./src/Inputs/InputClassesFactory.ts"); /* harmony import */ var _VideoPlayer_VideoPlayer__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../VideoPlayer/VideoPlayer */ "./src/VideoPlayer/VideoPlayer.ts"); /* harmony import */ var _UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../UeInstanceMessage/StreamMessageController */ "./src/UeInstanceMessage/StreamMessageController.ts"); /* harmony import */ var _UeInstanceMessage_ResponseController__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../UeInstanceMessage/ResponseController */ "./src/UeInstanceMessage/ResponseController.ts"); /* harmony import */ var _UeInstanceMessage_SendMessageController__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ../UeInstanceMessage/SendMessageController */ "./src/UeInstanceMessage/SendMessageController.ts"); /* harmony import */ var _UeInstanceMessage_ToStreamerMessagesController__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ../UeInstanceMessage/ToStreamerMessagesController */ "./src/UeInstanceMessage/ToStreamerMessagesController.ts"); /* harmony import */ var _DataChannel_DataChannelSender__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../DataChannel/DataChannelSender */ "./src/DataChannel/DataChannelSender.ts"); /* harmony import */ var _Util_CoordinateConverter__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../Util/CoordinateConverter */ "./src/Util/CoordinateConverter.ts"); /* harmony import */ var _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ../Util/EventEmitter */ "./src/Util/EventEmitter.ts"); // Copyright Epic Games, Inc. All Rights Reserved. /** * Entry point for the WebRTC Player */ class WebRtcPlayerController { /** * * @param config - the frontend config object * @param pixelStreaming - the PixelStreaming object */ constructor(config, pixelStreaming) { this.shouldShowPlayOverlay = true; this.autoJoinTimer = undefined; this.config = config; this.pixelStreaming = pixelStreaming; this.responseController = new _UeInstanceMessage_ResponseController__WEBPACK_IMPORTED_MODULE_0__.ResponseController(); this.file = new _Util_FileUtil__WEBPACK_IMPORTED_MODULE_1__.FileTemplate(); this.sdpConstraints = { offerToReceiveAudio: true, offerToReceiveVideo: true }; // set up the afk logic class and connect up its method for closing the signaling server this.afkController = new _AFK_AFKController__WEBPACK_IMPORTED_MODULE_2__.AFKController(this.config, this.pixelStreaming, this.onAfkTriggered.bind(this)); this.afkController.onAFKTimedOutCallback = () => { this.closeSignalingServer('You have been disconnected due to inactivity'); }; this.freezeFrameController = new _FreezeFrame_FreezeFrameController__WEBPACK_IMPORTED_MODULE_3__.FreezeFrameController(this.pixelStreaming.videoElementParent); this.videoPlayer = new _VideoPlayer_VideoPlayer__WEBPACK_IMPORTED_MODULE_4__.VideoPlayer(this.pixelStreaming.videoElementParent, this.config); this.videoPlayer.onVideoInitialized = () => this.handleVideoInitialized(); // When in match viewport resolution mode, when the browser viewport is resized we send a resize command back to UE. this.videoPlayer.onMatchViewportResolutionCallback = (width, height) => { const descriptor = { 'Resolution.Width': width, 'Resolution.Height': height }; this.streamMessageController.toStreamerHandlers.get('Command')([JSON.stringify(descriptor)]); }; // Every time video player is resized in browser we need to reinitialize the mouse coordinate conversion and freeze frame sizing logic. this.videoPlayer.onResizePlayerCallback = () => { this.setUpMouseAndFreezeFrame(); }; this.streamController = new _VideoPlayer_StreamController__WEBPACK_IMPORTED_MODULE_5__.StreamController(this.videoPlayer); this.coordinateConverter = new _Util_CoordinateConverter__WEBPACK_IMPORTED_MODULE_6__.CoordinateConverter(this.videoPlayer); this.sendrecvDataChannelController = new _DataChannel_DataChannelController__WEBPACK_IMPORTED_MODULE_7__.DataChannelController(); this.recvDataChannelController = new _DataChannel_DataChannelController__WEBPACK_IMPORTED_MODULE_7__.DataChannelController(); this.registerDataChannelEventEmitters(this.sendrecvDataChannelController); this.registerDataChannelEventEmitters(this.recvDataChannelController); this.dataChannelSender = new _DataChannel_DataChannelSender__WEBPACK_IMPORTED_MODULE_8__.DataChannelSender(this.sendrecvDataChannelController); this.dataChannelSender.resetAfkWarningTimerOnDataSend = () => this.afkController.resetAfkWarningTimer(); this.streamMessageController = new _UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.StreamMessageController(); // set up websocket methods this.webSocketController = new _WebSockets_WebSocketController__WEBPACK_IMPORTED_MODULE_10__.WebSocketController(); this.webSocketController.onConfig = (messageConfig) => this.handleOnConfigMessage(messageConfig); this.webSocketController.onStreamerList = (messageList) => this.handleStreamerListMessage(messageList); this.webSocketController.onPlayerCount = (playerCount) => { this.pixelStreaming._onPlayerCount(playerCount.count); }; this.webSocketController.onOpen.addEventListener('open', () => { const BrowserSendsOffer = this.config.isFlagEnabled(_Config_Config__WEBPACK_IMPORTED_MODULE_11__.Flags.BrowserSendOffer); if (!BrowserSendsOffer) { this.webSocketController.requestStreamerList(); } }); this.webSocketController.onClose.addEventListener('close', (event) => { // when we refresh the page during a stream we get the going away code. // in that case we don't want to reconnect since we're navigating away. // https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent/code // lists all the codes. const CODE_GOING_AWAY = 1001; const willTryReconnect = this.shouldReconnect && event.detail.code != CODE_GOING_AWAY && this.config.getNumericSettingValue(_Config_Config__WEBPACK_IMPORTED_MODULE_11__.NumericParameters.MaxReconnectAttempts) > 0; const disconnectMessage = this.disconnectMessage ? this.disconnectMessage : event.detail.reason; this.pixelStreaming._onDisconnect(disconnectMessage, !willTryReconnect && !this.isReconnecting); this.afkController.stopAfkWarningTimer(); // stop sending stats on interval if we have closed our connection if (this.statsTimerHandle && this.statsTimerHandle !== undefined) { window.clearInterval(this.statsTimerHandle); } // reset the stream quality icon. this.setVideoEncoderAvgQP(0); // unregister all input device event handlers on disconnect this.setTouchInputEnabled(false); this.setMouseInputEnabled(false); this.setKeyboardInputEnabled(false); this.setGamePadInputEnabled(false); if (willTryReconnect) { // need a small delay here to prevent reconnect spamming setTimeout(() => { this.isReconnecting = true; this.reconnectAttempt++; this.tryReconnect(event.detail.reason); }, 2000); } }); // set up the final webRtc player controller methods from within our application so a connection can be activated this.sendMessageController = new _UeInstanceMessage_SendMessageController__WEBPACK_IMPORTED_MODULE_12__.SendMessageController(this.dataChannelSender, this.streamMessageController); this.toStreamerMessagesController = new _UeInstanceMessage_ToStreamerMessagesController__WEBPACK_IMPORTED_MODULE_13__.ToStreamerMessagesController(this.sendMessageController); this.registerMessageHandlers(); this.streamMessageController.populateDefaultProtocol(); this.inputClassesFactory = new _Inputs_InputClassesFactory__WEBPACK_IMPORTED_MODULE_14__.InputClassesFactory(this.streamMessageController, this.videoPlayer, this.coordinateConverter); this.isUsingSFU = false; this.isQualityController = false; this.preferredCodec = ''; this.shouldReconnect = true; this.isReconnecting = false; this.reconnectAttempt = 0; this.config._addOnOptionSettingChangedListener(_Config_Config__WEBPACK_IMPORTED_MODULE_11__.OptionParameters.StreamerId, (streamerid) => { if (streamerid === "") { return; } // close the current peer connection and create a new one this.peerConnectionController.peerConnection.close(); this.peerConnectionController.createPeerConnection(this.peerConfig, this.preferredCodec); this.subscribedStream = streamerid; this.webSocketController.sendSubscribe(streamerid); }); this.setVideoEncoderAvgQP(-1); this.signallingUrlBuilder = () => { let signallingServerUrl = this.config.getTextSettingValue(_Config_Config__WEBPACK_IMPORTED_MODULE_11__.TextParameters.SignallingServerUrl); // If we are connecting to the SFU add a special url parameter to the url if (this.config.isFlagEnabled(_Config_Config__WEBPACK_IMPORTED_MODULE_11__.Flags.BrowserSendOffer)) { signallingServerUrl += '?' + _Config_Config__WEBPACK_IMPORTED_MODULE_11__.Flags.BrowserSendOffer + '=true'; } // This code is no longer needed, but is a good example for how subsequent config flags can be appended // if (this.config.isFlagEnabled(Flags.BrowserSendOffer)) { // signallingServerUrl += (signallingServerUrl.includes('?') ? '&' : '?') + Flags.BrowserSendOffer + '=true'; // } return signallingServerUrl; }; } /** * Make a request to UnquantizedAndDenormalizeUnsigned coordinates * @param x x axis coordinate * @param y y axis coordinate */ requestUnquantizedAndDenormalizeUnsigned(x, y) { return this.coordinateConverter.unquantizeAndDenormalizeUnsigned(x, y); } /** * Handles when a message is received * @param event - Message Event */ handleOnMessage(event) { const message = new Uint8Array(event.data); _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), 'Message incoming:' + message, 6); //try { const messageType = this.streamMessageController.fromStreamerMessages.get(message[0]); this.streamMessageController.fromStreamerHandlers.get(messageType)(event.data); //} catch (e) { //Logger.Error(Logger.GetStackTrace(), `Custom data channel message with message type that is unknown to the Pixel Streaming protocol. Does your PixelStreamingProtocol need updating? The message type was: ${message[0]}`); //} } /** * Register message all handlers */ registerMessageHandlers() { // From Streamer // Message events from the streamer have a data type of ArrayBuffer as we force this type in the DatachannelController this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.FromStreamer, 'QualityControlOwnership', (data) => this.onQualityControlOwnership(data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.FromStreamer, 'Response', (data) => this.responseController.onResponse(data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.FromStreamer, 'Command', (data) => { this.onCommand(data); }); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.FromStreamer, 'FreezeFrame', (data) => this.onFreezeFrameMessage(data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.FromStreamer, 'UnfreezeFrame', () => this.invalidateFreezeFrameAndEnableVideo()); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.FromStreamer, 'VideoEncoderAvgQP', (data) => this.handleVideoEncoderAvgQP(data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.FromStreamer, 'LatencyTest', (data) => this.handleLatencyTestResult(data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.FromStreamer, 'DataChannelLatencyTest', (data) => this.handleDataChannelLatencyTestResponse(data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.FromStreamer, 'InitialSettings', (data) => this.handleInitialSettings(data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.FromStreamer, 'FileExtension', (data) => this.onFileExtension(data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.FromStreamer, 'FileMimeType', (data) => this.onFileMimeType(data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.FromStreamer, 'FileContents', (data) => this.onFileContents(data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.FromStreamer, 'TestEcho', () => { /* Do nothing */ }); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.FromStreamer, 'InputControlOwnership', (data) => this.onInputControlOwnership(data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.FromStreamer, 'GamepadResponse', (data) => this.onGamepadResponse(data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.FromStreamer, 'Protocol', (data) => this.onProtocolMessage(data)); // To Streamer this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'IFrameRequest', () => this.sendMessageController.sendMessageToStreamer('IFrameRequest')); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'RequestQualityControl', () => this.sendMessageController.sendMessageToStreamer('RequestQualityControl')); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'FpsRequest', () => this.sendMessageController.sendMessageToStreamer('FpsRequest')); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'AverageBitrateRequest', () => this.sendMessageController.sendMessageToStreamer('AverageBitrateRequest')); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'StartStreaming', () => this.sendMessageController.sendMessageToStreamer('StartStreaming')); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'StopStreaming', () => this.sendMessageController.sendMessageToStreamer('StopStreaming')); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'LatencyTest', (data) => this.sendMessageController.sendMessageToStreamer('LatencyTest', data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'RequestInitialSettings', () => this.sendMessageController.sendMessageToStreamer('RequestInitialSettings')); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'TestEcho', () => { /* Do nothing */ }); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'UIInteraction', (data) => this.sendMessageController.sendMessageToStreamer('UIInteraction', data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'Command', (data) => this.sendMessageController.sendMessageToStreamer('Command', data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'TextboxEntry', (data) => this.sendMessageController.sendMessageToStreamer('TextboxEntry', data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'KeyDown', (data) => this.sendMessageController.sendMessageToStreamer('KeyDown', data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'KeyUp', (data) => this.sendMessageController.sendMessageToStreamer('KeyUp', data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'KeyPress', (data) => this.sendMessageController.sendMessageToStreamer('KeyPress', data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'MouseEnter', (data) => this.sendMessageController.sendMessageToStreamer('MouseEnter', data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'MouseLeave', (data) => this.sendMessageController.sendMessageToStreamer('MouseLeave', data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'MouseDown', (data) => this.sendMessageController.sendMessageToStreamer('MouseDown', data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'MouseUp', (data) => this.sendMessageController.sendMessageToStreamer('MouseUp', data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'MouseMove', (data) => this.sendMessageController.sendMessageToStreamer('MouseMove', data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'MouseWheel', (data) => this.sendMessageController.sendMessageToStreamer('MouseWheel', data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'MouseDouble', (data) => this.sendMessageController.sendMessageToStreamer('MouseDouble', data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'TouchStart', (data) => this.sendMessageController.sendMessageToStreamer('TouchStart', data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'TouchEnd', (data) => this.sendMessageController.sendMessageToStreamer('TouchEnd', data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'TouchMove', (data) => this.sendMessageController.sendMessageToStreamer('TouchMove', data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'GamepadConnected', () => this.sendMessageController.sendMessageToStreamer('GamepadConnected')); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'GamepadButtonPressed', (data) => this.sendMessageController.sendMessageToStreamer('GamepadButtonPressed', data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'GamepadButtonReleased', (data) => this.sendMessageController.sendMessageToStreamer('GamepadButtonReleased', data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'GamepadAnalog', (data) => this.sendMessageController.sendMessageToStreamer('GamepadAnalog', data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'GamepadDisconnected', (data) => this.sendMessageController.sendMessageToStreamer('GamepadDisconnected', data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'XRHMDTransform', (data) => this.sendMessageController.sendMessageToStreamer('XRHMDTransform', data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'XRControllerTransform', (data) => this.sendMessageController.sendMessageToStreamer('XRControllerTransform', data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'XRSystem', (data) => this.sendMessageController.sendMessageToStreamer('XRSystem', data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'XRButtonTouched', (data) => this.sendMessageController.sendMessageToStreamer('XRButtonTouched', data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'XRButtonPressed', (data) => this.sendMessageController.sendMessageToStreamer('XRButtonPressed', data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'XRButtonReleased', (data) => this.sendMessageController.sendMessageToStreamer('XRButtonReleased', data)); this.streamMessageController.registerMessageHandler(_UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer, 'XRAnalog', (data) => this.sendMessageController.sendMessageToStreamer('XRAnalog', data)); } /** * Activate the logic associated with a command from UE * @param message */ onCommand(message) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), 'DataChannelReceiveMessageType.Command', 6); const commandAsString = new TextDecoder('utf-16').decode(message.slice(1)); _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), 'Data Channel Command: ' + commandAsString, 6); const command = JSON.parse(commandAsString); if (command.command === 'onScreenKeyboard') { this.pixelStreaming._activateOnScreenKeyboard(command); } } /** * Handles a protocol message received from the streamer * @param message the message data from the streamer */ onProtocolMessage(message) { try { const protocolString = new TextDecoder('utf-16').decode(message.slice(1)); const protocolJSON = JSON.parse(protocolString); if (!Object.prototype.hasOwnProperty.call(protocolJSON, 'Direction')) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Error(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), 'Malformed protocol received. Ensure the protocol message contains a direction'); } const direction = protocolJSON.Direction; delete protocolJSON.Direction; _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), `Received new ${direction == _UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.FromStreamer ? 'FromStreamer' : 'ToStreamer'} protocol. Updating existing protocol...`); Object.keys(protocolJSON).forEach((messageType) => { const message = protocolJSON[messageType]; switch (direction) { case _UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer: // Check that the message contains all the relevant params if (!Object.prototype.hasOwnProperty.call(message, 'id')) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Error(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), `ToStreamer->${messageType} protocol definition was malformed as it didn't contain at least an id\n Definition was: ${JSON.stringify(message, null, 2)}`); // return in a forEach is equivalent to a continue in a normal for loop return; } // UE5.1 and UE5.2 don't send a structure for these message types, but they actually do have a structure so ignore updating them if ((messageType === "UIInteraction" || messageType === "Command" || messageType === "LatencyTest")) { return; } if (this.streamMessageController.toStreamerHandlers.get(messageType)) { // If we've registered a handler for this message type we can add it to our supported messages. ie registerMessageHandler(...) this.streamMessageController.toStreamerMessages.set(messageType, message); } else { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Error(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), `There was no registered handler for "${messageType}" - try adding one using registerMessageHandler(MessageDirection.ToStreamer, "${messageType}", myHandler)`); } break; case _UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.FromStreamer: // Check that the message contains all the relevant params if (!Object.prototype.hasOwnProperty.call(message, 'id')) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Error(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), `FromStreamer->${messageType} protocol definition was malformed as it didn't contain at least an id\n Definition was: ${JSON.stringify(message, null, 2)}`); // return in a forEach is equivalent to a continue in a normal for loop return; } if (this.streamMessageController.fromStreamerHandlers.get(messageType)) { // If we've registered a handler for this message type. ie registerMessageHandler(...) this.streamMessageController.fromStreamerMessages.set(message.id, messageType); } else { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Error(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), `There was no registered handler for "${message}" - try adding one using registerMessageHandler(MessageDirection.FromStreamer, "${messageType}", myHandler)`); } break; default: _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Error(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), `Unknown direction: ${direction}`); } }); // Once the protocol has been received, we can send our control messages this.toStreamerMessagesController.SendRequestInitialSettings(); this.toStreamerMessagesController.SendRequestQualityControl(); } catch (e) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), e); } } /** * Handles an input control message when it is received from the streamer * @param message The input control message */ onInputControlOwnership(message) { const view = new Uint8Array(message); _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), 'DataChannelReceiveMessageType.InputControlOwnership', 6); const inputControlOwnership = new Boolean(view[1]).valueOf(); _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), `Received input controller message - will your input control the stream: ${inputControlOwnership}`); this.pixelStreaming._onInputControlOwnership(inputControlOwnership); } /** * * @param message */ onGamepadResponse(message) { const responseString = new TextDecoder('utf-16').decode(message.slice(1)); const responseJSON = JSON.parse(responseString); this.gamePadController.onGamepadResponseReceived(responseJSON.controllerId); } onAfkTriggered() { this.afkController.onAfkClick(); // if the stream is paused play it, if we can if (this.videoPlayer.isPaused() && this.videoPlayer.hasVideoSource()) { this.playStream(); } } /** * Set whether we should timeout when afk. * @param afkEnabled If true we timeout when idle for some given amount of time. */ setAfkEnabled(afkEnabled) { if (afkEnabled) { this.onAfkTriggered(); } else { this.afkController.stopAfkWarningTimer(); } } /** * Attempt a reconnection to the signalling server */ tryReconnect(message) { // if there is no webSocketController return immediately or this will not work if (!this.webSocketController) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), 'The Web Socket Controller does not exist so this will not work right now.'); return; } // if the connection is open, first close it. wait some time and try again. this.isReconnecting = true; if (this.webSocketController.webSocket && this.webSocketController.webSocket.readyState != WebSocket.CLOSED) { this.closeSignalingServer(`${message} Restarting stream...`); setTimeout(() => { this.tryReconnect(message); }, 3000); } else { this.pixelStreaming._onWebRtcAutoConnect(); this.connectToSignallingServer(); } } /** * Loads a freeze frame if it is required otherwise shows the play overlay */ loadFreezeFrameOrShowPlayOverlay() { this.pixelStreaming.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_16__.LoadFreezeFrameEvent({ shouldShowPlayOverlay: this.shouldShowPlayOverlay, isValid: this.freezeFrameController.valid, jpegData: this.freezeFrameController.jpeg })); if (this.shouldShowPlayOverlay === true) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), 'showing play overlay'); this.resizePlayerStyle(); } else { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), 'showing freeze frame'); this.freezeFrameController.showFreezeFrame(); } setTimeout(() => { this.videoPlayer.setVideoEnabled(false); }, this.freezeFrameController.freezeFrameDelay); } /** * Process the freeze frame and load it * @param message The freeze frame data in bytes */ onFreezeFrameMessage(message) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), 'DataChannelReceiveMessageType.FreezeFrame', 6); const view = new Uint8Array(message); this.freezeFrameController.processFreezeFrameMessage(view, () => this.loadFreezeFrameOrShowPlayOverlay()); } /** * Enable the video after hiding a freeze frame */ invalidateFreezeFrameAndEnableVideo() { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), 'DataChannelReceiveMessageType.FreezeFrame', 6); setTimeout(() => { this.pixelStreaming.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_16__.HideFreezeFrameEvent()); this.freezeFrameController.hideFreezeFrame(); }, this.freezeFrameController.freezeFrameDelay); if (this.videoPlayer.getVideoElement()) { this.videoPlayer.setVideoEnabled(true); } } /** * Prep datachannel data for processing file extension * @param data the file extension data */ onFileExtension(data) { const view = new Uint8Array(data); _Util_FileUtil__WEBPACK_IMPORTED_MODULE_1__.FileUtil.setExtensionFromBytes(view, this.file); } /** * Prep datachannel data for processing the file mime type * @param data the file mime type data */ onFileMimeType(data) { const view = new Uint8Array(data); _Util_FileUtil__WEBPACK_IMPORTED_MODULE_1__.FileUtil.setMimeTypeFromBytes(view, this.file); } /** * Prep datachannel data for processing the file contents * @param data the file contents data */ onFileContents(data) { const view = new Uint8Array(data); _Util_FileUtil__WEBPACK_IMPORTED_MODULE_1__.FileUtil.setContentsFromBytes(view, this.file); } /** * Plays the stream audio and video source and sets up other pieces while the stream starts */ playStream() { if (!this.videoPlayer.getVideoElement()) { const message = 'Could not play video stream because the video player was not initialized correctly.'; this.pixelStreaming.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_16__.PlayStreamErrorEvent({ message })); _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Error(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), message); // close the connection this.closeSignalingServer('Stream not initialized correctly'); return; } if (!this.videoPlayer.hasVideoSource()) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Warning(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), 'Cannot play stream, the video element has no srcObject to play.'); return; } this.setTouchInputEnabled(this.config.isFlagEnabled(_Config_Config__WEBPACK_IMPORTED_MODULE_11__.Flags.TouchInput)); this.pixelStreaming.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_16__.PlayStreamEvent()); if (this.streamController.audioElement.srcObject) { const startMuted = this.config.isFlagEnabled(_Config_Config__WEBPACK_IMPORTED_MODULE_11__.Flags.StartVideoMuted); this.streamController.audioElement.muted = startMuted; if (startMuted) { this.playVideo(); } else { this.streamController.audioElement .play() .then(() => { this.playVideo(); }) .catch((onRejectedReason) => { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), onRejectedReason); _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), 'Browser does not support autoplaying video without interaction - to resolve this we are going to show the play button overlay.'); this.pixelStreaming.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_16__.PlayStreamRejectedEvent({ reason: onRejectedReason })); }); } } else { this.playVideo(); } this.shouldShowPlayOverlay = false; this.freezeFrameController.showFreezeFrame(); } /** * Plays the video stream */ playVideo() { // handle play() with promise as it is an asynchronous call this.videoPlayer.play().catch((onRejectedReason) => { if (this.streamController.audioElement.srcObject) { this.streamController.audioElement.pause(); } _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), onRejectedReason); _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), 'Browser does not support autoplaying video without interaction - to resolve this we are going to show the play button overlay.'); this.pixelStreaming.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_16__.PlayStreamRejectedEvent({ reason: onRejectedReason })); }); } /** * Enable the video to play automatically if enableAutoplay is true */ autoPlayVideoOrSetUpPlayOverlay() { if (this.config.isFlagEnabled(_Config_Config__WEBPACK_IMPORTED_MODULE_11__.Flags.AutoPlayVideo)) { // attempt to play the video this.playStream(); } this.resizePlayerStyle(); } /** * Connect to the Signaling server */ connectToSignallingServer() { this.locallyClosed = false; this.shouldReconnect = true; this.disconnectMessage = null; const signallingUrl = this.signallingUrlBuilder(); this.webSocketController.connect(signallingUrl); } /** * This will start the handshake to the signalling server * @param peerConfig - RTC Configuration Options from the Signaling server * @remark RTC Peer Connection on Ice Candidate event have it handled by handle Send Ice Candidate */ startSession(peerConfig) { this.peerConfig = peerConfig; // check for forcing turn if (this.config.isFlagEnabled(_Config_Config__WEBPACK_IMPORTED_MODULE_11__.Flags.ForceTURN)) { // check for a turn server const hasTurnServer = this.checkTurnServerAvailability(peerConfig); // close and error if turn is forced and there is no turn server if (!hasTurnServer) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Info(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), 'No turn server was found in the Peer Connection Options. TURN cannot be forced, closing connection. Please use STUN instead'); this.closeSignalingServer('TURN cannot be forced, closing connection. Please use STUN instead.'); return; } } // set up the peer connection controller this.peerConnectionController = new _PeerConnectionController_PeerConnectionController__WEBPACK_IMPORTED_MODULE_17__.PeerConnectionController(this.peerConfig, this.config, this.preferredCodec); // set up peer connection controller video stats this.peerConnectionController.onVideoStats = (event) => this.handleVideoStats(event); /* When the Peer Connection wants to send an offer have it handled */ this.peerConnectionController.onSendWebRTCOffer = (offer) => this.handleSendWebRTCOffer(offer); /* When the Peer Connection wants to send an answer have it handled */ this.peerConnectionController.onSendWebRTCAnswer = (offer) => this.handleSendWebRTCAnswer(offer); /* When the Peer Connection ice candidate is added have it handled */ this.peerConnectionController.onPeerIceCandidate = (peerConnectionIceEvent) => this.handleSendIceCandidate(peerConnectionIceEvent); /* When the Peer Connection has a data channel created for it by the browser, handle it */ this.peerConnectionController.onDataChannel = (datachannelEvent) => this.handleDataChannel(datachannelEvent); // set up webRtc text overlays this.peerConnectionController.showTextOverlayConnecting = () => this.pixelStreaming._onWebRtcConnecting(); this.peerConnectionController.showTextOverlaySetupFailure = () => this.pixelStreaming._onWebRtcFailed(); let webRtcConnectedSent = false; this.peerConnectionController.onIceConnectionStateChange = () => { // Browsers emit "connected" when getting first connection and "completed" when finishing // candidate checking. However, sometimes browsers can skip "connected" and only emit "completed". // Therefore need to check both cases and emit onWebRtcConnected only once on the first hit. if (!webRtcConnectedSent && ["connected", "completed"].includes(this.peerConnectionController.peerConnection.iceConnectionState)) { this.pixelStreaming._onWebRtcConnected(); webRtcConnectedSent = true; } }; /* RTC Peer Connection on Track event -> handle on track */ this.peerConnectionController.onTrack = (trackEvent) => this.streamController.handleOnTrack(trackEvent); /* Start the Hand shake process by creating an Offer */ const BrowserSendsOffer = this.config.isFlagEnabled(_Config_Config__WEBPACK_IMPORTED_MODULE_11__.Flags.BrowserSendOffer); if (BrowserSendsOffer) { // If browser is sending the offer, create an offer and send it to the streamer this.sendrecvDataChannelController.createDataChannel(this.peerConnectionController.peerConnection, 'cirrus', this.datachannelOptions); this.sendrecvDataChannelController.handleOnMessage = (ev) => this.handleOnMessage(ev); this.peerConnectionController.createOffer(this.sdpConstraints, this.config); } } /** * Checks the peer connection options for a turn server and returns true or false */ checkTurnServerAvailability(options) { // if iceServers is empty return false this should not be the general use case but is here incase if (!options.iceServers) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Info(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), 'A turn sever was not found'); return false; } // loop through the ice servers to check for a turn url for (const iceServer of options.iceServers) { for (const url of iceServer.urls) { if (url.includes('turn')) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), `A turn sever was found at ${url}`); return true; } } } _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Info(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), 'A turn sever was not found'); return false; } /** * Handles when a Config Message is received contains the Peer Connection Options required (STUN and TURN Server Info) * @param messageConfig - Config Message received from the signaling server */ handleOnConfigMessage(messageConfig) { this.resizePlayerStyle(); // Tell the WebRtcController to start a session with the peer options sent from the signaling server this.startSession(messageConfig.peerConnectionOptions); // When the signaling server sends a WebRTC Answer over the websocket connection have the WebRtcController handle the message this.webSocketController.onWebRtcAnswer = (messageAnswer) => this.handleWebRtcAnswer(messageAnswer); this.webSocketController.onWebRtcOffer = (messageOffer) => this.handleWebRtcOffer(messageOffer); this.webSocketController.onWebRtcPeerDataChannels = (messageDataChannels) => this.handleWebRtcSFUPeerDatachannels(messageDataChannels); // When the signaling server sends a IceCandidate over the websocket connection have the WebRtcController handle the message this.webSocketController.onIceCandidate = (iceCandidate) => this.handleIceCandidate(iceCandidate); } /** * Handles when the signalling server gives us the list of streamer ids. */ handleStreamerListMessage(messageStreamerList) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), `Got streamer list ${messageStreamerList.ids}`, 6); // add the streamers to the UI const settingOptions = [...messageStreamerList.ids]; // copy the original messageStreamerList.ids settingOptions.unshift(''); // add an empty option at the top this.config.setOptionSettingOptions(_Config_Config__WEBPACK_IMPORTED_MODULE_11__.OptionParameters.StreamerId, settingOptions); let wantedStreamerId = null; let autoSelectedStreamerId = null; const waitForStreamer = this.config.isFlagEnabled(_Config_Config__WEBPACK_IMPORTED_MODULE_11__.Flags.WaitForStreamer); const reconnectLimit = this.config.getNumericSettingValue(_Config_Config__WEBPACK_IMPORTED_MODULE_11__.NumericParameters.MaxReconnectAttempts); const reconnectDelay = this.config.getNumericSettingValue(_Config_Config__WEBPACK_IMPORTED_MODULE_11__.NumericParameters.StreamerAutoJoinInterval); // first we figure out a wanted streamer id through various means const urlParams = new URLSearchParams(window.location.search); if (urlParams.has(_Config_Config__WEBPACK_IMPORTED_MODULE_11__.OptionParameters.StreamerId)) { // if we've set the streamer id on the url we only want that streamer id wantedStreamerId = urlParams.get(_Config_Config__WEBPACK_IMPORTED_MODULE_11__.OptionParameters.StreamerId); } else if (this.subscribedStream) { // we were previously subscribed to a streamer, we want that wantedStreamerId = this.subscribedStream; } // now lets see if we can pick it. if (wantedStreamerId && messageStreamerList.ids.includes(wantedStreamerId)) { // if the wanted stream is in the list. we pick that autoSelectedStreamerId = wantedStreamerId; } else if ((!wantedStreamerId || !waitForStreamer) && messageStreamerList.ids.length == 1) { // otherwise, if we're not waiting for the wanted streamer and there's only one streamer, connect to it autoSelectedStreamerId = messageStreamerList.ids[0]; } // if we found a streamer id to auto select, select it if (autoSelectedStreamerId) { this.isReconnecting = false; this.reconnectAttempt = 0; this.config.setOptionSettingValue(_Config_Config__WEBPACK_IMPORTED_MODULE_11__.OptionParameters.StreamerId, autoSelectedStreamerId); } else { // no auto selected streamer. // if we're waiting for a streamer then try reconnecting if (waitForStreamer) { if (this.reconnectAttempt < reconnectLimit) { // still reconnects available this.isReconnecting = true; this.reconnectAttempt++; setTimeout(() => { this.webSocketController.requestStreamerList(); }, reconnectDelay); } else { // We've exhausted our reconnect attempts, return to main screen this.reconnectAttempt = 0; this.isReconnecting = false; this.shouldReconnect = false; } } } // dispatch this event finally this.pixelStreaming.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_16__.StreamerListMessageEvent({ messageStreamerList, autoSelectedStreamerId, wantedStreamerId })); } /** * Handle the RTC Answer from the signaling server * @param Answer - Answer SDP from the peer. */ handleWebRtcAnswer(Answer) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), `Got answer sdp ${Answer.sdp}`, 6); const sdpAnswer = { sdp: Answer.sdp, type: 'answer' }; this.peerConnectionController.receiveAnswer(sdpAnswer); this.handlePostWebrtcNegotiation(); } /** * Handle the RTC offer from a WebRTC peer (received through the signalling server). * @param Offer - Offer SDP from the peer. */ handleWebRtcOffer(Offer) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), `Got offer sdp ${Offer.sdp}`, 6); this.isUsingSFU = Offer.sfu ? Offer.sfu : false; if (this.isUsingSFU) { // Disable negotiating with the sfu as the sfu only supports one codec at a time this.peerConnectionController.preferredCodec = ''; } const sdpOffer = { sdp: Offer.sdp, type: 'offer' }; this.peerConnectionController.receiveOffer(sdpOffer, this.config); this.handlePostWebrtcNegotiation(); } /** * Handle when the SFU provides the peer with its data channels * @param DataChannels - The message from the SFU containing the data channels ids */ handleWebRtcSFUPeerDatachannels(DataChannels) { const SendOptions = { ordered: true, negotiated: true, id: DataChannels.sendStreamId }; const unidirectional = DataChannels.sendStreamId != DataChannels.recvStreamId; this.sendrecvDataChannelController.createDataChannel(this.peerConnectionController.peerConnection, unidirectional ? 'send-datachannel' : 'datachannel', SendOptions); if (unidirectional) { const RecvOptions = { ordered: true, negotiated: true, id: DataChannels.recvStreamId }; this.recvDataChannelController.createDataChannel(this.peerConnectionController.peerConnection, 'recv-datachannel', RecvOptions); this.recvDataChannelController.handleOnOpen = () => this.webSocketController.sendSFURecvDataChannelReady(); // If we're uni-directional, only the recv data channel should handle incoming messages this.recvDataChannelController.handleOnMessage = (ev) => this.handleOnMessage(ev); } else { // else our primary datachannel is send/recv so it can handle incoming messages this.sendrecvDataChannelController.handleOnMessage = (ev) => this.handleOnMessage(ev); } } handlePostWebrtcNegotiation() { // start the afk warning timer as PS is now running this.afkController.startAfkWarningTimer(); // show the overlay that we have negotiated a connection this.pixelStreaming._onWebRtcSdp(); if (this.statsTimerHandle && this.statsTimerHandle !== undefined) { window.clearInterval(this.statsTimerHandle); } this.statsTimerHandle = window.setInterval(() => this.getStats(), 1000); /* */ this.setMouseInputEnabled(this.config.isFlagEnabled(_Config_Config__WEBPACK_IMPORTED_MODULE_11__.Flags.MouseInput)); this.setKeyboardInputEnabled(this.config.isFlagEnabled(_Config_Config__WEBPACK_IMPORTED_MODULE_11__.Flags.KeyboardInput)); this.setGamePadInputEnabled(this.config.isFlagEnabled(_Config_Config__WEBPACK_IMPORTED_MODULE_11__.Flags.GamepadInput)); } /** * When an ice Candidate is received from the Signaling server add it to the Peer Connection Client * @param iceCandidate - Ice Candidate from Server */ handleIceCandidate(iceCandidate) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), 'Web RTC Controller: onWebRtcIce', 6); const candidate = new RTCIceCandidate(iceCandidate); this.peerConnectionController.handleOnIce(candidate); } /** * Send the ice Candidate to the signaling server via websocket * @param iceEvent - RTC Peer ConnectionIceEvent) { */ handleSendIceCandidate(iceEvent) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), 'OnIceCandidate', 6); if (iceEvent.candidate && iceEvent.candidate.candidate) { this.webSocketController.sendIceCandidate(iceEvent.candidate); } } /** * Send the ice Candidate to the signaling server via websocket * @param iceEvent - RTC Peer ConnectionIceEvent) { */ handleDataChannel(datachannelEvent) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), 'Data channel created for us by browser as we are a receiving peer.', 6); this.sendrecvDataChannelController.dataChannel = datachannelEvent.channel; // Data channel was created for us, so we just need to setup its callbacks and array type this.sendrecvDataChannelController.setupDataChannel(); this.sendrecvDataChannelController.handleOnMessage = (ev) => this.handleOnMessage(ev); } /** * Send the RTC Offer Session to the Signaling server via websocket * @param offer - RTC Session Description */ handleSendWebRTCOffer(offer) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), 'Sending the offer to the Server', 6); this.webSocketController.sendWebRtcOffer(offer); } /** * Send the RTC Offer Session to the Signaling server via websocket * @param answer - RTC Session Description */ handleSendWebRTCAnswer(answer) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), 'Sending the answer to the Server', 6); this.webSocketController.sendWebRtcAnswer(answer); if (this.isUsingSFU) { this.webSocketController.sendWebRtcDatachannelRequest(); } } /** * Set the freeze frame overlay to the player div */ setUpMouseAndFreezeFrame() { // Calculating and normalizing positions depends on the width and height of the player. this.videoElementParentClientRect = this.videoPlayer .getVideoParentElement() .getBoundingClientRect(); this.coordinateConverter.setupNormalizeAndQuantize(); this.freezeFrameController.freezeFrame.resize(); } /** * Close the Connection to the signaling server */ closeSignalingServer(message) { var _a; // We explicitly called close, therefore we don't want to trigger auto reconnect this.locallyClosed = true; this.shouldReconnect = false; this.disconnectMessage = message; (_a = this.webSocketController) === null || _a === void 0 ? void 0 : _a.close(); } /** * Close the peer connection */ closePeerConnection() { var _a; (_a = this.peerConnectionController) === null || _a === void 0 ? void 0 : _a.close(); } /** * Close all connections */ close() { this.closeSignalingServer(''); this.closePeerConnection(); } /** * Fires a Video Stats Event in the RTC Peer Connection */ getStats() { this.peerConnectionController.generateStats(); } /** * Send a Latency Test Request to the UE Instance */ sendLatencyTest() { this.latencyStartTime = Date.now(); this.streamMessageController.toStreamerHandlers.get('LatencyTest')([JSON.stringify({ StartTime: this.latencyStartTime })]); } /** * Send a Data Channel Latency Test Request to the UE Instance */ sendDataChannelLatencyTest(descriptor) { this.streamMessageController.toStreamerHandlers.get('DataChannelLatencyTest')([JSON.stringify(descriptor)]); } /** * Send the MinQP encoder setting to the UE Instance. * @param minQP - The lower bound for QP when encoding * valid values are (1-51) where: * 1 = Best quality but highest bitrate. * 51 = Worst quality but lowest bitrate. * By default the minQP is 1 meaning the encoder is free * to aim for the best quality it can on the given network link. */ sendEncoderMinQP(minQP) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), `MinQP=${minQP}\n`, 6); if (minQP != null) { this.streamMessageController.toStreamerHandlers.get('Command')([JSON.stringify({ 'Encoder.MinQP': minQP })]); } } /** * Send the MaxQP encoder setting to the UE Instance. * @param maxQP - The upper bound for QP when encoding * valid values are (1-51) where: * 1 = Best quality but highest bitrate. * 51 = Worst quality but lowest bitrate. * By default the maxQP is 51 meaning the encoder is free * to drop quality as low as needed on the given network link. */ sendEncoderMaxQP(maxQP) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), `MaxQP=${maxQP}\n`, 6); if (maxQP != null) { this.streamMessageController.toStreamerHandlers.get('Command')([JSON.stringify({ 'Encoder.MaxQP': maxQP })]); } } /** * Send the { WebRTC.MinBitrate: SomeNumber }} command to UE to set * the minimum bitrate that we allow WebRTC to use * (note setting this too high in poor networks can be problematic). * @param minBitrate - The minimum bitrate we would like WebRTC to not fall below. */ sendWebRTCMinBitrate(minBitrate) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), `WebRTC Min Bitrate=${minBitrate}`, 6); if (minBitrate != null) { this.streamMessageController.toStreamerHandlers.get('Command')([JSON.stringify({ 'WebRTC.MinBitrate': minBitrate })]); } } /** * Send the { WebRTC.MaxBitrate: SomeNumber }} command to UE to set * the minimum bitrate that we allow WebRTC to use * (note setting this too low could result in blocky video). * @param minBitrate - The minimum bitrate we would like WebRTC to not fall below. */ sendWebRTCMaxBitrate(maxBitrate) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), `WebRTC Max Bitrate=${maxBitrate}`, 6); if (maxBitrate != null) { this.streamMessageController.toStreamerHandlers.get('Command')([JSON.stringify({ 'WebRTC.MaxBitrate': maxBitrate })]); } } /** * Send the { WebRTC.Fps: SomeNumber }} UE 5.0+ * and { WebRTC.MaxFps } UE 4.27 command to set * the maximum fps we would like WebRTC to stream at. * @param fps - The maximum stream fps. */ sendWebRTCFps(fps) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), `WebRTC FPS=${fps}`, 6); if (fps != null) { this.streamMessageController.toStreamerHandlers.get('Command')([JSON.stringify({ 'WebRTC.Fps': fps })]); /* TODO: Remove when UE 4.27 unsupported. */ this.streamMessageController.toStreamerHandlers.get('Command')([JSON.stringify({ 'WebRTC.MaxFps': fps })]); } } /** * Sends the UI Descriptor `stat fps` to the UE Instance */ sendShowFps() { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), '---- Sending show stat to UE ----', 6); this.streamMessageController.toStreamerHandlers.get('Command')([JSON.stringify({ 'stat.fps': '' })]); } /** * Send an Iframe request to the streamer */ sendIframeRequest() { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), '---- Sending Request for an IFrame ----', 6); this.streamMessageController.toStreamerHandlers.get('IFrameRequest')(); } /** * Send a UIInteraction message */ emitUIInteraction(descriptor) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), '---- Sending custom UIInteraction message ----', 6); this.streamMessageController.toStreamerHandlers.get('UIInteraction')([JSON.stringify(descriptor)]); } /** * Send a Command message */ emitCommand(descriptor) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), '---- Sending custom Command message ----', 6); this.streamMessageController.toStreamerHandlers.get('Command')([JSON.stringify(descriptor)]); } /** * Send a console command message */ emitConsoleCommand(command) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), '---- Sending custom Command:ConsoleCommand message ----', 6); this.streamMessageController.toStreamerHandlers.get('Command')([JSON.stringify({ ConsoleCommand: command, })]); } /** * Sends a request to the UE Instance to have ownership of Quality */ sendRequestQualityControlOwnership() { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), '---- Sending Request to Control Quality ----', 6); this.toStreamerMessagesController.SendRequestQualityControl(); } /** * Handles when a Latency Test Result are received from the UE Instance * @param message - Latency Test Timings */ handleLatencyTestResult(message) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), 'DataChannelReceiveMessageType.latencyTest', 6); const latencyAsString = new TextDecoder('utf-16').decode(message.slice(1)); const latencyTestResults = new _DataChannel_LatencyTestResults__WEBPACK_IMPORTED_MODULE_18__.LatencyTestResults(); Object.assign(latencyTestResults, JSON.parse(latencyAsString)); latencyTestResults.processFields(); latencyTestResults.testStartTimeMs = this.latencyStartTime; latencyTestResults.browserReceiptTimeMs = Date.now(); latencyTestResults.latencyExcludingDecode = ~~(latencyTestResults.browserReceiptTimeMs - latencyTestResults.testStartTimeMs); latencyTestResults.testDuration = ~~(latencyTestResults.TransmissionTimeMs - latencyTestResults.ReceiptTimeMs); latencyTestResults.networkLatency = ~~(latencyTestResults.latencyExcludingDecode - latencyTestResults.testDuration); if (latencyTestResults.frameDisplayDeltaTimeMs && latencyTestResults.browserReceiptTimeMs) { latencyTestResults.endToEndLatency = ~~(latencyTestResults.frameDisplayDeltaTimeMs + latencyTestResults.networkLatency, +latencyTestResults.CaptureToSendMs); } this.pixelStreaming._onLatencyTestResult(latencyTestResults); } /** * Handles when a Data Channel Latency Test Response is received from the UE Instance * @param message - Data Channel Latency Test Response */ handleDataChannelLatencyTestResponse(message) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), 'DataChannelReceiveMessageType.dataChannelLatencyResponse', 6); const responseAsString = new TextDecoder('utf-16').decode(message.slice(1)); const latencyTestResponse = JSON.parse(responseAsString); this.pixelStreaming._onDataChannelLatencyTestResponse(latencyTestResponse); } /** * Handles when the Encoder and Web RTC Settings are received from the UE Instance * @param message - Initial Encoder and Web RTC Settings */ handleInitialSettings(message) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), 'DataChannelReceiveMessageType.InitialSettings', 6); const payloadAsString = new TextDecoder('utf-16').decode(message.slice(1)); const parsedInitialSettings = JSON.parse(payloadAsString); const initialSettings = new _DataChannel_InitialSettings__WEBPACK_IMPORTED_MODULE_19__.InitialSettings(); if (parsedInitialSettings.Encoder) { initialSettings.EncoderSettings = parsedInitialSettings.Encoder; } if (parsedInitialSettings.WebRTC) { initialSettings.WebRTCSettings = parsedInitialSettings.WebRTC; } if (parsedInitialSettings.PixelStreaming) { initialSettings.PixelStreamingSettings = parsedInitialSettings.PixelStreaming; } if (parsedInitialSettings.ConfigOptions && parsedInitialSettings.ConfigOptions.DefaultToHover !== undefined) { this.config.setFlagEnabled(_Config_Config__WEBPACK_IMPORTED_MODULE_11__.Flags.HoveringMouseMode, !!parsedInitialSettings.ConfigOptions.DefaultToHover); } initialSettings.ueCompatible(); _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), payloadAsString, 6); this.pixelStreaming._onInitialSettings(initialSettings); } /** * Handles when the Quantization Parameter are received from the UE Instance * @param message - Encoders Quantization Parameter */ handleVideoEncoderAvgQP(message) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), 'DataChannelReceiveMessageType.VideoEncoderAvgQP', 6); const AvgQP = Number(new TextDecoder('utf-16').decode(message.slice(1))); this.setVideoEncoderAvgQP(AvgQP); } /** * Handles when the video element has been loaded with a srcObject */ handleVideoInitialized() { this.pixelStreaming._onVideoInitialized(); // either autoplay the video or set up the play overlay this.autoPlayVideoOrSetUpPlayOverlay(); this.resizePlayerStyle(); this.videoPlayer.updateVideoStreamSize(); } /** * Flag set if the user has Quality Ownership * @param message - Does the current client have Quality Ownership */ onQualityControlOwnership(message) { const view = new Uint8Array(message); _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), 'DataChannelReceiveMessageType.QualityControlOwnership', 6); this.isQualityController = new Boolean(view[1]).valueOf(); _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), `Received quality controller message, will control quality: ${this.isQualityController}`); this.pixelStreaming._onQualityControlOwnership(this.isQualityController); } /** * Handles when the Aggregated stats are Collected * @param stats - Aggregated Stats */ handleVideoStats(stats) { this.pixelStreaming._onVideoStats(stats); } /** * To Resize the Video Player element */ resizePlayerStyle() { this.videoPlayer.resizePlayerStyle(); } setPreferredCodec(codec) { this.preferredCodec = codec; if (this.peerConnectionController) { this.peerConnectionController.preferredCodec = codec; this.peerConnectionController.updateCodecSelection = false; } } setVideoEncoderAvgQP(avgQP) { this.videoAvgQp = avgQP; this.pixelStreaming._onVideoEncoderAvgQP(this.videoAvgQp); } /** * enables/disables keyboard event listeners */ setKeyboardInputEnabled(isEnabled) { var _a; (_a = this.keyboardController) === null || _a === void 0 ? void 0 : _a.unregisterKeyBoardEvents(); if (isEnabled) { this.keyboardController = this.inputClassesFactory.registerKeyBoard(this.config); } } /** * enables/disables mouse event listeners */ setMouseInputEnabled(isEnabled) { var _a; (_a = this.mouseController) === null || _a === void 0 ? void 0 : _a.unregisterMouseEvents(); if (isEnabled) { const mouseMode = this.config.isFlagEnabled(_Config_Config__WEBPACK_IMPORTED_MODULE_11__.Flags.HoveringMouseMode) ? _Config_Config__WEBPACK_IMPORTED_MODULE_11__.ControlSchemeType.HoveringMouse : _Config_Config__WEBPACK_IMPORTED_MODULE_11__.ControlSchemeType.LockedMouse; this.mouseController = this.inputClassesFactory.registerMouse(mouseMode); } } /** * enables/disables touch event listeners */ setTouchInputEnabled(isEnabled) { var _a; (_a = this.touchController) === null || _a === void 0 ? void 0 : _a.unregisterTouchEvents(); if (isEnabled) { this.touchController = this.inputClassesFactory.registerTouch(this.config.isFlagEnabled(_Config_Config__WEBPACK_IMPORTED_MODULE_11__.Flags.FakeMouseWithTouches), this.videoElementParentClientRect); } } /** * enables/disables game pad event listeners */ setGamePadInputEnabled(isEnabled) { var _a; (_a = this.gamePadController) === null || _a === void 0 ? void 0 : _a.unregisterGamePadEvents(); if (isEnabled) { this.gamePadController = this.inputClassesFactory.registerGamePad(); this.gamePadController.onGamepadConnected = () => { this.streamMessageController.toStreamerHandlers.get('GamepadConnected')(); }; this.gamePadController.onGamepadDisconnected = (controllerIdx) => { this.streamMessageController.toStreamerHandlers.get('GamepadDisconnected')([controllerIdx]); }; } } registerDataChannelEventEmitters(dataChannel) { dataChannel.onOpen = (label, event) => this.pixelStreaming.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_16__.DataChannelOpenEvent({ label, event })); dataChannel.onClose = (label, event) => this.pixelStreaming.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_16__.DataChannelCloseEvent({ label, event })); dataChannel.onError = (label, event) => this.pixelStreaming.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_16__.DataChannelErrorEvent({ label, event })); } registerMessageHandler(name, direction, handler) { if (direction === _UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.FromStreamer && typeof handler === 'undefined') { _Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.Warning(_Logger_Logger__WEBPACK_IMPORTED_MODULE_15__.Logger.GetStackTrace(), `Unable to register handler for ${name} as no handler was passed`); } this.streamMessageController.registerMessageHandler(direction, name, (data) => (typeof handler === 'undefined' && direction === _UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_9__.MessageDirection.ToStreamer) ? this.sendMessageController.sendMessageToStreamer(name, data) : handler(data)); } } /***/ }), /***/ "./src/WebSockets/MessageReceive.ts": /*!******************************************!*\ !*** ./src/WebSockets/MessageReceive.ts ***! \******************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "MessageAnswer": () => (/* binding */ MessageAnswer), /* harmony export */ "MessageAuthRequired": () => (/* binding */ MessageAuthRequired), /* harmony export */ "MessageConfig": () => (/* binding */ MessageConfig), /* harmony export */ "MessageIceCandidate": () => (/* binding */ MessageIceCandidate), /* harmony export */ "MessageOffer": () => (/* binding */ MessageOffer), /* harmony export */ "MessageOnScreenKeyboard": () => (/* binding */ MessageOnScreenKeyboard), /* harmony export */ "MessagePeerDataChannels": () => (/* binding */ MessagePeerDataChannels), /* harmony export */ "MessagePlayerCount": () => (/* binding */ MessagePlayerCount), /* harmony export */ "MessageRecv": () => (/* binding */ MessageRecv), /* harmony export */ "MessageRecvTypes": () => (/* binding */ MessageRecvTypes), /* harmony export */ "MessageStreamerList": () => (/* binding */ MessageStreamerList) /* harmony export */ }); // Copyright Epic Games, Inc. All Rights Reserved. /** * The Types of Messages that will be received */ var MessageRecvTypes; (function (MessageRecvTypes) { MessageRecvTypes["CONFIG"] = "config"; MessageRecvTypes["STREAMER_LIST"] = "streamerList"; MessageRecvTypes["PLAYER_COUNT"] = "playerCount"; MessageRecvTypes["OFFER"] = "offer"; MessageRecvTypes["ANSWER"] = "answer"; MessageRecvTypes["ICE_CANDIDATE"] = "iceCandidate"; MessageRecvTypes["PEER_DATA_CHANNELS"] = "peerDataChannels"; MessageRecvTypes["PING"] = "ping"; MessageRecvTypes["WARNING"] = "warning"; })(MessageRecvTypes || (MessageRecvTypes = {})); /** * Concrete Received Message wrapper */ class MessageRecv { } /** * Authentication Required Message wrapper */ class MessageAuthRequired extends MessageRecv { } /** * Config Message Wrapper */ class MessageConfig extends MessageRecv { } /** * Streamer List Message Wrapper */ class MessageStreamerList extends MessageRecv { } /** * Player Count Message wrapper */ class MessagePlayerCount extends MessageRecv { } /** * Web RTC offer Answer Message wrapper */ class MessageAnswer extends MessageRecv { } /** * WebRTC sdp offer Message wrapper. */ class MessageOffer extends MessageRecv { } /** * Ice Candidate Message wrapper */ class MessageIceCandidate extends MessageRecv { } /** * Peer Data Channels Message wrapper */ class MessagePeerDataChannels extends MessageRecv { } class MessageOnScreenKeyboard { } /***/ }), /***/ "./src/WebSockets/MessageSend.ts": /*!***************************************!*\ !*** ./src/WebSockets/MessageSend.ts ***! \***************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "MessageIceCandidate": () => (/* binding */ MessageIceCandidate), /* harmony export */ "MessageListStreamers": () => (/* binding */ MessageListStreamers), /* harmony export */ "MessagePong": () => (/* binding */ MessagePong), /* harmony export */ "MessageSFURecvDataChannelReady": () => (/* binding */ MessageSFURecvDataChannelReady), /* harmony export */ "MessageSend": () => (/* binding */ MessageSend), /* harmony export */ "MessageSendTypes": () => (/* binding */ MessageSendTypes), /* harmony export */ "MessageSubscribe": () => (/* binding */ MessageSubscribe), /* harmony export */ "MessageUnsubscribe": () => (/* binding */ MessageUnsubscribe), /* harmony export */ "MessageWebRTCAnswer": () => (/* binding */ MessageWebRTCAnswer), /* harmony export */ "MessageWebRTCDatachannelRequest": () => (/* binding */ MessageWebRTCDatachannelRequest), /* harmony export */ "MessageWebRTCOffer": () => (/* binding */ MessageWebRTCOffer) /* harmony export */ }); /* harmony import */ var _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Logger/Logger */ "./src/Logger/Logger.ts"); // Copyright Epic Games, Inc. All Rights Reserved. /** * The Send Types that are pushed from the signaling server */ var MessageSendTypes; (function (MessageSendTypes) { MessageSendTypes["LIST_STREAMERS"] = "listStreamers"; MessageSendTypes["SUBSCRIBE"] = "subscribe"; MessageSendTypes["UNSUBSCRIBE"] = "unsubscribe"; MessageSendTypes["ICE_CANDIDATE"] = "iceCandidate"; MessageSendTypes["OFFER"] = "offer"; MessageSendTypes["ANSWER"] = "answer"; MessageSendTypes["DATACHANNELREQUEST"] = "dataChannelRequest"; MessageSendTypes["SFURECVDATACHANNELREADY"] = "peerDataChannelsReady"; MessageSendTypes["PONG"] = "pong"; })(MessageSendTypes || (MessageSendTypes = {})); /** * A Wrapper for the message to send to the signaling server */ class MessageSend { /** * Turns the wrapper into a JSON String * @returns - JSON String of the Message to send */ payload() { _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), 'Sending => \n' + JSON.stringify(this, undefined, 4), 6); return JSON.stringify(this); } } class MessageListStreamers extends MessageSend { constructor() { super(); this.type = MessageSendTypes.LIST_STREAMERS; } } class MessageSubscribe extends MessageSend { constructor(streamerid) { super(); this.type = MessageSendTypes.SUBSCRIBE; this.streamerId = streamerid; } } class MessageUnsubscribe extends MessageSend { constructor() { super(); this.type = MessageSendTypes.UNSUBSCRIBE; } } /** * Instance Request Message Wrapper */ class MessagePong extends MessageSend { constructor(time) { super(); this.type = MessageSendTypes.PONG; this.time = time; } } /** * Web RTC Offer message wrapper */ class MessageWebRTCOffer extends MessageSend { /** * @param offer - Generated Web RTC Offer */ constructor(offer) { super(); this.type = MessageSendTypes.OFFER; if (offer) { this.type = offer.type; this.sdp = offer.sdp; } } } /** * Web RTC Answer message wrapper */ class MessageWebRTCAnswer extends MessageSend { /** * @param answer - Generated Web RTC Offer */ constructor(answer) { super(); this.type = MessageSendTypes.ANSWER; if (answer) { this.type = answer.type; this.sdp = answer.sdp; } } } /** * Web RTC Data channel request message wrapper */ class MessageWebRTCDatachannelRequest extends MessageSend { constructor() { super(); this.type = MessageSendTypes.DATACHANNELREQUEST; } } /** * Web RTC SFU Data channel ready message wrapper */ class MessageSFURecvDataChannelReady extends MessageSend { constructor() { super(); this.type = MessageSendTypes.SFURECVDATACHANNELREADY; } } /** * RTC Ice Candidate Wrapper */ class MessageIceCandidate { /** * @param candidate - RTC Ice Candidate */ constructor(candidate) { this.type = MessageSendTypes.ICE_CANDIDATE; this.candidate = candidate; } /** * Turns the wrapper into a JSON String * @returns - JSON String of the Message to send */ payload() { _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), 'Sending => \n' + JSON.stringify(this, undefined, 4), 6); return JSON.stringify(this); } } /***/ }), /***/ "./src/WebSockets/SignallingProtocol.ts": /*!**********************************************!*\ !*** ./src/WebSockets/SignallingProtocol.ts ***! \**********************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "SignallingProtocol": () => (/* binding */ SignallingProtocol) /* harmony export */ }); /* harmony import */ var _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Logger/Logger */ "./src/Logger/Logger.ts"); /* harmony import */ var _MessageReceive__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./MessageReceive */ "./src/WebSockets/MessageReceive.ts"); /* harmony import */ var _MessageSend__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./MessageSend */ "./src/WebSockets/MessageSend.ts"); // Copyright Epic Games, Inc. All Rights Reserved. /** * Signalling protocol for handling messages from the signalling server. */ class SignallingProtocol { constructor() { this.FromUEMessageHandlers = new Map(); } addMessageHandler(messageId, messageHandler) { this.FromUEMessageHandlers.set(messageId, messageHandler); } handleMessage(messageId, messageData) { if (this.FromUEMessageHandlers.has(messageId)) { this.FromUEMessageHandlers.get(messageId)(messageData); } else { _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Error(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), `Message type of ${messageId} does not have a message handler registered on the frontend - ignoring message.`); } } /** * Setup any default signalling message handling, these can be overridden or additional handlers added with `addMessageHandler`. * @param websocketController The controller to setup these handlers on. */ static setupDefaultHandlers(websocketController) { // PING websocketController.signallingProtocol.addMessageHandler(_MessageReceive__WEBPACK_IMPORTED_MODULE_1__.MessageRecvTypes.PING, (pingPayload) => { // send our pong payload back to the signalling server const pongPayload = new _MessageSend__WEBPACK_IMPORTED_MODULE_2__.MessagePong(new Date().getTime()).payload(); _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), _MessageReceive__WEBPACK_IMPORTED_MODULE_1__.MessageRecvTypes.PING + ': ' + pingPayload, 6); websocketController.webSocket.send(pongPayload); }); // CONFIG websocketController.signallingProtocol.addMessageHandler(_MessageReceive__WEBPACK_IMPORTED_MODULE_1__.MessageRecvTypes.CONFIG, (configPayload) => { _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), _MessageReceive__WEBPACK_IMPORTED_MODULE_1__.MessageRecvTypes.CONFIG, 6); const config = JSON.parse(configPayload); websocketController.onConfig(config); }); // STREAMER_LIST websocketController.signallingProtocol.addMessageHandler(_MessageReceive__WEBPACK_IMPORTED_MODULE_1__.MessageRecvTypes.STREAMER_LIST, (listPayload) => { _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), _MessageReceive__WEBPACK_IMPORTED_MODULE_1__.MessageRecvTypes.STREAMER_LIST, 6); const streamerList = JSON.parse(listPayload); websocketController.onStreamerList(streamerList); }); // PLAYER_COUNT websocketController.signallingProtocol.addMessageHandler(_MessageReceive__WEBPACK_IMPORTED_MODULE_1__.MessageRecvTypes.PLAYER_COUNT, (playerCountPayload) => { _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), _MessageReceive__WEBPACK_IMPORTED_MODULE_1__.MessageRecvTypes.PLAYER_COUNT, 6); const playerCount = JSON.parse(playerCountPayload); _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), 'Player Count: ' + playerCount.count, 6); websocketController.onPlayerCount(playerCount); }); // ANSWER websocketController.signallingProtocol.addMessageHandler(_MessageReceive__WEBPACK_IMPORTED_MODULE_1__.MessageRecvTypes.ANSWER, (answerPayload) => { // send our pong payload back to the signalling server _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), _MessageReceive__WEBPACK_IMPORTED_MODULE_1__.MessageRecvTypes.ANSWER, 6); const answer = JSON.parse(answerPayload); websocketController.onWebRtcAnswer(answer); }); // OFFER websocketController.signallingProtocol.addMessageHandler(_MessageReceive__WEBPACK_IMPORTED_MODULE_1__.MessageRecvTypes.OFFER, (offerPayload) => { // send our pong payload back to the signalling server _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), _MessageReceive__WEBPACK_IMPORTED_MODULE_1__.MessageRecvTypes.OFFER, 6); const offer = JSON.parse(offerPayload); websocketController.onWebRtcOffer(offer); }); // ICE CANDIDATE websocketController.signallingProtocol.addMessageHandler(_MessageReceive__WEBPACK_IMPORTED_MODULE_1__.MessageRecvTypes.ICE_CANDIDATE, (iceCandidatePayload) => { // send our pong payload back to the signalling server _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), _MessageReceive__WEBPACK_IMPORTED_MODULE_1__.MessageRecvTypes.ICE_CANDIDATE, 6); const iceCandidate = JSON.parse(iceCandidatePayload); websocketController.onIceCandidate(iceCandidate.candidate); }); // WARNING websocketController.signallingProtocol.addMessageHandler(_MessageReceive__WEBPACK_IMPORTED_MODULE_1__.MessageRecvTypes.WARNING, (warningPayload) => { _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Warning(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), `Warning received: ${warningPayload}`); }); // PEER DATA CHANNELS websocketController.signallingProtocol.addMessageHandler(_MessageReceive__WEBPACK_IMPORTED_MODULE_1__.MessageRecvTypes.PEER_DATA_CHANNELS, (peerDataChannelsPayload) => { _Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_0__.Logger.GetStackTrace(), _MessageReceive__WEBPACK_IMPORTED_MODULE_1__.MessageRecvTypes.PEER_DATA_CHANNELS, 6); const peerDataChannels = JSON.parse(peerDataChannelsPayload); websocketController.onWebRtcPeerDataChannels(peerDataChannels); }); } } /***/ }), /***/ "./src/WebSockets/WebSocketController.ts": /*!***********************************************!*\ !*** ./src/WebSockets/WebSocketController.ts ***! \***********************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "WebSocketController": () => (/* binding */ WebSocketController) /* harmony export */ }); /* harmony import */ var _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Logger/Logger */ "./src/Logger/Logger.ts"); /* harmony import */ var _MessageSend__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./MessageSend */ "./src/WebSockets/MessageSend.ts"); /* harmony import */ var _SignallingProtocol__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./SignallingProtocol */ "./src/WebSockets/SignallingProtocol.ts"); // Copyright Epic Games, Inc. All Rights Reserved. /** * The controller for the WebSocket and all associated methods */ class WebSocketController { constructor() { this.WS_OPEN_STATE = 1; this.onOpen = new EventTarget(); this.onClose = new EventTarget(); this.signallingProtocol = new _SignallingProtocol__WEBPACK_IMPORTED_MODULE_0__.SignallingProtocol(); _SignallingProtocol__WEBPACK_IMPORTED_MODULE_0__.SignallingProtocol.setupDefaultHandlers(this); } /** * Connect to the signaling server * @param connectionURL - The Address of the signaling server * @returns - If there is a connection */ connect(connectionURL) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.GetStackTrace(), connectionURL, 6); try { this.webSocket = new WebSocket(connectionURL); this.webSocket.onopen = (event) => this.handleOnOpen(event); this.webSocket.onerror = () => this.handleOnError(); this.webSocket.onclose = (event) => this.handleOnClose(event); this.webSocket.onmessage = (event) => this.handleOnMessage(event); this.webSocket.onmessagebinary = (event) => this.handleOnMessageBinary(event); return true; } catch (error) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Error(error, error); return false; } } /** * Handles what happens when a message is received in binary form * @param event - Message Received */ handleOnMessageBinary(event) { // if the event is empty return if (!event || !event.data) { return; } // handle the binary and then handle the message event.data .text() .then((messageString) => { // build a new message const constructedMessage = new MessageEvent('messageFromBinary', { data: messageString }); // send the new stringified event back into `onmessage` this.handleOnMessage(constructedMessage); }) .catch((error) => { _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Error(_Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.GetStackTrace(), `Failed to parse binary blob from websocket, reason: ${error}`); }); } /** * Handles what happens when a message is received * @param event - Message Received */ handleOnMessage(event) { // Check if websocket message is binary, if so, stringify it. if (event.data && event.data instanceof Blob) { this.handleOnMessageBinary(event); return; } const message = JSON.parse(event.data); _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.GetStackTrace(), 'received => \n' + JSON.stringify(JSON.parse(event.data), undefined, 4), 6); // Send to our signalling protocol to handle the incoming message this.signallingProtocol.handleMessage(message.type, event.data); } /** * Handles when the Websocket is opened * @param event - Not Used */ // eslint-disable-next-line @typescript-eslint/no-unused-vars handleOnOpen(event) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.GetStackTrace(), 'Connected to the signalling server via WebSocket', 6); this.onOpen.dispatchEvent(new Event('open')); } /** * Handles when there is an error on the websocket * @param event - Error Payload */ handleOnError() { _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Error(_Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.GetStackTrace(), 'WebSocket error'); } /** * Handles when the Websocket is closed * @param event - Close Event */ handleOnClose(event) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.GetStackTrace(), 'Disconnected to the signalling server via WebSocket: ' + JSON.stringify(event.code) + ' - ' + event.reason); this.onClose.dispatchEvent(new CustomEvent('close', { 'detail': event })); } requestStreamerList() { const payload = new _MessageSend__WEBPACK_IMPORTED_MODULE_2__.MessageListStreamers(); this.webSocket.send(payload.payload()); } sendSubscribe(streamerid) { const payload = new _MessageSend__WEBPACK_IMPORTED_MODULE_2__.MessageSubscribe(streamerid); this.webSocket.send(payload.payload()); } sendUnsubscribe() { const payload = new _MessageSend__WEBPACK_IMPORTED_MODULE_2__.MessageUnsubscribe(); this.webSocket.send(payload.payload()); } sendWebRtcOffer(offer) { const payload = new _MessageSend__WEBPACK_IMPORTED_MODULE_2__.MessageWebRTCOffer(offer); this.webSocket.send(payload.payload()); } sendWebRtcAnswer(answer) { const payload = new _MessageSend__WEBPACK_IMPORTED_MODULE_2__.MessageWebRTCAnswer(answer); this.webSocket.send(payload.payload()); } sendWebRtcDatachannelRequest() { const payload = new _MessageSend__WEBPACK_IMPORTED_MODULE_2__.MessageWebRTCDatachannelRequest(); this.webSocket.send(payload.payload()); } sendSFURecvDataChannelReady() { const payload = new _MessageSend__WEBPACK_IMPORTED_MODULE_2__.MessageSFURecvDataChannelReady(); this.webSocket.send(payload.payload()); } /** * Sends an RTC Ice Candidate to the Server * @param candidate - RTC Ice Candidate */ sendIceCandidate(candidate) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.GetStackTrace(), 'Sending Ice Candidate'); if (this.webSocket && this.webSocket.readyState === this.WS_OPEN_STATE) { //ws.send(JSON.stringify({ type: 'iceCandidate', candidate: candidate })); const IceCandidate = new _MessageSend__WEBPACK_IMPORTED_MODULE_2__.MessageIceCandidate(candidate); this.webSocket.send(IceCandidate.payload()); } } /** * Closes the Websocket connection */ close() { var _a; (_a = this.webSocket) === null || _a === void 0 ? void 0 : _a.close(); } /** * The Message Contains the payload of the peer connection options used for the RTC Peer hand shake * @param messageConfig - Config Message received from he signaling server */ // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function onConfig(messageConfig) { } /** * The Message Contains the payload of the peer connection options used for the RTC Peer hand shake * @param messageConfig - Config Message received from he signaling server */ // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function onStreamerList(messageStreamerList) { } /** * @param iceCandidate - Ice Candidate sent from the Signaling server server's RTC hand shake */ // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function onIceCandidate(iceCandidate) { } /** * Event is fired when the websocket receives the answer for the RTC peer Connection * @param messageAnswer - The RTC Answer payload from the signaling server */ // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function onWebRtcAnswer(messageAnswer) { } /** * Event is fired when the websocket receives the offer for the RTC peer Connection * @param messageOffer - The sdp offer */ // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function onWebRtcOffer(messageOffer) { } /** * Event is fired when the websocket receives the data channels for the RTC peer Connection from the SFU * @param messageDataChannels - The data channels details */ // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function onWebRtcPeerDataChannels(messageDataChannels) { } /** * Event is fired when the websocket receives the an updated player count from cirrus * @param MessagePlayerCount - The new player count */ // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function onPlayerCount(playerCount) { } } /***/ }), /***/ "./src/WebXR/WebXRController.ts": /*!**************************************!*\ !*** ./src/WebXR/WebXRController.ts ***! \**************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "WebXRController": () => (/* binding */ WebXRController) /* harmony export */ }); /* harmony import */ var _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../Logger/Logger */ "./src/Logger/Logger.ts"); /* harmony import */ var _Util_WebGLUtils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../Util/WebGLUtils */ "./src/Util/WebGLUtils.ts"); /* harmony import */ var _Inputs_XRGamepadController__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../Inputs/XRGamepadController */ "./src/Inputs/XRGamepadController.ts"); /* harmony import */ var _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../Util/EventEmitter */ "./src/Util/EventEmitter.ts"); /* harmony import */ var _pixelstreamingfrontend__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../pixelstreamingfrontend */ "./src/Config/Config.ts"); // Copyright Epic Games, Inc. All Rights Reserved. class WebXRController { constructor(webRtcPlayerController) { this.xrSession = null; this.webRtcController = webRtcPlayerController; this.xrControllers = []; this.xrGamepadController = new _Inputs_XRGamepadController__WEBPACK_IMPORTED_MODULE_0__.XRGamepadController(this.webRtcController.streamMessageController); this.onSessionEnded = new EventTarget(); this.onSessionStarted = new EventTarget(); this.onFrame = new EventTarget(); } xrClicked() { if (!this.xrSession) { navigator.xr .requestSession('immersive-vr') .then((session) => { this.onXrSessionStarted(session); }); } else { this.xrSession.end(); } } onXrSessionEnded() { _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.GetStackTrace(), 'XR Session ended'); this.xrSession = null; this.onSessionEnded.dispatchEvent(new Event('xrSessionEnded')); } onXrSessionStarted(session) { _Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Log(_Logger_Logger__WEBPACK_IMPORTED_MODULE_1__.Logger.GetStackTrace(), 'XR Session started'); this.xrSession = session; this.xrSession.addEventListener('end', () => { this.onXrSessionEnded(); }); const canvas = document.createElement('canvas'); this.gl = canvas.getContext('webgl2', { xrCompatible: true }); this.xrSession.updateRenderState({ baseLayer: new XRWebGLLayer(this.xrSession, this.gl) }); // setup vertex shader const vertexShader = this.gl.createShader(this.gl.VERTEX_SHADER); this.gl.shaderSource(vertexShader, _Util_WebGLUtils__WEBPACK_IMPORTED_MODULE_2__.WebGLUtils.vertexShader()); this.gl.compileShader(vertexShader); // setup fragment shader const fragmentShader = this.gl.createShader(this.gl.FRAGMENT_SHADER); this.gl.shaderSource(fragmentShader, _Util_WebGLUtils__WEBPACK_IMPORTED_MODULE_2__.WebGLUtils.fragmentShader()); this.gl.compileShader(fragmentShader); // setup GLSL program const shaderProgram = this.gl.createProgram(); this.gl.attachShader(shaderProgram, vertexShader); this.gl.attachShader(shaderProgram, fragmentShader); this.gl.linkProgram(shaderProgram); this.gl.useProgram(shaderProgram); // look up where vertex data needs to go this.positionLocation = this.gl.getAttribLocation(shaderProgram, 'a_position'); this.texcoordLocation = this.gl.getAttribLocation(shaderProgram, 'a_texCoord'); // Create a buffer to put three 2d clip space points in this.positionBuffer = this.gl.createBuffer(); // Bind it to ARRAY_BUFFER (think of it as ARRAY_BUFFER = positionBuffer) this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.positionBuffer); // Turn on the position attribute this.gl.enableVertexAttribArray(this.positionLocation); // Create a texture. const texture = this.gl.createTexture(); this.gl.bindTexture(this.gl.TEXTURE_2D, texture); // Set the parameters so we can render any size image. this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE); this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE); this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.NEAREST); this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.NEAREST); this.texcoordBuffer = this.gl.createBuffer(); // lookup uniforms this.resolutionLocation = this.gl.getUniformLocation(shaderProgram, 'u_resolution'); this.offsetLocation = this.gl.getUniformLocation(shaderProgram, 'u_offset'); session.requestReferenceSpace('local').then((refSpace) => { this.xrRefSpace = refSpace; this.xrSession.requestAnimationFrame((time, frame) => this.onXrFrame(time, frame)); }); this.onSessionStarted.dispatchEvent(new Event('xrSessionStarted')); } onXrFrame(time, frame) { const pose = frame.getViewerPose(this.xrRefSpace); if (pose) { const matrix = pose.transform.matrix; const mat = []; for (let i = 0; i < 16; i++) { mat[i] = new Float32Array([matrix[i]])[0]; } // prettier-ignore this.webRtcController.streamMessageController.toStreamerHandlers.get('XRHMDTransform')([ mat[0], mat[4], mat[8], mat[12], mat[1], mat[5], mat[9], mat[13], mat[2], mat[6], mat[10], mat[14], mat[3], mat[7], mat[11], mat[15] ]); const glLayer = this.xrSession.renderState.baseLayer; // If we do have a valid pose, bind the WebGL layer's framebuffer, // which is where any content to be displayed on the XRDevice must be // rendered. this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, glLayer.framebuffer); // Upload the image into the texture. WebGL knows how to extract the current frame from the video element this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.gl.RGBA, this.gl.UNSIGNED_BYTE, this.webRtcController.videoPlayer.getVideoElement()); this.render(this.webRtcController.videoPlayer.getVideoElement()); } if (this.webRtcController.config.isFlagEnabled(_pixelstreamingfrontend__WEBPACK_IMPORTED_MODULE_3__.Flags.XRControllerInput)) { this.xrSession.inputSources.forEach((source, index, array) => { this.xrGamepadController.updateStatus(source, frame, this.xrRefSpace); }, this); } this.xrSession.requestAnimationFrame((time, frame) => this.onXrFrame(time, frame)); this.onFrame.dispatchEvent(new _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_4__.XrFrameEvent({ time, frame })); } render(videoElement) { if (!this.gl) { return; } const glLayer = this.xrSession.renderState.baseLayer; this.gl.viewport(0, 0, glLayer.framebufferWidth, glLayer.framebufferHeight); this.gl.uniform4f(this.offsetLocation, 1.0, 1.0, 0.0, 0.0); // Set rectangle // prettier-ignore this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array([ 0, 0, videoElement.videoWidth, 0, 0, videoElement.videoHeight, 0, videoElement.videoHeight, videoElement.videoWidth, 0, videoElement.videoWidth, videoElement.videoHeight ]), this.gl.STATIC_DRAW); // Provide texture coordinates for the rectangle this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.texcoordBuffer); this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array([ 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0 ]), this.gl.STATIC_DRAW); let size; // components per iteration let type; // the data type let normalize; // normalize the data let stride; // 0 = move forward size * sizeof(type) each iteration to get the next position let offset; // start position of the buffer // Bind the position buffer. this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.positionBuffer); // Tell the position attribute how to get data out of positionBuffer (ARRAY_BUFFER) size = 2; // 2 components per iteration type = this.gl.FLOAT; // the data is 32bit floats normalize = false; // don't normalize the data stride = 0; // 0 = move forward size * sizeof(type) each iteration to get the next position offset = 0; // start at the beginning of the buffer this.gl.vertexAttribPointer(this.positionLocation, size, type, normalize, stride, offset); // Turn on the texcoord attribute this.gl.enableVertexAttribArray(this.texcoordLocation); // bind the texcoord buffer. this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.texcoordBuffer); // Tell the texcoord attribute how to get data out of texcoordBuffer (ARRAY_BUFFER) size = 2; // 2 components per iteration type = this.gl.FLOAT; // the data is 32bit floats normalize = false; // don't normalize the data stride = 0; // 0 = move forward size * sizeof(type) each iteration to get the next position offset = 0; // start at the beginning of the buffer this.gl.vertexAttribPointer(this.texcoordLocation, size, type, normalize, stride, offset); // set the resolution this.gl.uniform2f(this.resolutionLocation, videoElement.videoWidth, videoElement.videoHeight); // draw the rectangle. const primitiveType = this.gl.TRIANGLES; const count = 6; offset = 0; this.gl.drawArrays(primitiveType, offset, count); } static isSessionSupported(mode) { if (navigator.xr) { return navigator.xr.isSessionSupported(mode); } else { return new Promise(() => { return false; }); } } } /***/ }), /***/ "sdp": /*!**********************!*\ !*** external "sdp" ***! \**********************/ /***/ ((module) => { var x = y => { var x = {}; __webpack_require__.d(x, y); return x; } var y = x => () => x module.exports = __WEBPACK_EXTERNAL_MODULE_sdp__; /***/ }) /******/ }); /************************************************************************/ /******/ // The module cache /******/ var __webpack_module_cache__ = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache /******/ var cachedModule = __webpack_module_cache__[moduleId]; /******/ if (cachedModule !== undefined) { /******/ return cachedModule.exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = __webpack_module_cache__[moduleId] = { /******/ // no module.id needed /******/ // no module.loaded needed /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /************************************************************************/ /******/ /* webpack/runtime/define property getters */ /******/ (() => { /******/ // define getter functions for harmony exports /******/ __webpack_require__.d = (exports, definition) => { /******/ for(var key in definition) { /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); /******/ } /******/ } /******/ }; /******/ })(); /******/ /******/ /* webpack/runtime/hasOwnProperty shorthand */ /******/ (() => { /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) /******/ })(); /******/ /******/ /* webpack/runtime/make namespace object */ /******/ (() => { /******/ // define __esModule on exports /******/ __webpack_require__.r = (exports) => { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ })(); /******/ /************************************************************************/ var __webpack_exports__ = {}; // This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. (() => { /*!***************************************!*\ !*** ./src/pixelstreamingfrontend.ts ***! \***************************************/ __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "AfkLogic": () => (/* reexport safe */ _AFK_AFKController__WEBPACK_IMPORTED_MODULE_9__.AFKController), /* harmony export */ "AfkTimedOutEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.AfkTimedOutEvent), /* harmony export */ "AfkWarningActivateEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.AfkWarningActivateEvent), /* harmony export */ "AfkWarningDeactivateEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.AfkWarningDeactivateEvent), /* harmony export */ "AfkWarningUpdateEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.AfkWarningUpdateEvent), /* harmony export */ "AggregatedStats": () => (/* reexport safe */ _PeerConnectionController_AggregatedStats__WEBPACK_IMPORTED_MODULE_12__.AggregatedStats), /* harmony export */ "CandidatePairStats": () => (/* reexport safe */ _PeerConnectionController_CandidatePairStats__WEBPACK_IMPORTED_MODULE_20__.CandidatePairStats), /* harmony export */ "CandidateStat": () => (/* reexport safe */ _PeerConnectionController_CandidateStat__WEBPACK_IMPORTED_MODULE_21__.CandidateStat), /* harmony export */ "Config": () => (/* reexport safe */ _Config_Config__WEBPACK_IMPORTED_MODULE_2__.Config), /* harmony export */ "ControlSchemeType": () => (/* reexport safe */ _Config_Config__WEBPACK_IMPORTED_MODULE_2__.ControlSchemeType), /* harmony export */ "DataChannelCloseEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.DataChannelCloseEvent), /* harmony export */ "DataChannelErrorEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.DataChannelErrorEvent), /* harmony export */ "DataChannelLatencyTestResponseEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.DataChannelLatencyTestResponseEvent), /* harmony export */ "DataChannelLatencyTestResultEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.DataChannelLatencyTestResultEvent), /* harmony export */ "DataChannelOpenEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.DataChannelOpenEvent), /* harmony export */ "DataChannelStats": () => (/* reexport safe */ _PeerConnectionController_DataChannelStats__WEBPACK_IMPORTED_MODULE_22__.DataChannelStats), /* harmony export */ "EncoderSettings": () => (/* reexport safe */ _DataChannel_InitialSettings__WEBPACK_IMPORTED_MODULE_11__.EncoderSettings), /* harmony export */ "EventEmitter": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.EventEmitter), /* harmony export */ "Flags": () => (/* reexport safe */ _Config_Config__WEBPACK_IMPORTED_MODULE_2__.Flags), /* harmony export */ "HideFreezeFrameEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.HideFreezeFrameEvent), /* harmony export */ "InboundAudioStats": () => (/* reexport safe */ _PeerConnectionController_InboundRTPStats__WEBPACK_IMPORTED_MODULE_23__.InboundAudioStats), /* harmony export */ "InboundVideoStats": () => (/* reexport safe */ _PeerConnectionController_InboundRTPStats__WEBPACK_IMPORTED_MODULE_23__.InboundVideoStats), /* harmony export */ "InitialSettings": () => (/* reexport safe */ _DataChannel_InitialSettings__WEBPACK_IMPORTED_MODULE_11__.InitialSettings), /* harmony export */ "InitialSettingsEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.InitialSettingsEvent), /* harmony export */ "LatencyTestResultEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.LatencyTestResultEvent), /* harmony export */ "LatencyTestResults": () => (/* reexport safe */ _DataChannel_LatencyTestResults__WEBPACK_IMPORTED_MODULE_10__.LatencyTestResults), /* harmony export */ "LoadFreezeFrameEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.LoadFreezeFrameEvent), /* harmony export */ "Logger": () => (/* reexport safe */ _Logger_Logger__WEBPACK_IMPORTED_MODULE_13__.Logger), /* harmony export */ "MessageDirection": () => (/* reexport safe */ _UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_15__.MessageDirection), /* harmony export */ "MessageRecv": () => (/* reexport safe */ _WebSockets_MessageReceive__WEBPACK_IMPORTED_MODULE_17__.MessageRecv), /* harmony export */ "MessageSend": () => (/* reexport safe */ _WebSockets_MessageSend__WEBPACK_IMPORTED_MODULE_16__.MessageSend), /* harmony export */ "MessageStreamerList": () => (/* reexport safe */ _WebSockets_MessageReceive__WEBPACK_IMPORTED_MODULE_17__.MessageStreamerList), /* harmony export */ "NumericParameters": () => (/* reexport safe */ _Config_Config__WEBPACK_IMPORTED_MODULE_2__.NumericParameters), /* harmony export */ "OptionParameters": () => (/* reexport safe */ _Config_Config__WEBPACK_IMPORTED_MODULE_2__.OptionParameters), /* harmony export */ "OutBoundVideoStats": () => (/* reexport safe */ _PeerConnectionController_OutBoundRTPStats__WEBPACK_IMPORTED_MODULE_24__.OutBoundVideoStats), /* harmony export */ "PixelStreaming": () => (/* reexport safe */ _PixelStreaming_PixelStreaming__WEBPACK_IMPORTED_MODULE_8__.PixelStreaming), /* harmony export */ "PlayStreamErrorEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.PlayStreamErrorEvent), /* harmony export */ "PlayStreamEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.PlayStreamEvent), /* harmony export */ "PlayStreamRejectedEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.PlayStreamRejectedEvent), /* harmony export */ "PlayerCountEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.PlayerCountEvent), /* harmony export */ "SettingBase": () => (/* reexport safe */ _Config_SettingBase__WEBPACK_IMPORTED_MODULE_3__.SettingBase), /* harmony export */ "SettingFlag": () => (/* reexport safe */ _Config_SettingFlag__WEBPACK_IMPORTED_MODULE_4__.SettingFlag), /* harmony export */ "SettingNumber": () => (/* reexport safe */ _Config_SettingNumber__WEBPACK_IMPORTED_MODULE_5__.SettingNumber), /* harmony export */ "SettingOption": () => (/* reexport safe */ _Config_SettingOption__WEBPACK_IMPORTED_MODULE_6__.SettingOption), /* harmony export */ "SettingText": () => (/* reexport safe */ _Config_SettingText__WEBPACK_IMPORTED_MODULE_7__.SettingText), /* harmony export */ "SettingsChangedEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.SettingsChangedEvent), /* harmony export */ "SignallingProtocol": () => (/* reexport safe */ _WebSockets_SignallingProtocol__WEBPACK_IMPORTED_MODULE_19__.SignallingProtocol), /* harmony export */ "StatsReceivedEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.StatsReceivedEvent), /* harmony export */ "StreamLoadingEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.StreamLoadingEvent), /* harmony export */ "StreamPreConnectEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.StreamPreConnectEvent), /* harmony export */ "StreamPreDisconnectEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.StreamPreDisconnectEvent), /* harmony export */ "StreamReconnectEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.StreamReconnectEvent), /* harmony export */ "StreamerListMessageEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.StreamerListMessageEvent), /* harmony export */ "TextParameters": () => (/* reexport safe */ _Config_Config__WEBPACK_IMPORTED_MODULE_2__.TextParameters), /* harmony export */ "UnquantizedAndDenormalizeUnsigned": () => (/* reexport safe */ _Util_CoordinateConverter__WEBPACK_IMPORTED_MODULE_14__.UnquantizedDenormalizedUnsignedCoord), /* harmony export */ "VideoEncoderAvgQPEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.VideoEncoderAvgQPEvent), /* harmony export */ "VideoInitializedEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.VideoInitializedEvent), /* harmony export */ "WebRTCSettings": () => (/* reexport safe */ _DataChannel_InitialSettings__WEBPACK_IMPORTED_MODULE_11__.WebRTCSettings), /* harmony export */ "WebRtcAutoConnectEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.WebRtcAutoConnectEvent), /* harmony export */ "WebRtcConnectedEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.WebRtcConnectedEvent), /* harmony export */ "WebRtcConnectingEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.WebRtcConnectingEvent), /* harmony export */ "WebRtcDisconnectedEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.WebRtcDisconnectedEvent), /* harmony export */ "WebRtcFailedEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.WebRtcFailedEvent), /* harmony export */ "WebRtcPlayerController": () => (/* reexport safe */ _WebRtcPlayer_WebRtcPlayerController__WEBPACK_IMPORTED_MODULE_0__.WebRtcPlayerController), /* harmony export */ "WebRtcSdpEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.WebRtcSdpEvent), /* harmony export */ "WebSocketController": () => (/* reexport safe */ _WebSockets_WebSocketController__WEBPACK_IMPORTED_MODULE_18__.WebSocketController), /* harmony export */ "WebXRController": () => (/* reexport safe */ _WebXR_WebXRController__WEBPACK_IMPORTED_MODULE_1__.WebXRController), /* harmony export */ "XrFrameEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.XrFrameEvent), /* harmony export */ "XrSessionEndedEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.XrSessionEndedEvent), /* harmony export */ "XrSessionStartedEvent": () => (/* reexport safe */ _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__.XrSessionStartedEvent) /* harmony export */ }); /* harmony import */ var _WebRtcPlayer_WebRtcPlayerController__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./WebRtcPlayer/WebRtcPlayerController */ "./src/WebRtcPlayer/WebRtcPlayerController.ts"); /* harmony import */ var _WebXR_WebXRController__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./WebXR/WebXRController */ "./src/WebXR/WebXRController.ts"); /* harmony import */ var _Config_Config__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Config/Config */ "./src/Config/Config.ts"); /* harmony import */ var _Config_SettingBase__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Config/SettingBase */ "./src/Config/SettingBase.ts"); /* harmony import */ var _Config_SettingFlag__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./Config/SettingFlag */ "./src/Config/SettingFlag.ts"); /* harmony import */ var _Config_SettingNumber__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./Config/SettingNumber */ "./src/Config/SettingNumber.ts"); /* harmony import */ var _Config_SettingOption__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./Config/SettingOption */ "./src/Config/SettingOption.ts"); /* harmony import */ var _Config_SettingText__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./Config/SettingText */ "./src/Config/SettingText.ts"); /* harmony import */ var _PixelStreaming_PixelStreaming__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./PixelStreaming/PixelStreaming */ "./src/PixelStreaming/PixelStreaming.ts"); /* harmony import */ var _AFK_AFKController__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./AFK/AFKController */ "./src/AFK/AFKController.ts"); /* harmony import */ var _DataChannel_LatencyTestResults__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./DataChannel/LatencyTestResults */ "./src/DataChannel/LatencyTestResults.ts"); /* harmony import */ var _DataChannel_InitialSettings__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./DataChannel/InitialSettings */ "./src/DataChannel/InitialSettings.ts"); /* harmony import */ var _PeerConnectionController_AggregatedStats__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./PeerConnectionController/AggregatedStats */ "./src/PeerConnectionController/AggregatedStats.ts"); /* harmony import */ var _Logger_Logger__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./Logger/Logger */ "./src/Logger/Logger.ts"); /* harmony import */ var _Util_CoordinateConverter__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./Util/CoordinateConverter */ "./src/Util/CoordinateConverter.ts"); /* harmony import */ var _UeInstanceMessage_StreamMessageController__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./UeInstanceMessage/StreamMessageController */ "./src/UeInstanceMessage/StreamMessageController.ts"); /* harmony import */ var _WebSockets_MessageSend__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./WebSockets/MessageSend */ "./src/WebSockets/MessageSend.ts"); /* harmony import */ var _WebSockets_MessageReceive__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./WebSockets/MessageReceive */ "./src/WebSockets/MessageReceive.ts"); /* harmony import */ var _WebSockets_WebSocketController__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./WebSockets/WebSocketController */ "./src/WebSockets/WebSocketController.ts"); /* harmony import */ var _WebSockets_SignallingProtocol__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./WebSockets/SignallingProtocol */ "./src/WebSockets/SignallingProtocol.ts"); /* harmony import */ var _PeerConnectionController_CandidatePairStats__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ./PeerConnectionController/CandidatePairStats */ "./src/PeerConnectionController/CandidatePairStats.ts"); /* harmony import */ var _PeerConnectionController_CandidateStat__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ./PeerConnectionController/CandidateStat */ "./src/PeerConnectionController/CandidateStat.ts"); /* harmony import */ var _PeerConnectionController_DataChannelStats__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ./PeerConnectionController/DataChannelStats */ "./src/PeerConnectionController/DataChannelStats.ts"); /* harmony import */ var _PeerConnectionController_InboundRTPStats__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ./PeerConnectionController/InboundRTPStats */ "./src/PeerConnectionController/InboundRTPStats.ts"); /* harmony import */ var _PeerConnectionController_OutBoundRTPStats__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ./PeerConnectionController/OutBoundRTPStats */ "./src/PeerConnectionController/OutBoundRTPStats.ts"); /* harmony import */ var _Util_EventEmitter__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ./Util/EventEmitter */ "./src/Util/EventEmitter.ts"); // Copyright Epic Games, Inc. All Rights Reserved. })(); var __webpack_exports__AfkLogic = __webpack_exports__.AfkLogic; var __webpack_exports__AfkTimedOutEvent = __webpack_exports__.AfkTimedOutEvent; var __webpack_exports__AfkWarningActivateEvent = __webpack_exports__.AfkWarningActivateEvent; var __webpack_exports__AfkWarningDeactivateEvent = __webpack_exports__.AfkWarningDeactivateEvent; var __webpack_exports__AfkWarningUpdateEvent = __webpack_exports__.AfkWarningUpdateEvent; var __webpack_exports__AggregatedStats = __webpack_exports__.AggregatedStats; var __webpack_exports__CandidatePairStats = __webpack_exports__.CandidatePairStats; var __webpack_exports__CandidateStat = __webpack_exports__.CandidateStat; var __webpack_exports__Config = __webpack_exports__.Config; var __webpack_exports__ControlSchemeType = __webpack_exports__.ControlSchemeType; var __webpack_exports__DataChannelCloseEvent = __webpack_exports__.DataChannelCloseEvent; var __webpack_exports__DataChannelErrorEvent = __webpack_exports__.DataChannelErrorEvent; var __webpack_exports__DataChannelLatencyTestResponseEvent = __webpack_exports__.DataChannelLatencyTestResponseEvent; var __webpack_exports__DataChannelLatencyTestResultEvent = __webpack_exports__.DataChannelLatencyTestResultEvent; var __webpack_exports__DataChannelOpenEvent = __webpack_exports__.DataChannelOpenEvent; var __webpack_exports__DataChannelStats = __webpack_exports__.DataChannelStats; var __webpack_exports__EncoderSettings = __webpack_exports__.EncoderSettings; var __webpack_exports__EventEmitter = __webpack_exports__.EventEmitter; var __webpack_exports__Flags = __webpack_exports__.Flags; var __webpack_exports__HideFreezeFrameEvent = __webpack_exports__.HideFreezeFrameEvent; var __webpack_exports__InboundAudioStats = __webpack_exports__.InboundAudioStats; var __webpack_exports__InboundVideoStats = __webpack_exports__.InboundVideoStats; var __webpack_exports__InitialSettings = __webpack_exports__.InitialSettings; var __webpack_exports__InitialSettingsEvent = __webpack_exports__.InitialSettingsEvent; var __webpack_exports__LatencyTestResultEvent = __webpack_exports__.LatencyTestResultEvent; var __webpack_exports__LatencyTestResults = __webpack_exports__.LatencyTestResults; var __webpack_exports__LoadFreezeFrameEvent = __webpack_exports__.LoadFreezeFrameEvent; var __webpack_exports__Logger = __webpack_exports__.Logger; var __webpack_exports__MessageDirection = __webpack_exports__.MessageDirection; var __webpack_exports__MessageRecv = __webpack_exports__.MessageRecv; var __webpack_exports__MessageSend = __webpack_exports__.MessageSend; var __webpack_exports__MessageStreamerList = __webpack_exports__.MessageStreamerList; var __webpack_exports__NumericParameters = __webpack_exports__.NumericParameters; var __webpack_exports__OptionParameters = __webpack_exports__.OptionParameters; var __webpack_exports__OutBoundVideoStats = __webpack_exports__.OutBoundVideoStats; var __webpack_exports__PixelStreaming = __webpack_exports__.PixelStreaming; var __webpack_exports__PlayStreamErrorEvent = __webpack_exports__.PlayStreamErrorEvent; var __webpack_exports__PlayStreamEvent = __webpack_exports__.PlayStreamEvent; var __webpack_exports__PlayStreamRejectedEvent = __webpack_exports__.PlayStreamRejectedEvent; var __webpack_exports__PlayerCountEvent = __webpack_exports__.PlayerCountEvent; var __webpack_exports__SettingBase = __webpack_exports__.SettingBase; var __webpack_exports__SettingFlag = __webpack_exports__.SettingFlag; var __webpack_exports__SettingNumber = __webpack_exports__.SettingNumber; var __webpack_exports__SettingOption = __webpack_exports__.SettingOption; var __webpack_exports__SettingText = __webpack_exports__.SettingText; var __webpack_exports__SettingsChangedEvent = __webpack_exports__.SettingsChangedEvent; var __webpack_exports__SignallingProtocol = __webpack_exports__.SignallingProtocol; var __webpack_exports__StatsReceivedEvent = __webpack_exports__.StatsReceivedEvent; var __webpack_exports__StreamLoadingEvent = __webpack_exports__.StreamLoadingEvent; var __webpack_exports__StreamPreConnectEvent = __webpack_exports__.StreamPreConnectEvent; var __webpack_exports__StreamPreDisconnectEvent = __webpack_exports__.StreamPreDisconnectEvent; var __webpack_exports__StreamReconnectEvent = __webpack_exports__.StreamReconnectEvent; var __webpack_exports__StreamerListMessageEvent = __webpack_exports__.StreamerListMessageEvent; var __webpack_exports__TextParameters = __webpack_exports__.TextParameters; var __webpack_exports__UnquantizedAndDenormalizeUnsigned = __webpack_exports__.UnquantizedAndDenormalizeUnsigned; var __webpack_exports__VideoEncoderAvgQPEvent = __webpack_exports__.VideoEncoderAvgQPEvent; var __webpack_exports__VideoInitializedEvent = __webpack_exports__.VideoInitializedEvent; var __webpack_exports__WebRTCSettings = __webpack_exports__.WebRTCSettings; var __webpack_exports__WebRtcAutoConnectEvent = __webpack_exports__.WebRtcAutoConnectEvent; var __webpack_exports__WebRtcConnectedEvent = __webpack_exports__.WebRtcConnectedEvent; var __webpack_exports__WebRtcConnectingEvent = __webpack_exports__.WebRtcConnectingEvent; var __webpack_exports__WebRtcDisconnectedEvent = __webpack_exports__.WebRtcDisconnectedEvent; var __webpack_exports__WebRtcFailedEvent = __webpack_exports__.WebRtcFailedEvent; var __webpack_exports__WebRtcPlayerController = __webpack_exports__.WebRtcPlayerController; var __webpack_exports__WebRtcSdpEvent = __webpack_exports__.WebRtcSdpEvent; var __webpack_exports__WebSocketController = __webpack_exports__.WebSocketController; var __webpack_exports__WebXRController = __webpack_exports__.WebXRController; var __webpack_exports__XrFrameEvent = __webpack_exports__.XrFrameEvent; var __webpack_exports__XrSessionEndedEvent = __webpack_exports__.XrSessionEndedEvent; var __webpack_exports__XrSessionStartedEvent = __webpack_exports__.XrSessionStartedEvent; export { __webpack_exports__AfkLogic as AfkLogic, __webpack_exports__AfkTimedOutEvent as AfkTimedOutEvent, __webpack_exports__AfkWarningActivateEvent as AfkWarningActivateEvent, __webpack_exports__AfkWarningDeactivateEvent as AfkWarningDeactivateEvent, __webpack_exports__AfkWarningUpdateEvent as AfkWarningUpdateEvent, __webpack_exports__AggregatedStats as AggregatedStats, __webpack_exports__CandidatePairStats as CandidatePairStats, __webpack_exports__CandidateStat as CandidateStat, __webpack_exports__Config as Config, __webpack_exports__ControlSchemeType as ControlSchemeType, __webpack_exports__DataChannelCloseEvent as DataChannelCloseEvent, __webpack_exports__DataChannelErrorEvent as DataChannelErrorEvent, __webpack_exports__DataChannelLatencyTestResponseEvent as DataChannelLatencyTestResponseEvent, __webpack_exports__DataChannelLatencyTestResultEvent as DataChannelLatencyTestResultEvent, __webpack_exports__DataChannelOpenEvent as DataChannelOpenEvent, __webpack_exports__DataChannelStats as DataChannelStats, __webpack_exports__EncoderSettings as EncoderSettings, __webpack_exports__EventEmitter as EventEmitter, __webpack_exports__Flags as Flags, __webpack_exports__HideFreezeFrameEvent as HideFreezeFrameEvent, __webpack_exports__InboundAudioStats as InboundAudioStats, __webpack_exports__InboundVideoStats as InboundVideoStats, __webpack_exports__InitialSettings as InitialSettings, __webpack_exports__InitialSettingsEvent as InitialSettingsEvent, __webpack_exports__LatencyTestResultEvent as LatencyTestResultEvent, __webpack_exports__LatencyTestResults as LatencyTestResults, __webpack_exports__LoadFreezeFrameEvent as LoadFreezeFrameEvent, __webpack_exports__Logger as Logger, __webpack_exports__MessageDirection as MessageDirection, __webpack_exports__MessageRecv as MessageRecv, __webpack_exports__MessageSend as MessageSend, __webpack_exports__MessageStreamerList as MessageStreamerList, __webpack_exports__NumericParameters as NumericParameters, __webpack_exports__OptionParameters as OptionParameters, __webpack_exports__OutBoundVideoStats as OutBoundVideoStats, __webpack_exports__PixelStreaming as PixelStreaming, __webpack_exports__PlayStreamErrorEvent as PlayStreamErrorEvent, __webpack_exports__PlayStreamEvent as PlayStreamEvent, __webpack_exports__PlayStreamRejectedEvent as PlayStreamRejectedEvent, __webpack_exports__PlayerCountEvent as PlayerCountEvent, __webpack_exports__SettingBase as SettingBase, __webpack_exports__SettingFlag as SettingFlag, __webpack_exports__SettingNumber as SettingNumber, __webpack_exports__SettingOption as SettingOption, __webpack_exports__SettingText as SettingText, __webpack_exports__SettingsChangedEvent as SettingsChangedEvent, __webpack_exports__SignallingProtocol as SignallingProtocol, __webpack_exports__StatsReceivedEvent as StatsReceivedEvent, __webpack_exports__StreamLoadingEvent as StreamLoadingEvent, __webpack_exports__StreamPreConnectEvent as StreamPreConnectEvent, __webpack_exports__StreamPreDisconnectEvent as StreamPreDisconnectEvent, __webpack_exports__StreamReconnectEvent as StreamReconnectEvent, __webpack_exports__StreamerListMessageEvent as StreamerListMessageEvent, __webpack_exports__TextParameters as TextParameters, __webpack_exports__UnquantizedAndDenormalizeUnsigned as UnquantizedAndDenormalizeUnsigned, __webpack_exports__VideoEncoderAvgQPEvent as VideoEncoderAvgQPEvent, __webpack_exports__VideoInitializedEvent as VideoInitializedEvent, __webpack_exports__WebRTCSettings as WebRTCSettings, __webpack_exports__WebRtcAutoConnectEvent as WebRtcAutoConnectEvent, __webpack_exports__WebRtcConnectedEvent as WebRtcConnectedEvent, __webpack_exports__WebRtcConnectingEvent as WebRtcConnectingEvent, __webpack_exports__WebRtcDisconnectedEvent as WebRtcDisconnectedEvent, __webpack_exports__WebRtcFailedEvent as WebRtcFailedEvent, __webpack_exports__WebRtcPlayerController as WebRtcPlayerController, __webpack_exports__WebRtcSdpEvent as WebRtcSdpEvent, __webpack_exports__WebSocketController as WebSocketController, __webpack_exports__WebXRController as WebXRController, __webpack_exports__XrFrameEvent as XrFrameEvent, __webpack_exports__XrSessionEndedEvent as XrSessionEndedEvent, __webpack_exports__XrSessionStartedEvent as XrSessionStartedEvent }; //# sourceMappingURL=data:application/json;charset=utf-8;base64,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 set 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BQ0E7U0FDQTs7Ozs7VUN0QkE7VUFDQTtVQUNBO1VBQ0E7VUFDQSx5Q0FBeUMsd0NBQXdDO1VBQ2pGO1VBQ0E7VUFDQTs7Ozs7VUNQQTs7Ozs7VUNBQTtVQUNBO1VBQ0E7VUFDQSx1REFBdUQsaUJBQWlCO1VBQ3hFO1VBQ0EsZ0RBQWdELGFBQWE7VUFDN0Q7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUNOQSxrREFBa0Q7QUFFNkI7QUFDckI7QUFhakM7QUFDMEI7QUFDQTtBQUNJO0FBQ0E7QUFDSjtBQUNjO0FBRUQ7QUFFTTtBQUsvQjtBQUNzQztBQUNwQztBQUM4RTtBQUN4QztBQUN4QjtBQUN3QjtBQUNSO0FBQ0Y7QUFFYztBQUNWO0FBQ007QUFJM0I7QUFDNkI7QUFDN0MiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9AZXBpY2dhbWVzLXBzL2xpYi1waXhlbHN0cmVhbWluZ2Zyb250ZW5kLXVlNS4zLy4vc3JjL0FGSy9BRktDb250cm9sbGVyLnRzIiwid2VicGFjazovL0BlcGljZ2FtZXMtcHMvbGliLXBpeGVsc3RyZWFtaW5nZnJvbnRlbmQtdWU1LjMvLi9zcmMvQ29uZmlnL0NvbmZpZy50cyIsIndlYnBhY2s6Ly9AZXBpY2dhbWVzLXBzL2xpYi1waXhlbHN0cmVhbWluZ2Zyb250ZW5kLXVlNS4zLy4vc3JjL0NvbmZpZy9TZXR0aW5nQmFzZS50cyIsIndlYnBhY2s6Ly9AZXBpY2dhbWVzLXBzL2xpYi1waXhlbHN0cmVhbWluZ2Zyb250ZW5kLXVlNS4zLy4vc3JjL0NvbmZpZy9TZXR0aW5nRmxhZy50cyIsIndlYnBhY2s6Ly9AZXBpY2dhbWVzLXBzL2xpYi1waXhlbHN0cmVhbWluZ2Zyb250ZW5kLXVlNS4zLy4vc3JjL0NvbmZpZy9TZXR0aW5nTnVtYmVyLnRzIiwid2VicGFjazovL0BlcGljZ2FtZXMtcHMvbGliLXBpeGVsc3RyZWFtaW5nZnJvbnRlbmQtdWU1LjMvLi9zcmMvQ29uZmlnL1NldHRpbmdPcHRpb24udHMiLCJ3ZWJwYWNrOi8vQGVwaWNnYW1lcy1wcy9saWItcGl4ZWxzdHJlYW1pbmdmcm9udGVuZC11ZTUuMy8uL3NyYy9Db25maWcvU2V0dGluZ1RleHQudHMiLCJ3ZWJwYWNrOi8vQGVwaWNnYW1lcy1wcy9saWItcGl4ZWxzdHJlYW1pbmdmcm9udGVuZC11ZTUuMy8uL3NyYy9EYXRhQ2hhbm5lbC9EYXRhQ2hhbm5lbENvbnRyb2xsZXIudHMiLCJ3ZWJwYWNrOi8vQGVwaWNnYW1lcy1wcy9saWItcGl4ZWxzdHJlYW1pbmdmcm9udGVuZC11ZTUuMy8uL3NyYy9EYXRhQ2hhbm5lbC9EYXRhQ2hhbm5lbExhdGVuY3lUZXN0Q29udHJvbGxlci50cyIsIndlYnBhY2s6Ly9AZXBpY2dhbWVzLXBzL2xpYi1waXhlbHN0cmVhbWluZ2Zyb250ZW5kLXVlNS4zLy4vc3JjL0RhdGFDaGFubmVsL0RhdGFDaGFubmVsTGF0ZW5jeVRlc3RSZXN1bHRzLnRzIiwid2VicGFjazovL0BlcGljZ2FtZXMtcHMvbGliLXBpeGVsc3RyZWFtaW5nZnJvbnRlbmQtdWU1LjMvLi9zcmMvRGF0YUNoYW5uZWwvRGF0YUNoYW5uZWxTZW5kZXIudHMiLCJ3ZWJwYWNrOi8vQGVwaWNnYW1lcy1wcy9saWItcGl4ZWxzdHJlYW1pbmdmcm9udGVuZC11ZTUuMy8uL3NyYy9EYXRhQ2hhbm5lbC9Jbml0aWFsU2V0dGluZ3MudHMiLCJ3ZWJwYWNrOi8vQGVwaWNnYW1lcy1wcy9saWItcGl4ZWxzdHJlYW1pbmdmcm9udGVuZC11ZTUuMy8uL3NyYy9EYXRhQ2hhbm5lbC9MYXRlbmN5VGVzdFJlc3VsdHMudHMiLCJ3ZWJwYWNrOi8vQGVwaWNnYW1lcy1wcy9saWItcGl4ZWxzdHJlYW1pbmdmcm9udGVuZC11ZTUuMy8uL3NyYy9GcmVlemVGcmFtZS9GcmVlemVGcmFtZS50cyIsIndlYnBhY2s6Ly9AZXBpY2dhbWVzLXBzL2xpYi1waXhlbHN0cmVhbWluZ2Zyb250ZW5kLXVlNS4zLy4vc3JjL0ZyZWV6ZUZyYW1lL0ZyZWV6ZUZyYW1lQ29udHJvbGxlci50cyIsIndlYnBhY2s6Ly9AZXBpY2dhbWVzLXBzL2xpYi1waXhlbHN0cmVhbWluZ2Zyb250ZW5kLXVlNS4zLy4vc3JjL0lucHV0cy9GYWtlVG91Y2hDb250cm9sbGVyLnRzIiwid2VicGFjazovL0BlcGljZ2FtZXMtcHMvbGliLXBpeGVsc3RyZWFtaW5nZnJvbnRlbmQtdWU1LjMvLi9zcmMvSW5wdXRzL0dhbWVwYWRDb250cm9sbGVyLnRzIiwid2VicGFjazovL0BlcGljZ2FtZXMtcHMvbGliLXBpeGVsc3RyZWFtaW5nZnJvbnRlbmQtdWU1LjMvLi9zcmMvSW5wdXRzL0hvdmVyaW5nTW91c2VFdmVudHMudHMiLCJ3ZWJwYWNrOi8vQGVwaWNnYW1lcy1wcy9saWItcGl4ZWxzdHJlYW1pbmdmcm9udGVuZC11ZTUuMy8uL3NyYy9JbnB1dHMvSW5wdXRDbGFzc2VzRmFjdG9yeS50cyIsIndlYnBhY2s6Ly9AZXBpY2dhbWVzLXBzL2xpYi1waXhlbHN0cmVhbWluZ2Zyb250ZW5kLXVlNS4zLy4vc3JjL0lucHV0cy9LZXlib2FyZENvbnRyb2xsZXIudHMiLCJ3ZWJwYWNrOi8vQGVwaWNnYW1lcy1wcy9saWItcGl4ZWxzdHJlYW1pbmdmcm9udGVuZC11ZTUuMy8uL3NyYy9JbnB1dHMvTG9ja2VkTW91c2VFdmVudHMudHMiLCJ3ZWJwYWNrOi8vQGVwaWNnYW1lcy1wcy9saWItcGl4ZWxzdHJlYW1pbmdmcm9udGVuZC11ZTUuMy8uL3NyYy9JbnB1dHMvTW91c2VCdXR0b25zLnRzIiwid2VicGFjazovL0BlcGljZ2FtZXMtcHMvbGliLXBpeGVsc3RyZWFtaW5nZnJvbnRlbmQtdWU1LjMvLi9zcmMvSW5wdXRzL01vdXNlQ29udHJvbGxlci50cyIsIndlYnBhY2s6Ly9AZXBpY2dhbWVzLXBzL2xpYi1waXhlbHN0cmVhbWluZ2Zyb250ZW5kLXVlNS4zLy4vc3JjL0lucHV0cy9TcGVjaWFsS2V5Q29kZXMudHMiLCJ3ZWJwYWNrOi8vQGVwaWNnYW1lcy1wcy9saWItcGl4ZWxzdHJlYW1pbmdmcm9udGVuZC11ZTUuMy8uL3NyYy9JbnB1dHMvVG91Y2hDb250cm9sbGVyLnRzIiwid2VicGFjazovL0BlcGljZ2FtZXMtcHMvbGliLXBpeGVsc3RyZWFtaW5nZnJvbnRlbmQtdWU1LjMvLi9zcmMvSW5wdXRzL1hSR2FtZXBhZENvbnRyb2xsZXIudHMiLCJ3ZWJwYWNrOi8vQGVwaWNnYW1lcy1wcy9saWItcGl4ZWxzdHJlYW1pbmdmcm9udGVuZC11ZTUuMy8uL3NyYy9Mb2dnZXIvTG9nZ2VyLnRzIiwid2VicGFjazovL0BlcGljZ2FtZXMtcHMvbGliLXBpeGVsc3RyZWFtaW5nZnJvbnRlbmQtdWU1LjMvLi9zcmMvUGVlckNvbm5lY3Rpb25Db250cm9sbGVyL0FnZ3JlZ2F0ZWRTdGF0cy50cyIsIndlYnBhY2s6Ly9AZXBpY2dhbWVzLXBzL2xpYi1waXhlbHN0cmVhbWluZ2Zyb250ZW5kLXVlNS4zLy4vc3JjL1BlZXJDb25uZWN0aW9uQ29udHJvbGxlci9DYW5kaWRhdGVQYWlyU3RhdHMudHMiLCJ3ZWJwYWNrOi8vQGVwaWNnYW1lcy1wcy9saWItcGl4ZWxzdHJlYW1pbmdmcm9udGVuZC11ZTUuMy8uL3NyYy9QZWVyQ29ubmVjdGlvbkNvbnRyb2xsZXIvQ2FuZGlkYXRlU3RhdC50cyIsIndlYnBhY2s6Ly9AZXBpY2dhbWVzLXBzL2xpYi1waXhlbHN0cmVhbWluZ2Zyb250ZW5kLXVlNS4zLy4vc3JjL1BlZXJDb25uZWN0aW9uQ29udHJvbGxlci9EYXRhQ2hhbm5lbFN0YXRzLnRzIiwid2VicGFjazovL0BlcGljZ2FtZXMtcHMvbGliLXBpeGVsc3RyZWFtaW5nZnJvbnRlbmQtdWU1LjMvLi9zcmMvUGVlckNvbm5lY3Rpb25Db250cm9sbGVyL0luYm91bmRSVFBTdGF0cy50cyIsIndlYnBhY2s6Ly9AZXBpY2dhbWVzLXBzL2xpYi1waXhlbHN0cmVhbWluZ2Zyb250ZW5kLXVlNS4zLy4vc3JjL1BlZXJDb25uZWN0aW9uQ29udHJvbGxlci9PdXRCb3VuZFJUUFN0YXRzLnRzIiwid2VicGFjazovL0BlcGljZ2FtZXMtcHMvbGliLXBpeGVsc3RyZWFtaW5nZnJvbnRlbmQtdWU1LjMvLi9zcmMvUGVlckNvbm5lY3Rpb25Db250cm9sbGVyL1BlZXJDb25uZWN0aW9uQ29udHJvbGxlci50cyIsIndlYnBhY2s6Ly9AZXBpY2dhbWVzLXBzL2xpYi1waXhlbHN0cmVhbWluZ2Zyb250ZW5kLXVlNS4zLy4vc3JjL1BlZXJDb25uZWN0aW9uQ29udHJvbGxlci9TZXNzaW9uU3RhdHMudHMiLCJ3ZWJwYWNrOi8vQGVwaWNnYW1lcy1wcy9saWItcGl4ZWxzdHJlYW1pbmdmcm9udGVuZC11ZTUuMy8uL3NyYy9QZWVyQ29ubmVjdGlvbkNvbnRyb2xsZXIvU3RyZWFtU3RhdHMudHMiLCJ3ZWJwYWNrOi8vQGVwaWNnYW1lcy1wcy9saWItcGl4ZWxzdHJlYW1pbmdmcm9udGVuZC11ZTUuMy8uL3NyYy9QaXhlbFN0cmVhbWluZy9QaXhlbFN0cmVhbWluZy50cyIsIndlYnBhY2s6Ly9AZXBpY2dhbWVzLXBzL2xpYi1waXhlbHN0cmVhbWluZ2Zyb250ZW5kLXVlNS4zLy4vc3JjL1VJL09uU2NyZWVuS2V5Ym9hcmQudHMiLCJ3ZWJwYWNrOi8vQGVwaWNnYW1lcy1wcy9saWItcGl4ZWxzdHJlYW1pbmdmcm9udGVuZC11ZTUuMy8uL3NyYy9VZUluc3RhbmNlTWVzc2FnZS9SZXNwb25zZUNvbnRyb2xsZXIudHMiLCJ3ZWJwYWNrOi8vQGVwaWNnYW1lcy1wcy9saWItcGl4ZWxzdHJlYW1pbmdmcm9udGVuZC11ZTUuMy8uL3NyYy9VZUluc3RhbmNlTWVzc2FnZS9TZW5kTWVzc2FnZUNvbnRyb2xsZXIudHMiLCJ3ZWJwYWNrOi8vQGVwaWNnYW1lcy1wcy9saWItcGl4ZWxzdHJlYW1pbmdmcm9udGVuZC11ZTUuMy8uL3NyYy9VZUluc3RhbmNlTWVzc2FnZS9TdHJlYW1NZXNzYWdlQ29udHJvbGxlci50cyIsIndlYnBhY2s6Ly9AZXBpY2dhbWVzLXBzL2xpYi1waXhlbHN0cmVhbWluZ2Zyb250ZW5kLXVlNS4zLy4vc3JjL1VlSW5zdGFuY2VNZXNzYWdlL1RvU3RyZWFtZXJNZXNzYWdlc0NvbnRyb2xsZXIudHMiLCJ3ZWJwYWNrOi8vQGVwaWNnYW1lcy1wcy9saWItcGl4ZWxzdHJlYW1pbmdmcm9udGVuZC11ZTUuMy8uL3NyYy9VdGlsL0Nvb3JkaW5hdGVDb252ZXJ0ZXIudHMiLCJ3ZWJwYWNrOi8vQGVwaWNnYW1lcy1wcy9saWItcGl4ZWxzdHJlYW1pbmdmcm9udGVuZC11ZTUuMy8uL3NyYy9VdGlsL0V2ZW50RW1pdHRlci50cyIsIndlYnBhY2s6Ly9AZXBpY2dhbWVzLXBzL2xpYi1waXhlbHN0cmVhbWluZ2Zyb250ZW5kLXVlNS4zLy4vc3JjL1V0aWwvRXZlbnRMaXN0ZW5lclRyYWNrZXIudHMiLCJ3ZWJwYWNrOi8vQGVwaWNnYW1lcy1wcy9saWItcGl4ZWxzdHJlYW1pbmdmcm9udGVuZC11ZTUuMy8uL3NyYy9VdGlsL0ZpbGVVdGlsLnRzIiwid2VicGFjazovL0BlcGljZ2FtZXMtcHMvbGliLXBpeGVsc3RyZWFtaW5nZnJvbnRlbmQtdWU1LjMvLi9zcmMvVXRpbC9SVENVdGlscy50cyIsIndlYnBhY2s6Ly9AZXBpY2dhbWVzLXBzL2xpYi1waXhlbHN0cmVhbWluZ2Zyb250ZW5kLXVlNS4zLy4vc3JjL1V0aWwvV2ViR0xVdGlscy50cyIsIndlYnBhY2s6Ly9AZXBpY2dhbWVzLXBzL2xpYi1waXhlbHN0cmVhbWluZ2Zyb250ZW5kLXVlNS4zLy4vc3JjL1V0aWwvV2ViWFJVdGlscy50cyIsIndlYnBhY2s6Ly9AZXBpY2dhbWVzLXBzL2xpYi1waXhlbHN0cmVhbWluZ2Zyb250ZW5kLXVlNS4zLy4vc3JjL1ZpZGVvUGxheWVyL1N0cmVhbUNvbnRyb2xsZXIudHMiLCJ3ZWJwYWNrOi8vQGVwaWNnYW1lcy1wcy9saWItcGl4ZWxzdHJlYW1pbmdmcm9udGVuZC11ZTUuMy8uL3NyYy9WaWRlb1BsYXllci9WaWRlb1BsYXllci50cyIsIndlYnBhY2s6Ly9AZXBpY2dhbWVzLXBzL2xpYi1waXhlbHN0cmVhbWluZ2Zyb250ZW5kLXVlNS4zLy4vc3JjL1dlYlJ0Y1BsYXllci9XZWJSdGNQbGF5ZXJDb250cm9sbGVyLnRzIiwid2VicGFjazovL0BlcGljZ2FtZXMtcHMvbGliLXBpeGVsc3RyZWFtaW5nZnJvbnRlbmQtdWU1LjMvLi9zcmMvV2ViU29ja2V0cy9NZXNzYWdlUmVjZWl2ZS50cyIsIndlYnBhY2s6Ly9AZXBpY2dhbWVzLXBzL2xpYi1waXhlbHN0cmVhbWluZ2Zyb250ZW5kLXVlNS4zLy4vc3JjL1dlYlNvY2tldHMvTWVzc2FnZVNlbmQudHMiLCJ3ZWJwYWNrOi8vQGVwaWNnYW1lcy1wcy9saWItcGl4ZWxzdHJlYW1pbmdmcm9udGVuZC11ZTUuMy8uL3NyYy9XZWJTb2NrZXRzL1NpZ25hbGxpbmdQcm90b2NvbC50cyIsIndlYnBhY2s6Ly9AZXBpY2dhbWVzLXBzL2xpYi1waXhlbHN0cmVhbWluZ2Zyb250ZW5kLXVlNS4zLy4vc3JjL1dlYlNvY2tldHMvV2ViU29ja2V0Q29udHJvbGxlci50cyIsIndlYnBhY2s6Ly9AZXBpY2dhbWVzLXBzL2xpYi1waXhlbHN0cmVhbWluZ2Zyb250ZW5kLXVlNS4zLy4vc3JjL1dlYlhSL1dlYlhSQ29udHJvbGxlci50cyIsIndlYnBhY2s6Ly9AZXBpY2dhbWVzLXBzL2xpYi1waXhlbHN0cmVhbWluZ2Zyb250ZW5kLXVlNS4zL2V4dGVybmFsIG1vZHVsZSBcInNkcFwiIiwid2VicGFjazovL0BlcGljZ2FtZXMtcHMvbGliLXBpeGVsc3RyZWFtaW5nZnJvbnRlbmQtdWU1LjMvd2VicGFjay9ib290c3RyYXAiLCJ3ZWJwYWNrOi8vQGVwaWNnYW1lcy1wcy9saWItcGl4ZWxzdHJlYW1pbmdmcm9udGVuZC11ZTUuMy93ZWJwYWNrL3J1bnRpbWUvZGVmaW5lIHByb3BlcnR5IGdldHRlcnMiLCJ3ZWJwYWNrOi8vQGVwaWNnYW1lcy1wcy9saWItcGl4ZWxzdHJlYW1pbmdmcm9udGVuZC11ZTUuMy93ZWJwYWNrL3J1bnRpbWUvaGFzT3duUHJvcGVydHkgc2hvcnRoYW5kIiwid2VicGFjazovL0BlcGljZ2FtZXMtcHMvbGliLXBpeGVsc3RyZWFtaW5nZnJvbnRlbmQtdWU1LjMvd2VicGFjay9ydW50aW1lL21ha2UgbmFtZXNwYWNlIG9iamVjdCIsIndlYnBhY2s6Ly9AZXBpY2dhbWVzLXBzL2xpYi1waXhlbHN0cmVhbWluZ2Zyb250ZW5kLXVlNS4zLy4vc3JjL3BpeGVsc3RyZWFtaW5nZnJvbnRlbmQudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IEVwaWMgR2FtZXMsIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cblxuaW1wb3J0IHsgQ29uZmlnLCBGbGFncywgTnVtZXJpY1BhcmFtZXRlcnMgfSBmcm9tICcuLi9Db25maWcvQ29uZmlnJztcbmltcG9ydCB7IExvZ2dlciB9IGZyb20gJy4uL0xvZ2dlci9Mb2dnZXInO1xuaW1wb3J0IHsgUGl4ZWxTdHJlYW1pbmcgfSBmcm9tICcuLi9QaXhlbFN0cmVhbWluZy9QaXhlbFN0cmVhbWluZyc7XG5pbXBvcnQge1xuICAgIEFma1RpbWVkT3V0RXZlbnQsXG4gICAgQWZrV2FybmluZ0FjdGl2YXRlRXZlbnQsXG4gICAgQWZrV2FybmluZ0RlYWN0aXZhdGVFdmVudCxcbiAgICBBZmtXYXJuaW5nVXBkYXRlRXZlbnRcbn0gZnJvbSAnLi4vVXRpbC9FdmVudEVtaXR0ZXInO1xuXG5leHBvcnQgY2xhc3MgQUZLQ29udHJvbGxlciB7XG4gICAgLy8gdGltZSBvdXQgbG9naWMgZGV0YWlsc1xuICAgIGNsb3NlVGltZW91dCA9IDEwO1xuICAgIGFjdGl2ZSA9IGZhbHNlO1xuICAgIGNvdW50ZG93bkFjdGl2ZSA9IGZhbHNlO1xuICAgIHdhcm5UaW1lcjogUmV0dXJuVHlwZTx0eXBlb2Ygc2V0VGltZW91dD4gPSB1bmRlZmluZWQ7XG4gICAgY291bnREb3duID0gMDtcbiAgICBjb3VudERvd25UaW1lcjogUmV0dXJuVHlwZTx0eXBlb2Ygc2V0SW50ZXJ2YWw+ID0gdW5kZWZpbmVkO1xuICAgIGNvbmZpZzogQ29uZmlnO1xuICAgIHBpeGVsU3RyZWFtaW5nOiBQaXhlbFN0cmVhbWluZztcbiAgICBvbkRpc21pc3NBZms6ICgpID0+IHZvaWQ7XG5cbiAgICBvbkFGS1RpbWVkT3V0Q2FsbGJhY2s6ICgpID0+IHZvaWQ7XG5cbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgY29uZmlnOiBDb25maWcsXG4gICAgICAgIHBpeGVsU3RyZWFtaW5nOiBQaXhlbFN0cmVhbWluZyxcbiAgICAgICAgb25EaXNtaXNzQWZrOiAoKSA9PiB2b2lkXG4gICAgKSB7XG4gICAgICAgIHRoaXMuY29uZmlnID0gY29uZmlnO1xuICAgICAgICB0aGlzLnBpeGVsU3RyZWFtaW5nID0gcGl4ZWxTdHJlYW1pbmc7XG4gICAgICAgIHRoaXMub25EaXNtaXNzQWZrID0gb25EaXNtaXNzQWZrO1xuICAgICAgICB0aGlzLm9uQUZLVGltZWRPdXRDYWxsYmFjayA9ICgpID0+IHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgICAgICAgICdBRksgdGltZWQgb3V0LCBkaWQgeW91IHdhbnQgdG8gb3ZlcnJpZGUgdGhpcyBjYWxsYmFjaz8nXG4gICAgICAgICAgICApO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBtZXRob2RzIHRoYXQgb2NjdXIgd2hlbiBhbiBhZmsgZXZlbnQgbGlzdGVuZXIgaXMgY2xpY2tlZFxuICAgICAqL1xuICAgIG9uQWZrQ2xpY2soKSB7XG4gICAgICAgIGNsZWFySW50ZXJ2YWwodGhpcy5jb3VudERvd25UaW1lcik7XG5cbiAgICAgICAgaWYgKHRoaXMuYWN0aXZlIHx8IHRoaXMuY291bnRkb3duQWN0aXZlKSB7XG4gICAgICAgICAgICB0aGlzLnN0YXJ0QWZrV2FybmluZ1RpbWVyKCk7XG4gICAgICAgICAgICB0aGlzLnBpeGVsU3RyZWFtaW5nLmRpc3BhdGNoRXZlbnQoXG4gICAgICAgICAgICAgICAgbmV3IEFma1dhcm5pbmdEZWFjdGl2YXRlRXZlbnQoKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFN0YXJ0IHRoZSB3YXJuaW5nIHRpbWVyIGlmIGEgdGltZW91dCBpcyBzZXQgZ3JlYXRlciB0aGF0IDAgc2Vjb25kc1xuICAgICAqL1xuICAgIHN0YXJ0QWZrV2FybmluZ1RpbWVyKCkge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgICB0aGlzLmNvbmZpZy5nZXROdW1lcmljU2V0dGluZ1ZhbHVlKFxuICAgICAgICAgICAgICAgIE51bWVyaWNQYXJhbWV0ZXJzLkFGS1RpbWVvdXRTZWNzXG4gICAgICAgICAgICApID4gMCAmJlxuICAgICAgICAgICAgdGhpcy5jb25maWcuaXNGbGFnRW5hYmxlZChGbGFncy5BRktEZXRlY3Rpb24pXG4gICAgICAgICkge1xuICAgICAgICAgICAgdGhpcy5hY3RpdmUgPSB0cnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5hY3RpdmUgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlc2V0QWZrV2FybmluZ1RpbWVyKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3RvcCB0aGUgYWZrIHdhcm5pbmcgdGltZXJcbiAgICAgKi9cbiAgICBzdG9wQWZrV2FybmluZ1RpbWVyKCkge1xuICAgICAgICB0aGlzLmFjdGl2ZSA9IGZhbHNlO1xuICAgICAgICB0aGlzLmNvdW50ZG93bkFjdGl2ZSA9IGZhbHNlO1xuICAgICAgICBjbGVhclRpbWVvdXQodGhpcy53YXJuVGltZXIpO1xuICAgICAgICBjbGVhckludGVydmFsKHRoaXMuY291bnREb3duVGltZXIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBhdXNlIHRoZSB0aW1lciB3aGljaCB3aGVuIGVsYXBzZWQgd2lsbCB3YXJuIHRoZSB1c2VyIHRoZXkgYXJlIGluYWN0aXZlLlxuICAgICAqL1xuICAgIHBhdXNlQWZrV2FybmluZ1RpbWVyKCkge1xuICAgICAgICB0aGlzLmFjdGl2ZSA9IGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIElmIHRoZSB1c2VyIGludGVyYWN0cyB0aGVuIHJlc2V0IHRoZSB3YXJuaW5nIHRpbWVyLlxuICAgICAqL1xuICAgIHJlc2V0QWZrV2FybmluZ1RpbWVyKCkge1xuICAgICAgICBpZiAodGhpcy5hY3RpdmUgJiYgdGhpcy5jb25maWcuaXNGbGFnRW5hYmxlZChGbGFncy5BRktEZXRlY3Rpb24pKSB7XG4gICAgICAgICAgICBjbGVhclRpbWVvdXQodGhpcy53YXJuVGltZXIpO1xuICAgICAgICAgICAgdGhpcy53YXJuVGltZXIgPSBzZXRUaW1lb3V0KFxuICAgICAgICAgICAgICAgICgpID0+IHRoaXMuYWN0aXZhdGVBZmtFdmVudCgpLFxuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLmdldE51bWVyaWNTZXR0aW5nVmFsdWUoXG4gICAgICAgICAgICAgICAgICAgIE51bWVyaWNQYXJhbWV0ZXJzLkFGS1RpbWVvdXRTZWNzXG4gICAgICAgICAgICAgICAgKSAqIDEwMDBcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTaG93IHRoZSBBRksgb3ZlcmxheSBhbmQgYmVnaW4gdGhlIGNvdW50RG93blxuICAgICAqL1xuICAgIGFjdGl2YXRlQWZrRXZlbnQoKSB7XG4gICAgICAgIC8vIFBhdXNlIHRoZSB0aW1lciB3aGlsZSB0aGUgdXNlciBpcyBsb29raW5nIGF0IHRoZSBpbmFjdGl2aXR5IHdhcm5pbmcgb3ZlcmxheVxuICAgICAgICB0aGlzLnBhdXNlQWZrV2FybmluZ1RpbWVyKCk7XG5cbiAgICAgICAgLy8gaW5zdGFudGlhdGUgYSBuZXcgb3ZlcmxheVxuICAgICAgICB0aGlzLnBpeGVsU3RyZWFtaW5nLmRpc3BhdGNoRXZlbnQoXG4gICAgICAgICAgICBuZXcgQWZrV2FybmluZ0FjdGl2YXRlRXZlbnQoe1xuICAgICAgICAgICAgICAgIGNvdW50RG93bjogdGhpcy5jb3VudERvd24sXG4gICAgICAgICAgICAgICAgZGlzbWlzc0FmazogdGhpcy5vbkRpc21pc3NBZmtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gdXBkYXRlIG91ciBjb3VudERvd24gdGltZXIgYW5kIG92ZXJsYXkgY29udGVudHNcbiAgICAgICAgdGhpcy5jb3VudERvd24gPSB0aGlzLmNsb3NlVGltZW91dDtcbiAgICAgICAgdGhpcy5jb3VudGRvd25BY3RpdmUgPSB0cnVlO1xuICAgICAgICB0aGlzLnBpeGVsU3RyZWFtaW5nLmRpc3BhdGNoRXZlbnQoXG4gICAgICAgICAgICBuZXcgQWZrV2FybmluZ1VwZGF0ZUV2ZW50KHsgY291bnREb3duOiB0aGlzLmNvdW50RG93biB9KVxuICAgICAgICApO1xuXG4gICAgICAgIC8vIGlmIHdlIGFyZSBpbiBsb2NrZWQgbW91c2UgZXhpdCBwb2ludGVybG9ja1xuICAgICAgICBpZiAoIXRoaXMuY29uZmlnLmlzRmxhZ0VuYWJsZWQoRmxhZ3MuSG92ZXJpbmdNb3VzZU1vZGUpKSB7XG4gICAgICAgICAgICAvLyBtaW5vciBoYWNrIHRvIGFsbGV2aWF0ZSBpb3Mgbm90IHN1cHBvcnRpbmcgcG9pbnRlcmxvY2tcbiAgICAgICAgICAgIGlmIChkb2N1bWVudC5leGl0UG9pbnRlckxvY2spIHtcbiAgICAgICAgICAgICAgICBkb2N1bWVudC5leGl0UG9pbnRlckxvY2soKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHJlc2V0IG91ciBjb3VudERvd24gaW50ZXJ2YWwgYWNjb3JkaW5nbHlcbiAgICAgICAgdGhpcy5jb3VudERvd25UaW1lciA9IHNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuY291bnREb3duLS07XG4gICAgICAgICAgICBpZiAodGhpcy5jb3VudERvd24gPT0gMCkge1xuICAgICAgICAgICAgICAgIC8vIFRoZSB1c2VyIGZhaWxlZCB0byBjbGljayBzbyBoaWRlIHRoZSBvdmVybGF5IGFuZCBkaXNjb25uZWN0IHRoZW0uXG4gICAgICAgICAgICAgICAgdGhpcy5waXhlbFN0cmVhbWluZy5kaXNwYXRjaEV2ZW50KFxuICAgICAgICAgICAgICAgICAgICBuZXcgQWZrVGltZWRPdXRFdmVudCgpXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB0aGlzLm9uQUZLVGltZWRPdXRDYWxsYmFjaygpO1xuICAgICAgICAgICAgICAgIExvZ2dlci5Mb2coXG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAgICAgICAgICdZb3UgaGF2ZSBiZWVuIGRpc2Nvbm5lY3RlZCBkdWUgdG8gaW5hY3Rpdml0eSdcbiAgICAgICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAgICAgLy8gc3dpdGNoIG9mZiB0aGUgYWZrIGZlYXR1cmUgYXMgc3RyZWFtIGhhcyBjbG9zZWRcbiAgICAgICAgICAgICAgICB0aGlzLnN0b3BBZmtXYXJuaW5nVGltZXIoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5waXhlbFN0cmVhbWluZy5kaXNwYXRjaEV2ZW50KFxuICAgICAgICAgICAgICAgICAgICBuZXcgQWZrV2FybmluZ1VwZGF0ZUV2ZW50KHsgY291bnREb3duOiB0aGlzLmNvdW50RG93biB9KVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sIDEwMDApO1xuICAgIH1cbn1cbiIsIi8vIENvcHlyaWdodCBFcGljIEdhbWVzLCBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG5cbmltcG9ydCB7IExvZ2dlciB9IGZyb20gJy4uL0xvZ2dlci9Mb2dnZXInO1xuaW1wb3J0IHsgU2V0dGluZ0ZsYWcgfSBmcm9tICcuL1NldHRpbmdGbGFnJztcbmltcG9ydCB7IFNldHRpbmdOdW1iZXIgfSBmcm9tICcuL1NldHRpbmdOdW1iZXInO1xuaW1wb3J0IHsgU2V0dGluZ1RleHQgfSBmcm9tICcuL1NldHRpbmdUZXh0JztcbmltcG9ydCB7IFNldHRpbmdPcHRpb24gfSBmcm9tICcuL1NldHRpbmdPcHRpb24nO1xuaW1wb3J0IHsgRXZlbnRFbWl0dGVyLCBTZXR0aW5nc0NoYW5nZWRFdmVudCB9IGZyb20gJy4uL1V0aWwvRXZlbnRFbWl0dGVyJztcbmltcG9ydCB7IFNldHRpbmdCYXNlIH0gZnJvbSAnLi9TZXR0aW5nQmFzZSc7XG5cbi8qKlxuICogQSBjb2xsZWN0aW9uIG9mIGZsYWdzIHRoYXQgY2FuIGJlIHRvZ2dsZWQgYW5kIGFyZSBjb3JlIHRvIGFsbCBQaXhlbCBTdHJlYW1pbmcgZXhwZXJpZW5jZXMuXG4gKiBUaGVzZSBhcmUgdXNlZCBpbiB0aGUgYENvbmZpZy5GbGFnc2AgbWFwLlxuICovXG5leHBvcnQgY2xhc3MgRmxhZ3Mge1xuICAgIHN0YXRpYyBBdXRvQ29ubmVjdCA9ICdBdXRvQ29ubmVjdCcgYXMgY29uc3Q7XG4gICAgc3RhdGljIEF1dG9QbGF5VmlkZW8gPSAnQXV0b1BsYXlWaWRlbycgYXMgY29uc3Q7XG4gICAgc3RhdGljIEFGS0RldGVjdGlvbiA9ICdUaW1lb3V0SWZJZGxlJyBhcyBjb25zdDtcbiAgICBzdGF0aWMgQnJvd3NlclNlbmRPZmZlciA9ICdPZmZlclRvUmVjZWl2ZScgYXMgY29uc3Q7XG4gICAgc3RhdGljIEhvdmVyaW5nTW91c2VNb2RlID0gJ0hvdmVyaW5nTW91c2UnIGFzIGNvbnN0O1xuICAgIHN0YXRpYyBGb3JjZU1vbm9BdWRpbyA9ICdGb3JjZU1vbm9BdWRpbycgYXMgY29uc3Q7XG4gICAgc3RhdGljIEZvcmNlVFVSTiA9ICdGb3JjZVRVUk4nIGFzIGNvbnN0O1xuICAgIHN0YXRpYyBGYWtlTW91c2VXaXRoVG91Y2hlcyA9ICdGYWtlTW91c2VXaXRoVG91Y2hlcycgYXMgY29uc3Q7XG4gICAgc3RhdGljIElzUXVhbGl0eUNvbnRyb2xsZXIgPSAnQ29udHJvbHNRdWFsaXR5JyBhcyBjb25zdDtcbiAgICBzdGF0aWMgTWF0Y2hWaWV3cG9ydFJlc29sdXRpb24gPSAnTWF0Y2hWaWV3cG9ydFJlcycgYXMgY29uc3Q7XG4gICAgc3RhdGljIFN0YXJ0VmlkZW9NdXRlZCA9ICdTdGFydFZpZGVvTXV0ZWQnIGFzIGNvbnN0O1xuICAgIHN0YXRpYyBTdXBwcmVzc0Jyb3dzZXJLZXlzID0gJ1N1cHByZXNzQnJvd3NlcktleXMnIGFzIGNvbnN0O1xuICAgIHN0YXRpYyBVc2VNaWMgPSAnVXNlTWljJyBhcyBjb25zdDtcbiAgICBzdGF0aWMgS2V5Ym9hcmRJbnB1dCA9ICdLZXlib2FyZElucHV0JyBhcyBjb25zdDtcbiAgICBzdGF0aWMgTW91c2VJbnB1dCA9ICdNb3VzZUlucHV0JyBhcyBjb25zdDtcbiAgICBzdGF0aWMgVG91Y2hJbnB1dCA9ICdUb3VjaElucHV0JyBhcyBjb25zdDtcbiAgICBzdGF0aWMgR2FtZXBhZElucHV0ID0gJ0dhbWVwYWRJbnB1dCcgYXMgY29uc3Q7XG4gICAgc3RhdGljIFhSQ29udHJvbGxlcklucHV0ID0gJ1hSQ29udHJvbGxlcklucHV0JyBhcyBjb25zdDtcbiAgICBzdGF0aWMgV2FpdEZvclN0cmVhbWVyID0gXCJXYWl0Rm9yU3RyZWFtZXJcIiBhcyBjb25zdDtcbn1cblxuZXhwb3J0IHR5cGUgRmxhZ3NLZXlzID0gRXhjbHVkZTxrZXlvZiB0eXBlb2YgRmxhZ3MsICdwcm90b3R5cGUnPjtcbmV4cG9ydCB0eXBlIEZsYWdzSWRzID0gdHlwZW9mIEZsYWdzW0ZsYWdzS2V5c107XG5cbmNvbnN0IGlzRmxhZ0lkID0gKGlkOiBzdHJpbmcpOiBpZCBpcyBGbGFnc0lkcyA9PlxuICAgIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKEZsYWdzKS5zb21lKFxuICAgICAgICAobmFtZTogRmxhZ3NLZXlzKSA9PiBGbGFnc1tuYW1lXSA9PT0gaWRcbiAgICApO1xuXG4vKipcbiAqIEEgY29sbGVjdGlvbiBvZiBudW1lcmljIHBhcmFtZXRlcnMgdGhhdCBhcmUgY29yZSB0byBhbGwgUGl4ZWwgU3RyZWFtaW5nIGV4cGVyaWVuY2VzLlxuICpcbiAqL1xuZXhwb3J0IGNsYXNzIE51bWVyaWNQYXJhbWV0ZXJzIHtcbiAgICBzdGF0aWMgQUZLVGltZW91dFNlY3MgPSAnQUZLVGltZW91dCcgYXMgY29uc3Q7XG4gICAgc3RhdGljIE1pblFQID0gJ01pblFQJyBhcyBjb25zdDtcbiAgICBzdGF0aWMgTWF4UVAgPSAnTWF4UVAnIGFzIGNvbnN0O1xuICAgIHN0YXRpYyBXZWJSVENGUFMgPSAnV2ViUlRDRlBTJyBhcyBjb25zdDtcbiAgICBzdGF0aWMgV2ViUlRDTWluQml0cmF0ZSA9ICdXZWJSVENNaW5CaXRyYXRlJyBhcyBjb25zdDtcbiAgICBzdGF0aWMgV2ViUlRDTWF4Qml0cmF0ZSA9ICdXZWJSVENNYXhCaXRyYXRlJyBhcyBjb25zdDtcbiAgICBzdGF0aWMgTWF4UmVjb25uZWN0QXR0ZW1wdHMgPSAnTWF4UmVjb25uZWN0QXR0ZW1wdHMnIGFzIGNvbnN0O1xuICAgIHN0YXRpYyBTdHJlYW1lckF1dG9Kb2luSW50ZXJ2YWwgPSAnU3RyZWFtZXJBdXRvSm9pbkludGVydmFsJyBhcyBjb25zdDtcbn1cblxuZXhwb3J0IHR5cGUgTnVtZXJpY1BhcmFtZXRlcnNLZXlzID0gRXhjbHVkZTxcbiAgICBrZXlvZiB0eXBlb2YgTnVtZXJpY1BhcmFtZXRlcnMsXG4gICAgJ3Byb3RvdHlwZSdcbj47XG5leHBvcnQgdHlwZSBOdW1lcmljUGFyYW1ldGVyc0lkcyA9XG4gICAgdHlwZW9mIE51bWVyaWNQYXJhbWV0ZXJzW051bWVyaWNQYXJhbWV0ZXJzS2V5c107XG5cbmNvbnN0IGlzTnVtZXJpY0lkID0gKGlkOiBzdHJpbmcpOiBpZCBpcyBOdW1lcmljUGFyYW1ldGVyc0lkcyA9PlxuICAgIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKE51bWVyaWNQYXJhbWV0ZXJzKS5zb21lKFxuICAgICAgICAobmFtZTogTnVtZXJpY1BhcmFtZXRlcnNLZXlzKSA9PiBOdW1lcmljUGFyYW1ldGVyc1tuYW1lXSA9PT0gaWRcbiAgICApO1xuXG4vKipcbiAqIEEgY29sbGVjdGlvbiBvZiB0ZXh0dWFsIHBhcmFtZXRlcnMgdGhhdCBhcmUgY29yZSB0byBhbGwgUGl4ZWwgU3RyZWFtaW5nIGV4cGVyaWVuY2VzLlxuICpcbiAqL1xuZXhwb3J0IGNsYXNzIFRleHRQYXJhbWV0ZXJzIHtcbiAgICBzdGF0aWMgU2lnbmFsbGluZ1NlcnZlclVybCA9ICdzcycgYXMgY29uc3Q7XG59XG5cbmV4cG9ydCB0eXBlIFRleHRQYXJhbWV0ZXJzS2V5cyA9IEV4Y2x1ZGU8XG4gICAga2V5b2YgdHlwZW9mIFRleHRQYXJhbWV0ZXJzLFxuICAgICdwcm90b3R5cGUnXG4+O1xuZXhwb3J0IHR5cGUgVGV4dFBhcmFtZXRlcnNJZHMgPSB0eXBlb2YgVGV4dFBhcmFtZXRlcnNbVGV4dFBhcmFtZXRlcnNLZXlzXTtcblxuY29uc3QgaXNUZXh0SWQgPSAoaWQ6IHN0cmluZyk6IGlkIGlzIFRleHRQYXJhbWV0ZXJzSWRzID0+XG4gICAgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMoVGV4dFBhcmFtZXRlcnMpLnNvbWUoXG4gICAgICAgIChuYW1lOiBUZXh0UGFyYW1ldGVyc0tleXMpID0+IFRleHRQYXJhbWV0ZXJzW25hbWVdID09PSBpZFxuICAgICk7XG5cbi8qKlxuICogQSBjb2xsZWN0aW9uIG9mIGVudW0gYmFzZWQgcGFyYW1ldGVycyB0aGF0IGFyZSBjb3JlIHRvIGFsbCBQaXhlbCBTdHJlYW1pbmcgZXhwZXJpZW5jZXMuXG4gKlxuICovXG5leHBvcnQgY2xhc3MgT3B0aW9uUGFyYW1ldGVycyB7XG4gICAgc3RhdGljIFByZWZlcnJlZENvZGVjID0gJ1ByZWZlcnJlZENvZGVjJyBhcyBjb25zdDtcbiAgICBzdGF0aWMgU3RyZWFtZXJJZCA9ICdTdHJlYW1lcklkJyBhcyBjb25zdDtcbn1cblxuZXhwb3J0IHR5cGUgT3B0aW9uUGFyYW1ldGVyc0tleXMgPSBFeGNsdWRlPFxuICAgIGtleW9mIHR5cGVvZiBPcHRpb25QYXJhbWV0ZXJzLFxuICAgICdwcm90b3R5cGUnXG4+O1xuZXhwb3J0IHR5cGUgT3B0aW9uUGFyYW1ldGVyc0lkcyA9IHR5cGVvZiBPcHRpb25QYXJhbWV0ZXJzW09wdGlvblBhcmFtZXRlcnNLZXlzXTtcblxuY29uc3QgaXNPcHRpb25JZCA9IChpZDogc3RyaW5nKTogaWQgaXMgT3B0aW9uUGFyYW1ldGVyc0lkcyA9PlxuICAgIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKE9wdGlvblBhcmFtZXRlcnMpLnNvbWUoXG4gICAgICAgIChuYW1lOiBPcHRpb25QYXJhbWV0ZXJzS2V5cykgPT4gT3B0aW9uUGFyYW1ldGVyc1tuYW1lXSA9PT0gaWRcbiAgICApO1xuXG4vKipcbiAqIFV0aWxpdHkgdHlwZXMgZm9yIGluZmVycmluZyBkYXRhIHR5cGUgYmFzZWQgb24gc2V0dGluZyBJRFxuICovXG5leHBvcnQgdHlwZSBPcHRpb25JZHMgPVxuICAgIHwgRmxhZ3NJZHNcbiAgICB8IE51bWVyaWNQYXJhbWV0ZXJzSWRzXG4gICAgfCBUZXh0UGFyYW1ldGVyc0lkc1xuICAgIHwgT3B0aW9uUGFyYW1ldGVyc0lkcztcbmV4cG9ydCB0eXBlIE9wdGlvbktleXM8VD4gPSBUIGV4dGVuZHMgRmxhZ3NJZHNcbiAgICA/IGJvb2xlYW5cbiAgICA6IFQgZXh0ZW5kcyBOdW1lcmljUGFyYW1ldGVyc0lkc1xuICAgID8gbnVtYmVyXG4gICAgOiBUIGV4dGVuZHMgVGV4dFBhcmFtZXRlcnNJZHNcbiAgICA/IHN0cmluZ1xuICAgIDogVCBleHRlbmRzIE9wdGlvblBhcmFtZXRlcnNJZHNcbiAgICA/IHN0cmluZ1xuICAgIDogbmV2ZXI7XG5cbmV4cG9ydCB0eXBlIEFsbFNldHRpbmdzID0ge1xuICAgIFtLIGluIE9wdGlvbklkc106IE9wdGlvbktleXM8Sz47XG59O1xuXG5leHBvcnQgaW50ZXJmYWNlIENvbmZpZ1BhcmFtcyB7XG4gICAgLyoqIEluaXRpYWwgUGl4ZWwgU3RyZWFtaW5nIHNldHRpbmdzICovXG4gICAgaW5pdGlhbFNldHRpbmdzPzogUGFydGlhbDxBbGxTZXR0aW5ncz47XG4gICAgLyoqIElmIHVzZVVybFBhcmFtcyBpcyBzZXQgdHJ1ZSwgd2lsbCByZWFkIGluaXRpYWwgdmFsdWVzIGZyb20gVVJMIHBhcmFtZXRlcnMgYW5kIHBlcnNpc3QgY2hhbmdlZCBzZXR0aW5ncyBpbnRvIFVSTCAqL1xuICAgIHVzZVVybFBhcmFtcz86IGJvb2xlYW47XG59XG5leHBvcnQgY2xhc3MgQ29uZmlnIHtcbiAgICAvKiBBIG1hcCBvZiBmbGFncyB0aGF0IGNhbiBiZSB0b2dnbGVkIC0gb3B0aW9ucyB0aGF0IGNhbiBiZSBzZXQgaW4gdGhlIGFwcGxpY2F0aW9uIC0gZS5nLiBVc2UgTWljPyAqL1xuICAgIHByaXZhdGUgZmxhZ3MgPSBuZXcgTWFwPEZsYWdzSWRzLCBTZXR0aW5nRmxhZz4oKTtcblxuICAgIC8qIEEgbWFwIG9mIG51bWVyaWNhbCBzZXR0aW5ncyAtIG9wdGlvbnMgdGhhdCBjYW4gYmUgaW4gdGhlIGFwcGxpY2F0aW9uIC0gZS5nLiBNaW5CaXRyYXRlICovXG4gICAgcHJpdmF0ZSBudW1lcmljUGFyYW1ldGVycyA9IG5ldyBNYXA8TnVtZXJpY1BhcmFtZXRlcnNJZHMsIFNldHRpbmdOdW1iZXI+KCk7XG5cbiAgICAvKiBBIG1hcCBvZiB0ZXh0IHNldHRpbmdzIC0gZS5nLiBzaWduYWxsaW5nIHNlcnZlciB1cmwgKi9cbiAgICBwcml2YXRlIHRleHRQYXJhbWV0ZXJzID0gbmV3IE1hcDxUZXh0UGFyYW1ldGVyc0lkcywgU2V0dGluZ1RleHQ+KCk7XG5cbiAgICAvKiBBIG1hcCBvZiBlbnVtIGJhc2VkIHNldHRpbmdzIC0gZS5nLiBwcmVmZXJyZWQgY29kZWMgKi9cbiAgICBwcml2YXRlIG9wdGlvblBhcmFtZXRlcnMgPSBuZXcgTWFwPE9wdGlvblBhcmFtZXRlcnNJZHMsIFNldHRpbmdPcHRpb24+KCk7XG5cbiAgICBwcml2YXRlIF91c2VVcmxQYXJhbXM6IGJvb2xlYW47XG5cbiAgICAvLyAtLS0tLS0tLS0tLS0gU2V0dGluZ3MgLS0tLS0tLS0tLS0tLS0tLS1cblxuICAgIGNvbnN0cnVjdG9yKGNvbmZpZzogQ29uZmlnUGFyYW1zID0ge30pIHtcbiAgICAgICAgY29uc3QgeyBpbml0aWFsU2V0dGluZ3MsIHVzZVVybFBhcmFtcyB9ID0gY29uZmlnO1xuICAgICAgICB0aGlzLl91c2VVcmxQYXJhbXMgPSAhIXVzZVVybFBhcmFtcztcbiAgICAgICAgdGhpcy5wb3B1bGF0ZURlZmF1bHRTZXR0aW5ncyh0aGlzLl91c2VVcmxQYXJhbXMpO1xuICAgICAgICBpZiAoaW5pdGlhbFNldHRpbmdzKSB7XG4gICAgICAgICAgICB0aGlzLnNldFNldHRpbmdzKGluaXRpYWxTZXR0aW5ncyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUcnVlIGlmIHJlYWRpbmcgY29uZmlndXJhdGlvbiBpbml0aWFsIHZhbHVlcyBmcm9tIFVSTCBwYXJhbWV0ZXJzLCBhbmRcbiAgICAgKiBwZXJzaXN0aW5nIGNoYW5nZXMgaW4gVVJMIHdoZW4gY2hhbmdlZC5cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0IHVzZVVybFBhcmFtcygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3VzZVVybFBhcmFtcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQb3B1bGF0ZSB0aGUgZGVmYXVsdCBzZXR0aW5ncyBmb3IgYSBQaXhlbCBTdHJlYW1pbmcgYXBwbGljYXRpb25cbiAgICAgKi9cbiAgICBwcml2YXRlIHBvcHVsYXRlRGVmYXVsdFNldHRpbmdzKHVzZVVybFBhcmFtczogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICAvKipcbiAgICAgICAgICogVGV4dCBQYXJhbWV0ZXJzXG4gICAgICAgICAqL1xuXG4gICAgICAgIHRoaXMudGV4dFBhcmFtZXRlcnMuc2V0KFxuICAgICAgICAgICAgVGV4dFBhcmFtZXRlcnMuU2lnbmFsbGluZ1NlcnZlclVybCxcbiAgICAgICAgICAgIG5ldyBTZXR0aW5nVGV4dChcbiAgICAgICAgICAgICAgICBUZXh0UGFyYW1ldGVycy5TaWduYWxsaW5nU2VydmVyVXJsLFxuICAgICAgICAgICAgICAgICdTaWduYWxsaW5nIHVybCcsXG4gICAgICAgICAgICAgICAgJ1VybCBvZiB0aGUgc2lnbmFsbGluZyBzZXJ2ZXInLFxuICAgICAgICAgICAgICAgIChsb2NhdGlvbi5wcm90b2NvbCA9PT0gJ2h0dHBzOicgPyAnd3NzOi8vJyA6ICd3czovLycpICtcbiAgICAgICAgICAgICAgICAgICAgd2luZG93LmxvY2F0aW9uLmhvc3RuYW1lICtcbiAgICAgICAgICAgICAgICAgICAgLy8gZm9yIHJlYWRhYmlsaXR5LCB3ZSBvbWl0IHRoZSBwb3J0IGlmIGl0J3MgODBcbiAgICAgICAgICAgICAgICAgICAgKHdpbmRvdy5sb2NhdGlvbi5wb3J0ID09PSAnODAnIHx8XG4gICAgICAgICAgICAgICAgICAgIHdpbmRvdy5sb2NhdGlvbi5wb3J0ID09PSAnJ1xuICAgICAgICAgICAgICAgICAgICAgICAgPyAnJ1xuICAgICAgICAgICAgICAgICAgICAgICAgOiBgOiR7d2luZG93LmxvY2F0aW9uLnBvcnR9YCksXG4gICAgICAgICAgICAgICAgdXNlVXJsUGFyYW1zXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG5cbiAgICAgICAgdGhpcy5vcHRpb25QYXJhbWV0ZXJzLnNldChcbiAgICAgICAgICAgIE9wdGlvblBhcmFtZXRlcnMuU3RyZWFtZXJJZCxcbiAgICAgICAgICAgIG5ldyBTZXR0aW5nT3B0aW9uKFxuICAgICAgICAgICAgICAgIE9wdGlvblBhcmFtZXRlcnMuU3RyZWFtZXJJZCxcbiAgICAgICAgICAgICAgICAnU3RyZWFtZXIgSUQnLFxuICAgICAgICAgICAgICAgICdUaGUgSUQgb2YgdGhlIHN0cmVhbWVyIHRvIHN0cmVhbS4nLFxuICAgICAgICAgICAgICAgICcnLFxuICAgICAgICAgICAgICAgIFtdLFxuICAgICAgICAgICAgICAgIHVzZVVybFBhcmFtc1xuICAgICAgICAgICAgKVxuICAgICAgICApO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBFbnVtIFBhcmFtZXRlcnNcbiAgICAgICAgICovXG4gICAgICAgIHRoaXMub3B0aW9uUGFyYW1ldGVycy5zZXQoXG4gICAgICAgICAgICBPcHRpb25QYXJhbWV0ZXJzLlByZWZlcnJlZENvZGVjLFxuICAgICAgICAgICAgbmV3IFNldHRpbmdPcHRpb24oXG4gICAgICAgICAgICAgICAgT3B0aW9uUGFyYW1ldGVycy5QcmVmZXJyZWRDb2RlYyxcbiAgICAgICAgICAgICAgICAnUHJlZmVycmVkIENvZGVjJyxcbiAgICAgICAgICAgICAgICAnVGhlIHByZWZlcnJlZCBjb2RlYyB0byBiZSB1c2VkIGR1cmluZyBjb2RlYyBuZWdvdGlhdGlvbicsXG4gICAgICAgICAgICAgICAgJ0gyNjQgbGV2ZWwtYXN5bW1ldHJ5LWFsbG93ZWQ9MTtwYWNrZXRpemF0aW9uLW1vZGU9MTtwcm9maWxlLWxldmVsLWlkPTQyZTAxZicsXG4gICAgICAgICAgICAgICAgKGZ1bmN0aW9uICgpOiBBcnJheTxzdHJpbmc+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgYnJvd3NlclN1cHBvcnRlZENvZGVjczogQXJyYXk8c3RyaW5nPiA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAvLyBUcnkgZ2V0IHRoZSBpbmZvIG5lZWRlZCBmcm9tIHRoZSBSVENSdHBSZWNlaXZlci4gVGhpcyBpcyBvbmx5IGF2YWlsYWJsZSBvbiBjaHJvbWVcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFSVENSdHBSZWNlaXZlci5nZXRDYXBhYmlsaXRpZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyb3dzZXJTdXBwb3J0ZWRDb2RlY3MucHVzaCgnT25seSBhdmFpbGFibGUgb24gQ2hyb21lJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYnJvd3NlclN1cHBvcnRlZENvZGVjcztcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG1hdGNoZXIgPSAvKFZQXFxkfEgyNlxcZHxBVjEpLiovO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBjb2RlY3MgPVxuICAgICAgICAgICAgICAgICAgICAgICAgUlRDUnRwUmVjZWl2ZXIuZ2V0Q2FwYWJpbGl0aWVzKCd2aWRlbycpLmNvZGVjcztcbiAgICAgICAgICAgICAgICAgICAgY29kZWNzLmZvckVhY2goKGNvZGVjKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzdHIgPVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZGVjLm1pbWVUeXBlLnNwbGl0KCcvJylbMV0gK1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICcgJyArXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNvZGVjLnNkcEZtdHBMaW5lIHx8ICcnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1hdGNoID0gbWF0Y2hlci5leGVjKHN0cik7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAobWF0Y2ggIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicm93c2VyU3VwcG9ydGVkQ29kZWNzLnB1c2goc3RyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBicm93c2VyU3VwcG9ydGVkQ29kZWNzO1xuICAgICAgICAgICAgICAgIH0pKCksXG4gICAgICAgICAgICAgICAgdXNlVXJsUGFyYW1zXG4gICAgICAgICAgICApXG4gICAgICAgICk7XHRcblxuICAgICAgICAvKipcbiAgICAgICAgICogQm9vbGVhbiBwYXJhbWV0ZXJzXG4gICAgICAgICAqL1xuXG4gICAgICAgIHRoaXMuZmxhZ3Muc2V0KFxuICAgICAgICAgICAgRmxhZ3MuQXV0b0Nvbm5lY3QsXG4gICAgICAgICAgICBuZXcgU2V0dGluZ0ZsYWcoXG4gICAgICAgICAgICAgICAgRmxhZ3MuQXV0b0Nvbm5lY3QsXG4gICAgICAgICAgICAgICAgJ0F1dG8gY29ubmVjdCB0byBzdHJlYW0nLFxuICAgICAgICAgICAgICAgICdXaGV0aGVyIHdlIHNob3VsZCBhdHRlbXB0IHRvIGF1dG8gY29ubmVjdCB0byB0aGUgc2lnbmFsbGluZyBzZXJ2ZXIgb3Igc2hvdyBhIGNsaWNrIHRvIHN0YXJ0IHByb21wdC4nLFxuICAgICAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgICAgICAgIHVzZVVybFBhcmFtc1xuICAgICAgICAgICAgKVxuICAgICAgICApO1xuXG4gICAgICAgIHRoaXMuZmxhZ3Muc2V0KFxuICAgICAgICAgICAgRmxhZ3MuQXV0b1BsYXlWaWRlbyxcbiAgICAgICAgICAgIG5ldyBTZXR0aW5nRmxhZyhcbiAgICAgICAgICAgICAgICBGbGFncy5BdXRvUGxheVZpZGVvLFxuICAgICAgICAgICAgICAgICdBdXRvIHBsYXkgdmlkZW8nLFxuICAgICAgICAgICAgICAgICdXaGVuIHZpZGVvIGlzIHJlYWR5IGF1dG9tYXRpY2FsbHkgc3RhcnQgcGxheWluZyBpdCBhcyBvcHBvc2VkIHRvIHNob3dpbmcgYSBwbGF5IGJ1dHRvbi4nLFxuICAgICAgICAgICAgICAgIHRydWUsXG4gICAgICAgICAgICAgICAgdXNlVXJsUGFyYW1zXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG5cbiAgICAgICAgdGhpcy5mbGFncy5zZXQoXG4gICAgICAgICAgICBGbGFncy5Ccm93c2VyU2VuZE9mZmVyLFxuICAgICAgICAgICAgbmV3IFNldHRpbmdGbGFnKFxuICAgICAgICAgICAgICAgIEZsYWdzLkJyb3dzZXJTZW5kT2ZmZXIsXG4gICAgICAgICAgICAgICAgJ0Jyb3dzZXIgc2VuZCBvZmZlcicsXG4gICAgICAgICAgICAgICAgJ0Jyb3dzZXIgd2lsbCBpbml0aWF0ZSB0aGUgV2ViUlRDIGhhbmRzaGFrZSBieSBzZW5kaW5nIHRoZSBvZmZlciB0byB0aGUgc3RyZWFtZXInLFxuICAgICAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgICAgICAgIHVzZVVybFBhcmFtc1xuICAgICAgICAgICAgKVxuICAgICAgICApO1xuXG4gICAgICAgIHRoaXMuZmxhZ3Muc2V0KFxuICAgICAgICAgICAgRmxhZ3MuVXNlTWljLFxuICAgICAgICAgICAgbmV3IFNldHRpbmdGbGFnKFxuICAgICAgICAgICAgICAgIEZsYWdzLlVzZU1pYyxcbiAgICAgICAgICAgICAgICAnVXNlIG1pY3JvcGhvbmUnLFxuICAgICAgICAgICAgICAgICdNYWtlIGJyb3dzZXIgcmVxdWVzdCBtaWNyb3Bob25lIGFjY2VzcyBhbmQgb3BlbiBhbiBpbnB1dCBhdWRpbyB0cmFjay4nLFxuICAgICAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgICAgICAgIHVzZVVybFBhcmFtc1xuICAgICAgICAgICAgKVxuICAgICAgICApO1xuXG4gICAgICAgIHRoaXMuZmxhZ3Muc2V0KFxuICAgICAgICAgICAgRmxhZ3MuU3RhcnRWaWRlb011dGVkLFxuICAgICAgICAgICAgbmV3IFNldHRpbmdGbGFnKFxuICAgICAgICAgICAgICAgIEZsYWdzLlN0YXJ0VmlkZW9NdXRlZCxcbiAgICAgICAgICAgICAgICAnU3RhcnQgdmlkZW8gbXV0ZWQnLFxuICAgICAgICAgICAgICAgICdWaWRlbyB3aWxsIHN0YXJ0IG11dGVkIGlmIHRydWUuJyxcbiAgICAgICAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICAgICAgICB1c2VVcmxQYXJhbXNcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcblxuICAgICAgICB0aGlzLmZsYWdzLnNldChcbiAgICAgICAgICAgIEZsYWdzLlN1cHByZXNzQnJvd3NlcktleXMsXG4gICAgICAgICAgICBuZXcgU2V0dGluZ0ZsYWcoXG4gICAgICAgICAgICAgICAgRmxhZ3MuU3VwcHJlc3NCcm93c2VyS2V5cyxcbiAgICAgICAgICAgICAgICAnU3VwcHJlc3MgYnJvd3NlciBrZXlzJyxcbiAgICAgICAgICAgICAgICAnU3VwcHJlc3MgY2VydGFpbiBicm93c2VyIGtleXMgdGhhdCB3ZSB1c2UgaW4gVUUsIGZvciBleGFtcGxlIEY1IHRvIHNob3cgc2hhZGVyIGNvbXBsZXhpdHkgaW5zdGVhZCBvZiByZWZyZXNoIHRoZSBwYWdlLicsXG4gICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgICAgICAgICB1c2VVcmxQYXJhbXNcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcblxuICAgICAgICB0aGlzLmZsYWdzLnNldChcbiAgICAgICAgICAgIEZsYWdzLklzUXVhbGl0eUNvbnRyb2xsZXIsXG4gICAgICAgICAgICBuZXcgU2V0dGluZ0ZsYWcoXG4gICAgICAgICAgICAgICAgRmxhZ3MuSXNRdWFsaXR5Q29udHJvbGxlcixcbiAgICAgICAgICAgICAgICAnSXMgcXVhbGl0eSBjb250cm9sbGVyPycsXG4gICAgICAgICAgICAgICAgJ1RydWUgaWYgdGhpcyBwZWVyIGNvbnRyb2xzIHN0cmVhbSBxdWFsaXR5JyxcbiAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICAgICAgICAgIHVzZVVybFBhcmFtc1xuICAgICAgICAgICAgKVxuICAgICAgICApO1xuXG4gICAgICAgIHRoaXMuZmxhZ3Muc2V0KFxuICAgICAgICAgICAgRmxhZ3MuRm9yY2VNb25vQXVkaW8sXG4gICAgICAgICAgICBuZXcgU2V0dGluZ0ZsYWcoXG4gICAgICAgICAgICAgICAgRmxhZ3MuRm9yY2VNb25vQXVkaW8sXG4gICAgICAgICAgICAgICAgJ0ZvcmNlIG1vbm8gYXVkaW8nLFxuICAgICAgICAgICAgICAgICdGb3JjZSBicm93c2VyIHRvIHJlcXVlc3QgbW9ubyBhdWRpbyBpbiB0aGUgU0RQJyxcbiAgICAgICAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICAgICAgICB1c2VVcmxQYXJhbXNcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcblxuICAgICAgICB0aGlzLmZsYWdzLnNldChcbiAgICAgICAgICAgIEZsYWdzLkZvcmNlVFVSTixcbiAgICAgICAgICAgIG5ldyBTZXR0aW5nRmxhZyhcbiAgICAgICAgICAgICAgICBGbGFncy5Gb3JjZVRVUk4sXG4gICAgICAgICAgICAgICAgJ0ZvcmNlIFRVUk4nLFxuICAgICAgICAgICAgICAgICdPbmx5IGdlbmVyYXRlIFRVUk4vUmVsYXllZCBJQ0UgY2FuZGlkYXRlcy4nLFxuICAgICAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgICAgICAgIHVzZVVybFBhcmFtc1xuICAgICAgICAgICAgKVxuICAgICAgICApO1xuXG4gICAgICAgIHRoaXMuZmxhZ3Muc2V0KFxuICAgICAgICAgICAgRmxhZ3MuQUZLRGV0ZWN0aW9uLFxuICAgICAgICAgICAgbmV3IFNldHRpbmdGbGFnKFxuICAgICAgICAgICAgICAgIEZsYWdzLkFGS0RldGVjdGlvbixcbiAgICAgICAgICAgICAgICAnQUZLIGlmIGlkbGUnLFxuICAgICAgICAgICAgICAgICdUaW1lb3V0IHRoZSBleHBlcmllbmNlIGlmIHVzZXIgaXMgQUZLIGZvciBhIHBlcmlvZC4nLFxuICAgICAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgICAgICAgIHVzZVVybFBhcmFtc1xuICAgICAgICAgICAgKVxuICAgICAgICApO1xuXG4gICAgICAgIHRoaXMuZmxhZ3Muc2V0KFxuICAgICAgICAgICAgRmxhZ3MuTWF0Y2hWaWV3cG9ydFJlc29sdXRpb24sXG4gICAgICAgICAgICBuZXcgU2V0dGluZ0ZsYWcoXG4gICAgICAgICAgICAgICAgRmxhZ3MuTWF0Y2hWaWV3cG9ydFJlc29sdXRpb24sXG4gICAgICAgICAgICAgICAgJ01hdGNoIHZpZXdwb3J0IHJlc29sdXRpb24nLFxuICAgICAgICAgICAgICAgICdQaXhlbCBTdHJlYW1pbmcgd2lsbCBiZSBpbnN0cnVjdGVkIHRvIGR5bmFtaWNhbGx5IHJlc2l6ZSB0aGUgdmlkZW8gc3RyZWFtIHRvIG1hdGNoIHRoZSBzaXplIG9mIHRoZSB2aWRlbyBlbGVtZW50LicsXG4gICAgICAgICAgICAgICAgZmFsc2UsXG4gICAgICAgICAgICAgICAgdXNlVXJsUGFyYW1zXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG5cbiAgICAgICAgdGhpcy5mbGFncy5zZXQoXG4gICAgICAgICAgICBGbGFncy5Ib3ZlcmluZ01vdXNlTW9kZSxcbiAgICAgICAgICAgIG5ldyBTZXR0aW5nRmxhZyhcbiAgICAgICAgICAgICAgICBGbGFncy5Ib3ZlcmluZ01vdXNlTW9kZSxcbiAgICAgICAgICAgICAgICAnQ29udHJvbCBTY2hlbWU6IExvY2tlZCBNb3VzZScsXG4gICAgICAgICAgICAgICAgJ0VpdGhlciBsb2NrZWQgbW91c2UsIHdoZXJlIHRoZSBwb2ludGVyIGlzIGNvbnN1bWVkIGJ5IHRoZSB2aWRlbyBhbmQgbG9ja2VkIHRvIGl0LCBvciBob3ZlcmluZyBtb3VzZSwgd2hlcmUgdGhlIG1vdXNlIGlzIG5vdCBjb25zdW1lZC4nLFxuICAgICAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgICAgICAgIHVzZVVybFBhcmFtcyxcbiAgICAgICAgICAgICAgICAoaXNIb3ZlcmluZ01vdXNlOiBib29sZWFuLCBzZXR0aW5nOiBTZXR0aW5nQmFzZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBzZXR0aW5nLmxhYmVsID0gYENvbnRyb2wgU2NoZW1lOiAke2lzSG92ZXJpbmdNb3VzZSA/ICdIb3ZlcmluZycgOiAnTG9ja2VkJ30gTW91c2VgO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcblxuICAgICAgICB0aGlzLmZsYWdzLnNldChcbiAgICAgICAgICAgIEZsYWdzLkZha2VNb3VzZVdpdGhUb3VjaGVzLFxuICAgICAgICAgICAgbmV3IFNldHRpbmdGbGFnKFxuICAgICAgICAgICAgICAgIEZsYWdzLkZha2VNb3VzZVdpdGhUb3VjaGVzLFxuICAgICAgICAgICAgICAgICdGYWtlIG1vdXNlIHdpdGggdG91Y2hlcycsXG4gICAgICAgICAgICAgICAgJ0Egc2luZ2xlIGZpbmdlciB0b3VjaCBpcyBjb252ZXJ0ZWQgaW50byBhIG1vdXNlIGV2ZW50LiBUaGlzIGFsbG93cyBhIG5vbi10b3VjaCBhcHBsaWNhdGlvbiB0byBiZSBjb250cm9sbGVkIHBhcnRpYWxseSB2aWEgYSB0b3VjaCBkZXZpY2UuJyxcbiAgICAgICAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICAgICAgICB1c2VVcmxQYXJhbXNcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcblxuICAgICAgICB0aGlzLmZsYWdzLnNldChcbiAgICAgICAgICAgIEZsYWdzLktleWJvYXJkSW5wdXQsXG4gICAgICAgICAgICBuZXcgU2V0dGluZ0ZsYWcoXG4gICAgICAgICAgICAgICAgRmxhZ3MuS2V5Ym9hcmRJbnB1dCxcbiAgICAgICAgICAgICAgICAnS2V5Ym9hcmQgaW5wdXQnLFxuICAgICAgICAgICAgICAgICdJZiBlbmFibGVkLCBzZW5kIGtleWJvYXJkIGV2ZW50cyB0byBzdHJlYW1lcicsXG4gICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgICAgICAgICB1c2VVcmxQYXJhbXNcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcblxuICAgICAgICB0aGlzLmZsYWdzLnNldChcbiAgICAgICAgICAgIEZsYWdzLk1vdXNlSW5wdXQsXG4gICAgICAgICAgICBuZXcgU2V0dGluZ0ZsYWcoXG4gICAgICAgICAgICAgICAgRmxhZ3MuTW91c2VJbnB1dCxcbiAgICAgICAgICAgICAgICAnTW91c2UgaW5wdXQnLFxuICAgICAgICAgICAgICAgICdJZiBlbmFibGVkLCBzZW5kIG1vdXNlIGV2ZW50cyB0byBzdHJlYW1lcicsXG4gICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgICAgICAgICB1c2VVcmxQYXJhbXNcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcblxuICAgICAgICB0aGlzLmZsYWdzLnNldChcbiAgICAgICAgICAgIEZsYWdzLlRvdWNoSW5wdXQsXG4gICAgICAgICAgICBuZXcgU2V0dGluZ0ZsYWcoXG4gICAgICAgICAgICAgICAgRmxhZ3MuVG91Y2hJbnB1dCxcbiAgICAgICAgICAgICAgICAnVG91Y2ggaW5wdXQnLFxuICAgICAgICAgICAgICAgICdJZiBlbmFibGVkLCBzZW5kIHRvdWNoIGV2ZW50cyB0byBzdHJlYW1lcicsXG4gICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgICAgICAgICB1c2VVcmxQYXJhbXNcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcblxuICAgICAgICB0aGlzLmZsYWdzLnNldChcbiAgICAgICAgICAgIEZsYWdzLkdhbWVwYWRJbnB1dCxcbiAgICAgICAgICAgIG5ldyBTZXR0aW5nRmxhZyhcbiAgICAgICAgICAgICAgICBGbGFncy5HYW1lcGFkSW5wdXQsXG4gICAgICAgICAgICAgICAgJ0dhbWVwYWQgaW5wdXQnLFxuICAgICAgICAgICAgICAgICdJZiBlbmFibGVkLCBzZW5kIGdhbWVwYWQgZXZlbnRzIHRvIHN0cmVhbWVyJyxcbiAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICAgICAgICAgIHVzZVVybFBhcmFtc1xuICAgICAgICAgICAgKVxuICAgICAgICApO1xuXG4gICAgICAgIHRoaXMuZmxhZ3Muc2V0KFxuICAgICAgICAgICAgRmxhZ3MuWFJDb250cm9sbGVySW5wdXQsXG4gICAgICAgICAgICBuZXcgU2V0dGluZ0ZsYWcoXG4gICAgICAgICAgICAgICAgRmxhZ3MuWFJDb250cm9sbGVySW5wdXQsXG4gICAgICAgICAgICAgICAgJ1hSIGNvbnRyb2xsZXIgaW5wdXQnLFxuICAgICAgICAgICAgICAgICdJZiBlbmFibGVkLCBzZW5kIFhSIGNvbnRyb2xsZXIgZXZlbnRzIHRvIHN0cmVhbWVyJyxcbiAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICAgICAgICAgIHVzZVVybFBhcmFtc1xuICAgICAgICAgICAgKVxuICAgICAgICApO1xuXG4gICAgICAgIHRoaXMuZmxhZ3Muc2V0KFxuICAgICAgICAgICAgRmxhZ3MuV2FpdEZvclN0cmVhbWVyLFxuICAgICAgICAgICAgbmV3IFNldHRpbmdGbGFnKFxuICAgICAgICAgICAgICAgIEZsYWdzLldhaXRGb3JTdHJlYW1lcixcbiAgICAgICAgICAgICAgICAnV2FpdCBmb3Igc3RyZWFtZXInLFxuICAgICAgICAgICAgICAgICdXaWxsIGNvbnRpbnVlIHRyeWluZyB0byBjb25uZWN0IHRvIHRoZSBmaXJzdCBzdHJlYW1lciBhdmFpbGFibGUuJyxcbiAgICAgICAgICAgICAgICB0cnVlLFxuICAgICAgICAgICAgICAgIHVzZVVybFBhcmFtc1xuICAgICAgICAgICAgKVxuICAgICAgICApO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBOdW1lcmljIHBhcmFtZXRlcnNcbiAgICAgICAgICovXG5cbiAgICAgICAgdGhpcy5udW1lcmljUGFyYW1ldGVycy5zZXQoXG4gICAgICAgICAgICBOdW1lcmljUGFyYW1ldGVycy5BRktUaW1lb3V0U2VjcyxcbiAgICAgICAgICAgIG5ldyBTZXR0aW5nTnVtYmVyKFxuICAgICAgICAgICAgICAgIE51bWVyaWNQYXJhbWV0ZXJzLkFGS1RpbWVvdXRTZWNzLFxuICAgICAgICAgICAgICAgICdBRksgdGltZW91dCcsXG4gICAgICAgICAgICAgICAgJ1RoZSB0aW1lIChpbiBzZWNvbmRzKSBpdCB0YWtlcyBmb3IgdGhlIGFwcGxpY2F0aW9uIHRvIHRpbWUgb3V0IGlmIEFGSyB0aW1lb3V0IGlzIGVuYWJsZWQuJyxcbiAgICAgICAgICAgICAgICAwIC8qbWluKi8sXG4gICAgICAgICAgICAgICAgNjAwIC8qbWF4Ki8sXG4gICAgICAgICAgICAgICAgMTIwIC8qdmFsdWUqLyxcbiAgICAgICAgICAgICAgICB1c2VVcmxQYXJhbXNcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcblxuICAgICAgICB0aGlzLm51bWVyaWNQYXJhbWV0ZXJzLnNldChcbiAgICAgICAgICAgIE51bWVyaWNQYXJhbWV0ZXJzLk1heFJlY29ubmVjdEF0dGVtcHRzLFxuICAgICAgICAgICAgbmV3IFNldHRpbmdOdW1iZXIoXG4gICAgICAgICAgICAgICAgTnVtZXJpY1BhcmFtZXRlcnMuTWF4UmVjb25uZWN0QXR0ZW1wdHMsXG4gICAgICAgICAgICAgICAgJ01heCBSZWNvbm5lY3RzJyxcbiAgICAgICAgICAgICAgICAnTWF4aW11bSBudW1iZXIgb2YgcmVjb25uZWN0cyB0aGUgYXBwbGljYXRpb24gd2lsbCBhdHRlbXB0IHdoZW4gYSBzdHJlYW1lciBkaXNjb25uZWN0cy4nLFxuICAgICAgICAgICAgICAgIDAgLyptaW4qLyxcbiAgICAgICAgICAgICAgICA5OTkgLyptYXgqLyxcbiAgICAgICAgICAgICAgICAzIC8qdmFsdWUqLyxcbiAgICAgICAgICAgICAgICB1c2VVcmxQYXJhbXNcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcblxuICAgICAgICB0aGlzLm51bWVyaWNQYXJhbWV0ZXJzLnNldChcbiAgICAgICAgICAgIE51bWVyaWNQYXJhbWV0ZXJzLk1pblFQLFxuICAgICAgICAgICAgbmV3IFNldHRpbmdOdW1iZXIoXG4gICAgICAgICAgICAgICAgTnVtZXJpY1BhcmFtZXRlcnMuTWluUVAsXG4gICAgICAgICAgICAgICAgJ01pbiBRUCcsXG4gICAgICAgICAgICAgICAgJ1RoZSBsb3dlciBib3VuZCBmb3IgdGhlIHF1YW50aXphdGlvbiBwYXJhbWV0ZXIgKFFQKSBvZiB0aGUgZW5jb2Rlci4gMCA9IEJlc3QgcXVhbGl0eSwgNTEgPSB3b3JzdCBxdWFsaXR5LicsXG4gICAgICAgICAgICAgICAgMCAvKm1pbiovLFxuICAgICAgICAgICAgICAgIDUxIC8qbWF4Ki8sXG4gICAgICAgICAgICAgICAgMCAvKnZhbHVlKi8sXG4gICAgICAgICAgICAgICAgdXNlVXJsUGFyYW1zXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG5cbiAgICAgICAgdGhpcy5udW1lcmljUGFyYW1ldGVycy5zZXQoXG4gICAgICAgICAgICBOdW1lcmljUGFyYW1ldGVycy5NYXhRUCxcbiAgICAgICAgICAgIG5ldyBTZXR0aW5nTnVtYmVyKFxuICAgICAgICAgICAgICAgIE51bWVyaWNQYXJhbWV0ZXJzLk1heFFQLFxuICAgICAgICAgICAgICAgICdNYXggUVAnLFxuICAgICAgICAgICAgICAgICdUaGUgdXBwZXIgYm91bmQgZm9yIHRoZSBxdWFudGl6YXRpb24gcGFyYW1ldGVyIChRUCkgb2YgdGhlIGVuY29kZXIuIDAgPSBCZXN0IHF1YWxpdHksIDUxID0gd29yc3QgcXVhbGl0eS4nLFxuICAgICAgICAgICAgICAgIDAgLyptaW4qLyxcbiAgICAgICAgICAgICAgICA1MSAvKm1heCovLFxuICAgICAgICAgICAgICAgIDUxIC8qdmFsdWUqLyxcbiAgICAgICAgICAgICAgICB1c2VVcmxQYXJhbXNcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcblxuICAgICAgICB0aGlzLm51bWVyaWNQYXJhbWV0ZXJzLnNldChcbiAgICAgICAgICAgIE51bWVyaWNQYXJhbWV0ZXJzLldlYlJUQ0ZQUyxcbiAgICAgICAgICAgIG5ldyBTZXR0aW5nTnVtYmVyKFxuICAgICAgICAgICAgICAgIE51bWVyaWNQYXJhbWV0ZXJzLldlYlJUQ0ZQUyxcbiAgICAgICAgICAgICAgICAnTWF4IEZQUycsXG4gICAgICAgICAgICAgICAgJ1RoZSBtYXhpbXVtIEZQUyB0aGF0IFdlYlJUQyB3aWxsIHRyeSB0byB0cmFuc21pdCBmcmFtZXMgYXQuJyxcbiAgICAgICAgICAgICAgICAxIC8qbWluKi8sXG4gICAgICAgICAgICAgICAgOTk5IC8qbWF4Ki8sXG4gICAgICAgICAgICAgICAgNjAgLyp2YWx1ZSovLFxuICAgICAgICAgICAgICAgIHVzZVVybFBhcmFtc1xuICAgICAgICAgICAgKVxuICAgICAgICApO1xuXG4gICAgICAgIHRoaXMubnVtZXJpY1BhcmFtZXRlcnMuc2V0KFxuICAgICAgICAgICAgTnVtZXJpY1BhcmFtZXRlcnMuV2ViUlRDTWluQml0cmF0ZSxcbiAgICAgICAgICAgIG5ldyBTZXR0aW5nTnVtYmVyKFxuICAgICAgICAgICAgICAgIE51bWVyaWNQYXJhbWV0ZXJzLldlYlJUQ01pbkJpdHJhdGUsXG4gICAgICAgICAgICAgICAgJ01pbiBCaXRyYXRlIChrYnBzKScsXG4gICAgICAgICAgICAgICAgJ1RoZSBtaW5pbXVtIGJpdHJhdGUgdGhhdCBXZWJSVEMgc2hvdWxkIHVzZS4nLFxuICAgICAgICAgICAgICAgIDAgLyptaW4qLyxcbiAgICAgICAgICAgICAgICA1MDAwMDAgLyptYXgqLyxcbiAgICAgICAgICAgICAgICAwIC8qdmFsdWUqLyxcbiAgICAgICAgICAgICAgICB1c2VVcmxQYXJhbXNcbiAgICAgICAgICAgIClcbiAgICAgICAgKTtcblxuICAgICAgICB0aGlzLm51bWVyaWNQYXJhbWV0ZXJzLnNldChcbiAgICAgICAgICAgIE51bWVyaWNQYXJhbWV0ZXJzLldlYlJUQ01heEJpdHJhdGUsXG4gICAgICAgICAgICBuZXcgU2V0dGluZ051bWJlcihcbiAgICAgICAgICAgICAgICBOdW1lcmljUGFyYW1ldGVycy5XZWJSVENNYXhCaXRyYXRlLFxuICAgICAgICAgICAgICAgICdNYXggQml0cmF0ZSAoa2JwcyknLFxuICAgICAgICAgICAgICAgICdUaGUgbWF4aW11bSBiaXRyYXRlIHRoYXQgV2ViUlRDIHNob3VsZCB1c2UuJyxcbiAgICAgICAgICAgICAgICAwIC8qbWluKi8sXG4gICAgICAgICAgICAgICAgNTAwMDAwIC8qbWF4Ki8sXG4gICAgICAgICAgICAgICAgMCAvKnZhbHVlKi8sXG4gICAgICAgICAgICAgICAgdXNlVXJsUGFyYW1zXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG5cbiAgICAgICAgdGhpcy5udW1lcmljUGFyYW1ldGVycy5zZXQoXG4gICAgICAgICAgICBOdW1lcmljUGFyYW1ldGVycy5TdHJlYW1lckF1dG9Kb2luSW50ZXJ2YWwsXG4gICAgICAgICAgICBuZXcgU2V0dGluZ051bWJlcihcbiAgICAgICAgICAgICAgICBOdW1lcmljUGFyYW1ldGVycy5TdHJlYW1lckF1dG9Kb2luSW50ZXJ2YWwsXG4gICAgICAgICAgICAgICAgJ1N0cmVhbWVyIEF1dG8gSm9pbiBJbnRlcnZhbCAobXMpJyxcbiAgICAgICAgICAgICAgICAnRGVsYXkgYmV0d2VlbiByZXRyaWVzIHdoZW4gd2FpdGluZyBmb3IgYW4gYXZhaWxhYmxlIHN0cmVhbWVyLicsXG4gICAgICAgICAgICAgICAgNTAwIC8qbWluKi8sXG4gICAgICAgICAgICAgICAgOTAwMDAwIC8qbWF4Ki8sXG4gICAgICAgICAgICAgICAgMzAwMCAvKnZhbHVlKi8sXG4gICAgICAgICAgICAgICAgdXNlVXJsUGFyYW1zXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkIGEgY2FsbGJhY2sgdG8gZmlyZSB3aGVuIHRoZSBudW1lcmljIHNldHRpbmcgaXMgdG9nZ2xlZC5cbiAgICAgKiBAcGFyYW0gaWQgVGhlIGlkIG9mIHRoZSBmbGFnLlxuICAgICAqIEBwYXJhbSBvbkNoYW5nZWRMaXN0ZW5lciBUaGUgY2FsbGJhY2sgdG8gZmlyZSB3aGVuIHRoZSBudW1lcmljIHZhbHVlIGNoYW5nZXMuXG4gICAgICovXG4gICAgX2FkZE9uTnVtZXJpY1NldHRpbmdDaGFuZ2VkTGlzdGVuZXIoXG4gICAgICAgIGlkOiBOdW1lcmljUGFyYW1ldGVyc0lkcyxcbiAgICAgICAgb25DaGFuZ2VkTGlzdGVuZXI6IChuZXdWYWx1ZTogbnVtYmVyKSA9PiB2b2lkXG4gICAgKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLm51bWVyaWNQYXJhbWV0ZXJzLmhhcyhpZCkpIHtcbiAgICAgICAgICAgIHRoaXMubnVtZXJpY1BhcmFtZXRlcnNcbiAgICAgICAgICAgICAgICAuZ2V0KGlkKVxuICAgICAgICAgICAgICAgIC5hZGRPbkNoYW5nZWRMaXN0ZW5lcihvbkNoYW5nZWRMaXN0ZW5lcik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBfYWRkT25PcHRpb25TZXR0aW5nQ2hhbmdlZExpc3RlbmVyKFxuICAgICAgICBpZDogT3B0aW9uUGFyYW1ldGVyc0lkcyxcbiAgICAgICAgb25DaGFuZ2VkTGlzdGVuZXI6IChuZXdWYWx1ZTogc3RyaW5nKSA9PiB2b2lkXG4gICAgKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLm9wdGlvblBhcmFtZXRlcnMuaGFzKGlkKSkge1xuICAgICAgICAgICAgdGhpcy5vcHRpb25QYXJhbWV0ZXJzXG4gICAgICAgICAgICAgICAgLmdldChpZClcbiAgICAgICAgICAgICAgICAuYWRkT25DaGFuZ2VkTGlzdGVuZXIob25DaGFuZ2VkTGlzdGVuZXIpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGlkIFRoZSBpZCBvZiB0aGUgbnVtZXJpYyBzZXR0aW5nIHdlIGFyZSBpbnRlcmVzdGVkIGluIGdldHRpbmcgYSB2YWx1ZSBmb3IuXG4gICAgICogQHJldHVybnMgVGhlIG51bWVyaWMgdmFsdWUgc3RvcmVkIGluIHRoZSBwYXJhbWV0ZXIgd2l0aCB0aGUgcGFzc2VkIGlkLlxuICAgICAqL1xuICAgIGdldE51bWVyaWNTZXR0aW5nVmFsdWUoaWQ6IE51bWVyaWNQYXJhbWV0ZXJzSWRzKTogbnVtYmVyIHtcbiAgICAgICAgaWYgKHRoaXMubnVtZXJpY1BhcmFtZXRlcnMuaGFzKGlkKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubnVtZXJpY1BhcmFtZXRlcnMuZ2V0KGlkKS5udW1iZXI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFRoZXJlIGlzIG5vIG51bWVyaWMgc2V0dGluZyB3aXRoIHRoZSBpZCBvZiAke2lkfWApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGlkIFRoZSBpZCBvZiB0aGUgdGV4dCBzZXR0aW5nIHdlIGFyZSBpbnRlcmVzdGVkIGluIGdldHRpbmcgYSB2YWx1ZSBmb3IuXG4gICAgICogQHJldHVybnMgVGhlIHRleHQgdmFsdWUgc3RvcmVkIGluIHRoZSBwYXJhbWV0ZXIgd2l0aCB0aGUgcGFzc2VkIGlkLlxuICAgICAqL1xuICAgIGdldFRleHRTZXR0aW5nVmFsdWUoaWQ6IFRleHRQYXJhbWV0ZXJzSWRzKTogc3RyaW5nIHtcbiAgICAgICAgaWYgKHRoaXMudGV4dFBhcmFtZXRlcnMuaGFzKGlkKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudGV4dFBhcmFtZXRlcnMuZ2V0KGlkKS52YWx1ZSBhcyBzdHJpbmc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFRoZXJlIGlzIG5vIG51bWVyaWMgc2V0dGluZyB3aXRoIHRoZSBpZCBvZiAke2lkfWApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IG51bWJlciBpbiB0aGUgc2V0dGluZy5cbiAgICAgKiBAcGFyYW0gaWQgVGhlIGlkIG9mIHRoZSBudW1lcmljIHNldHRpbmcgd2UgYXJlIGludGVyZXN0ZWQgaW4uXG4gICAgICogQHBhcmFtIHZhbHVlIFRoZSBudW1lcmljIHZhbHVlIHRvIHNldC5cbiAgICAgKi9cbiAgICBzZXROdW1lcmljU2V0dGluZyhpZDogTnVtZXJpY1BhcmFtZXRlcnNJZHMsIHZhbHVlOiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMubnVtZXJpY1BhcmFtZXRlcnMuaGFzKGlkKSkge1xuICAgICAgICAgICAgdGhpcy5udW1lcmljUGFyYW1ldGVycy5nZXQoaWQpLm51bWJlciA9IHZhbHVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBUaGVyZSBpcyBubyBudW1lcmljIHNldHRpbmcgd2l0aCB0aGUgaWQgb2YgJHtpZH1gKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZCBhIGNhbGxiYWNrIHRvIGZpcmUgd2hlbiB0aGUgZmxhZyBpcyB0b2dnbGVkLlxuICAgICAqIEBwYXJhbSBpZCBUaGUgaWQgb2YgdGhlIGZsYWcuXG4gICAgICogQHBhcmFtIG9uQ2hhbmdlTGlzdGVuZXIgVGhlIGNhbGxiYWNrIHRvIGZpcmUgd2hlbiB0aGUgdmFsdWUgY2hhbmdlcy5cbiAgICAgKi9cbiAgICBfYWRkT25TZXR0aW5nQ2hhbmdlZExpc3RlbmVyKFxuICAgICAgICBpZDogRmxhZ3NJZHMsXG4gICAgICAgIG9uQ2hhbmdlTGlzdGVuZXI6IChuZXdGbGFnVmFsdWU6IGJvb2xlYW4pID0+IHZvaWRcbiAgICApOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuZmxhZ3MuaGFzKGlkKSkge1xuICAgICAgICAgICAgdGhpcy5mbGFncy5nZXQoaWQpLm9uQ2hhbmdlID0gb25DaGFuZ2VMaXN0ZW5lcjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZCBhIGNhbGxiYWNrIHRvIGZpcmUgd2hlbiB0aGUgdGV4dCBpcyBjaGFuZ2VkLlxuICAgICAqIEBwYXJhbSBpZCBUaGUgaWQgb2YgdGhlIGZsYWcuXG4gICAgICogQHBhcmFtIG9uQ2hhbmdlTGlzdGVuZXIgVGhlIGNhbGxiYWNrIHRvIGZpcmUgd2hlbiB0aGUgdmFsdWUgY2hhbmdlcy5cbiAgICAgKi9cbiAgICBfYWRkT25UZXh0U2V0dGluZ0NoYW5nZWRMaXN0ZW5lcihcbiAgICAgICAgaWQ6IFRleHRQYXJhbWV0ZXJzSWRzLFxuICAgICAgICBvbkNoYW5nZUxpc3RlbmVyOiAobmV3VGV4dFZhbHVlOiBzdHJpbmcpID0+IHZvaWRcbiAgICApOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMudGV4dFBhcmFtZXRlcnMuaGFzKGlkKSkge1xuICAgICAgICAgICAgdGhpcy50ZXh0UGFyYW1ldGVycy5nZXQoaWQpLm9uQ2hhbmdlID0gb25DaGFuZ2VMaXN0ZW5lcjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgb3B0aW9uIHdoaWNoIGhhcyB0aGUgZ2l2ZW4gaWQuXG4gICAgICogQHBhcmFtIGlkIFRoZSBpZCBvZiB0aGUgb3B0aW9uLlxuICAgICAqIEByZXR1cm5zIFRoZSBTZXR0aW5nT3B0aW9uIG9iamVjdCBtYXRjaGluZyBpZFxuICAgICAqL1xuICAgIGdldFNldHRpbmdPcHRpb24oaWQ6IE9wdGlvblBhcmFtZXRlcnNJZHMpOiBTZXR0aW5nT3B0aW9uIHtcbiAgICAgICAgcmV0dXJuIHRoaXMub3B0aW9uUGFyYW1ldGVycy5nZXQoaWQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgdmFsdWUgb2YgdGhlIGNvbmZpZ3VyYXRpb24gZmxhZyB3aGljaCBoYXMgdGhlIGdpdmVuIGlkLlxuICAgICAqIEBwYXJhbSBpZCBUaGUgdW5pcXVlIGlkIGZvciB0aGUgZmxhZy5cbiAgICAgKiBAcmV0dXJucyBUcnVlIGlmIHRoZSBmbGFnIGlzIGVuYWJsZWQuXG4gICAgICovXG4gICAgaXNGbGFnRW5hYmxlZChpZDogRmxhZ3NJZHMpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZmxhZ3MuZ2V0KGlkKS5mbGFnIGFzIGJvb2xlYW47XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IGZsYWcgdG8gYmUgZW5hYmxlZC9kaXNhYmxlZC5cbiAgICAgKiBAcGFyYW0gaWQgVGhlIGlkIG9mIHRoZSBmbGFnIHRvIHRvZ2dsZS5cbiAgICAgKiBAcGFyYW0gZmxhZ0VuYWJsZWQgVHJ1ZSBpZiB0aGUgZmxhZyBzaG91bGQgYmUgZW5hYmxlZC5cbiAgICAgKi9cbiAgICBzZXRGbGFnRW5hYmxlZChpZDogRmxhZ3NJZHMsIGZsYWdFbmFibGVkOiBib29sZWFuKSB7XG4gICAgICAgIGlmICghdGhpcy5mbGFncy5oYXMoaWQpKSB7XG4gICAgICAgICAgICBMb2dnZXIuV2FybmluZyhcbiAgICAgICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgICAgIGBDYW5ub3QgdG9nZ2xlIGZsYWcgY2FsbGVkICR7aWR9IC0gaXQgZG9lcyBub3QgZXhpc3QgaW4gdGhlIENvbmZpZy5mbGFncyBtYXAuYFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZmxhZ3MuZ2V0KGlkKS5mbGFnID0gZmxhZ0VuYWJsZWQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIHRleHQgc2V0dGluZy5cbiAgICAgKiBAcGFyYW0gaWQgVGhlIGlkIG9mIHRoZSBzZXR0aW5nXG4gICAgICogQHBhcmFtIHNldHRpbmdWYWx1ZSBUaGUgdmFsdWUgdG8gc2V0IGluIHRoZSBzZXR0aW5nLlxuICAgICAqL1xuICAgIHNldFRleHRTZXR0aW5nKGlkOiBUZXh0UGFyYW1ldGVyc0lkcywgc2V0dGluZ1ZhbHVlOiBzdHJpbmcpIHtcbiAgICAgICAgaWYgKCF0aGlzLnRleHRQYXJhbWV0ZXJzLmhhcyhpZCkpIHtcbiAgICAgICAgICAgIExvZ2dlci5XYXJuaW5nKFxuICAgICAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAgICAgYENhbm5vdCBzZXQgdGV4dCBzZXR0aW5nIGNhbGxlZCAke2lkfSAtIGl0IGRvZXMgbm90IGV4aXN0IGluIHRoZSBDb25maWcudGV4dFBhcmFtZXRlcnMgbWFwLmBcbiAgICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnRleHRQYXJhbWV0ZXJzLmdldChpZCkudGV4dCA9IHNldHRpbmdWYWx1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgb3B0aW9uIHNldHRpbmcgbGlzdCBvZiBvcHRpb25zLlxuICAgICAqIEBwYXJhbSBpZCBUaGUgaWQgb2YgdGhlIHNldHRpbmdcbiAgICAgKiBAcGFyYW0gc2V0dGluZ09wdGlvbnMgVGhlIHZhbHVlcyB0aGUgc2V0dGluZyBjb3VsZCB0YWtlXG4gICAgICovXG4gICAgc2V0T3B0aW9uU2V0dGluZ09wdGlvbnMoXG4gICAgICAgIGlkOiBPcHRpb25QYXJhbWV0ZXJzSWRzLFxuICAgICAgICBzZXR0aW5nT3B0aW9uczogQXJyYXk8c3RyaW5nPlxuICAgICkge1xuICAgICAgICBpZiAoIXRoaXMub3B0aW9uUGFyYW1ldGVycy5oYXMoaWQpKSB7XG4gICAgICAgICAgICBMb2dnZXIuV2FybmluZyhcbiAgICAgICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgICAgIGBDYW5ub3Qgc2V0IHRleHQgc2V0dGluZyBjYWxsZWQgJHtpZH0gLSBpdCBkb2VzIG5vdCBleGlzdCBpbiB0aGUgQ29uZmlnLm9wdGlvblBhcmFtZXRlcnMgbWFwLmBcbiAgICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLm9wdGlvblBhcmFtZXRlcnMuZ2V0KGlkKS5vcHRpb25zID0gc2V0dGluZ09wdGlvbnM7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgb3B0aW9uIGVudW0gc2V0dGluZ3Mgc2VsZWN0ZWQgb3B0aW9uLlxuICAgICAqIEBwYXJhbSBpZCBUaGUgaWQgb2YgdGhlIHNldHRpbmdcbiAgICAgKiBAcGFyYW0gc2V0dGluZ09wdGlvbnMgVGhlIHZhbHVlIHRvIHNlbGVjdCBvdXQgb2YgYWxsIHRoZSBvcHRpb25zXG4gICAgICovXG4gICAgc2V0T3B0aW9uU2V0dGluZ1ZhbHVlKGlkOiBPcHRpb25QYXJhbWV0ZXJzSWRzLCBzZXR0aW5nVmFsdWU6IHN0cmluZykge1xuICAgICAgICBpZiAoIXRoaXMub3B0aW9uUGFyYW1ldGVycy5oYXMoaWQpKSB7XG4gICAgICAgICAgICBMb2dnZXIuV2FybmluZyhcbiAgICAgICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgICAgIGBDYW5ub3Qgc2V0IHRleHQgc2V0dGluZyBjYWxsZWQgJHtpZH0gLSBpdCBkb2VzIG5vdCBleGlzdCBpbiB0aGUgQ29uZmlnLmVudW1QYXJhbWV0ZXJzIG1hcC5gXG4gICAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5vcHRpb25QYXJhbWV0ZXJzLmdldChpZCkuc2VsZWN0ZWQgPSBzZXR0aW5nVmFsdWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIGxhYmVsIGZvciB0aGUgZmxhZy5cbiAgICAgKiBAcGFyYW0gaWQgVGhlIGlkIG9mIHRoZSBmbGFnLlxuICAgICAqIEBwYXJhbSBsYWJlbCBUaGUgbmV3IGxhYmVsIHRvIHVzZSBmb3IgdGhlIGZsYWcuXG4gICAgICovXG4gICAgc2V0RmxhZ0xhYmVsKGlkOiBGbGFnc0lkcywgbGFiZWw6IHN0cmluZykge1xuICAgICAgICBpZiAoIXRoaXMuZmxhZ3MuaGFzKGlkKSkge1xuICAgICAgICAgICAgTG9nZ2VyLldhcm5pbmcoXG4gICAgICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICAgICBgQ2Fubm90IHNldCBsYWJlbCBmb3IgZmxhZyBjYWxsZWQgJHtpZH0gLSBpdCBkb2VzIG5vdCBleGlzdCBpbiB0aGUgQ29uZmlnLmZsYWdzIG1hcC5gXG4gICAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5mbGFncy5nZXQoaWQpLmxhYmVsID0gbGFiZWw7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgYSBzdWJzZXQgb2YgYWxsIHNldHRpbmdzIGluIG9uZSBmdW5jdGlvbiBjYWxsLlxuICAgICAqXG4gICAgICogQHBhcmFtIHNldHRpbmdzIEEgKHBhcnRpYWwpIGxpc3Qgb2Ygc2V0dGluZ3MgdG8gc2V0XG4gICAgICovXG4gICAgc2V0U2V0dGluZ3Moc2V0dGluZ3M6IFBhcnRpYWw8QWxsU2V0dGluZ3M+KSB7XG4gICAgICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKHNldHRpbmdzKSkge1xuICAgICAgICAgICAgaWYgKGlzRmxhZ0lkKGtleSkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldEZsYWdFbmFibGVkKGtleSwgc2V0dGluZ3Nba2V5XSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGlzTnVtZXJpY0lkKGtleSkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldE51bWVyaWNTZXR0aW5nKGtleSwgc2V0dGluZ3Nba2V5XSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGlzVGV4dElkKGtleSkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFRleHRTZXR0aW5nKGtleSwgc2V0dGluZ3Nba2V5XSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGlzT3B0aW9uSWQoa2V5KSkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0T3B0aW9uU2V0dGluZ1ZhbHVlKGtleSwgc2V0dGluZ3Nba2V5XSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgYWxsIHNldHRpbmdzXG4gICAgICogQHJldHVybnMgQWxsIHNldHRpbmcgdmFsdWVzIGFzIGFuIG9iamVjdCB3aXRoIHNldHRpbmcgaWRzIGFzIGtleXNcbiAgICAgKi9cbiAgICBnZXRTZXR0aW5ncygpOiBQYXJ0aWFsPEFsbFNldHRpbmdzPiB7XG4gICAgICAgIGNvbnN0IHNldHRpbmdzOiBQYXJ0aWFsPEFsbFNldHRpbmdzPiA9IHt9O1xuICAgICAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiB0aGlzLmZsYWdzLmVudHJpZXMoKSkge1xuICAgICAgICAgICAgc2V0dGluZ3Nba2V5XSA9IHZhbHVlLmZsYWc7XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgdGhpcy5udW1lcmljUGFyYW1ldGVycy5lbnRyaWVzKCkpIHtcbiAgICAgICAgICAgIHNldHRpbmdzW2tleV0gPSB2YWx1ZS5udW1iZXI7XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChjb25zdCBba2V5LCB2YWx1ZV0gb2YgdGhpcy50ZXh0UGFyYW1ldGVycy5lbnRyaWVzKCkpIHtcbiAgICAgICAgICAgIHNldHRpbmdzW2tleV0gPSB2YWx1ZS50ZXh0O1xuICAgICAgICB9XG4gICAgICAgIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIHRoaXMub3B0aW9uUGFyYW1ldGVycy5lbnRyaWVzKCkpIHtcbiAgICAgICAgICAgIHNldHRpbmdzW2tleV0gPSB2YWx1ZS5zZWxlY3RlZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc2V0dGluZ3M7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IGFsbCBGbGFnIHNldHRpbmdzIGFzIGFuIGFycmF5LlxuICAgICAqIEByZXR1cm5zIEFsbCBTZXR0aW5nRmxhZyBvYmplY3RzXG4gICAgICovXG4gICAgZ2V0RmxhZ3MoKTogQXJyYXk8U2V0dGluZ0ZsYWc+IHtcbiAgICAgICAgcmV0dXJuIEFycmF5LmZyb20odGhpcy5mbGFncy52YWx1ZXMoKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IGFsbCBUZXh0IHNldHRpbmdzIGFzIGFuIGFycmF5LlxuICAgICAqIEByZXR1cm5zIEFsbCBTZXR0aW5nVGV4dCBvYmplY3RzXG4gICAgICovXG4gICAgZ2V0VGV4dFNldHRpbmdzKCk6IEFycmF5PFNldHRpbmdUZXh0PiB7XG4gICAgICAgIHJldHVybiBBcnJheS5mcm9tKHRoaXMudGV4dFBhcmFtZXRlcnMudmFsdWVzKCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCBhbGwgTnVtYmVyIHNldHRpbmdzIGFzIGFuIGFycmF5LlxuICAgICAqIEByZXR1cm5zIEFsbCBTZXR0aW5nTnVtYmVyIG9iamVjdHNcbiAgICAgKi9cbiAgICBnZXROdW1lcmljU2V0dGluZ3MoKTogQXJyYXk8U2V0dGluZ051bWJlcj4ge1xuICAgICAgICByZXR1cm4gQXJyYXkuZnJvbSh0aGlzLm51bWVyaWNQYXJhbWV0ZXJzLnZhbHVlcygpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgYWxsIE9wdGlvbiBzZXR0aW5ncyBhcyBhbiBhcnJheS5cbiAgICAgKiBAcmV0dXJucyBBbGwgU2V0dGluZ09wdGlvbiBvYmplY3RzXG4gICAgICovXG4gICAgZ2V0T3B0aW9uU2V0dGluZ3MoKTogQXJyYXk8U2V0dGluZ09wdGlvbj4ge1xuICAgICAgICByZXR1cm4gQXJyYXkuZnJvbSh0aGlzLm9wdGlvblBhcmFtZXRlcnMudmFsdWVzKCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEVtaXQgZXZlbnRzIHdoZW4gc2V0dGluZ3MgY2hhbmdlLlxuICAgICAqIEBwYXJhbSBldmVudEVtaXR0ZXJcbiAgICAgKi9cbiAgICBfcmVnaXN0ZXJPbkNoYW5nZUV2ZW50cyhldmVudEVtaXR0ZXI6IEV2ZW50RW1pdHRlcikge1xuICAgICAgICBmb3IgKGNvbnN0IGtleSBvZiB0aGlzLmZsYWdzLmtleXMoKSkge1xuICAgICAgICAgICAgY29uc3QgZmxhZyA9IHRoaXMuZmxhZ3MuZ2V0KGtleSk7XG4gICAgICAgICAgICBpZiAoZmxhZykge1xuICAgICAgICAgICAgICAgIGZsYWcub25DaGFuZ2VFbWl0ID0gKG5ld1ZhbHVlOiBib29sZWFuKSA9PlxuICAgICAgICAgICAgICAgICAgICBldmVudEVtaXR0ZXIuZGlzcGF0Y2hFdmVudChcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBTZXR0aW5nc0NoYW5nZWRFdmVudCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWQ6IGZsYWcuaWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2ZsYWcnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBuZXdWYWx1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXQ6IGZsYWdcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChjb25zdCBrZXkgb2YgdGhpcy5udW1lcmljUGFyYW1ldGVycy5rZXlzKCkpIHtcbiAgICAgICAgICAgIGNvbnN0IG51bWJlciA9IHRoaXMubnVtZXJpY1BhcmFtZXRlcnMuZ2V0KGtleSk7XG4gICAgICAgICAgICBpZiAobnVtYmVyKSB7XG4gICAgICAgICAgICAgICAgbnVtYmVyLm9uQ2hhbmdlRW1pdCA9IChuZXdWYWx1ZTogbnVtYmVyKSA9PlxuICAgICAgICAgICAgICAgICAgICBldmVudEVtaXR0ZXIuZGlzcGF0Y2hFdmVudChcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBTZXR0aW5nc0NoYW5nZWRFdmVudCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWQ6IG51bWJlci5pZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnbnVtYmVyJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZTogbmV3VmFsdWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0OiBudW1iZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChjb25zdCBrZXkgb2YgdGhpcy50ZXh0UGFyYW1ldGVycy5rZXlzKCkpIHtcbiAgICAgICAgICAgIGNvbnN0IHRleHQgPSB0aGlzLnRleHRQYXJhbWV0ZXJzLmdldChrZXkpO1xuICAgICAgICAgICAgaWYgKHRleHQpIHtcbiAgICAgICAgICAgICAgICB0ZXh0Lm9uQ2hhbmdlRW1pdCA9IChuZXdWYWx1ZTogc3RyaW5nKSA9PlxuICAgICAgICAgICAgICAgICAgICBldmVudEVtaXR0ZXIuZGlzcGF0Y2hFdmVudChcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBTZXR0aW5nc0NoYW5nZWRFdmVudCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWQ6IHRleHQuaWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ3RleHQnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBuZXdWYWx1ZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXQ6IHRleHRcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChjb25zdCBrZXkgb2YgdGhpcy5vcHRpb25QYXJhbWV0ZXJzLmtleXMoKSkge1xuICAgICAgICAgICAgY29uc3Qgb3B0aW9uID0gdGhpcy5vcHRpb25QYXJhbWV0ZXJzLmdldChrZXkpO1xuICAgICAgICAgICAgaWYgKG9wdGlvbikge1xuICAgICAgICAgICAgICAgIG9wdGlvbi5vbkNoYW5nZUVtaXQgPSAobmV3VmFsdWU6IHN0cmluZykgPT5cbiAgICAgICAgICAgICAgICAgICAgZXZlbnRFbWl0dGVyLmRpc3BhdGNoRXZlbnQoXG4gICAgICAgICAgICAgICAgICAgICAgICBuZXcgU2V0dGluZ3NDaGFuZ2VkRXZlbnQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkOiBvcHRpb24uaWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ29wdGlvbicsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IG5ld1ZhbHVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldDogb3B0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuXG4vKipcbiAqIFRoZSBlbnVtIGFzc29jaWF0ZWQgd2l0aCB0aGUgbW91c2UgYmVpbmcgbG9ja2VkIG9yIGhvdmVyaW5nXG4gKi9cbmV4cG9ydCBlbnVtIENvbnRyb2xTY2hlbWVUeXBlIHtcbiAgICBMb2NrZWRNb3VzZSA9IDAsXG4gICAgSG92ZXJpbmdNb3VzZSA9IDFcbn1cbiIsIi8vIENvcHlyaWdodCBFcGljIEdhbWVzLCBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG5cbi8qKlxuICogQmFzZSBjbGFzcyBmb3IgYSBzZXR0aW5nIHRoYXQgaGFzIGEgdGV4dCBsYWJlbCBhbmQgYW4gYXJiaXRyYXJ5IHNldHRpbmcgdmFsdWUgaXQgc3RvcmVzLlxuICovXG5leHBvcnQgY2xhc3MgU2V0dGluZ0Jhc2Uge1xuICAgIGlkOiBzdHJpbmc7XG4gICAgZGVzY3JpcHRpb246IHN0cmluZztcbiAgICBfbGFiZWw6IHN0cmluZztcbiAgICBfdmFsdWU6IHVua25vd247XG4gICAgb25DaGFuZ2U6IChjaGFuZ2VkVmFsdWU6IHVua25vd24sIHNldHRpbmc6IFNldHRpbmdCYXNlKSA9PiB2b2lkO1xuICAgIG9uQ2hhbmdlRW1pdDogKGNoYW5nZWRWYWx1ZTogdW5rbm93bikgPT4gdm9pZDtcblxuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBpZDogc3RyaW5nLFxuICAgICAgICBsYWJlbDogc3RyaW5nLFxuICAgICAgICBkZXNjcmlwdGlvbjogc3RyaW5nLFxuICAgICAgICBkZWZhdWx0U2V0dGluZ1ZhbHVlOiB1bmtub3duLFxuXHRcdC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZW1wdHktZnVuY3Rpb25cblx0XHRkZWZhdWx0T25DaGFuZ2VMaXN0ZW5lcjogKGNoYW5nZWRWYWx1ZTogdW5rbm93biwgc2V0dGluZzogU2V0dGluZ0Jhc2UpID0+IHZvaWQgPSAoKSA9PiB7IC8qIERvIG5vdGhpbmcsIHRvIGJlIG92ZXJyaWRkZW4uICovIH1cbiAgICApIHtcbiAgICAgICAgdGhpcy5vbkNoYW5nZSA9IGRlZmF1bHRPbkNoYW5nZUxpc3RlbmVyO1xuXG4gICAgICAgIHRoaXMub25DaGFuZ2VFbWl0ID0gKCkgPT4ge1xuICAgICAgICAgICAgLyogRG8gbm90aGluZywgdG8gYmUgb3ZlcnJpZGRlbi4gKi9cbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5pZCA9IGlkO1xuICAgICAgICB0aGlzLmRlc2NyaXB0aW9uID0gZGVzY3JpcHRpb247XG4gICAgICAgIHRoaXMubGFiZWwgPSBsYWJlbDtcbiAgICAgICAgdGhpcy52YWx1ZSA9IGRlZmF1bHRTZXR0aW5nVmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSBsYWJlbCB0ZXh0IGZvciB0aGUgc2V0dGluZy5cbiAgICAgKiBAcGFyYW0gbGFiZWwgc2V0dGluZyBsYWJlbC5cbiAgICAgKi9cbiAgICBwdWJsaWMgc2V0IGxhYmVsKGluTGFiZWw6IHN0cmluZykge1xuICAgICAgICB0aGlzLl9sYWJlbCA9IGluTGFiZWw7XG4gICAgICAgIHRoaXMub25DaGFuZ2VFbWl0KHRoaXMuX3ZhbHVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBUaGUgbGFiZWwgdGV4dCBmb3IgdGhlIHNldHRpbmcuXG4gICAgICovXG4gICAgcHVibGljIGdldCBsYWJlbCgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy5fbGFiZWw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybiBUaGUgc2V0dGluZydzIHZhbHVlLlxuICAgICAqL1xuICAgIHB1YmxpYyBnZXQgdmFsdWUoKTogdW5rbm93biB7XG4gICAgICAgIHJldHVybiB0aGlzLl92YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGUgdGhlIHNldHRpbmcncyBzdG9yZWQgdmFsdWUuXG4gICAgICogQHBhcmFtIGluVmFsdWUgVGhlIG5ldyB2YWx1ZSBmb3IgdGhlIHNldHRpbmcuXG4gICAgICovXG4gICAgcHVibGljIHNldCB2YWx1ZShpblZhbHVlOiB1bmtub3duKSB7XG4gICAgICAgIHRoaXMuX3ZhbHVlID0gaW5WYWx1ZTtcbiAgICAgICAgdGhpcy5vbkNoYW5nZSh0aGlzLl92YWx1ZSwgdGhpcyk7XG4gICAgICAgIHRoaXMub25DaGFuZ2VFbWl0KHRoaXMuX3ZhbHVlKTtcbiAgICB9XG59XG4iLCIvLyBDb3B5cmlnaHQgRXBpYyBHYW1lcywgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuXG5pbXBvcnQgdHlwZSB7IEZsYWdzSWRzIH0gZnJvbSAnLi9Db25maWcnO1xuaW1wb3J0IHsgU2V0dGluZ0Jhc2UgfSBmcm9tICcuL1NldHRpbmdCYXNlJztcblxuLyoqXG4gKiBBIGJvb2xlYW4gZmxhZyBzZXR0aW5nIG9iamVjdCB3aXRoIGEgdGV4dCBsYWJlbC5cbiAqL1xuZXhwb3J0IGNsYXNzIFNldHRpbmdGbGFnPFxuICAgIEN1c3RvbUlkcyBleHRlbmRzIHN0cmluZyA9IEZsYWdzSWRzXG4+IGV4dGVuZHMgU2V0dGluZ0Jhc2Uge1xuICAgIGlkOiBGbGFnc0lkcyB8IEN1c3RvbUlkcztcbiAgICBvbkNoYW5nZUVtaXQ6IChjaGFuZ2VkVmFsdWU6IGJvb2xlYW4pID0+IHZvaWQ7XG4gICAgdXNlVXJsUGFyYW1zOiBib29sZWFuO1xuXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIGlkOiBGbGFnc0lkcyB8IEN1c3RvbUlkcyxcbiAgICAgICAgbGFiZWw6IHN0cmluZyxcbiAgICAgICAgZGVzY3JpcHRpb246IHN0cmluZyxcbiAgICAgICAgZGVmYXVsdEZsYWdWYWx1ZTogYm9vbGVhbixcbiAgICAgICAgdXNlVXJsUGFyYW1zOiBib29sZWFuLFxuXHRcdC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZW1wdHktZnVuY3Rpb25cblx0XHRkZWZhdWx0T25DaGFuZ2VMaXN0ZW5lcjogKGNoYW5nZWRWYWx1ZTogdW5rbm93biwgc2V0dGluZzogU2V0dGluZ0Jhc2UpID0+IHZvaWQgPSAoKSA9PiB7IC8qIERvIG5vdGhpbmcsIHRvIGJlIG92ZXJyaWRkZW4uICovIH1cbiAgICApIHtcbiAgICAgICAgc3VwZXIoaWQsIGxhYmVsLCBkZXNjcmlwdGlvbiwgZGVmYXVsdEZsYWdWYWx1ZSwgZGVmYXVsdE9uQ2hhbmdlTGlzdGVuZXIpO1xuXG4gICAgICAgIGNvbnN0IHVybFBhcmFtcyA9IG5ldyBVUkxTZWFyY2hQYXJhbXMod2luZG93LmxvY2F0aW9uLnNlYXJjaCk7XG4gICAgICAgIGlmICghdXNlVXJsUGFyYW1zIHx8ICF1cmxQYXJhbXMuaGFzKHRoaXMuaWQpKSB7XG4gICAgICAgICAgICB0aGlzLmZsYWcgPSBkZWZhdWx0RmxhZ1ZhbHVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gcGFyc2UgZmxhZyBmcm9tIHVybCBwYXJhbWV0ZXJzXG4gICAgICAgICAgICBjb25zdCB1cmxQYXJhbUZsYWcgPSB0aGlzLmdldFVybFBhcmFtRmxhZygpO1xuICAgICAgICAgICAgdGhpcy5mbGFnID0gdXJsUGFyYW1GbGFnO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMudXNlVXJsUGFyYW1zID0gdXNlVXJsUGFyYW1zO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBhcnNlIHRoZSBmbGFnIHZhbHVlIGZyb20gdGhlIHVybCBwYXJhbWV0ZXJzLlxuICAgICAqIEByZXR1cm5zIFRydWUgaWYgdGhlIHVybCBwYXJhbWV0ZXJzIGNvbnRhaW5zIC8/aWQsIGJ1dCBGYWxzZSBpZiAvP2lkPWZhbHNlXG4gICAgICovXG4gICAgZ2V0VXJsUGFyYW1GbGFnKCk6IGJvb2xlYW4ge1xuICAgICAgICBjb25zdCB1cmxQYXJhbXMgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKHdpbmRvdy5sb2NhdGlvbi5zZWFyY2gpO1xuICAgICAgICBpZiAodXJsUGFyYW1zLmhhcyh0aGlzLmlkKSkge1xuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgIHVybFBhcmFtcy5nZXQodGhpcy5pZCkgPT09ICdmYWxzZScgfHxcbiAgICAgICAgICAgICAgICB1cmxQYXJhbXMuZ2V0KHRoaXMuaWQpID09PSAnRmFsc2UnXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGVyc2lzdCB0aGUgc2V0dGluZyB2YWx1ZSBpbiBVUkwuXG4gICAgICovXG4gICAgcHVibGljIHVwZGF0ZVVSTFBhcmFtcygpIHtcbiAgICAgICAgaWYgKHRoaXMudXNlVXJsUGFyYW1zKSB7XG4gICAgICAgICAgICAvLyBzZXQgdXJsIHBhcmFtc1xuICAgICAgICAgICAgY29uc3QgdXJsUGFyYW1zID0gbmV3IFVSTFNlYXJjaFBhcmFtcyh3aW5kb3cubG9jYXRpb24uc2VhcmNoKTtcbiAgICAgICAgICAgIGlmICh0aGlzLmZsYWcgPT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICB1cmxQYXJhbXMuc2V0KHRoaXMuaWQsICd0cnVlJyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHVybFBhcmFtcy5zZXQodGhpcy5pZCwgJ2ZhbHNlJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB3aW5kb3cuaGlzdG9yeS5yZXBsYWNlU3RhdGUoXG4gICAgICAgICAgICAgICAge30sXG4gICAgICAgICAgICAgICAgJycsXG4gICAgICAgICAgICAgICAgdXJsUGFyYW1zLnRvU3RyaW5nKCkgIT09ICcnXG4gICAgICAgICAgICAgICAgICAgID8gYCR7bG9jYXRpb24ucGF0aG5hbWV9PyR7dXJsUGFyYW1zfWBcbiAgICAgICAgICAgICAgICAgICAgOiBgJHtsb2NhdGlvbi5wYXRobmFtZX1gXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRW5hYmxlcyB0aGlzIGZsYWcuXG4gICAgICovXG4gICAgcHVibGljIGVuYWJsZSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5mbGFnID0gdHJ1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJuIFRoZSBzZXR0aW5nJ3MgdmFsdWUuXG4gICAgICovXG4gICAgcHVibGljIGdldCBmbGFnKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gISF0aGlzLnZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVwZGF0ZSB0aGUgc2V0dGluZydzIHN0b3JlZCB2YWx1ZS5cbiAgICAgKiBAcGFyYW0gaW5WYWx1ZSBUaGUgbmV3IHZhbHVlIGZvciB0aGUgc2V0dGluZy5cbiAgICAgKi9cbiAgICBwdWJsaWMgc2V0IGZsYWcoaW5WYWx1ZTogYm9vbGVhbikge1xuICAgICAgICB0aGlzLnZhbHVlID0gaW5WYWx1ZTtcbiAgICB9XG59XG4iLCIvLyBDb3B5cmlnaHQgRXBpYyBHYW1lcywgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuXG5pbXBvcnQgdHlwZSB7IE51bWVyaWNQYXJhbWV0ZXJzSWRzIH0gZnJvbSAnLi9Db25maWcnO1xuaW1wb3J0IHsgU2V0dGluZ0Jhc2UgfSBmcm9tICcuL1NldHRpbmdCYXNlJztcblxuLyoqXG4gKiBBIG51bWJlciBzZXR0aW5nIG9iamVjdCB3aXRoIGEgdGV4dCBsYWJlbC4gTWluIGFuZCBtYXggbGltaXQgdGhlIHJhbmdlIG9mIGFsbG93ZWQgdmFsdWVzLlxuICovXG5leHBvcnQgY2xhc3MgU2V0dGluZ051bWJlcjxcbiAgICBDdXN0b21JZHMgZXh0ZW5kcyBzdHJpbmcgPSBOdW1lcmljUGFyYW1ldGVyc0lkc1xuPiBleHRlbmRzIFNldHRpbmdCYXNlIHtcbiAgICBfbWluOiBudW1iZXI7XG4gICAgX21heDogbnVtYmVyO1xuXG4gICAgaWQ6IE51bWVyaWNQYXJhbWV0ZXJzSWRzIHwgQ3VzdG9tSWRzO1xuICAgIG9uQ2hhbmdlRW1pdDogKGNoYW5nZWRWYWx1ZTogbnVtYmVyKSA9PiB2b2lkO1xuICAgIHVzZVVybFBhcmFtczogYm9vbGVhbjtcblxuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBpZDogTnVtZXJpY1BhcmFtZXRlcnNJZHMgfCBDdXN0b21JZHMsXG4gICAgICAgIGxhYmVsOiBzdHJpbmcsXG4gICAgICAgIGRlc2NyaXB0aW9uOiBzdHJpbmcsXG4gICAgICAgIG1pbjogbnVtYmVyLFxuICAgICAgICBtYXg6IG51bWJlcixcbiAgICAgICAgZGVmYXVsdE51bWJlcjogbnVtYmVyLFxuICAgICAgICB1c2VVcmxQYXJhbXM6IGJvb2xlYW4sXG5cdFx0Ly8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1lbXB0eS1mdW5jdGlvblxuXHRcdGRlZmF1bHRPbkNoYW5nZUxpc3RlbmVyOiAoY2hhbmdlZFZhbHVlOiB1bmtub3duLCBzZXR0aW5nOiBTZXR0aW5nQmFzZSkgPT4gdm9pZCA9ICgpID0+IHsgLyogRG8gbm90aGluZywgdG8gYmUgb3ZlcnJpZGRlbi4gKi8gfVxuICAgICkge1xuICAgICAgICBzdXBlcihpZCwgbGFiZWwsIGRlc2NyaXB0aW9uLCBkZWZhdWx0TnVtYmVyLCBkZWZhdWx0T25DaGFuZ2VMaXN0ZW5lcik7XG5cbiAgICAgICAgdGhpcy5fbWluID0gbWluO1xuICAgICAgICB0aGlzLl9tYXggPSBtYXg7XG5cbiAgICAgICAgLy8gYXR0ZW1wdCB0byByZWFkIHRoZSBudW1iZXIgZnJvbSB0aGUgdXJsIHBhcmFtc1xuICAgICAgICBjb25zdCB1cmxQYXJhbXMgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKHdpbmRvdy5sb2NhdGlvbi5zZWFyY2gpO1xuICAgICAgICBpZiAoIXVzZVVybFBhcmFtcyB8fCAhdXJsUGFyYW1zLmhhcyh0aGlzLmlkKSkge1xuICAgICAgICAgICAgdGhpcy5udW1iZXIgPSBkZWZhdWx0TnVtYmVyO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3QgcGFyc2VkVmFsdWUgPSBOdW1iZXIucGFyc2VJbnQodXJsUGFyYW1zLmdldCh0aGlzLmlkKSk7XG4gICAgICAgICAgICB0aGlzLm51bWJlciA9IE51bWJlci5pc05hTihwYXJzZWRWYWx1ZSlcbiAgICAgICAgICAgICAgICA/IGRlZmF1bHROdW1iZXJcbiAgICAgICAgICAgICAgICA6IHBhcnNlZFZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMudXNlVXJsUGFyYW1zID0gdXNlVXJsUGFyYW1zO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBlcnNpc3QgdGhlIHNldHRpbmcgdmFsdWUgaW4gVVJMLlxuICAgICAqL1xuICAgIHB1YmxpYyB1cGRhdGVVUkxQYXJhbXMoKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnVzZVVybFBhcmFtcykge1xuICAgICAgICAgICAgLy8gc2V0IHVybCBwYXJhbXMgbGlrZSA/aWQ9bnVtYmVyXG4gICAgICAgICAgICBjb25zdCB1cmxQYXJhbXMgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKHdpbmRvdy5sb2NhdGlvbi5zZWFyY2gpO1xuICAgICAgICAgICAgdXJsUGFyYW1zLnNldCh0aGlzLmlkLCB0aGlzLm51bWJlci50b1N0cmluZygpKTtcbiAgICAgICAgICAgIHdpbmRvdy5oaXN0b3J5LnJlcGxhY2VTdGF0ZShcbiAgICAgICAgICAgICAgICB7fSxcbiAgICAgICAgICAgICAgICAnJyxcbiAgICAgICAgICAgICAgICB1cmxQYXJhbXMudG9TdHJpbmcoKSAhPT0gJydcbiAgICAgICAgICAgICAgICAgICAgPyBgJHtsb2NhdGlvbi5wYXRobmFtZX0/JHt1cmxQYXJhbXN9YFxuICAgICAgICAgICAgICAgICAgICA6IGAke2xvY2F0aW9uLnBhdGhuYW1lfWBcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIG51bWJlciB2YWx1ZSAod2lsbCBiZSBjbGFtcGVkIHdpdGhpbiByYW5nZSkuXG4gICAgICovXG4gICAgcHVibGljIHNldCBudW1iZXIobmV3TnVtYmVyOiBudW1iZXIpIHtcbiAgICAgICAgdGhpcy52YWx1ZSA9IHRoaXMuY2xhbXAobmV3TnVtYmVyKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBUaGUgbnVtYmVyIHN0b3JlZC5cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0IG51bWJlcigpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy52YWx1ZSBhcyBudW1iZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2xhbXBzIGEgbnVtYmVyIGJldHdlZW4gdGhlIG1pbiBhbmQgbWF4IHZhbHVlcyAoaW5jbHVzaXZlKS5cbiAgICAgKiBAcGFyYW0gaW5OdW1iZXIgVGhlIG51bWJlciB0byBjbGFtcC5cbiAgICAgKiBAcmV0dXJucyBUaGUgY2xhbXBlZCBudW1iZXIuXG4gICAgICovXG4gICAgcHVibGljIGNsYW1wKGluTnVtYmVyOiBudW1iZXIpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gTWF0aC5tYXgoTWF0aC5taW4odGhpcy5fbWF4LCBpbk51bWJlciksIHRoaXMuX21pbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgbWluaW11bSB2YWx1ZVxuICAgICAqIEByZXR1cm5zIFRoZSBtaW5pbXVtIHZhbHVlXG4gICAgICovXG4gICAgcHVibGljIGdldCBtaW4oKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX21pbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBtYXhpbXVtIHZhbHVlXG4gICAgICogQHJldHVybnMgVGhlIG1heGltdW0gdmFsdWVcbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0IG1heCgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5fbWF4O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZCBhIGNoYW5nZSBsaXN0ZW5lciB0byB0aGUgbnVtYmVyIG9iamVjdC5cbiAgICAgKi9cbiAgICBwdWJsaWMgYWRkT25DaGFuZ2VkTGlzdGVuZXIob25DaGFuZ2VkRnVuYzogKG5ld051bWJlcjogbnVtYmVyKSA9PiB2b2lkKSB7XG4gICAgICAgIHRoaXMub25DaGFuZ2UgPSBvbkNoYW5nZWRGdW5jO1xuICAgIH1cbn1cbiIsIi8vIENvcHlyaWdodCBFcGljIEdhbWVzLCBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG5cbmltcG9ydCB0eXBlIHsgT3B0aW9uUGFyYW1ldGVyc0lkcyB9IGZyb20gJy4vQ29uZmlnJztcbmltcG9ydCB7IFNldHRpbmdCYXNlIH0gZnJvbSAnLi9TZXR0aW5nQmFzZSc7XG5cbi8qKlxuICogQW4gT3B0aW9uIHNldHRpbmcgb2JqZWN0IHdpdGggYSB0ZXh0IGxhYmVsLiBBbGxvd3MgeW91IHRvIHNwZWNpZnkgYW4gYXJyYXkgb2Ygb3B0aW9ucyBhbmQgc2VsZWN0IG9uZSBvZiB0aGVtLlxuICovXG5leHBvcnQgY2xhc3MgU2V0dGluZ09wdGlvbjxcbiAgICBDdXN0b21JZHMgZXh0ZW5kcyBzdHJpbmcgPSBPcHRpb25QYXJhbWV0ZXJzSWRzXG4+IGV4dGVuZHMgU2V0dGluZ0Jhc2Uge1xuICAgIGlkOiBPcHRpb25QYXJhbWV0ZXJzSWRzIHwgQ3VzdG9tSWRzO1xuICAgIG9uQ2hhbmdlRW1pdDogKGNoYW5nZWRWYWx1ZTogc3RyaW5nKSA9PiB2b2lkO1xuICAgIF9vcHRpb25zOiBBcnJheTxzdHJpbmc+O1xuICAgIHVzZVVybFBhcmFtczogYm9vbGVhbjtcblxuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBpZDogT3B0aW9uUGFyYW1ldGVyc0lkcyB8IEN1c3RvbUlkcyxcbiAgICAgICAgbGFiZWw6IHN0cmluZyxcbiAgICAgICAgZGVzY3JpcHRpb246IHN0cmluZyxcbiAgICAgICAgZGVmYXVsdFRleHRWYWx1ZTogc3RyaW5nLFxuICAgICAgICBvcHRpb25zOiBBcnJheTxzdHJpbmc+LFxuICAgICAgICB1c2VVcmxQYXJhbXM6IGJvb2xlYW4sXG5cdFx0Ly8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1lbXB0eS1mdW5jdGlvblxuXHRcdGRlZmF1bHRPbkNoYW5nZUxpc3RlbmVyOiAoY2hhbmdlZFZhbHVlOiB1bmtub3duLCBzZXR0aW5nOiBTZXR0aW5nQmFzZSkgPT4gdm9pZCA9ICgpID0+IHsgLyogRG8gbm90aGluZywgdG8gYmUgb3ZlcnJpZGRlbi4gKi8gfVxuICAgICkge1xuICAgICAgICBzdXBlcihpZCwgbGFiZWwsIGRlc2NyaXB0aW9uLCBbZGVmYXVsdFRleHRWYWx1ZSwgZGVmYXVsdFRleHRWYWx1ZV0sIGRlZmF1bHRPbkNoYW5nZUxpc3RlbmVyKTtcblxuICAgICAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zO1xuICAgICAgICBjb25zdCB1cmxQYXJhbXMgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKHdpbmRvdy5sb2NhdGlvbi5zZWFyY2gpO1xuICAgICAgICBjb25zdCBzdHJpbmdUb01hdGNoOiBzdHJpbmcgPVxuICAgICAgICAgICAgdXNlVXJsUGFyYW1zICYmIHVybFBhcmFtcy5oYXModGhpcy5pZClcbiAgICAgICAgICAgICAgICA/IHRoaXMuZ2V0VXJsUGFyYW1UZXh0KClcbiAgICAgICAgICAgICAgICA6IGRlZmF1bHRUZXh0VmFsdWU7XG4gICAgICAgIHRoaXMuc2VsZWN0ZWQgPSBzdHJpbmdUb01hdGNoO1xuICAgICAgICB0aGlzLnVzZVVybFBhcmFtcyA9IHVzZVVybFBhcmFtcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQYXJzZSB0aGUgdGV4dCB2YWx1ZSBmcm9tIHRoZSB1cmwgcGFyYW1ldGVycy5cbiAgICAgKiBAcmV0dXJucyBUaGUgdGV4dCB2YWx1ZSBwYXJzZWQgZnJvbSB0aGUgdXJsIGlmIHRoZSB1cmwgcGFyYW1ldGVycyBjb250YWlucyAvP2lkPXZhbHVlLCBidXQgZW1wdHkgc3RyaW5nIGlmIGp1c3QgLz9pZCBvciBubyB1cmwgcGFyYW0gZm91bmQuXG4gICAgICovXG4gICAgZ2V0VXJsUGFyYW1UZXh0KCk6IHN0cmluZyB7XG4gICAgICAgIGNvbnN0IHVybFBhcmFtcyA9IG5ldyBVUkxTZWFyY2hQYXJhbXMod2luZG93LmxvY2F0aW9uLnNlYXJjaCk7XG4gICAgICAgIGlmICh1cmxQYXJhbXMuaGFzKHRoaXMuaWQpKSB7XG4gICAgICAgICAgICByZXR1cm4gdXJsUGFyYW1zLmdldCh0aGlzLmlkKSA/PyAnJztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gJyc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGVyc2lzdCB0aGUgc2V0dGluZyB2YWx1ZSBpbiBVUkwuXG4gICAgICovXG4gICAgcHVibGljIHVwZGF0ZVVSTFBhcmFtcygpIHtcbiAgICAgICAgaWYgKHRoaXMudXNlVXJsUGFyYW1zKSB7XG4gICAgICAgICAgICAvLyBzZXQgdXJsIHBhcmFtc1xuICAgICAgICAgICAgY29uc3QgdXJsUGFyYW1zID0gbmV3IFVSTFNlYXJjaFBhcmFtcyh3aW5kb3cubG9jYXRpb24uc2VhcmNoKTtcbiAgICAgICAgICAgIHVybFBhcmFtcy5zZXQodGhpcy5pZCwgdGhpcy5zZWxlY3RlZCk7XG4gICAgICAgICAgICB3aW5kb3cuaGlzdG9yeS5yZXBsYWNlU3RhdGUoXG4gICAgICAgICAgICAgICAge30sXG4gICAgICAgICAgICAgICAgJycsXG4gICAgICAgICAgICAgICAgdXJsUGFyYW1zLnRvU3RyaW5nKCkgIT09ICcnXG4gICAgICAgICAgICAgICAgICAgID8gYCR7bG9jYXRpb24ucGF0aG5hbWV9PyR7dXJsUGFyYW1zfWBcbiAgICAgICAgICAgICAgICAgICAgOiBgJHtsb2NhdGlvbi5wYXRobmFtZX1gXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkIGEgY2hhbmdlIGxpc3RlbmVyIHRvIHRoZSBzZWxlY3QgZWxlbWVudC5cbiAgICAgKi9cbiAgICBwdWJsaWMgYWRkT25DaGFuZ2VkTGlzdGVuZXIob25DaGFuZ2VkRnVuYzogKG5ld1ZhbHVlOiBzdHJpbmcpID0+IHZvaWQpIHtcbiAgICAgICAgdGhpcy5vbkNoYW5nZSA9IG9uQ2hhbmdlZEZ1bmM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgQWxsIGF2YWlsYWJsZSBvcHRpb25zIGFzIGFuIGFycmF5XG4gICAgICovXG4gICAgcHVibGljIGdldCBvcHRpb25zKCk6IEFycmF5PHN0cmluZz4ge1xuICAgICAgICByZXR1cm4gdGhpcy5fb3B0aW9ucztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgb3B0aW9uc1xuICAgICAqIEBwYXJhbSB2YWx1ZXMgQXJyYXkgb2Ygb3B0aW9uc1xuICAgICAqL1xuICAgIHB1YmxpYyBzZXQgb3B0aW9ucyh2YWx1ZXM6IEFycmF5PHN0cmluZz4pIHtcbiAgICAgICAgdGhpcy5fb3B0aW9ucyA9IHZhbHVlcztcbiAgICAgICAgdGhpcy5vbkNoYW5nZUVtaXQodGhpcy5zZWxlY3RlZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgU2VsZWN0ZWQgb3B0aW9uIGFzIGEgc3RyaW5nXG4gICAgICovXG4gICAgcHVibGljIGdldCBzZWxlY3RlZCgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy52YWx1ZSBhcyBzdHJpbmc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHNlbGVjdGVkIG9wdGlvbiBpZiBpdCBtYXRjaGVzIG9uZSBvZiB0aGUgYXZhaWxhYmxlIG9wdGlvbnNcbiAgICAgKiBAcGFyYW0gdmFsdWUgU2VsZWN0ZWQgb3B0aW9uXG4gICAgICovXG4gICAgcHVibGljIHNldCBzZWxlY3RlZCh2YWx1ZTogc3RyaW5nKSB7XG4gICAgICAgIC8vIEEgdXNlciBtYXkgbm90IHNwZWNpZnkgdGhlIGZ1bGwgcG9zc2libGUgdmFsdWUgc28gd2UgaW5zdGVhZCB1c2UgdGhlIGNsb3Nlc3QgbWF0Y2guXG4gICAgICAgIC8vIGVnID94eHg9SDI2NCB3b3VsZCBzZWxlY3QgJ0gyNjQgbGV2ZWwtYXN5bW1ldHJ5LWFsbG93ZWQ9MTtwYWNrZXRpemF0aW9uLW1vZGU9MTtwcm9maWxlLWxldmVsLWlkPTQyMDAxZidcbiAgICAgICAgbGV0IGZpbHRlcmVkTGlzdCA9IHRoaXMub3B0aW9ucy5maWx0ZXIoXG4gICAgICAgICAgICAob3B0aW9uOiBzdHJpbmcpID0+IG9wdGlvbi5pbmRleE9mKHZhbHVlKSAhPT0gLTFcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKGZpbHRlcmVkTGlzdC5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRoaXMudmFsdWUgPSBmaWx0ZXJlZExpc3RbMF07XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gXG5cbiAgICAgICAgLy8gQSB1c2VyIGhhcyBzcGVjaWZpZWQgYSBjb2RlYyB3aXRoIGEgZm10cCBzdHJpbmcgYnV0IHRoaXMgY29kZWMgKyBmbXRwIGxpbmUgaXNuJ3QgYXZhaWxhYmxlLlxuICAgICAgICAvLyBpbiB0aGF0IGNhc2UsIGp1c3QgdXNlIHRoZSBjb2RlY1xuICAgICAgICBmaWx0ZXJlZExpc3QgPSB0aGlzLm9wdGlvbnMuZmlsdGVyKFxuICAgICAgICAgICAgKG9wdGlvbjogc3RyaW5nKSA9PiBvcHRpb24uaW5kZXhPZih2YWx1ZS5zcGxpdCgnICcpWzBdKSAhPT0gLTFcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKGZpbHRlcmVkTGlzdC5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRoaXMudmFsdWUgPSBmaWx0ZXJlZExpc3RbMF07XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICB9XG59XG4iLCIvLyBDb3B5cmlnaHQgRXBpYyBHYW1lcywgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuXG5pbXBvcnQgdHlwZSB7IFRleHRQYXJhbWV0ZXJzSWRzIH0gZnJvbSAnLi9Db25maWcnO1xuaW1wb3J0IHsgU2V0dGluZ0Jhc2UgfSBmcm9tICcuL1NldHRpbmdCYXNlJztcblxuLyoqXG4gKiBBIHRleHQgc2V0dGluZyBvYmplY3Qgd2l0aCBhIHRleHQgbGFiZWwuXG4gKi9cbmV4cG9ydCBjbGFzcyBTZXR0aW5nVGV4dDxcbiAgICBDdXN0b21JZHMgZXh0ZW5kcyBzdHJpbmcgPSBUZXh0UGFyYW1ldGVyc0lkc1xuPiBleHRlbmRzIFNldHRpbmdCYXNlIHtcbiAgICBpZDogVGV4dFBhcmFtZXRlcnNJZHMgfCBDdXN0b21JZHM7XG4gICAgb25DaGFuZ2VFbWl0OiAoY2hhbmdlZFZhbHVlOiBzdHJpbmcpID0+IHZvaWQ7XG4gICAgdXNlVXJsUGFyYW1zOiBib29sZWFuO1xuXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIGlkOiBUZXh0UGFyYW1ldGVyc0lkcyB8IEN1c3RvbUlkcyxcbiAgICAgICAgbGFiZWw6IHN0cmluZyxcbiAgICAgICAgZGVzY3JpcHRpb246IHN0cmluZyxcbiAgICAgICAgZGVmYXVsdFRleHRWYWx1ZTogc3RyaW5nLFxuICAgICAgICB1c2VVcmxQYXJhbXM6IGJvb2xlYW4sXG5cdFx0Ly8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1lbXB0eS1mdW5jdGlvblxuXHRcdGRlZmF1bHRPbkNoYW5nZUxpc3RlbmVyOiAoY2hhbmdlZFZhbHVlOiB1bmtub3duLCBzZXR0aW5nOiBTZXR0aW5nQmFzZSkgPT4gdm9pZCA9ICgpID0+IHsgLyogRG8gbm90aGluZywgdG8gYmUgb3ZlcnJpZGRlbi4gKi8gfVxuICAgICkge1xuICAgICAgICBzdXBlcihpZCwgbGFiZWwsIGRlc2NyaXB0aW9uLCBkZWZhdWx0VGV4dFZhbHVlLCBkZWZhdWx0T25DaGFuZ2VMaXN0ZW5lcik7XG5cbiAgICAgICAgY29uc3QgdXJsUGFyYW1zID0gbmV3IFVSTFNlYXJjaFBhcmFtcyh3aW5kb3cubG9jYXRpb24uc2VhcmNoKTtcbiAgICAgICAgaWYgKCF1c2VVcmxQYXJhbXMgfHwgIXVybFBhcmFtcy5oYXModGhpcy5pZCkpIHtcbiAgICAgICAgICAgIHRoaXMudGV4dCA9IGRlZmF1bHRUZXh0VmFsdWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBwYXJzZSBmbGFnIGZyb20gdXJsIHBhcmFtZXRlcnNcbiAgICAgICAgICAgIGNvbnN0IHVybFBhcmFtRmxhZyA9IHRoaXMuZ2V0VXJsUGFyYW1UZXh0KCk7XG4gICAgICAgICAgICB0aGlzLnRleHQgPSB1cmxQYXJhbUZsYWc7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy51c2VVcmxQYXJhbXMgPSB1c2VVcmxQYXJhbXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGFyc2UgdGhlIHRleHQgdmFsdWUgZnJvbSB0aGUgdXJsIHBhcmFtZXRlcnMuXG4gICAgICogQHJldHVybnMgVGhlIHRleHQgdmFsdWUgcGFyc2VkIGZyb20gdGhlIHVybCBpZiB0aGUgdXJsIHBhcmFtZXRlcnMgY29udGFpbnMgLz9pZD12YWx1ZSwgYnV0IGVtcHR5IHN0cmluZyBpZiBqdXN0IC8/aWQgb3Igbm8gdXJsIHBhcmFtIGZvdW5kLlxuICAgICAqL1xuICAgIGdldFVybFBhcmFtVGV4dCgpOiBzdHJpbmcge1xuICAgICAgICBjb25zdCB1cmxQYXJhbXMgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKHdpbmRvdy5sb2NhdGlvbi5zZWFyY2gpO1xuICAgICAgICBpZiAodXJsUGFyYW1zLmhhcyh0aGlzLmlkKSkge1xuICAgICAgICAgICAgcmV0dXJuIHVybFBhcmFtcy5nZXQodGhpcy5pZCkgPz8gJyc7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICcnO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBlcnNpc3QgdGhlIHNldHRpbmcgdmFsdWUgaW4gVVJMLlxuICAgICAqL1xuICAgIHB1YmxpYyB1cGRhdGVVUkxQYXJhbXMoKSB7XG4gICAgICAgIGlmICh0aGlzLnVzZVVybFBhcmFtcykge1xuICAgICAgICAgICAgLy8gc2V0IHVybCBwYXJhbXNcbiAgICAgICAgICAgIGNvbnN0IHVybFBhcmFtcyA9IG5ldyBVUkxTZWFyY2hQYXJhbXMod2luZG93LmxvY2F0aW9uLnNlYXJjaCk7XG4gICAgICAgICAgICB1cmxQYXJhbXMuc2V0KHRoaXMuaWQsIHRoaXMudGV4dCk7XG4gICAgICAgICAgICB3aW5kb3cuaGlzdG9yeS5yZXBsYWNlU3RhdGUoXG4gICAgICAgICAgICAgICAge30sXG4gICAgICAgICAgICAgICAgJycsXG4gICAgICAgICAgICAgICAgdXJsUGFyYW1zLnRvU3RyaW5nKCkgIT09ICcnXG4gICAgICAgICAgICAgICAgICAgID8gYCR7bG9jYXRpb24ucGF0aG5hbWV9PyR7dXJsUGFyYW1zfWBcbiAgICAgICAgICAgICAgICAgICAgOiBgJHtsb2NhdGlvbi5wYXRobmFtZX1gXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybiBUaGUgc2V0dGluZydzIHZhbHVlLlxuICAgICAqL1xuICAgIHB1YmxpYyBnZXQgdGV4dCgpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy52YWx1ZSBhcyBzdHJpbmc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlIHRoZSBzZXR0aW5nJ3Mgc3RvcmVkIHZhbHVlLlxuICAgICAqIEBwYXJhbSBpblZhbHVlIFRoZSBuZXcgdmFsdWUgZm9yIHRoZSBzZXR0aW5nLlxuICAgICAqL1xuICAgIHB1YmxpYyBzZXQgdGV4dChpblZhbHVlOiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy52YWx1ZSA9IGluVmFsdWU7XG4gICAgfVxufVxuIiwiLy8gQ29weXJpZ2h0IEVwaWMgR2FtZXMsIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cblxuaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSAnLi4vTG9nZ2VyL0xvZ2dlcic7XG5cbi8qKlxuICogSGFuZGxlcyB0aGUgU2VuZGluZyBhbmQgUmVjZWl2aW5nIG9mIG1lc3NhZ2VzIHRvIHRoZSBVRSBJbnN0YW5jZSB2aWEgdGhlIERhdGEgQ2hhbm5lbFxuICovXG5leHBvcnQgY2xhc3MgRGF0YUNoYW5uZWxDb250cm9sbGVyIHtcbiAgICBkYXRhQ2hhbm5lbDogUlRDRGF0YUNoYW5uZWw7XG4gICAgcGVlckNvbm5lY3Rpb246IFJUQ1BlZXJDb25uZWN0aW9uO1xuICAgIGRhdGFjaGFubmVsT3B0aW9uczogUlRDRGF0YUNoYW5uZWxJbml0O1xuICAgIGxhYmVsOiBzdHJpbmc7XG4gICAgaXNSZWNlaXZpbmdGcmVlemVGcmFtZSA9IGZhbHNlO1xuXG4gICAgLyoqXG4gICAgICogcmV0dXJuIHRoZSBjdXJyZW50IHN0YXRlIG9mIGEgZGF0YWNoYW5uZWwgY29udHJvbGxlciBpbnN0YW5jZVxuICAgICAqIEByZXR1cm5zIHRoZSBjdXJyZW50IERhdGFDaGFubmVsQ29udHJvbGxlciBpbnN0YW5jZVxuICAgICAqL1xuICAgIGdldERhdGFDaGFubmVsSW5zdGFuY2UoKTogRGF0YUNoYW5uZWxDb250cm9sbGVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVG8gQ3JlYXRlIGFuZCBTZXQgdXAgYSBEYXRhIENoYW5uZWxcbiAgICAgKiBAcGFyYW0gcGVlckNvbm5lY3Rpb24gLSBUaGUgUlRDIFBlZXIgQ29ubmVjdGlvblxuICAgICAqIEBwYXJhbSBsYWJlbCAtIExhYmVsIG9mIHRoZSBEYXRhIENoYW5uZWxcbiAgICAgKiBAcGFyYW0gZGF0YWNoYW5uZWxPcHRpb25zIC0gT3B0aW9uYWwgUlRDIERhdGFDaGFubmVsIG9wdGlvbnNcbiAgICAgKi9cbiAgICBjcmVhdGVEYXRhQ2hhbm5lbChcbiAgICAgICAgcGVlckNvbm5lY3Rpb246IFJUQ1BlZXJDb25uZWN0aW9uLFxuICAgICAgICBsYWJlbDogc3RyaW5nLFxuICAgICAgICBkYXRhY2hhbm5lbE9wdGlvbnM/OiBSVENEYXRhQ2hhbm5lbEluaXRcbiAgICApIHtcbiAgICAgICAgdGhpcy5wZWVyQ29ubmVjdGlvbiA9IHBlZXJDb25uZWN0aW9uO1xuICAgICAgICB0aGlzLmxhYmVsID0gbGFiZWw7XG4gICAgICAgIHRoaXMuZGF0YWNoYW5uZWxPcHRpb25zID0gZGF0YWNoYW5uZWxPcHRpb25zO1xuICAgICAgICBpZiAoZGF0YWNoYW5uZWxPcHRpb25zID09IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMuZGF0YWNoYW5uZWxPcHRpb25zID0ge30gYXMgUlRDRGF0YUNoYW5uZWxJbml0O1xuICAgICAgICAgICAgdGhpcy5kYXRhY2hhbm5lbE9wdGlvbnMub3JkZXJlZCA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmRhdGFDaGFubmVsID0gdGhpcy5wZWVyQ29ubmVjdGlvbi5jcmVhdGVEYXRhQ2hhbm5lbChcbiAgICAgICAgICAgIHRoaXMubGFiZWwsXG4gICAgICAgICAgICB0aGlzLmRhdGFjaGFubmVsT3B0aW9uc1xuICAgICAgICApO1xuICAgICAgICB0aGlzLnNldHVwRGF0YUNoYW5uZWwoKTtcbiAgICB9XG5cbiAgICBzZXR1cERhdGFDaGFubmVsKCkge1xuICAgICAgICAvL1dlIFdhbnQgYW4gQXJyYXkgQnVmZmVyIG5vdCBhIGJsb2JcbiAgICAgICAgdGhpcy5kYXRhQ2hhbm5lbC5iaW5hcnlUeXBlID0gJ2FycmF5YnVmZmVyJztcbiAgICAgICAgdGhpcy5kYXRhQ2hhbm5lbC5vbm9wZW4gPSAoZXY6IEV2ZW50KSA9PiB0aGlzLmhhbmRsZU9uT3Blbihldik7XG4gICAgICAgIHRoaXMuZGF0YUNoYW5uZWwub25jbG9zZSA9IChldjogRXZlbnQpID0+IHRoaXMuaGFuZGxlT25DbG9zZShldik7XG4gICAgICAgIHRoaXMuZGF0YUNoYW5uZWwub25tZXNzYWdlID0gKGV2OiBNZXNzYWdlRXZlbnQpID0+XG4gICAgICAgICAgICB0aGlzLmhhbmRsZU9uTWVzc2FnZShldik7XG4gICAgICAgIHRoaXMuZGF0YUNoYW5uZWwub25lcnJvciA9IChldjogTWVzc2FnZUV2ZW50KSA9PiB0aGlzLmhhbmRsZU9uRXJyb3IoZXYpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXMgd2hlbiB0aGUgRGF0YSBDaGFubmVsIGlzIG9wZW5lZFxuICAgICAqL1xuICAgIGhhbmRsZU9uT3BlbihldjogRXZlbnQpIHtcbiAgICAgICAgTG9nZ2VyLkxvZyhcbiAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICBgRGF0YSBDaGFubmVsICgke3RoaXMubGFiZWx9KSBvcGVuZWQuYCxcbiAgICAgICAgICAgIDdcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5vbk9wZW4odGhpcy5kYXRhQ2hhbm5lbD8ubGFiZWwsIGV2KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVzIHdoZW4gdGhlIERhdGEgQ2hhbm5lbCBpcyBjbG9zZWRcbiAgICAgKi9cbiAgICBoYW5kbGVPbkNsb3NlKGV2OiBFdmVudCkge1xuICAgICAgICBMb2dnZXIuTG9nKFxuICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgIGBEYXRhIENoYW5uZWwgKCR7dGhpcy5sYWJlbH0pIGNsb3NlZC5gLFxuICAgICAgICAgICAgN1xuICAgICAgICApO1xuICAgICAgICB0aGlzLm9uQ2xvc2UodGhpcy5kYXRhQ2hhbm5lbD8ubGFiZWwsIGV2KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVzIHdoZW4gYSBtZXNzYWdlIGlzIHJlY2VpdmVkXG4gICAgICogQHBhcmFtIGV2ZW50IC0gTWVzc2FnZSBFdmVudFxuICAgICAqL1xuICAgIGhhbmRsZU9uTWVzc2FnZShldmVudDogTWVzc2FnZUV2ZW50KSB7XG4gICAgICAgIC8vIEhpZ2hlciBsb2cgbGV2ZWwgdG8gcHJldmVudCBsb2cgc3BhbSB3aXRoIG1lc3NhZ2VzIHJlY2VpdmVkXG4gICAgICAgIExvZ2dlci5Mb2coXG4gICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgYERhdGEgQ2hhbm5lbCAoJHt0aGlzLmxhYmVsfSkgbWVzc2FnZTogJHtldmVudH1gLFxuICAgICAgICAgICAgOFxuICAgICAgICApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXMgd2hlbiBhbiBlcnJvciBpcyB0aHJvd25cbiAgICAgKiBAcGFyYW0gZXZlbnQgLSBFcnJvciBFdmVudFxuICAgICAqL1xuICAgIGhhbmRsZU9uRXJyb3IoZXZlbnQ6IE1lc3NhZ2VFdmVudCkge1xuICAgICAgICBMb2dnZXIuTG9nKFxuICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgIGBEYXRhIENoYW5uZWwgKCR7dGhpcy5sYWJlbH0pIGVycm9yOiAke2V2ZW50fWAsXG4gICAgICAgICAgICA3XG4gICAgICAgICk7XG4gICAgICAgIHRoaXMub25FcnJvcih0aGlzLmRhdGFDaGFubmVsPy5sYWJlbCwgZXZlbnQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE92ZXJyaWRlIHRvIHJlZ2lzdGVyIG9uT3BlbiBoYW5kbGVyXG4gICAgICogQHBhcmFtIGxhYmVsIERhdGEgY2hhbm5lbCBsYWJlbCAoXCJkYXRhY2hhbm5lbFwiLCBcInNlbmQtZGF0YWNoYW5uZWxcIiwgXCJyZWN2LWRhdGFjaGFubmVsXCIpXG4gICAgICogQHBhcmFtIGV2IGV2ZW50XG4gICAgICovXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIG9uT3BlbihsYWJlbDogc3RyaW5nLCBldjogRXZlbnQpIHtcbiAgICAgICAgLy8gZW1wdHkgZGVmYXVsdCBpbXBsZW1lbnRhdGlvblxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE92ZXJyaWRlIHRvIHJlZ2lzdGVyIG9uQ2xvc2UgaGFuZGxlclxuICAgICAqIEBwYXJhbSBsYWJlbCBEYXRhIGNoYW5uZWwgbGFiZWwgKFwiZGF0YWNoYW5uZWxcIiwgXCJzZW5kLWRhdGFjaGFubmVsXCIsIFwicmVjdi1kYXRhY2hhbm5lbFwiKVxuICAgICAqIEBwYXJhbSBldiBldmVudFxuICAgICAqL1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICBvbkNsb3NlKGxhYmVsOiBzdHJpbmcsIGV2OiBFdmVudCkge1xuICAgICAgICAvLyBlbXB0eSBkZWZhdWx0IGltcGxlbWVudGF0aW9uXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogT3ZlcnJpZGUgdG8gcmVnaXN0ZXIgb25FcnJvciBoYW5kbGVyXG4gICAgICogQHBhcmFtIGxhYmVsIERhdGEgY2hhbm5lbCBsYWJlbCAoXCJkYXRhY2hhbm5lbFwiLCBcInNlbmQtZGF0YWNoYW5uZWxcIiwgXCJyZWN2LWRhdGFjaGFubmVsXCIpXG4gICAgICogQHBhcmFtIGV2IGV2ZW50XG4gICAgICovXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIG9uRXJyb3IobGFiZWw6IHN0cmluZywgZXY6IEV2ZW50KSB7XG4gICAgICAgIC8vIGVtcHR5IGRlZmF1bHQgaW1wbGVtZW50YXRpb25cbiAgICB9XG59XG4iLCIvLyBDb3B5cmlnaHQgRXBpYyBHYW1lcywgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuXG5pbXBvcnQgeyBMb2dnZXIgfSBmcm9tICcuLi9Mb2dnZXIvTG9nZ2VyJztcbmltcG9ydCB7XG4gICAgRGF0YUNoYW5uZWxMYXRlbmN5VGVzdFJlY29yZCxcbiAgICBEYXRhQ2hhbm5lbExhdGVuY3lUZXN0UmVxdWVzdCxcbiAgICBEYXRhQ2hhbm5lbExhdGVuY3lUZXN0UmVzcG9uc2UsXG4gICAgRGF0YUNoYW5uZWxMYXRlbmN5VGVzdFJlc3VsdCxcbiAgICBEYXRhQ2hhbm5lbExhdGVuY3lUZXN0U2VxLFxuICAgIERhdGFDaGFubmVsTGF0ZW5jeVRlc3RUaW1lc3RhbXBcbn0gZnJvbSBcIi4vRGF0YUNoYW5uZWxMYXRlbmN5VGVzdFJlc3VsdHNcIjtcblxuZXhwb3J0IHR5cGUgRGF0YUNoYW5uZWxMYXRlbmN5VGVzdENvbmZpZyA9IHtcbiAgICAvLyB0ZXN0IGR1cmF0aW9uIGluIG1pbGxpc2Vjb25kc1xuICAgIGR1cmF0aW9uOiBudW1iZXI7XG4gICAgLy9yZXF1ZXN0cyBwZXIgc2Vjb25kXG4gICAgcnBzOiBudW1iZXI7XG4gICAgLy9yZXF1ZXN0IGZpbGxlciBzaXplXG4gICAgcmVxdWVzdFNpemU6IG51bWJlcjtcbiAgICAvL3Jlc3BvbnNlIGZpbGxlciBzaXplXG4gICAgcmVzcG9uc2VTaXplOiBudW1iZXI7XG59XG5cbmV4cG9ydCB0eXBlIERhdGFDaGFubmVsTGF0ZW5jeVRlc3RTaW5rID0gKHJlcXVlc3Q6IERhdGFDaGFubmVsTGF0ZW5jeVRlc3RSZXF1ZXN0KSA9PiB2b2lkO1xuZXhwb3J0IHR5cGUgRGF0YUNoYW5uZWxMYXRlbmN5VGVzdFJlc3VsdENhbGxiYWNrID0gKHJlc3VsdDogRGF0YUNoYW5uZWxMYXRlbmN5VGVzdFJlc3VsdCkgPT4gdm9pZDtcblxuZXhwb3J0IGNsYXNzIERhdGFDaGFubmVsTGF0ZW5jeVRlc3RDb250cm9sbGVyIHtcbiAgICBzdGFydFRpbWU6IERhdGFDaGFubmVsTGF0ZW5jeVRlc3RUaW1lc3RhbXA7XG4gICAgc2luazogRGF0YUNoYW5uZWxMYXRlbmN5VGVzdFNpbms7XG4gICAgY2FsbGJhY2s6IERhdGFDaGFubmVsTGF0ZW5jeVRlc3RSZXN1bHRDYWxsYmFjaztcbiAgICByZWNvcmRzOiBNYXA8RGF0YUNoYW5uZWxMYXRlbmN5VGVzdFNlcSwgRGF0YUNoYW5uZWxMYXRlbmN5VGVzdFJlY29yZD47XG4gICAgc2VxOiBEYXRhQ2hhbm5lbExhdGVuY3lUZXN0U2VxO1xuICAgIGludGVydmFsOiBOb2RlSlMuVGltZXI7XG5cbiAgICBjb25zdHJ1Y3RvcihzaW5rOiBEYXRhQ2hhbm5lbExhdGVuY3lUZXN0U2luaywgY2FsbGJhY2s6IERhdGFDaGFubmVsTGF0ZW5jeVRlc3RSZXN1bHRDYWxsYmFjaykge1xuICAgICAgICB0aGlzLnNpbmsgPSBzaW5rO1xuICAgICAgICB0aGlzLmNhbGxiYWNrID0gY2FsbGJhY2s7XG4gICAgICAgIHRoaXMucmVjb3JkcyA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy5zZXEgPSAwO1xuICAgIH1cblxuICAgIHN0YXJ0KGNvbmZpZzogRGF0YUNoYW5uZWxMYXRlbmN5VGVzdENvbmZpZykge1xuICAgICAgICBpZiAodGhpcy5pc1J1bm5pbmcoKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgICAgdGhpcy5yZWNvcmRzLmNsZWFyKCk7XG4gICAgICAgIHRoaXMuaW50ZXJ2YWwgPSBzZXRJbnRlcnZhbCgoKCkgPT4ge1xuICAgICAgICAgICAgaWYgKERhdGUubm93KCkgLSB0aGlzLnN0YXJ0VGltZSA+PSBjb25maWcuZHVyYXRpb24pIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0b3AoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZW5kUmVxdWVzdChjb25maWcucmVxdWVzdFNpemUsIGNvbmZpZy5yZXNwb25zZVNpemUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KS5iaW5kKHRoaXMpLCBNYXRoLmZsb29yKDEwMDAvY29uZmlnLnJwcykpO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBzdG9wKCkge1xuICAgICAgICBpZiAodGhpcy5pbnRlcnZhbCkge1xuICAgICAgICAgICAgY2xlYXJJbnRlcnZhbCh0aGlzLmludGVydmFsKTtcbiAgICAgICAgICAgIHRoaXMuaW50ZXJ2YWwgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB0aGlzLmNhbGxiYWNrKHRoaXMucHJvZHVjZVJlc3VsdCgpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByb2R1Y2VSZXN1bHQoKTogRGF0YUNoYW5uZWxMYXRlbmN5VGVzdFJlc3VsdCB7XG4gICAgICAgIGNvbnN0IHJlc3VsdFJlY29yZHMgPSBuZXcgTWFwKHRoaXMucmVjb3Jkcyk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICByZWNvcmRzOiByZXN1bHRSZWNvcmRzLFxuICAgICAgICAgICAgZGF0YUNoYW5uZWxSdHQ6IE1hdGguY2VpbChBcnJheS5mcm9tKHRoaXMucmVjb3Jkcy52YWx1ZXMoKSkucmVkdWNlKChhY2MsIG5leHQpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYWNjICsgKG5leHQucGxheWVyUmVjZWl2ZWRUaW1lc3RhbXAgLSBuZXh0LnBsYXllclNlbnRUaW1lc3RhbXApO1xuICAgICAgICAgICAgfSwgMCkgLyB0aGlzLnJlY29yZHMuc2l6ZSksXG4gICAgICAgICAgICBwbGF5ZXJUb1N0cmVhbWVyVGltZTogTWF0aC5jZWlsKEFycmF5LmZyb20odGhpcy5yZWNvcmRzLnZhbHVlcygpKS5yZWR1Y2UoKGFjYywgbmV4dCkgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiBhY2MgKyAobmV4dC5zdHJlYW1lclJlY2VpdmVkVGltZXN0YW1wIC0gbmV4dC5wbGF5ZXJTZW50VGltZXN0YW1wKTtcbiAgICAgICAgICAgIH0sIDApIC8gdGhpcy5yZWNvcmRzLnNpemUpLFxuICAgICAgICAgICAgc3RyZWFtZXJUb1BsYXllclRpbWU6IE1hdGguY2VpbChBcnJheS5mcm9tKHRoaXMucmVjb3Jkcy52YWx1ZXMoKSkucmVkdWNlKChhY2MsIG5leHQpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gYWNjICsgKG5leHQucGxheWVyUmVjZWl2ZWRUaW1lc3RhbXAgLSBuZXh0LnN0cmVhbWVyU2VudFRpbWVzdGFtcCk7XG4gICAgICAgICAgICB9LCAwKSAvIHRoaXMucmVjb3Jkcy5zaXplKSxcbiAgICAgICAgICAgIGV4cG9ydExhdGVuY3lBc0NTVjogKCkgPT4ge1xuICAgICAgICAgICAgICAgIGxldCBjc3YgPSBcIlRpbWVzdGFtcDtSVFQ7UGxheWVyVG9TdHJlYW1lcjtTdHJlYW1lclRvUGxheWVyO1xcblwiO1xuICAgICAgICAgICAgICAgIHJlc3VsdFJlY29yZHMuZm9yRWFjaCgocmVjb3JkKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNzdiArPSByZWNvcmQucGxheWVyU2VudFRpbWVzdGFtcCArIFwiO1wiO1xuICAgICAgICAgICAgICAgICAgICBjc3YgKz0gKHJlY29yZC5wbGF5ZXJSZWNlaXZlZFRpbWVzdGFtcCAtIHJlY29yZC5wbGF5ZXJTZW50VGltZXN0YW1wKSArIFwiO1wiO1xuICAgICAgICAgICAgICAgICAgICBjc3YgKz0gKHJlY29yZC5zdHJlYW1lclJlY2VpdmVkVGltZXN0YW1wIC0gcmVjb3JkLnBsYXllclNlbnRUaW1lc3RhbXApICsgXCI7XCI7XG4gICAgICAgICAgICAgICAgICAgIGNzdiArPSAocmVjb3JkLnBsYXllclJlY2VpdmVkVGltZXN0YW1wIC0gcmVjb3JkLnN0cmVhbWVyU2VudFRpbWVzdGFtcCkgKyBcIjtcIjtcbiAgICAgICAgICAgICAgICAgICAgY3N2ICs9IFwiXFxuXCI7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICByZXR1cm4gY3N2O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgaXNSdW5uaW5nKCkge1xuICAgICAgICByZXR1cm4gISF0aGlzLmludGVydmFsO1xuICAgIH1cblxuICAgIHJlY2VpdmUocmVzcG9uc2U6IERhdGFDaGFubmVsTGF0ZW5jeVRlc3RSZXNwb25zZSkge1xuICAgICAgICBpZiAoIXRoaXMuaXNSdW5uaW5nKCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXJlc3BvbnNlKSB7XG4gICAgICAgICAgICBMb2dnZXIuRXJyb3IoXG4gICAgICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICAgICBcIlVuZGVmaW5lZCByZXNwb25zZSBmcm9tIHNlcnZlclwiXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGxldCByZWNvcmQgPSB0aGlzLnJlY29yZHMuZ2V0KHJlc3BvbnNlLlNlcSk7XG4gICAgICAgIGlmIChyZWNvcmQpIHtcbiAgICAgICAgICAgIHJlY29yZC51cGRhdGUocmVzcG9uc2UpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgc2VuZFJlcXVlc3QocmVxdWVzdFNpemU6IG51bWJlciwgcmVzcG9uc2VTaXplOiBudW1iZXIpIHtcbiAgICAgICAgbGV0IHJlcXVlc3QgPSB0aGlzLmNyZWF0ZVJlcXVlc3QocmVxdWVzdFNpemUsIHJlc3BvbnNlU2l6ZSk7XG4gICAgICAgIGxldCByZWNvcmQgPSBuZXcgRGF0YUNoYW5uZWxMYXRlbmN5VGVzdFJlY29yZChyZXF1ZXN0KTtcbiAgICAgICAgdGhpcy5yZWNvcmRzLnNldChyZWNvcmQuc2VxLCByZWNvcmQpO1xuICAgICAgICB0aGlzLnNpbmsocmVxdWVzdCk7XG4gICAgfVxuXG4gICAgY3JlYXRlUmVxdWVzdChyZXF1ZXN0U2l6ZTogbnVtYmVyLCByZXNwb25zZVNpemU6IG51bWJlcik6IERhdGFDaGFubmVsTGF0ZW5jeVRlc3RSZXF1ZXN0IHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIFNlcTogdGhpcy5zZXErKyxcbiAgICAgICAgICAgIEZpbGxSZXNwb25zZVNpemU6IHJlc3BvbnNlU2l6ZSxcbiAgICAgICAgICAgIEZpbGxlcjogcmVxdWVzdFNpemUgPyBcIkFcIi5yZXBlYXQocmVxdWVzdFNpemUpIDogXCJcIlxuICAgICAgICB9XG4gICAgfVxuXG59XG4iLCIvLyBDb3B5cmlnaHQgRXBpYyBHYW1lcywgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuXG4vKipcbiAqIERhdGEgQ2hhbm5lbCBMYXRlbmN5IFRlc3QgdHlwZXNcbiAqL1xuXG5cbi8qKlxuICogVW5peCBlcG9jaFxuICovXG5leHBvcnQgdHlwZSBEYXRhQ2hhbm5lbExhdGVuY3lUZXN0VGltZXN0YW1wID0gbnVtYmVyO1xuXG4vKipcbiAqIFNlcXVlbmNlIG51bWJlciByZXByZXNlbnRlZCBieSB1bnNpZ25lZCBpbnRcbiAqL1xuZXhwb3J0IHR5cGUgRGF0YUNoYW5uZWxMYXRlbmN5VGVzdFNlcSA9IG51bWJlcjtcblxuLyoqXG4gKiBSZXF1ZXN0IHNlbnQgdG8gU3RyZWFtZXJcbiAqL1xuZXhwb3J0IHR5cGUgRGF0YUNoYW5uZWxMYXRlbmN5VGVzdFJlcXVlc3QgPSB7XG4gICAgU2VxOiBEYXRhQ2hhbm5lbExhdGVuY3lUZXN0U2VxO1xuICAgIEZpbGxSZXNwb25zZVNpemU6IG51bWJlcjtcbiAgICBGaWxsZXI6IHN0cmluZztcbn1cblxuLyoqXG4gKiBSZXNwb25zZSBmcm9tIHRoZSBTdHJlYW1lclxuICovXG5leHBvcnQgdHlwZSBEYXRhQ2hhbm5lbExhdGVuY3lUZXN0UmVzcG9uc2UgPSB7XG4gICAgU2VxOiBEYXRhQ2hhbm5lbExhdGVuY3lUZXN0U2VxO1xuICAgIEZpbGxlcjogc3RyaW5nO1xuICAgIFJlY2VpdmVkVGltZXN0YW1wOiBEYXRhQ2hhbm5lbExhdGVuY3lUZXN0VGltZXN0YW1wO1xuICAgIFNlbnRUaW1lc3RhbXA6IERhdGFDaGFubmVsTGF0ZW5jeVRlc3RUaW1lc3RhbXA7XG59XG5cbmV4cG9ydCB0eXBlIERhdGFDaGFubmVsTGF0ZW5jeVRlc3RSZXN1bHQgPSB7XG4gICAgcmVjb3JkczogTWFwPERhdGFDaGFubmVsTGF0ZW5jeVRlc3RTZXEsIERhdGFDaGFubmVsTGF0ZW5jeVRlc3RSZWNvcmQ+XG4gICAgZGF0YUNoYW5uZWxSdHQ6IG51bWJlcixcbiAgICBwbGF5ZXJUb1N0cmVhbWVyVGltZTogbnVtYmVyLFxuICAgIHN0cmVhbWVyVG9QbGF5ZXJUaW1lOiBudW1iZXIsXG4gICAgZXhwb3J0TGF0ZW5jeUFzQ1NWOiAoKSA9PiBzdHJpbmdcbn1cblxuZXhwb3J0IGNsYXNzIERhdGFDaGFubmVsTGF0ZW5jeVRlc3RSZWNvcmQge1xuICAgIHNlcTogRGF0YUNoYW5uZWxMYXRlbmN5VGVzdFNlcTtcbiAgICBwbGF5ZXJTZW50VGltZXN0YW1wOiBEYXRhQ2hhbm5lbExhdGVuY3lUZXN0VGltZXN0YW1wO1xuICAgIHBsYXllclJlY2VpdmVkVGltZXN0YW1wOiBEYXRhQ2hhbm5lbExhdGVuY3lUZXN0VGltZXN0YW1wO1xuICAgIHN0cmVhbWVyUmVjZWl2ZWRUaW1lc3RhbXA6IERhdGFDaGFubmVsTGF0ZW5jeVRlc3RUaW1lc3RhbXA7XG4gICAgc3RyZWFtZXJTZW50VGltZXN0YW1wOiBEYXRhQ2hhbm5lbExhdGVuY3lUZXN0VGltZXN0YW1wO1xuICAgIHJlcXVlc3RGaWxsZXJTaXplOiBudW1iZXI7XG4gICAgcmVzcG9uc2VGaWxsZXJTaXplOiBudW1iZXI7XG5cbiAgICBjb25zdHJ1Y3RvcihyZXF1ZXN0OiBEYXRhQ2hhbm5lbExhdGVuY3lUZXN0UmVxdWVzdCkge1xuICAgICAgICB0aGlzLnNlcSA9IHJlcXVlc3QuU2VxO1xuICAgICAgICB0aGlzLnBsYXllclNlbnRUaW1lc3RhbXAgPSBEYXRlLm5vdygpO1xuICAgICAgICB0aGlzLnJlcXVlc3RGaWxsZXJTaXplID0gcmVxdWVzdC5GaWxsZXIgPyByZXF1ZXN0LkZpbGxlci5sZW5ndGggOiAwO1xuICAgIH1cblxuICAgIHVwZGF0ZShyZXNwb25zZTogRGF0YUNoYW5uZWxMYXRlbmN5VGVzdFJlc3BvbnNlKSB7XG4gICAgICAgIHRoaXMucGxheWVyUmVjZWl2ZWRUaW1lc3RhbXAgPSBEYXRlLm5vdygpO1xuICAgICAgICB0aGlzLnN0cmVhbWVyUmVjZWl2ZWRUaW1lc3RhbXAgPSByZXNwb25zZS5SZWNlaXZlZFRpbWVzdGFtcDtcbiAgICAgICAgdGhpcy5zdHJlYW1lclNlbnRUaW1lc3RhbXAgPSByZXNwb25zZS5TZW50VGltZXN0YW1wO1xuICAgICAgICB0aGlzLnJlc3BvbnNlRmlsbGVyU2l6ZSA9IHJlc3BvbnNlLkZpbGxlciA/IHJlc3BvbnNlLkZpbGxlci5sZW5ndGggOiAwO1xuICAgIH1cblxufVxuIiwiLy8gQ29weXJpZ2h0IEVwaWMgR2FtZXMsIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cblxuaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSAnLi4vTG9nZ2VyL0xvZ2dlcic7XG5pbXBvcnQgeyBEYXRhQ2hhbm5lbENvbnRyb2xsZXIgfSBmcm9tICcuL0RhdGFDaGFubmVsQ29udHJvbGxlcic7XG5cbi8qKlxuICogQSBjbGFzcyBmb3Igc2VuZGluZyBkYXRhIGNoYW5uZWwgbWVzc2FnZXNcbiAqL1xuZXhwb3J0IGNsYXNzIERhdGFDaGFubmVsU2VuZGVyIHtcbiAgICBkYXRhQ2hhbm5lbFByb3ZpZGVyOiBEYXRhQ2hhbm5lbENvbnRyb2xsZXI7XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gZGF0YUNoYW5uZWxQcm92aWRlciAtIERhdGEgY2hhbm5lbCBvYmplY3QgdHlwZVxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGRhdGFDaGFubmVsUHJvdmlkZXI6IERhdGFDaGFubmVsQ29udHJvbGxlcikge1xuICAgICAgICB0aGlzLmRhdGFDaGFubmVsUHJvdmlkZXIgPSBkYXRhQ2hhbm5lbFByb3ZpZGVyO1xuICAgIH1cblxuICAgIGNhblNlbmQoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICB0aGlzLmRhdGFDaGFubmVsUHJvdmlkZXIuZ2V0RGF0YUNoYW5uZWxJbnN0YW5jZSgpLmRhdGFDaGFubmVsICE9PVxuICAgICAgICAgICAgICAgIHVuZGVmaW5lZCAmJlxuICAgICAgICAgICAgdGhpcy5kYXRhQ2hhbm5lbFByb3ZpZGVyLmdldERhdGFDaGFubmVsSW5zdGFuY2UoKS5kYXRhQ2hhbm5lbFxuICAgICAgICAgICAgICAgIC5yZWFkeVN0YXRlID09ICdvcGVuJ1xuICAgICAgICApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlbmQgRGF0YSBvdmVyIHRoZSBEYXRhIGNoYW5uZWwgdG8gdGhlIFVFIEluc3RhbmNlXG4gICAgICogQHBhcmFtIGRhdGEgLSBNZXNzYWdlIERhdGEgQXJyYXkgQnVmZmVyXG4gICAgICovXG4gICAgc2VuZERhdGEoZGF0YTogQXJyYXlCdWZmZXIpIHtcbiAgICAgICAgLy8gcmVzZXQgdGhlIGFmayBpbmFjdGl2aXR5XG4gICAgICAgIGNvbnN0IGRhdGFDaGFubmVsSW5zdGFuY2UgPVxuICAgICAgICAgICAgdGhpcy5kYXRhQ2hhbm5lbFByb3ZpZGVyLmdldERhdGFDaGFubmVsSW5zdGFuY2UoKTtcblxuICAgICAgICBpZiAoZGF0YUNoYW5uZWxJbnN0YW5jZS5kYXRhQ2hhbm5lbC5yZWFkeVN0YXRlID09ICdvcGVuJykge1xuICAgICAgICAgICAgZGF0YUNoYW5uZWxJbnN0YW5jZS5kYXRhQ2hhbm5lbC5zZW5kKGRhdGEpO1xuICAgICAgICAgICAgTG9nZ2VyLkxvZyhcbiAgICAgICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgICAgIGBNZXNzYWdlIFNlbnQ6ICR7bmV3IFVpbnQ4QXJyYXkoZGF0YSl9YCxcbiAgICAgICAgICAgICAgICA2XG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgdGhpcy5yZXNldEFma1dhcm5pbmdUaW1lck9uRGF0YVNlbmQoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIExvZ2dlci5FcnJvcihcbiAgICAgICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgICAgIGBNZXNzYWdlIEZhaWxlZDogJHtuZXcgVWludDhBcnJheShkYXRhKX1gXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQW4gb3ZlcnJpZGUgbWV0aG9kIGZvciByZXNldHRpbmcgdGhlIEFmayB3YXJuaW5nIHRpbWVyIHdoZW4gZGF0YSBpcyBzZW50IG92ZXIgdGhlIGRhdGEgY2hhbm5lbFxuICAgICAqL1xuICAgIHJlc2V0QWZrV2FybmluZ1RpbWVyT25EYXRhU2VuZCgpIHtcbiAgICAgICAgLy8gQmFzZSBGdW5jdGlvbmFsaXR5OiBEbyBOb3RoaW5nXG4gICAgfVxufVxuIiwiLy8gQ29weXJpZ2h0IEVwaWMgR2FtZXMsIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cblxuLyoqXG4gKiBMYXRlbmN5IFRlc3QgUmVzdWx0cyBEYXRhXG4gKi9cbmV4cG9ydCBjbGFzcyBJbml0aWFsU2V0dGluZ3Mge1xuICAgIFBpeGVsU3RyZWFtaW5nU2V0dGluZ3M6IFBpeGVsU3RyZWFtaW5nU2V0dGluZ3M7XG4gICAgRW5jb2RlclNldHRpbmdzOiBFbmNvZGVyU2V0dGluZ3M7XG4gICAgV2ViUlRDU2V0dGluZ3M6IFdlYlJUQ1NldHRpbmdzO1xuXG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMuUGl4ZWxTdHJlYW1pbmdTZXR0aW5ncyA9IG5ldyBQaXhlbFN0cmVhbWluZ1NldHRpbmdzKCk7XG4gICAgICAgIHRoaXMuRW5jb2RlclNldHRpbmdzID0gbmV3IEVuY29kZXJTZXR0aW5ncygpO1xuICAgICAgICB0aGlzLldlYlJUQ1NldHRpbmdzID0gbmV3IFdlYlJUQ1NldHRpbmdzKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2tzIGZvciBjb21wYXRpYmlsaXR5IHdpdGggdGhlIEZQUyBhbmQgTWF4RlBTIHN0YXRzIGJldHdlZW4gNC4yNyBhbmQgNVxuICAgICAqL1xuICAgIHVlQ29tcGF0aWJsZSgpIHtcbiAgICAgICAgaWYgKHRoaXMuV2ViUlRDU2V0dGluZ3MuTWF4RlBTICE9IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMuV2ViUlRDU2V0dGluZ3MuRlBTID0gdGhpcy5XZWJSVENTZXR0aW5ncy5NYXhGUFM7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbi8qKlxuICogQSBjbGFzcyBmb3IgaGFuZGxpbmcgUGl4ZWwgU3RyZWFtaW5nIGRldGFpbHNcbiAqL1xuZXhwb3J0IGNsYXNzIFBpeGVsU3RyZWFtaW5nU2V0dGluZ3Mge1xuICAgIEFsbG93UGl4ZWxTdHJlYW1pbmdDb21tYW5kcz86IGJvb2xlYW47XG4gICAgRGlzYWJsZUxhdGVuY3lUZXN0PzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBBIGNsYXNzIGZvciBoYW5kbGluZyBlbmNvZGVyIHN0YXRzXG4gKi9cbmV4cG9ydCBjbGFzcyBFbmNvZGVyU2V0dGluZ3Mge1xuICAgIFRhcmdldEJpdHJhdGU/OiBudW1iZXI7XG4gICAgTWF4Qml0cmF0ZT86IG51bWJlcjtcbiAgICBNaW5RUD86IG51bWJlcjtcbiAgICBNYXhRUD86IG51bWJlcjtcbiAgICBSYXRlQ29udHJvbD86ICdDQlInIHwgJ1ZCUicgfCAnQ29uc3RRUCc7XG4gICAgRmlsbGVyRGF0YT86IGJvb2xlYW47XG4gICAgTXVsdGlQYXNzPzogJ0RJU0FCTEVEJyB8ICdRVUFSVEVSJyB8ICdGVUxMJztcbn1cblxuLyoqXG4gKiBBIGNsYXNzIGZvciBoYW5kbGluZyB3ZWIgcnRjIHN0YXRzXG4gKi9cbmV4cG9ydCBjbGFzcyBXZWJSVENTZXR0aW5ncyB7XG4gICAgRGVncmFkYXRpb25QcmVmPzogJ0JBTEFOQ0VEJyB8ICdNQUlOVEFJTl9GUkFNRVJBVEUnIHwgJ01BSU5UQUlOX1JFU09MVVRJT04nO1xuICAgIE1pbkJpdHJhdGU/OiBudW1iZXI7XG4gICAgTWF4Qml0cmF0ZT86IG51bWJlcjtcbiAgICBMb3dRUD86IG51bWJlcjtcbiAgICBIaWdoUVA/OiBudW1iZXI7XG4gICAgLy8gVUU0LjI3IGNvbXBhdGlibGVcbiAgICBNYXhGUFM/OiBudW1iZXI7XG4gICAgLy8gVUU1IGNvbXBhdGlibGVcbiAgICBGUFM/OiBudW1iZXI7XG59XG4iLCIvLyBDb3B5cmlnaHQgRXBpYyBHYW1lcywgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuXG5pbXBvcnQgeyBMb2dnZXIgfSBmcm9tICcuLi9Mb2dnZXIvTG9nZ2VyJztcbi8qKlxuICogTGF0ZW5jeSBUZXN0IFJlc3VsdHMgRGF0YVxuICovXG5leHBvcnQgY2xhc3MgTGF0ZW5jeVRlc3RSZXN1bHRzIHtcbiAgICAvL0ZpZWxkcyBTZXQgZnJvbSB0aGUgbGF0ZW5jeSBwYXlsb2FkIHJlZ2FyZGxlc3Mgb2YgdmVyc2lvblxuICAgIFJlY2VpcHRUaW1lTXM6IG51bWJlciA9IG51bGw7XG4gICAgVHJhbnNtaXNzaW9uVGltZU1zOiBudW1iZXIgPSBudWxsO1xuXG4gICAgLy9GaWVsZHMgU2V0IGZyb20gdGhlIGxhdGVuY3kgcGF5bG9hZCBmcm9tIDQuMjcuMlxuICAgIFByZUNhcHR1cmVUaW1lTXM6IG51bWJlciA9IG51bGw7XG4gICAgUG9zdENhcHR1cmVUaW1lTXM6IG51bWJlciA9IG51bGw7XG4gICAgUHJlRW5jb2RlVGltZU1zOiBudW1iZXIgPSBudWxsO1xuICAgIFBvc3RFbmNvZGVUaW1lTXM6IG51bWJlciA9IG51bGw7XG5cbiAgICAvL0ZpZWxkcyBTZXQgZnJvbSB0aGUgbGF0ZW5jeSBwYXlsb2FkIGZyb20gNS4wXG4gICAgRW5jb2RlTXM6IG51bWJlciA9IG51bGw7XG4gICAgQ2FwdHVyZVRvU2VuZE1zOiBudW1iZXIgPSBudWxsO1xuXG4gICAgLy9GaWVsZHMgU2V0IHdoZW4gcHJvY2Vzc2VkXG4gICAgdGVzdFN0YXJ0VGltZU1zID0gMDtcbiAgICBicm93c2VyUmVjZWlwdFRpbWVNcyA9IDA7XG5cbiAgICAvL0ZpZWxkcyBzZXQgZnJvbSBjYWxjdWxhdGlvbnNcbiAgICBsYXRlbmN5RXhjbHVkaW5nRGVjb2RlID0gMDtcbiAgICB0ZXN0RHVyYXRpb24gPSAwO1xuICAgIC8vdWVMYXRlbmN5OiBudW1iZXIgPSAwO1xuICAgIG5ldHdvcmtMYXRlbmN5ID0gMDtcbiAgICBicm93c2VyU2VuZExhdGVuY3kgPSAwO1xuICAgIGZyYW1lRGlzcGxheURlbHRhVGltZU1zID0gMDtcbiAgICBlbmRUb0VuZExhdGVuY3kgPSAwO1xuICAgIC8vdWVQaXhlbFN0cmVhbUxhdGVuY3k6IG51bWJlciA9IDA7XG4gICAgZW5jb2RlTGF0ZW5jeSA9IDA7XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBEZWx0YSBUaW1lIE1pbGxpc2Vjb25kc1xuICAgICAqIEBwYXJhbSBEZWx0YVRpbWVNcyAtIERlbHRhIFRpbWUgTWlsbGlzZWNvbmRzXG4gICAgICovXG4gICAgc2V0RnJhbWVEaXNwbGF5RGVsdGFUaW1lKERlbHRhVGltZU1zOiBudW1iZXIpIHtcbiAgICAgICAgaWYgKHRoaXMuZnJhbWVEaXNwbGF5RGVsdGFUaW1lTXMgPT0gMCkge1xuICAgICAgICAgICAgdGhpcy5mcmFtZURpc3BsYXlEZWx0YVRpbWVNcyA9IE1hdGgucm91bmQoRGVsdGFUaW1lTXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUHJvY2VzcyB0aGUgZW5jb2RlciB0aW1lcyBhbmQgc2V0IHRoZW1cbiAgICAgKi9cbiAgICBwcm9jZXNzRmllbGRzKCkge1xuICAgICAgICBpZiAoXG4gICAgICAgICAgICB0aGlzLkVuY29kZU1zID09IG51bGwgJiZcbiAgICAgICAgICAgICh0aGlzLlByZUVuY29kZVRpbWVNcyAhPSBudWxsIHx8IHRoaXMuUG9zdEVuY29kZVRpbWVNcyAhPSBudWxsKVxuICAgICAgICApIHtcbiAgICAgICAgICAgIExvZ2dlci5Mb2coXG4gICAgICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICAgICBgU2V0dGluZyBFbmNvZGUgTXMgXFxuICR7dGhpcy5Qb3N0RW5jb2RlVGltZU1zfSBcXG4gJHt0aGlzLlByZUVuY29kZVRpbWVNc31gLFxuICAgICAgICAgICAgICAgIDZcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICB0aGlzLkVuY29kZU1zID0gdGhpcy5Qb3N0RW5jb2RlVGltZU1zIC0gdGhpcy5QcmVFbmNvZGVUaW1lTXM7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoXG4gICAgICAgICAgICB0aGlzLkNhcHR1cmVUb1NlbmRNcyA9PSBudWxsICYmXG4gICAgICAgICAgICAodGhpcy5QcmVDYXB0dXJlVGltZU1zICE9IG51bGwgfHwgdGhpcy5Qb3N0Q2FwdHVyZVRpbWVNcyAhPSBudWxsKVxuICAgICAgICApIHtcbiAgICAgICAgICAgIExvZ2dlci5Mb2coXG4gICAgICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICAgICBgU2V0dGluZyBDYXB0dXJlVG9TZW5kTXMgTXMgXFxuICR7dGhpcy5Qb3N0Q2FwdHVyZVRpbWVNc30gXFxuICR7dGhpcy5QcmVDYXB0dXJlVGltZU1zfWAsXG4gICAgICAgICAgICAgICAgNlxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHRoaXMuQ2FwdHVyZVRvU2VuZE1zID1cbiAgICAgICAgICAgICAgICB0aGlzLlBvc3RDYXB0dXJlVGltZU1zIC0gdGhpcy5QcmVDYXB0dXJlVGltZU1zO1xuICAgICAgICB9XG4gICAgfVxufVxuIiwiLy8gQ29weXJpZ2h0IEVwaWMgR2FtZXMsIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cblxuLyoqXG4gKiBBIGNsYXNzIGZvciBtYW5hZ2luZyB0aGUgZnJlZXplIGZyYW1lIG9iamVjdFxuICovXG5leHBvcnQgY2xhc3MgRnJlZXplRnJhbWUge1xuICAgIHByb3RlY3RlZCByb290RGl2OiBIVE1MRWxlbWVudDtcbiAgICBwcm90ZWN0ZWQgcm9vdEVsZW1lbnQ6IEhUTUxEaXZFbGVtZW50O1xuICAgIGltYWdlRWxlbWVudDogSFRNTEltYWdlRWxlbWVudDtcbiAgICBmcmVlemVGcmFtZUhlaWdodCA9IDA7XG4gICAgZnJlZXplRnJhbWVXaWR0aCA9IDA7XG5cbiAgICAvKipcbiAgICAgKiBDb25zdHJ1Y3QgYSBmcmVlemUgZnJhbWVcbiAgICAgKiBAcGFyYW0gcm9vdERpdiB0aGUgZGl2IHRoYXQgYSBmcmVlemUgZnJhbWUgZWxlbWVudCB3aWxsIGJlIGluamVjdGVkIGludG9cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcihyb290RGl2OiBIVE1MRWxlbWVudCkge1xuICAgICAgICB0aGlzLnJvb3REaXYgPSByb290RGl2O1xuXG4gICAgICAgIC8vIGNyZWF0ZSB0aGUgb3ZlcmxheVxuICAgICAgICB0aGlzLnJvb3RFbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgIHRoaXMucm9vdEVsZW1lbnQuaWQgPSAnZnJlZXplRnJhbWUnO1xuICAgICAgICB0aGlzLnJvb3RFbGVtZW50LnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgICAgIHRoaXMucm9vdEVsZW1lbnQuc3R5bGUucG9pbnRlckV2ZW50cyA9ICdub25lJztcbiAgICAgICAgdGhpcy5yb290RWxlbWVudC5zdHlsZS5wb3NpdGlvbiA9ICdhYnNvbHV0ZSc7XG4gICAgICAgIHRoaXMucm9vdEVsZW1lbnQuc3R5bGUuekluZGV4ID0gJzIwJztcblxuICAgICAgICAvLyBjcmVhdGUgdGhlIGltYWdlIHBsYWNlIGhvbGRlclxuICAgICAgICB0aGlzLmltYWdlRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2ltZycpO1xuICAgICAgICB0aGlzLmltYWdlRWxlbWVudC5zdHlsZS5wb3NpdGlvbiA9ICdhYnNvbHV0ZSc7XG5cbiAgICAgICAgLy8gYXBwZW5kIHRoZSBpbWFnZSBpbnRvIHRoZSByb290IGVsZW1lbnQgYW5kIGFwcGVuZCB0aGUgZWxlbWVudCB0byB0aGUgcm9vdCBkaXZcbiAgICAgICAgdGhpcy5yb290RWxlbWVudC5hcHBlbmRDaGlsZCh0aGlzLmltYWdlRWxlbWVudCk7XG4gICAgICAgIHRoaXMucm9vdERpdi5hcHBlbmRDaGlsZCh0aGlzLnJvb3RFbGVtZW50KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIGZyZWV6ZSBmcmFtZSBlbGVtZW50IGZvciBzaG93aW5nXG4gICAgICovXG4gICAgc2V0RWxlbWVudEZvclNob3coKSB7XG4gICAgICAgIHRoaXMucm9vdEVsZW1lbnQuc3R5bGUuZGlzcGxheSA9ICdibG9jayc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSBmcmVlemUgZnJhbWUgZWxlbWVudCBmb3IgaGlkaW5nXG4gICAgICovXG4gICAgc2V0RWxlbWVudEZvckhpZGUoKSB7XG4gICAgICAgIHRoaXMucm9vdEVsZW1lbnQuc3R5bGUuZGlzcGxheSA9ICdub25lJztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGUgdGhlIGZyZWV6ZSBmcmFtZXMgaW1hZ2Ugc291cmNlXG4gICAgICogQHBhcmFtIGpwZWcgLSB0aGUgZnJlZXplIGZyYW1lIGltYWdlIGFzIGEgYnl0ZSBhcnJheSBkYXRhXG4gICAgICovXG4gICAgdXBkYXRlSW1hZ2VFbGVtZW50U291cmNlKGpwZWc6IFVpbnQ4QXJyYXkpIHtcbiAgICAgICAgY29uc3QgYmFzZTY0ID0gYnRvYShcbiAgICAgICAgICAgIGpwZWcucmVkdWNlKChkYXRhLCBieXRlKSA9PiBkYXRhICsgU3RyaW5nLmZyb21DaGFyQ29kZShieXRlKSwgJycpXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuaW1hZ2VFbGVtZW50LnNyYyA9ICdkYXRhOmltYWdlL2pwZWc7YmFzZTY0LCcgKyBiYXNlNjQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSBkaW1lbnNpb25zIGZvciB0aGUgZnJlZXplIGZyYW1lIGZyb20gdGhlIGVsZW1lbnQgYW5kIHJlc2l6ZSBpdFxuICAgICAqL1xuICAgIHNldERpbWVuc2lvbnNGcm9tRWxlbWVudEFuZFJlc2l6ZSgpIHtcbiAgICAgICAgdGhpcy5mcmVlemVGcmFtZUhlaWdodCA9IHRoaXMuaW1hZ2VFbGVtZW50Lm5hdHVyYWxIZWlnaHQ7XG4gICAgICAgIHRoaXMuZnJlZXplRnJhbWVXaWR0aCA9IHRoaXMuaW1hZ2VFbGVtZW50Lm5hdHVyYWxXaWR0aDtcbiAgICAgICAgdGhpcy5yZXNpemUoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXNpemUgYSBmcmVlemUgZnJhbWUgZWxlbWVudFxuICAgICAqL1xuICAgIHJlc2l6ZSgpIHtcbiAgICAgICAgaWYgKHRoaXMuZnJlZXplRnJhbWVXaWR0aCAhPT0gMCAmJiB0aGlzLmZyZWV6ZUZyYW1lSGVpZ2h0ICE9PSAwKSB7XG4gICAgICAgICAgICBsZXQgZGlzcGxheVdpZHRoID0gMDtcbiAgICAgICAgICAgIGxldCBkaXNwbGF5SGVpZ2h0ID0gMDtcbiAgICAgICAgICAgIGxldCBkaXNwbGF5VG9wID0gMDtcbiAgICAgICAgICAgIGxldCBkaXNwbGF5TGVmdCA9IDA7XG4gICAgICAgICAgICBjb25zdCBwYXJlbnRBc3BlY3RSYXRpbyA9XG4gICAgICAgICAgICAgICAgdGhpcy5yb290RGl2LmNsaWVudFdpZHRoIC8gdGhpcy5yb290RGl2LmNsaWVudEhlaWdodDtcbiAgICAgICAgICAgIGNvbnN0IHZpZGVvQXNwZWN0UmF0aW8gPVxuICAgICAgICAgICAgICAgIHRoaXMuZnJlZXplRnJhbWVXaWR0aCAvIHRoaXMuZnJlZXplRnJhbWVIZWlnaHQ7XG4gICAgICAgICAgICBpZiAocGFyZW50QXNwZWN0UmF0aW8gPCB2aWRlb0FzcGVjdFJhdGlvKSB7XG4gICAgICAgICAgICAgICAgZGlzcGxheVdpZHRoID0gdGhpcy5yb290RGl2LmNsaWVudFdpZHRoO1xuICAgICAgICAgICAgICAgIGRpc3BsYXlIZWlnaHQgPSBNYXRoLmZsb29yKFxuICAgICAgICAgICAgICAgICAgICB0aGlzLnJvb3REaXYuY2xpZW50V2lkdGggLyB2aWRlb0FzcGVjdFJhdGlvXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICBkaXNwbGF5VG9wID0gTWF0aC5mbG9vcihcbiAgICAgICAgICAgICAgICAgICAgKHRoaXMucm9vdERpdi5jbGllbnRIZWlnaHQgLSBkaXNwbGF5SGVpZ2h0KSAqIDAuNVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgZGlzcGxheUxlZnQgPSAwO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBkaXNwbGF5V2lkdGggPSBNYXRoLmZsb29yKFxuICAgICAgICAgICAgICAgICAgICB0aGlzLnJvb3REaXYuY2xpZW50SGVpZ2h0ICogdmlkZW9Bc3BlY3RSYXRpb1xuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgZGlzcGxheUhlaWdodCA9IHRoaXMucm9vdERpdi5jbGllbnRIZWlnaHQ7XG4gICAgICAgICAgICAgICAgZGlzcGxheVRvcCA9IDA7XG4gICAgICAgICAgICAgICAgZGlzcGxheUxlZnQgPSBNYXRoLmZsb29yKFxuICAgICAgICAgICAgICAgICAgICAodGhpcy5yb290RGl2LmNsaWVudFdpZHRoIC0gZGlzcGxheVdpZHRoKSAqIDAuNVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnJvb3RFbGVtZW50LnN0eWxlLndpZHRoID0gdGhpcy5yb290RGl2Lm9mZnNldFdpZHRoICsgJ3B4JztcbiAgICAgICAgICAgIHRoaXMucm9vdEVsZW1lbnQuc3R5bGUuaGVpZ2h0ID0gdGhpcy5yb290RGl2Lm9mZnNldEhlaWdodCArICdweCc7XG4gICAgICAgICAgICB0aGlzLnJvb3RFbGVtZW50LnN0eWxlLmxlZnQgPSAwICsgJ3B4JztcbiAgICAgICAgICAgIHRoaXMucm9vdEVsZW1lbnQuc3R5bGUudG9wID0gMCArICdweCc7XG5cbiAgICAgICAgICAgIHRoaXMuaW1hZ2VFbGVtZW50LnN0eWxlLndpZHRoID0gZGlzcGxheVdpZHRoICsgJ3B4JztcbiAgICAgICAgICAgIHRoaXMuaW1hZ2VFbGVtZW50LnN0eWxlLmhlaWdodCA9IGRpc3BsYXlIZWlnaHQgKyAncHgnO1xuICAgICAgICAgICAgdGhpcy5pbWFnZUVsZW1lbnQuc3R5bGUubGVmdCA9IGRpc3BsYXlMZWZ0ICsgJ3B4JztcbiAgICAgICAgICAgIHRoaXMuaW1hZ2VFbGVtZW50LnN0eWxlLnRvcCA9IGRpc3BsYXlUb3AgKyAncHgnO1xuICAgICAgICB9XG4gICAgfVxufVxuIiwiLy8gQ29weXJpZ2h0IEVwaWMgR2FtZXMsIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cblxuaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSAnLi4vTG9nZ2VyL0xvZ2dlcic7XG5pbXBvcnQgeyBGcmVlemVGcmFtZSB9IGZyb20gJy4vRnJlZXplRnJhbWUnO1xuXG4vKipcbiAqIEEgY2xhc3MgZm9yIGNvbnRyb2xsaW5nIGZyZWV6ZSBmcmFtZSBmdW5jdGlvbmFsaXR5XG4gKi9cbmV4cG9ydCBjbGFzcyBGcmVlemVGcmFtZUNvbnRyb2xsZXIge1xuICAgIGZyZWV6ZUZyYW1lOiBGcmVlemVGcmFtZTtcbiAgICByZWNlaXZpbmcgPSBmYWxzZTtcbiAgICBzaXplID0gMDtcbiAgICBqcGVnOiBVaW50OEFycmF5ID0gdW5kZWZpbmVkO1xuICAgIHZhbGlkID0gZmFsc2U7XG4gICAgZnJlZXplRnJhbWVEZWxheSA9IDUwO1xuXG4gICAgLyoqXG4gICAgICogQ29uc3RydWN0IGEgZnJlZXplIGZyYW1lIGNvbnRyb2xsZXJcbiAgICAgKiBAcGFyYW0gcm9vdERpdiAtIHRoZSBkaXYgdGhhdCBhIGZyZWV6ZSBmcmFtZSBlbGVtZW50IHdpbGwgYmUgaW5qZWN0ZWQgaW50b1xuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHJvb3REaXY6IEhUTUxFbGVtZW50KSB7XG4gICAgICAgIHRoaXMuZnJlZXplRnJhbWUgPSBuZXcgRnJlZXplRnJhbWUocm9vdERpdik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2hvdyB0aGUgZnJlZXplIGZyYW1lIGlmIGl0IGlzIHZhbGlkXG4gICAgICovXG4gICAgc2hvd0ZyZWV6ZUZyYW1lKCkge1xuICAgICAgICBpZiAodGhpcy52YWxpZCkge1xuICAgICAgICAgICAgdGhpcy5mcmVlemVGcmFtZS5zZXRFbGVtZW50Rm9yU2hvdygpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGlkZSB0aGUgZnJlZXplIGZyYW1lIGFuZCBzZXQgdGhlIHZhbGlkaXR5IHRvIGZhbHNlXG4gICAgICovXG4gICAgaGlkZUZyZWV6ZUZyYW1lKCkge1xuICAgICAgICB0aGlzLnZhbGlkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuZnJlZXplRnJhbWUuc2V0RWxlbWVudEZvckhpZGUoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGUgdGhlIGZyZWV6ZSBmcmFtZXMgaW1hZ2Ugc291cmNlIGFuZCBsb2FkIGl0XG4gICAgICogQHBhcmFtIGpwZWcgLSB0aGUgZnJlZXplIGZyYW1lIGltYWdlIGFzIGEgYnl0ZSBhcnJheSBkYXRhXG4gICAgICogQHBhcmFtIG9uTG9hZENhbGxCYWNrIC0gYSBjYWxsIGJhY2sgZm9yIG1hbmFnaW5nIGlmIHRoZSBwbGF5IG92ZXJsYXkgbmVlZHMgdG8gYmUgc2hvd24gb3Igbm90XG4gICAgICovXG4gICAgdXBkYXRlRnJlZXplRnJhbWVBbmRTaG93KGpwZWc6IFVpbnQ4QXJyYXksIG9uTG9hZENhbGxCYWNrOiAoKSA9PiB2b2lkKSB7XG4gICAgICAgIHRoaXMuZnJlZXplRnJhbWUudXBkYXRlSW1hZ2VFbGVtZW50U291cmNlKGpwZWcpO1xuICAgICAgICB0aGlzLmZyZWV6ZUZyYW1lLmltYWdlRWxlbWVudC5vbmxvYWQgPSAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLmZyZWV6ZUZyYW1lLnNldERpbWVuc2lvbnNGcm9tRWxlbWVudEFuZFJlc2l6ZSgpO1xuICAgICAgICAgICAgb25Mb2FkQ2FsbEJhY2soKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQcm9jZXNzIHRoZSBuZXcgZnJlZXplIGZyYW1lIGltYWdlIGFuZCB1cGRhdGUgaXRcbiAgICAgKiBAcGFyYW0gdmlldyAtIHRoZSBmcmVlemUgZnJhbWUgaW1hZ2UgYXMgYSBieXRlIGFycmF5IGRhdGFcbiAgICAgKiBAcGFyYW0gb25Mb2FkQ2FsbEJhY2sgLSBhIGNhbGwgYmFjayBmb3IgbWFuYWdpbmcgaWYgdGhlIHBsYXkgb3ZlcmxheSBuZWVkcyB0byBiZSBzaG93biBvciBub3RcbiAgICAgKi9cbiAgICBwcm9jZXNzRnJlZXplRnJhbWVNZXNzYWdlKHZpZXc6IFVpbnQ4QXJyYXksIG9uTG9hZENhbGxCYWNrOiAoKSA9PiB2b2lkKSB7XG4gICAgICAgIC8vIFJlc2V0IGZyZWV6ZSBmcmFtZSBpZiB3ZSBnb3QgYSBmcmVlemUgZnJhbWUgbWVzc2FnZSBhbmQgd2UgYXJlIG5vdCBcInJlY2VpdmluZ1wiIHlldC5cbiAgICAgICAgaWYgKCF0aGlzLnJlY2VpdmluZykge1xuICAgICAgICAgICAgdGhpcy5yZWNlaXZpbmcgPSB0cnVlO1xuICAgICAgICAgICAgdGhpcy52YWxpZCA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5zaXplID0gMDtcbiAgICAgICAgICAgIHRoaXMuanBlZyA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEV4dHJhY3QgdG90YWwgc2l6ZSBvZiBmcmVlemUgZnJhbWUgKGFjcm9zcyBhbGwgY2h1bmtzKVxuICAgICAgICB0aGlzLnNpemUgPSBuZXcgRGF0YVZpZXcodmlldy5zbGljZSgxLCA1KS5idWZmZXIpLmdldEludDMyKDAsIHRydWUpO1xuXG4gICAgICAgIC8vIEdldCB0aGUganBlZyBwYXJ0IG9mIHRoZSBwYXlsb2FkXG4gICAgICAgIGNvbnN0IGpwZWdCeXRlcyA9IHZpZXcuc2xpY2UoMSArIDQpO1xuXG4gICAgICAgIC8vIEFwcGVuZCB0byBleGlzdGluZyBqcGVnIHRoYXQgaG9sZHMgdGhlIGZyZWV6ZSBmcmFtZVxuICAgICAgICBpZiAodGhpcy5qcGVnKSB7XG4gICAgICAgICAgICBjb25zdCBqcGVnID0gbmV3IFVpbnQ4QXJyYXkodGhpcy5qcGVnLmxlbmd0aCArIGpwZWdCeXRlcy5sZW5ndGgpO1xuICAgICAgICAgICAganBlZy5zZXQodGhpcy5qcGVnLCAwKTtcbiAgICAgICAgICAgIGpwZWcuc2V0KGpwZWdCeXRlcywgdGhpcy5qcGVnLmxlbmd0aCk7XG4gICAgICAgICAgICB0aGlzLmpwZWcgPSBqcGVnO1xuICAgICAgICB9XG4gICAgICAgIC8vIE5vIGV4aXN0aW5nIGZyZWV6ZSBmcmFtZSBqcGVnLCBtYWtlIG9uZVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuanBlZyA9IGpwZWdCeXRlcztcbiAgICAgICAgICAgIHRoaXMucmVjZWl2aW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIExvZ2dlci5Mb2coXG4gICAgICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICAgICBgcmVjZWl2ZWQgZmlyc3QgY2h1bmsgb2YgZnJlZXplIGZyYW1lOiAke3RoaXMuanBlZy5sZW5ndGh9LyR7dGhpcy5zaXplfWAsXG4gICAgICAgICAgICAgICAgNlxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEZpbmlzaGVkIHJlY2VpdmluZyBmcmVlemUgZnJhbWUsIHdlIGNhbiBzaG93IGl0IG5vd1xuICAgICAgICBpZiAodGhpcy5qcGVnLmxlbmd0aCA9PT0gdGhpcy5zaXplKSB7XG4gICAgICAgICAgICB0aGlzLnJlY2VpdmluZyA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy52YWxpZCA9IHRydWU7XG4gICAgICAgICAgICBMb2dnZXIuTG9nKFxuICAgICAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAgICAgYHJlY2VpdmVkIGNvbXBsZXRlIGZyZWV6ZSBmcmFtZSAke3RoaXMuc2l6ZX1gLFxuICAgICAgICAgICAgICAgIDZcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZUZyZWV6ZUZyYW1lQW5kU2hvdyh0aGlzLmpwZWcsIG9uTG9hZENhbGxCYWNrKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBXZSByZWNlaXZlZCBtb3JlIGRhdGEgdGhhbiB0aGUgZnJlZXplIGZyYW1lIHBheWxvYWQgbWVzc2FnZSBpbmRpY2F0ZSAodGhpcyBpcyBhbiBlcnJvcilcbiAgICAgICAgZWxzZSBpZiAodGhpcy5qcGVnLmxlbmd0aCA+IHRoaXMuc2l6ZSkge1xuICAgICAgICAgICAgTG9nZ2VyLkVycm9yKFxuICAgICAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAgICAgYHJlY2VpdmVkIGJpZ2dlciBmcmVlemUgZnJhbWUgdGhhbiBhZHZlcnRpc2VkOiAke3RoaXMuanBlZy5sZW5ndGh9LyR7dGhpcy5zaXplfWBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICB0aGlzLmpwZWcgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB0aGlzLnJlY2VpdmluZyA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxufVxuIiwiLy8gQ29weXJpZ2h0IEVwaWMgR2FtZXMsIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cblxuaW1wb3J0IHsgQ29vcmRpbmF0ZUNvbnZlcnRlciB9IGZyb20gJy4uL1V0aWwvQ29vcmRpbmF0ZUNvbnZlcnRlcic7XG5pbXBvcnQgeyBTdHJlYW1NZXNzYWdlQ29udHJvbGxlciB9IGZyb20gJy4uL1VlSW5zdGFuY2VNZXNzYWdlL1N0cmVhbU1lc3NhZ2VDb250cm9sbGVyJztcbmltcG9ydCB7IFZpZGVvUGxheWVyIH0gZnJvbSAnLi4vVmlkZW9QbGF5ZXIvVmlkZW9QbGF5ZXInO1xuaW1wb3J0IHsgSVRvdWNoQ29udHJvbGxlciB9IGZyb20gJy4vSVRvdWNoQ29udHJvbGxlcic7XG5pbXBvcnQgeyBNb3VzZUJ1dHRvbiB9IGZyb20gJy4vTW91c2VCdXR0b25zJztcbmltcG9ydCB7IEV2ZW50TGlzdGVuZXJUcmFja2VyIH0gZnJvbSAnLi4vVXRpbC9FdmVudExpc3RlbmVyVHJhY2tlcic7XG5cbi8qKlxuICogQWxsb3dzIGZvciB0aGUgdXNhZ2Ugb2YgZmFrZSB0b3VjaCBldmVudHMgYW5kIGltcGxlbWVudHMgSVRvdWNoQ29udHJvbGxlclxuICogQHBhcmFtIGRhdGFDaGFubmVsQ29udHJvbGxlciAtIFRoZSBjb250cm9sbGVyIGZvciB0aGUgRGF0YSBjaGFubmVsXG4gKiBAcGFyYW0gdmlkZW9FbGVtZW50UGFyZW50IC0gVGhlIHZpZGVvIHBsYXllciBET00gZWxlbWVudFxuICovXG5leHBvcnQgY2xhc3MgRmFrZVRvdWNoQ29udHJvbGxlciBpbXBsZW1lbnRzIElUb3VjaENvbnRyb2xsZXIge1xuICAgIGZha2VUb3VjaEZpbmdlcjogRmFrZVRvdWNoRmluZ2VyO1xuICAgIHRvU3RyZWFtZXJNZXNzYWdlc1Byb3ZpZGVyOiBTdHJlYW1NZXNzYWdlQ29udHJvbGxlcjtcbiAgICB2aWRlb0VsZW1lbnRQcm92aWRlcjogVmlkZW9QbGF5ZXI7XG4gICAgY29vcmRpbmF0ZUNvbnZlcnRlcjogQ29vcmRpbmF0ZUNvbnZlcnRlcjtcbiAgICB2aWRlb0VsZW1lbnRQYXJlbnRDbGllbnRSZWN0OiBET01SZWN0O1xuXG4gICAgLy8gVXRpbGl0eSBmb3Iga2VlcGluZyB0cmFjayBvZiBldmVudCBoYW5kbGVycyBhbmQgdW5yZWdpc3RlcmluZyB0aGVtXG4gICAgcHJpdmF0ZSB0b3VjaEV2ZW50TGlzdGVuZXJUcmFja2VyID0gbmV3IEV2ZW50TGlzdGVuZXJUcmFja2VyKCk7XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gdG9TdHJlYW1lck1lc3NhZ2VzUHJvdmlkZXIgLSBTdHJlYW0gbWVzc2FnZSBpbnN0YW5jZVxuICAgICAqIEBwYXJhbSB2aWRlb0VsZW1lbnRQcm92aWRlciAtIFZpZGVvIGVsZW1lbnQgaW5zdGFuY2VcbiAgICAgKiBAcGFyYW0gY29vcmRpbmF0ZUNvbnZlcnRlciAtIEEgY29vcmRpbmF0ZSBjb252ZXJ0ZXIgaW5zdGFuY2VcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgdG9TdHJlYW1lck1lc3NhZ2VzUHJvdmlkZXI6IFN0cmVhbU1lc3NhZ2VDb250cm9sbGVyLFxuICAgICAgICB2aWRlb0VsZW1lbnRQcm92aWRlcjogVmlkZW9QbGF5ZXIsXG4gICAgICAgIGNvb3JkaW5hdGVDb252ZXJ0ZXI6IENvb3JkaW5hdGVDb252ZXJ0ZXJcbiAgICApIHtcbiAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlciA9IHRvU3RyZWFtZXJNZXNzYWdlc1Byb3ZpZGVyO1xuICAgICAgICB0aGlzLnZpZGVvRWxlbWVudFByb3ZpZGVyID0gdmlkZW9FbGVtZW50UHJvdmlkZXI7XG4gICAgICAgIHRoaXMuY29vcmRpbmF0ZUNvbnZlcnRlciA9IGNvb3JkaW5hdGVDb252ZXJ0ZXI7XG4gICAgICAgIGNvbnN0IG9udG91Y2hzdGFydCA9IChldjogVG91Y2hFdmVudCkgPT4gdGhpcy5vblRvdWNoU3RhcnQoZXYpO1xuICAgICAgICBjb25zdCBvbnRvdWNoZW5kID0gKGV2OiBUb3VjaEV2ZW50KSA9PiB0aGlzLm9uVG91Y2hFbmQoZXYpO1xuICAgICAgICBjb25zdCBvbnRvdWNobW92ZSA9IChldjogVG91Y2hFdmVudCkgPT4gdGhpcy5vblRvdWNoTW92ZShldik7XG4gICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoc3RhcnQnLCBvbnRvdWNoc3RhcnQsIHsgcGFzc2l2ZTogZmFsc2UgfSk7XG4gICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoZW5kJywgb250b3VjaGVuZCwgeyBwYXNzaXZlOiBmYWxzZSB9KTtcbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgb250b3VjaG1vdmUsIHsgcGFzc2l2ZTogZmFsc2UgfSk7XG4gICAgICAgIHRoaXMudG91Y2hFdmVudExpc3RlbmVyVHJhY2tlci5hZGRVbnJlZ2lzdGVyQ2FsbGJhY2soXG4gICAgICAgICAgICAoKSA9PiBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaHN0YXJ0Jywgb250b3VjaHN0YXJ0KVxuICAgICAgICApO1xuICAgICAgICB0aGlzLnRvdWNoRXZlbnRMaXN0ZW5lclRyYWNrZXIuYWRkVW5yZWdpc3RlckNhbGxiYWNrKFxuICAgICAgICAgICAgKCkgPT4gZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCBvbnRvdWNoZW5kKVxuICAgICAgICApO1xuICAgICAgICB0aGlzLnRvdWNoRXZlbnRMaXN0ZW5lclRyYWNrZXIuYWRkVW5yZWdpc3RlckNhbGxiYWNrKFxuICAgICAgICAgICAgKCkgPT4gZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgb250b3VjaG1vdmUpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVW5yZWdpc3RlciBhbGwgdG91Y2ggZXZlbnRzXG4gICAgICovXG4gICAgdW5yZWdpc3RlclRvdWNoRXZlbnRzKCkge1xuICAgICAgICB0aGlzLnRvdWNoRXZlbnRMaXN0ZW5lclRyYWNrZXIudW5yZWdpc3RlckFsbCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIHZpZGVvIEVsZW1lbnQgUGFyZW50IENsaWVudCBSZWN0IG51bWJlcnMgZm9yIHRoaXMgY2xhc3NcbiAgICAgKiBAcGFyYW0gdmlkZW9FbGVtZW50UGFyZW50Q2xpZW50UmVjdCAtIGEgaHRtbCBFbGVtZW50UGFyZW50Q2xpZW50UmVjdCBvYmplY3RcbiAgICAgKi9cbiAgICBzZXRWaWRlb0VsZW1lbnRQYXJlbnRDbGllbnRSZWN0KHZpZGVvRWxlbWVudFBhcmVudENsaWVudFJlY3Q6IERPTVJlY3QpIHtcbiAgICAgICAgdGhpcy52aWRlb0VsZW1lbnRQYXJlbnRDbGllbnRSZWN0ID0gdmlkZW9FbGVtZW50UGFyZW50Q2xpZW50UmVjdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBXaGVuIGEgdG91Y2ggZXZlbnQgYmVnaW5zXG4gICAgICogQHBhcmFtIHRvdWNoIC0gdGhlIGFjdGl2YXRpbmcgdG91Y2ggZXZlbnRcbiAgICAgKi9cbiAgICBvblRvdWNoU3RhcnQodG91Y2g6IFRvdWNoRXZlbnQpOiB2b2lkIHtcbiAgICAgICAgaWYgKCF0aGlzLnZpZGVvRWxlbWVudFByb3ZpZGVyLmlzVmlkZW9SZWFkeSgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuZmFrZVRvdWNoRmluZ2VyID09IG51bGwpIHtcbiAgICAgICAgICAgIGNvbnN0IGZpcnN0X3RvdWNoID0gdG91Y2guY2hhbmdlZFRvdWNoZXNbMF07XG4gICAgICAgICAgICB0aGlzLmZha2VUb3VjaEZpbmdlciA9IG5ldyBGYWtlVG91Y2hGaW5nZXIoXG4gICAgICAgICAgICAgICAgZmlyc3RfdG91Y2guaWRlbnRpZmllcixcbiAgICAgICAgICAgICAgICBmaXJzdF90b3VjaC5jbGllbnRYIC0gdGhpcy52aWRlb0VsZW1lbnRQYXJlbnRDbGllbnRSZWN0LmxlZnQsXG4gICAgICAgICAgICAgICAgZmlyc3RfdG91Y2guY2xpZW50WSAtIHRoaXMudmlkZW9FbGVtZW50UGFyZW50Q2xpZW50UmVjdC50b3BcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIGNvbnN0IHZpZGVvRWxlbWVudFBhcmVudCA9XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb0VsZW1lbnRQcm92aWRlci5nZXRWaWRlb1BhcmVudEVsZW1lbnQoKSBhcyBIVE1MRGl2RWxlbWVudDtcbiAgICAgICAgICAgIGNvbnN0IG1vdXNlRXZlbnQgPSBuZXcgTW91c2VFdmVudCgnbW91c2VlbnRlcicsIGZpcnN0X3RvdWNoKTtcbiAgICAgICAgICAgIHZpZGVvRWxlbWVudFBhcmVudC5kaXNwYXRjaEV2ZW50KG1vdXNlRXZlbnQpO1xuXG4gICAgICAgICAgICBjb25zdCBjb29yZCA9IHRoaXMuY29vcmRpbmF0ZUNvbnZlcnRlci5ub3JtYWxpemVBbmRRdWFudGl6ZVVuc2lnbmVkKFxuICAgICAgICAgICAgICAgIHRoaXMuZmFrZVRvdWNoRmluZ2VyLngsXG4gICAgICAgICAgICAgICAgdGhpcy5mYWtlVG91Y2hGaW5nZXIueVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGNvbnN0IHRvU3RyZWFtZXJIYW5kbGVycyA9XG4gICAgICAgICAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlci50b1N0cmVhbWVySGFuZGxlcnM7XG4gICAgICAgICAgICB0b1N0cmVhbWVySGFuZGxlcnMuZ2V0KCdNb3VzZURvd24nKShbXG4gICAgICAgICAgICAgICAgTW91c2VCdXR0b24ubWFpbkJ1dHRvbixcbiAgICAgICAgICAgICAgICBjb29yZC54LFxuICAgICAgICAgICAgICAgIGNvb3JkLnlcbiAgICAgICAgICAgIF0pO1xuICAgICAgICB9XG4gICAgICAgIHRvdWNoLnByZXZlbnREZWZhdWx0KCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogV2hlbiBhIHRvdWNoIGV2ZW50IGVuZHNcbiAgICAgKiBAcGFyYW0gdG91Y2hFdmVudCAtIHRoZSBhY3RpdmF0aW5nIHRvdWNoIGV2ZW50XG4gICAgICovXG4gICAgb25Ub3VjaEVuZCh0b3VjaEV2ZW50OiBUb3VjaEV2ZW50KTogdm9pZCB7XG4gICAgICAgIGlmICghdGhpcy52aWRlb0VsZW1lbnRQcm92aWRlci5pc1ZpZGVvUmVhZHkoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHZpZGVvRWxlbWVudFBhcmVudCA9XG4gICAgICAgICAgICB0aGlzLnZpZGVvRWxlbWVudFByb3ZpZGVyLmdldFZpZGVvUGFyZW50RWxlbWVudCgpO1xuICAgICAgICBjb25zdCB0b1N0cmVhbWVySGFuZGxlcnMgPVxuICAgICAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlci50b1N0cmVhbWVySGFuZGxlcnM7XG5cbiAgICAgICAgZm9yIChsZXQgdCA9IDA7IHQgPCB0b3VjaEV2ZW50LmNoYW5nZWRUb3VjaGVzLmxlbmd0aDsgdCsrKSB7XG4gICAgICAgICAgICBjb25zdCB0b3VjaCA9IHRvdWNoRXZlbnQuY2hhbmdlZFRvdWNoZXNbdF07XG4gICAgICAgICAgICBpZiAodG91Y2guaWRlbnRpZmllciA9PT0gdGhpcy5mYWtlVG91Y2hGaW5nZXIuaWQpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB4ID1cbiAgICAgICAgICAgICAgICAgICAgdG91Y2guY2xpZW50WCAtIHRoaXMudmlkZW9FbGVtZW50UGFyZW50Q2xpZW50UmVjdC5sZWZ0O1xuICAgICAgICAgICAgICAgIGNvbnN0IHkgPSB0b3VjaC5jbGllbnRZIC0gdGhpcy52aWRlb0VsZW1lbnRQYXJlbnRDbGllbnRSZWN0LnRvcDtcbiAgICAgICAgICAgICAgICBjb25zdCBjb29yZCA9XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29vcmRpbmF0ZUNvbnZlcnRlci5ub3JtYWxpemVBbmRRdWFudGl6ZVVuc2lnbmVkKHgsIHkpO1xuICAgICAgICAgICAgICAgIHRvU3RyZWFtZXJIYW5kbGVycy5nZXQoJ01vdXNlVXAnKShbXG4gICAgICAgICAgICAgICAgICAgIE1vdXNlQnV0dG9uLm1haW5CdXR0b24sXG4gICAgICAgICAgICAgICAgICAgIGNvb3JkLngsXG4gICAgICAgICAgICAgICAgICAgIGNvb3JkLnlcbiAgICAgICAgICAgICAgICBdKTtcblxuICAgICAgICAgICAgICAgIGNvbnN0IG1vdXNlRXZlbnQgPSBuZXcgTW91c2VFdmVudCgnbW91c2VsZWF2ZScsIHRvdWNoKTtcbiAgICAgICAgICAgICAgICB2aWRlb0VsZW1lbnRQYXJlbnQuZGlzcGF0Y2hFdmVudChtb3VzZUV2ZW50KTtcbiAgICAgICAgICAgICAgICB0aGlzLmZha2VUb3VjaEZpbmdlciA9IG51bGw7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdG91Y2hFdmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE9uIGEgTW92ZSB0b3VjaCBldmVudFxuICAgICAqIEBwYXJhbSB0b3VjaEV2ZW50IC0gdGhlIGFjdGl2YXRpbmcgdG91Y2ggZXZlbnRcbiAgICAgKi9cbiAgICBvblRvdWNoTW92ZSh0b3VjaEV2ZW50OiBUb3VjaEV2ZW50KTogdm9pZCB7XG4gICAgICAgIGlmICghdGhpcy52aWRlb0VsZW1lbnRQcm92aWRlci5pc1ZpZGVvUmVhZHkoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHRvU3RyZWFtZXJIYW5kbGVycyA9XG4gICAgICAgICAgICB0aGlzLnRvU3RyZWFtZXJNZXNzYWdlc1Byb3ZpZGVyLnRvU3RyZWFtZXJIYW5kbGVycztcblxuICAgICAgICBmb3IgKGxldCB0ID0gMDsgdCA8IHRvdWNoRXZlbnQudG91Y2hlcy5sZW5ndGg7IHQrKykge1xuICAgICAgICAgICAgY29uc3QgdG91Y2ggPSB0b3VjaEV2ZW50LnRvdWNoZXNbdF07XG4gICAgICAgICAgICBpZiAodG91Y2guaWRlbnRpZmllciA9PT0gdGhpcy5mYWtlVG91Y2hGaW5nZXIuaWQpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB4ID1cbiAgICAgICAgICAgICAgICAgICAgdG91Y2guY2xpZW50WCAtIHRoaXMudmlkZW9FbGVtZW50UGFyZW50Q2xpZW50UmVjdC5sZWZ0O1xuICAgICAgICAgICAgICAgIGNvbnN0IHkgPSB0b3VjaC5jbGllbnRZIC0gdGhpcy52aWRlb0VsZW1lbnRQYXJlbnRDbGllbnRSZWN0LnRvcDtcbiAgICAgICAgICAgICAgICBjb25zdCBjb29yZCA9XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29vcmRpbmF0ZUNvbnZlcnRlci5ub3JtYWxpemVBbmRRdWFudGl6ZVVuc2lnbmVkKHgsIHkpO1xuICAgICAgICAgICAgICAgIGNvbnN0IGRlbHRhID1cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb29yZGluYXRlQ29udmVydGVyLm5vcm1hbGl6ZUFuZFF1YW50aXplU2lnbmVkKFxuICAgICAgICAgICAgICAgICAgICAgICAgeCAtIHRoaXMuZmFrZVRvdWNoRmluZ2VyLngsXG4gICAgICAgICAgICAgICAgICAgICAgICB5IC0gdGhpcy5mYWtlVG91Y2hGaW5nZXIueVxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIHRvU3RyZWFtZXJIYW5kbGVycy5nZXQoJ01vdXNlTW92ZScpKFtcbiAgICAgICAgICAgICAgICAgICAgY29vcmQueCxcbiAgICAgICAgICAgICAgICAgICAgY29vcmQueSxcbiAgICAgICAgICAgICAgICAgICAgZGVsdGEueCxcbiAgICAgICAgICAgICAgICAgICAgZGVsdGEueVxuICAgICAgICAgICAgICAgIF0pO1xuICAgICAgICAgICAgICAgIHRoaXMuZmFrZVRvdWNoRmluZ2VyLnggPSB4O1xuICAgICAgICAgICAgICAgIHRoaXMuZmFrZVRvdWNoRmluZ2VyLnkgPSB5O1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRvdWNoRXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG59XG5cbi8qKlxuICogVGhlIGludGVyZmFjZSBmb3IgZmluZ2VyIHBvc2l0aW9uIG1hcHBpbmdcbiAqL1xuZXhwb3J0IGNsYXNzIEZha2VUb3VjaEZpbmdlciB7XG4gICAgaWQ6IG51bWJlcjtcbiAgICB4OiBudW1iZXI7XG4gICAgeTogbnVtYmVyO1xuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGlkIC0gdGhlIGJ1dHRvbiBpZFxuICAgICAqIEBwYXJhbSB4IC0gdGhlIHggYXhpcyB2YWx1ZVxuICAgICAqIEBwYXJhbSB5IC0gdGhlIHkgYXhpcyB2YWx1ZVxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGlkOiBudW1iZXIsIHg6IG51bWJlciwgeTogbnVtYmVyKSB7XG4gICAgICAgIHRoaXMuaWQgPSBpZDtcbiAgICAgICAgdGhpcy54ID0geDtcbiAgICAgICAgdGhpcy55ID0geTtcbiAgICB9XG59XG4iLCIvLyBDb3B5cmlnaHQgRXBpYyBHYW1lcywgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuXG5pbXBvcnQgeyBMb2dnZXIgfSBmcm9tICcuLi9Mb2dnZXIvTG9nZ2VyJztcbmltcG9ydCB7IFN0cmVhbU1lc3NhZ2VDb250cm9sbGVyIH0gZnJvbSAnLi4vVWVJbnN0YW5jZU1lc3NhZ2UvU3RyZWFtTWVzc2FnZUNvbnRyb2xsZXInO1xuaW1wb3J0IHsgRXZlbnRMaXN0ZW5lclRyYWNrZXIgfSBmcm9tICcuLi9VdGlsL0V2ZW50TGlzdGVuZXJUcmFja2VyJztcbmltcG9ydCB7IENvbnRyb2xsZXIgfSBmcm9tICcuL0dhbWVwYWRUeXBlcyc7XG5cbi8qKlxuICogVGhlIGNsYXNzIHRoYXQgaGFuZGxlcyB0aGUgZnVuY3Rpb25hbGl0eSBvZiBnYW1lcGFkcyBhbmQgY29udHJvbGxlcnNcbiAqL1xuZXhwb3J0IGNsYXNzIEdhbWVQYWRDb250cm9sbGVyIHtcbiAgICBjb250cm9sbGVyczogQXJyYXk8Q29udHJvbGxlcj47XG4gICAgcmVxdWVzdEFuaW1hdGlvbkZyYW1lOiAoY2FsbGJhY2s6IEZyYW1lUmVxdWVzdENhbGxiYWNrKSA9PiBudW1iZXI7XG4gICAgdG9TdHJlYW1lck1lc3NhZ2VzUHJvdmlkZXI6IFN0cmVhbU1lc3NhZ2VDb250cm9sbGVyO1xuXG4gICAgLy8gVXRpbGl0eSBmb3Iga2VlcGluZyB0cmFjayBvZiBldmVudCBoYW5kbGVycyBhbmQgdW5yZWdpc3RlcmluZyB0aGVtXG4gICAgcHJpdmF0ZSBnYW1lUGFkRXZlbnRMaXN0ZW5lclRyYWNrZXIgPSBuZXcgRXZlbnRMaXN0ZW5lclRyYWNrZXIoKTtcblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB0b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlciAtIFN0cmVhbSBtZXNzYWdlIGluc3RhbmNlXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodG9TdHJlYW1lck1lc3NhZ2VzUHJvdmlkZXI6IFN0cmVhbU1lc3NhZ2VDb250cm9sbGVyKSB7XG4gICAgICAgIHRoaXMudG9TdHJlYW1lck1lc3NhZ2VzUHJvdmlkZXIgPSB0b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlcjtcblxuICAgICAgICB0aGlzLnJlcXVlc3RBbmltYXRpb25GcmFtZSA9IChcbiAgICAgICAgICAgIHdpbmRvdy5tb3pSZXF1ZXN0QW5pbWF0aW9uRnJhbWUgfHxcbiAgICAgICAgICAgIHdpbmRvdy53ZWJraXRSZXF1ZXN0QW5pbWF0aW9uRnJhbWUgfHxcbiAgICAgICAgICAgIHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWVcbiAgICAgICAgKS5iaW5kKHdpbmRvdyk7XG4gICAgICAgIGNvbnN0IGJyb3dzZXJXaW5kb3cgPSB3aW5kb3cgYXMgV2luZG93O1xuICAgICAgICBpZiAoJ0dhbWVwYWRFdmVudCcgaW4gYnJvd3NlcldpbmRvdykge1xuICAgICAgICAgICAgY29uc3Qgb25HYW1lUGFkQ29ubmVjdGVkID0gKGV2OiBHYW1lcGFkRXZlbnQpID0+XG4gICAgICAgICAgICAgICAgdGhpcy5nYW1lUGFkQ29ubmVjdEhhbmRsZXIoZXYpO1xuICAgICAgICAgICAgY29uc3Qgb25HYW1lUGFkRGlzY29ubmVjdGVkID0gKGV2OiBHYW1lcGFkRXZlbnQpID0+XG4gICAgICAgICAgICAgICAgdGhpcy5nYW1lUGFkRGlzY29ubmVjdEhhbmRsZXIoZXYpO1xuICAgICAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2dhbWVwYWRjb25uZWN0ZWQnLCBvbkdhbWVQYWRDb25uZWN0ZWQpO1xuICAgICAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2dhbWVwYWRkaXNjb25uZWN0ZWQnLCBvbkdhbWVQYWREaXNjb25uZWN0ZWQpO1xuICAgICAgICAgICAgdGhpcy5nYW1lUGFkRXZlbnRMaXN0ZW5lclRyYWNrZXIuYWRkVW5yZWdpc3RlckNhbGxiYWNrKFxuICAgICAgICAgICAgICAgICgpID0+IHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdnYW1lcGFkY29ubmVjdGVkJywgb25HYW1lUGFkQ29ubmVjdGVkKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHRoaXMuZ2FtZVBhZEV2ZW50TGlzdGVuZXJUcmFja2VyLmFkZFVucmVnaXN0ZXJDYWxsYmFjayhcbiAgICAgICAgICAgICAgICAoKSA9PiB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcignZ2FtZXBhZGRpc2Nvbm5lY3RlZCcsIG9uR2FtZVBhZERpc2Nvbm5lY3RlZClcbiAgICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSBpZiAoJ1dlYktpdEdhbWVwYWRFdmVudCcgaW4gYnJvd3NlcldpbmRvdykge1xuICAgICAgICAgICAgY29uc3Qgb25XZWJraXRHYW1lUGFkQ29ubmVjdGVkID0gKGV2OiBHYW1lcGFkRXZlbnQpID0+IHRoaXMuZ2FtZVBhZENvbm5lY3RIYW5kbGVyKGV2KTtcbiAgICAgICAgICAgIGNvbnN0IG9uV2Via2l0R2FtZVBhZERpc2Nvbm5lY3RlZCA9IChldjogR2FtZXBhZEV2ZW50KSA9PiB0aGlzLmdhbWVQYWREaXNjb25uZWN0SGFuZGxlcihldik7XG4gICAgICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignd2Via2l0Z2FtZXBhZGNvbm5lY3RlZCcsIG9uV2Via2l0R2FtZVBhZENvbm5lY3RlZCk7XG4gICAgICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignd2Via2l0Z2FtZXBhZGRpc2Nvbm5lY3RlZCcsIG9uV2Via2l0R2FtZVBhZERpc2Nvbm5lY3RlZCk7XG4gICAgICAgICAgICB0aGlzLmdhbWVQYWRFdmVudExpc3RlbmVyVHJhY2tlci5hZGRVbnJlZ2lzdGVyQ2FsbGJhY2soXG4gICAgICAgICAgICAgICAgKCkgPT4gd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3dlYmtpdGdhbWVwYWRjb25uZWN0ZWQnLCBvbldlYmtpdEdhbWVQYWRDb25uZWN0ZWQpXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgdGhpcy5nYW1lUGFkRXZlbnRMaXN0ZW5lclRyYWNrZXIuYWRkVW5yZWdpc3RlckNhbGxiYWNrKFxuICAgICAgICAgICAgICAgICgpID0+IHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCd3ZWJraXRnYW1lcGFkZGlzY29ubmVjdGVkJywgb25XZWJraXRHYW1lUGFkRGlzY29ubmVjdGVkKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNvbnRyb2xsZXJzID0gW107XG4gICAgICAgIGlmIChuYXZpZ2F0b3IuZ2V0R2FtZXBhZHMpIHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgZ2FtZXBhZCBvZiBuYXZpZ2F0b3IuZ2V0R2FtZXBhZHMoKSkge1xuICAgICAgICAgICAgICAgIGlmIChnYW1lcGFkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZ2FtZVBhZENvbm5lY3RIYW5kbGVyKG5ldyBHYW1lcGFkRXZlbnQoJ2dhbWVwYWRjb25uZWN0ZWQnLCB7IGdhbWVwYWQgfSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVucmVnaXN0ZXJzIGFsbCBldmVudCBoYW5kbGVyc1xuICAgICAqL1xuICAgIHVucmVnaXN0ZXJHYW1lUGFkRXZlbnRzKCkge1xuICAgICAgICB0aGlzLmdhbWVQYWRFdmVudExpc3RlbmVyVHJhY2tlci51bnJlZ2lzdGVyQWxsKCk7XG4gICAgICAgIGZvcihjb25zdCBjb250cm9sbGVyIG9mIHRoaXMuY29udHJvbGxlcnMpIHtcbiAgICAgICAgICAgIGlmKGNvbnRyb2xsZXIuaWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHRoaXMub25HYW1lcGFkRGlzY29ubmVjdGVkKGNvbnRyb2xsZXIuaWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuY29udHJvbGxlcnMgPSBbXTtcbiAgICAgICAgdGhpcy5vbkdhbWVwYWRDb25uZWN0ZWQgPSAoKSA9PiB7IC8qICovIH07XG4gICAgICAgIHRoaXMub25HYW1lcGFkRGlzY29ubmVjdGVkID0gKCkgPT4geyAvKiAqLyB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbm5lY3RzIHRoZSBnYW1lcGFkIGhhbmRsZXJcbiAgICAgKiBAcGFyYW0gZ2FtZVBhZEV2ZW50IC0gdGhlIGFjdGl2YXRpbmcgZ2FtZXBhZCBldmVudFxuICAgICAqL1xuICAgIGdhbWVQYWRDb25uZWN0SGFuZGxlcihnYW1lUGFkRXZlbnQ6IEdhbWVwYWRFdmVudCkge1xuICAgICAgICBMb2dnZXIuTG9nKExvZ2dlci5HZXRTdGFja1RyYWNlKCksICdHYW1lcGFkIGNvbm5lY3QgaGFuZGxlcicsIDYpO1xuICAgICAgICBjb25zdCBnYW1lcGFkID0gZ2FtZVBhZEV2ZW50LmdhbWVwYWQ7XG5cbiAgICAgICAgY29uc3QgdGVtcDogQ29udHJvbGxlciA9IHtcbiAgICAgICAgICAgIGN1cnJlbnRTdGF0ZTogZ2FtZXBhZCxcbiAgICAgICAgICAgIHByZXZTdGF0ZTogZ2FtZXBhZCxcbiAgICAgICAgICAgIGlkOiB1bmRlZmluZWRcbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLmNvbnRyb2xsZXJzLnB1c2godGVtcCk7XG4gICAgICAgIHRoaXMuY29udHJvbGxlcnNbZ2FtZXBhZC5pbmRleF0uY3VycmVudFN0YXRlID0gZ2FtZXBhZDtcbiAgICAgICAgdGhpcy5jb250cm9sbGVyc1tnYW1lcGFkLmluZGV4XS5wcmV2U3RhdGUgPSBnYW1lcGFkO1xuICAgICAgICBMb2dnZXIuTG9nKFxuICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICdnYW1lcGFkOiAnICsgZ2FtZXBhZC5pZCArICcgY29ubmVjdGVkJyxcbiAgICAgICAgICAgIDZcbiAgICAgICAgKTtcbiAgICAgICAgd2luZG93LnJlcXVlc3RBbmltYXRpb25GcmFtZSgoKSA9PiB0aGlzLnVwZGF0ZVN0YXR1cygpKTtcbiAgICAgICAgdGhpcy5vbkdhbWVwYWRDb25uZWN0ZWQoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEaXNjb25uZWN0cyB0aGUgZ2FtZXBhZCBoYW5kbGVyXG4gICAgICogQHBhcmFtIGdhbWVQYWRFdmVudCAtIHRoZSBhY3RpdmF0aW5nIGdhbWVwYWQgZXZlbnRcbiAgICAgKi9cbiAgICBnYW1lUGFkRGlzY29ubmVjdEhhbmRsZXIoZ2FtZVBhZEV2ZW50OiBHYW1lcGFkRXZlbnQpIHtcbiAgICAgICAgTG9nZ2VyLkxvZyhMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLCAnR2FtZXBhZCBkaXNjb25uZWN0IGhhbmRsZXInLCA2KTtcbiAgICAgICAgTG9nZ2VyLkxvZyhcbiAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAnZ2FtZXBhZDogJyArIGdhbWVQYWRFdmVudC5nYW1lcGFkLmlkICsgJyBkaXNjb25uZWN0ZWQnLFxuICAgICAgICAgICAgNlxuICAgICAgICApO1xuICAgICAgICBjb25zdCBkZWxldGVkQ29udHJvbGxlciA9IHRoaXMuY29udHJvbGxlcnNbZ2FtZVBhZEV2ZW50LmdhbWVwYWQuaW5kZXhdO1xuICAgICAgICBkZWxldGUgdGhpcy5jb250cm9sbGVyc1tnYW1lUGFkRXZlbnQuZ2FtZXBhZC5pbmRleF07XG4gICAgICAgIHRoaXMuY29udHJvbGxlcnMgPSB0aGlzLmNvbnRyb2xsZXJzLmZpbHRlcihcbiAgICAgICAgICAgIChjb250cm9sbGVyKSA9PiBjb250cm9sbGVyICE9PSB1bmRlZmluZWRcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5vbkdhbWVwYWREaXNjb25uZWN0ZWQoZGVsZXRlZENvbnRyb2xsZXIuaWQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNjYW4gZm9yIGNvbm5lY3RlZCBnYW1lcGFkc1xuICAgICAqL1xuICAgIHNjYW5HYW1lUGFkcygpIHtcbiAgICAgICAgY29uc3QgZ2FtZXBhZHMgPSBuYXZpZ2F0b3IuZ2V0R2FtZXBhZHNcbiAgICAgICAgICAgID8gbmF2aWdhdG9yLmdldEdhbWVwYWRzKClcbiAgICAgICAgICAgIDogbmF2aWdhdG9yLndlYmtpdEdldEdhbWVwYWRzXG4gICAgICAgICAgICA/IG5hdmlnYXRvci53ZWJraXRHZXRHYW1lcGFkcygpXG4gICAgICAgICAgICA6IFtdO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGdhbWVwYWRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAoZ2FtZXBhZHNbaV0gJiYgZ2FtZXBhZHNbaV0uaW5kZXggaW4gdGhpcy5jb250cm9sbGVycykge1xuICAgICAgICAgICAgICAgIHRoaXMuY29udHJvbGxlcnNbZ2FtZXBhZHNbaV0uaW5kZXhdLmN1cnJlbnRTdGF0ZSA9IGdhbWVwYWRzW2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlcyB0aGUgc3RhdHVzIG9mIHRoZSBnYW1lcGFkIGFuZCBzZW5kcyB0aGUgaW5wdXRzXG4gICAgICovXG4gICAgdXBkYXRlU3RhdHVzKCkge1xuICAgICAgICB0aGlzLnNjYW5HYW1lUGFkcygpO1xuICAgICAgICBjb25zdCB0b1N0cmVhbWVySGFuZGxlcnMgPVxuICAgICAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlci50b1N0cmVhbWVySGFuZGxlcnM7XG5cbiAgICAgICAgLy8gSXRlcmF0ZSBvdmVyIG11bHRpcGxlIGNvbnRyb2xsZXJzIGluIHRoZSBjYXNlIHRoZSBtdWx0aXBsZSBnYW1lcGFkcyBhcmUgY29ubmVjdGVkXG4gICAgICAgIGZvciAoY29uc3QgY29udHJvbGxlciBvZiB0aGlzLmNvbnRyb2xsZXJzKSB7XG4gICAgICAgICAgICAvLyBJZiB3ZSBoYXZlbid0IHJlY2VpdmVkIGFuIGlkIChwb3NzaWJsZSBpZiB1c2luZyBhbiBvbGRlciB2ZXJzaW9uIG9mIFVFKSwgcmV0dXJuIHRvIG9yaWdpbmFsIGZ1bmN0aW9uYWxpdHlcbiAgICAgICAgICAgIGNvbnN0IGNvbnRyb2xsZXJJbmRleCA9IChjb250cm9sbGVyLmlkID09PSB1bmRlZmluZWQpID8gdGhpcy5jb250cm9sbGVycy5pbmRleE9mKGNvbnRyb2xsZXIpIDogY29udHJvbGxlci5pZDtcbiAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRTdGF0ZSA9IGNvbnRyb2xsZXIuY3VycmVudFN0YXRlO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjb250cm9sbGVyLmN1cnJlbnRTdGF0ZS5idXR0b25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgY3VycmVudEJ1dHRvbiA9IGNvbnRyb2xsZXIuY3VycmVudFN0YXRlLmJ1dHRvbnNbaV07XG4gICAgICAgICAgICAgICAgY29uc3QgcHJldmlvdXNCdXR0b24gPSBjb250cm9sbGVyLnByZXZTdGF0ZS5idXR0b25zW2ldO1xuICAgICAgICAgICAgICAgIGlmIChjdXJyZW50QnV0dG9uLnByZXNzZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gcHJlc3NcbiAgICAgICAgICAgICAgICAgICAgaWYgKGkgPT0gZ2FtZXBhZExheW91dC5MZWZ0VHJpZ2dlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgICAgICAgICAgICAgICAgICAgIFVFcyBsZWZ0IGFuYWxvZyBoYXMgYSBidXR0b24gaW5kZXggb2YgNVxuICAgICAgICAgICAgICAgICAgICAgICAgdG9TdHJlYW1lckhhbmRsZXJzLmdldCgnR2FtZXBhZEFuYWxvZycpKFtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sbGVySW5kZXgsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgNSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50QnV0dG9uLnZhbHVlXG4gICAgICAgICAgICAgICAgICAgICAgICBdKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpID09IGdhbWVwYWRMYXlvdXQuUmlnaHRUcmlnZ2VyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICAgICAgICAgICAgICAgICAgICAgVUVzIHJpZ2h0IGFuYWxvZyBoYXMgYSBidXR0b24gaW5kZXggb2YgNlxuICAgICAgICAgICAgICAgICAgICAgICAgdG9TdHJlYW1lckhhbmRsZXJzLmdldCgnR2FtZXBhZEFuYWxvZycpKFtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sbGVySW5kZXgsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgNixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50QnV0dG9uLnZhbHVlXG4gICAgICAgICAgICAgICAgICAgICAgICBdKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRvU3RyZWFtZXJIYW5kbGVycy5nZXQoJ0dhbWVwYWRCdXR0b25QcmVzc2VkJykoW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2xsZXJJbmRleCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZXZpb3VzQnV0dG9uLnByZXNzZWQgPyAxIDogMFxuICAgICAgICAgICAgICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFjdXJyZW50QnV0dG9uLnByZXNzZWQgJiYgcHJldmlvdXNCdXR0b24ucHJlc3NlZCkge1xuICAgICAgICAgICAgICAgICAgICAvLyByZWxlYXNlXG4gICAgICAgICAgICAgICAgICAgIGlmIChpID09IGdhbWVwYWRMYXlvdXQuTGVmdFRyaWdnZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vICAgICAgICAgICAgICAgICAgICAgICBVRXMgbGVmdCBhbmFsb2cgaGFzIGEgYnV0dG9uIGluZGV4IG9mIDVcbiAgICAgICAgICAgICAgICAgICAgICAgIHRvU3RyZWFtZXJIYW5kbGVycy5nZXQoJ0dhbWVwYWRBbmFsb2cnKShbXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbGxlckluZGV4LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMFxuICAgICAgICAgICAgICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaSA9PSBnYW1lcGFkTGF5b3V0LlJpZ2h0VHJpZ2dlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gICAgICAgICAgICAgICAgICAgICAgIFVFcyByaWdodCBhbmFsb2cgaGFzIGEgYnV0dG9uIGluZGV4IG9mIDZcbiAgICAgICAgICAgICAgICAgICAgICAgIHRvU3RyZWFtZXJIYW5kbGVycy5nZXQoJ0dhbWVwYWRBbmFsb2cnKShbXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbGxlckluZGV4LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDYsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgMFxuICAgICAgICAgICAgICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0b1N0cmVhbWVySGFuZGxlcnMuZ2V0KCdHYW1lcGFkQnV0dG9uUmVsZWFzZWQnKShbXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udHJvbGxlckluZGV4LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlcbiAgICAgICAgICAgICAgICAgICAgICAgIF0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gSXRlcmF0ZSBvdmVyIGdhbWVwYWQgYXhlcyAod2Ugd2lsbCBpbmNyZW1lbnQgaW4gbG90cyBvZiAyIGFzIHRoZXJlIGlzIDIgYXhlcyBwZXIgc3RpY2spXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGN1cnJlbnRTdGF0ZS5heGVzLmxlbmd0aDsgaSArPSAyKSB7XG4gICAgICAgICAgICAgICAgLy8gSG9yaXpvbnRhbCBheGVzIGFyZSBldmVuIG51bWJlcmVkXG4gICAgICAgICAgICAgICAgY29uc3QgeCA9IHBhcnNlRmxvYXQoY3VycmVudFN0YXRlLmF4ZXNbaV0udG9GaXhlZCg0KSk7XG5cbiAgICAgICAgICAgICAgICAvLyBWZXJ0aWNhbCBheGVzIGFyZSBvZGQgbnVtYmVyZWRcbiAgICAgICAgICAgICAgICAvLyBodHRwczovL3czYy5naXRodWIuaW8vZ2FtZXBhZC8jcmVtYXBwaW5nIEdhbWVwYWQgYnJvd3NlciBzaWRlIHN0YW5kYXJkIG1hcHBpbmcgaGFzIHBvc2l0aXZlIGRvd24sIG5lZ2F0aXZlIHVwLiBUaGlzIGlzIGRvd25yaWdodCBkaXNndXN0aW5nLiBTbyB3ZSBmaXggaXQuXG4gICAgICAgICAgICAgICAgY29uc3QgeSA9IC1wYXJzZUZsb2F0KGN1cnJlbnRTdGF0ZS5heGVzW2kgKyAxXS50b0ZpeGVkKDQpKTtcblxuICAgICAgICAgICAgICAgIC8vIFVFJ3MgYW5hbG9nIGF4ZXMgZm9sbG93IHRoZSBzYW1lIG9yZGVyIGFzIHRoZSBicm93c2VycywgYnV0IHN0YXJ0IGF0IGluZGV4IDEgc28gd2Ugd2lsbCBvZmZzZXQgYXMgc3VjaFxuICAgICAgICAgICAgICAgIHRvU3RyZWFtZXJIYW5kbGVycy5nZXQoJ0dhbWVwYWRBbmFsb2cnKShbXG4gICAgICAgICAgICAgICAgICAgIGNvbnRyb2xsZXJJbmRleCxcbiAgICAgICAgICAgICAgICAgICAgaSArIDEsXG4gICAgICAgICAgICAgICAgICAgIHhcbiAgICAgICAgICAgICAgICBdKTsgLy8gSG9yaXpvbnRhbCBheGVzLCBvbmx5IG9mZnNldCBieSAxXG4gICAgICAgICAgICAgICAgdG9TdHJlYW1lckhhbmRsZXJzLmdldCgnR2FtZXBhZEFuYWxvZycpKFtcbiAgICAgICAgICAgICAgICAgICAgY29udHJvbGxlckluZGV4LFxuICAgICAgICAgICAgICAgICAgICBpICsgMixcbiAgICAgICAgICAgICAgICAgICAgeVxuICAgICAgICAgICAgICAgIF0pOyAvLyBWZXJ0aWNhbCBheGVzLCBvZmZzZXQgYnkgdHdvICgxIHRvIG1hdGNoIFVFcyBheGVzIGNvbnZlbnRpb24gYW5kIHRoZW4gYW5vdGhlciAxIGZvciB0aGUgdmVydGljYWwgYXhlcylcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuY29udHJvbGxlcnNbY29udHJvbGxlckluZGV4XS5wcmV2U3RhdGUgPSBjdXJyZW50U3RhdGU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuY29udHJvbGxlcnMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgdGhpcy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKCkgPT4gdGhpcy51cGRhdGVTdGF0dXMoKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBvbkdhbWVwYWRSZXNwb25zZVJlY2VpdmVkKGdhbWVwYWRJZDogbnVtYmVyKSB7XG4gICAgICAgIGZvcihjb25zdCBjb250cm9sbGVyIG9mIHRoaXMuY29udHJvbGxlcnMpIHtcbiAgICAgICAgICAgIGlmKGNvbnRyb2xsZXIuaWQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGNvbnRyb2xsZXIuaWQgPSBnYW1lcGFkSWQ7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFdmVudCB0byBzZW5kIHRoZSBnYW1lcGFkY29ubmVjdGVkIG1lc3NhZ2UgdG8gdGhlIGFwcGxpY2F0aW9uXG4gICAgICovXG4gICAgb25HYW1lcGFkQ29ubmVjdGVkKCkge1xuICAgICAgICAvLyBEZWZhdWx0IEZ1bmN0aW9uYWxpdHk6IERvIE5vdGhpbmdcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFdmVudCB0byBzZW5kIHRoZSBnYW1lcGFkZGlzY29ubmVjdGVkIG1lc3NhZ2UgdG8gdGhlIGFwcGxpY2F0aW9uXG4gICAgICovXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIG9uR2FtZXBhZERpc2Nvbm5lY3RlZChjb250cm9sbGVySWR4OiBudW1iZXIpIHtcbiAgICAgICAgLy8gRGVmYXVsdCBGdW5jdGlvbmFsaXR5OiBEbyBOb3RoaW5nXG4gICAgfVxufVxuXG5cblxuLyoqXG4gKiBBZGRpdGlvbmFsIHR5cGVzIGZvciBXaW5kb3cgYW5kIE5hdmlnYXRvclxuICovXG5kZWNsYXJlIGdsb2JhbCB7XG4gICAgaW50ZXJmYWNlIFdpbmRvdyB7XG4gICAgICAgIG1velJlcXVlc3RBbmltYXRpb25GcmFtZShjYWxsYmFjazogRnJhbWVSZXF1ZXN0Q2FsbGJhY2spOiBudW1iZXI7XG4gICAgICAgIHdlYmtpdFJlcXVlc3RBbmltYXRpb25GcmFtZShjYWxsYmFjazogRnJhbWVSZXF1ZXN0Q2FsbGJhY2spOiBudW1iZXI7XG4gICAgfVxuXG4gICAgaW50ZXJmYWNlIE5hdmlnYXRvciB7XG4gICAgICAgIHdlYmtpdEdldEdhbWVwYWRzKCk6IEdhbWVwYWRbXTtcbiAgICB9XG59XG5cbi8qKlxuICogR2FtZXBhZCBsYXlvdXQgY29kZXMgZW51bVxuICovXG5leHBvcnQgZW51bSBnYW1lcGFkTGF5b3V0IHtcbiAgICBSaWdodENsdXN0ZXJCb3R0b21CdXR0b24gPSAwLFxuICAgIFJpZ2h0Q2x1c3RlclJpZ2h0QnV0dG9uID0gMSxcbiAgICBSaWdodENsdXN0ZXJMZWZ0QnV0dG9uID0gMixcbiAgICBSaWdodENsdXN0ZXJUb3BCdXR0b24gPSAzLFxuICAgIExlZnRTaG91bGRlciA9IDQsXG4gICAgUmlnaHRTaG91bGRlciA9IDUsXG4gICAgTGVmdFRyaWdnZXIgPSA2LFxuICAgIFJpZ2h0VHJpZ2dlciA9IDcsXG4gICAgU2VsZWN0T3JCYWNrID0gOCxcbiAgICBTdGFydE9yRm9yd2FyZCA9IDksXG4gICAgTGVmdEFuYWxvZ1ByZXNzID0gMTAsXG4gICAgUmlnaHRBbmFsb2dQcmVzcyA9IDExLFxuICAgIExlZnRDbHVzdGVyVG9wQnV0dG9uID0gMTIsXG4gICAgTGVmdENsdXN0ZXJCb3R0b21CdXR0b24gPSAxMyxcbiAgICBMZWZ0Q2x1c3RlckxlZnRCdXR0b24gPSAxNCxcbiAgICBMZWZ0Q2x1c3RlclJpZ2h0QnV0dG9uID0gMTUsXG4gICAgQ2VudHJlQnV0dG9uID0gMTYsXG4gICAgLy8gQXhlc1xuICAgIExlZnRTdGlja0hvcml6b250YWwgPSAwLFxuICAgIExlZnRTdGlja1ZlcnRpY2FsID0gMSxcbiAgICBSaWdodFN0aWNrSG9yaXpvbnRhbCA9IDIsXG4gICAgUmlnaHRTdGlja1ZlcnRpY2FsID0gM1xufVxuIiwiLy8gQ29weXJpZ2h0IEVwaWMgR2FtZXMsIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cblxuaW1wb3J0IHsgTW91c2VDb250cm9sbGVyIH0gZnJvbSAnLi9Nb3VzZUNvbnRyb2xsZXInO1xuaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSAnLi4vTG9nZ2VyL0xvZ2dlcic7XG5pbXBvcnQgeyBJTW91c2VFdmVudHMgfSBmcm9tICcuL0lNb3VzZUV2ZW50cyc7XG5cbi8qKlxuICogVmlkZW8gUGxheWVyIG1vdXNlIEhvdmVyIGhhbmRsZXJcbiAqL1xuZXhwb3J0IGNsYXNzIEhvdmVyaW5nTW91c2VFdmVudHMgaW1wbGVtZW50cyBJTW91c2VFdmVudHMge1xuICAgIG1vdXNlQ29udHJvbGxlcjogTW91c2VDb250cm9sbGVyO1xuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIG1vdXNlQ29udHJvbGxlciAtIE1vdXNlIENvbnRyb2xsZXIgaW5zdGFuY2VcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcihtb3VzZUNvbnRyb2xsZXI6IE1vdXNlQ29udHJvbGxlcikge1xuICAgICAgICB0aGlzLm1vdXNlQ29udHJvbGxlciA9IG1vdXNlQ29udHJvbGxlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVbnJlZ2lzdGVyIGV2ZW50IGhhbmRsZXJzXG4gICAgICovXG4gICAgdW5yZWdpc3Rlck1vdXNlRXZlbnRzKCk6IHZvaWQge1xuICAgICAgICAvLyBlbXB0eSBmb3IgSG92ZXJpbmdNb3VzZUV2ZW50cyBpbXBsZW1lbnRhdGlvblxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZSB0aGUgbW91c2UgbW92ZSBldmVudCwgc2VuZHMgdGhlIG1vdXNlIGRhdGEgdG8gdGhlIFVFIEluc3RhbmNlXG4gICAgICogQHBhcmFtIG1vdXNlRXZlbnQgLSBNb3VzZSBFdmVudFxuICAgICAqL1xuICAgIHVwZGF0ZU1vdXNlTW92ZVBvc2l0aW9uKG1vdXNlRXZlbnQ6IE1vdXNlRXZlbnQpIHtcbiAgICAgICAgaWYgKCF0aGlzLm1vdXNlQ29udHJvbGxlci52aWRlb0VsZW1lbnRQcm92aWRlci5pc1ZpZGVvUmVhZHkoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIExvZ2dlci5Mb2coTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSwgJ01vdXNlTW92ZScsIDYpO1xuICAgICAgICBjb25zdCBjb29yZCA9XG4gICAgICAgICAgICB0aGlzLm1vdXNlQ29udHJvbGxlci5jb29yZGluYXRlQ29udmVydGVyLm5vcm1hbGl6ZUFuZFF1YW50aXplVW5zaWduZWQoXG4gICAgICAgICAgICAgICAgbW91c2VFdmVudC5vZmZzZXRYLFxuICAgICAgICAgICAgICAgIG1vdXNlRXZlbnQub2Zmc2V0WVxuICAgICAgICAgICAgKTtcbiAgICAgICAgY29uc3QgZGVsdGEgPVxuICAgICAgICAgICAgdGhpcy5tb3VzZUNvbnRyb2xsZXIuY29vcmRpbmF0ZUNvbnZlcnRlci5ub3JtYWxpemVBbmRRdWFudGl6ZVNpZ25lZChcbiAgICAgICAgICAgICAgICBtb3VzZUV2ZW50Lm1vdmVtZW50WCxcbiAgICAgICAgICAgICAgICBtb3VzZUV2ZW50Lm1vdmVtZW50WVxuICAgICAgICAgICAgKTtcbiAgICAgICAgY29uc3QgdG9TdHJlYW1lckhhbmRsZXJzID1cbiAgICAgICAgICAgIHRoaXMubW91c2VDb250cm9sbGVyLnRvU3RyZWFtZXJNZXNzYWdlc1Byb3ZpZGVyLnRvU3RyZWFtZXJIYW5kbGVycztcbiAgICAgICAgdG9TdHJlYW1lckhhbmRsZXJzLmdldCgnTW91c2VNb3ZlJykoW1xuICAgICAgICAgICAgY29vcmQueCxcbiAgICAgICAgICAgIGNvb3JkLnksXG4gICAgICAgICAgICBkZWx0YS54LFxuICAgICAgICAgICAgZGVsdGEueVxuICAgICAgICBdKTtcbiAgICAgICAgbW91c2VFdmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZSB0aGUgbW91c2UgRG93biBldmVudCwgc2VuZHMgdGhlIG1vdXNlIGRhdGEgdG8gdGhlIFVFIEluc3RhbmNlXG4gICAgICogQHBhcmFtIG1vdXNlRXZlbnQgLSBNb3VzZSBFdmVudFxuICAgICAqL1xuICAgIGhhbmRsZU1vdXNlRG93bihtb3VzZUV2ZW50OiBNb3VzZUV2ZW50KSB7XG4gICAgICAgIGlmICghdGhpcy5tb3VzZUNvbnRyb2xsZXIudmlkZW9FbGVtZW50UHJvdmlkZXIuaXNWaWRlb1JlYWR5KCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBMb2dnZXIuTG9nKExvZ2dlci5HZXRTdGFja1RyYWNlKCksICdvbk1vdXNlIERvd24nLCA2KTtcbiAgICAgICAgY29uc3QgY29vcmQgPVxuICAgICAgICAgICAgdGhpcy5tb3VzZUNvbnRyb2xsZXIuY29vcmRpbmF0ZUNvbnZlcnRlci5ub3JtYWxpemVBbmRRdWFudGl6ZVVuc2lnbmVkKFxuICAgICAgICAgICAgICAgIG1vdXNlRXZlbnQub2Zmc2V0WCxcbiAgICAgICAgICAgICAgICBtb3VzZUV2ZW50Lm9mZnNldFlcbiAgICAgICAgICAgICk7XG4gICAgICAgIGNvbnN0IHRvU3RyZWFtZXJIYW5kbGVycyA9XG4gICAgICAgICAgICB0aGlzLm1vdXNlQ29udHJvbGxlci50b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlci50b1N0cmVhbWVySGFuZGxlcnM7XG4gICAgICAgIHRvU3RyZWFtZXJIYW5kbGVycy5nZXQoJ01vdXNlRG93bicpKFtcbiAgICAgICAgICAgIG1vdXNlRXZlbnQuYnV0dG9uLFxuICAgICAgICAgICAgY29vcmQueCxcbiAgICAgICAgICAgIGNvb3JkLnlcbiAgICAgICAgXSk7XG4gICAgICAgIG1vdXNlRXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGUgdGhlIG1vdXNlIFVwIGV2ZW50LCBzZW5kcyB0aGUgbW91c2UgZGF0YSB0byB0aGUgVUUgSW5zdGFuY2VcbiAgICAgKiBAcGFyYW0gbW91c2VFdmVudCAtIE1vdXNlIEV2ZW50XG4gICAgICovXG4gICAgaGFuZGxlTW91c2VVcChtb3VzZUV2ZW50OiBNb3VzZUV2ZW50KSB7XG4gICAgICAgIGlmICghdGhpcy5tb3VzZUNvbnRyb2xsZXIudmlkZW9FbGVtZW50UHJvdmlkZXIuaXNWaWRlb1JlYWR5KCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBMb2dnZXIuTG9nKExvZ2dlci5HZXRTdGFja1RyYWNlKCksICdvbk1vdXNlIFVwJywgNik7XG4gICAgICAgIGNvbnN0IGNvb3JkID1cbiAgICAgICAgICAgIHRoaXMubW91c2VDb250cm9sbGVyLmNvb3JkaW5hdGVDb252ZXJ0ZXIubm9ybWFsaXplQW5kUXVhbnRpemVVbnNpZ25lZChcbiAgICAgICAgICAgICAgICBtb3VzZUV2ZW50Lm9mZnNldFgsXG4gICAgICAgICAgICAgICAgbW91c2VFdmVudC5vZmZzZXRZXG4gICAgICAgICAgICApO1xuICAgICAgICBjb25zdCB0b1N0cmVhbWVySGFuZGxlcnMgPVxuICAgICAgICAgICAgdGhpcy5tb3VzZUNvbnRyb2xsZXIudG9TdHJlYW1lck1lc3NhZ2VzUHJvdmlkZXIudG9TdHJlYW1lckhhbmRsZXJzO1xuICAgICAgICB0b1N0cmVhbWVySGFuZGxlcnMuZ2V0KCdNb3VzZVVwJykoW1xuICAgICAgICAgICAgbW91c2VFdmVudC5idXR0b24sXG4gICAgICAgICAgICBjb29yZC54LFxuICAgICAgICAgICAgY29vcmQueVxuICAgICAgICBdKTtcbiAgICAgICAgbW91c2VFdmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnN1bWVzIHRoZSBtb3VzZSBjb250ZXh0IGV2ZW50LiBUaGUgVUUgaW5zdGFuY2UgaGFzIG5vIGVxdWl2YWxlbnQgYW5kIGRvZXNuJ3QgbmVlZCB0byBiZSBpbmZvcm1lZC5cbiAgICAgKiBAcGFyYW0gbW91c2VFdmVudCAtIE1vdXNlIEV2ZW50XG4gICAgICovXG4gICAgaGFuZGxlQ29udGV4dE1lbnUobW91c2VFdmVudDogTW91c2VFdmVudCkge1xuICAgICAgICBpZiAoIXRoaXMubW91c2VDb250cm9sbGVyLnZpZGVvRWxlbWVudFByb3ZpZGVyLmlzVmlkZW9SZWFkeSgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgbW91c2VFdmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZSB0aGUgbW91c2Ugd2hlZWwgZXZlbnQsIHNlbmRzIHRoZSBtb3VzZSB3aGVlbCBkYXRhIHRvIHRoZSBVRSBJbnN0YW5jZVxuICAgICAqIEBwYXJhbSB3aGVlbEV2ZW50IC0gTW91c2UgRXZlbnRcbiAgICAgKi9cbiAgICBoYW5kbGVNb3VzZVdoZWVsKHdoZWVsRXZlbnQ6IFdoZWVsRXZlbnQpIHtcbiAgICAgICAgaWYgKCF0aGlzLm1vdXNlQ29udHJvbGxlci52aWRlb0VsZW1lbnRQcm92aWRlci5pc1ZpZGVvUmVhZHkoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGNvb3JkID1cbiAgICAgICAgICAgIHRoaXMubW91c2VDb250cm9sbGVyLmNvb3JkaW5hdGVDb252ZXJ0ZXIubm9ybWFsaXplQW5kUXVhbnRpemVVbnNpZ25lZChcbiAgICAgICAgICAgICAgICB3aGVlbEV2ZW50Lm9mZnNldFgsXG4gICAgICAgICAgICAgICAgd2hlZWxFdmVudC5vZmZzZXRZXG4gICAgICAgICAgICApO1xuICAgICAgICBjb25zdCB0b1N0cmVhbWVySGFuZGxlcnMgPVxuICAgICAgICAgICAgdGhpcy5tb3VzZUNvbnRyb2xsZXIudG9TdHJlYW1lck1lc3NhZ2VzUHJvdmlkZXIudG9TdHJlYW1lckhhbmRsZXJzO1xuICAgICAgICB0b1N0cmVhbWVySGFuZGxlcnMuZ2V0KCdNb3VzZVdoZWVsJykoW1xuICAgICAgICAgICAgd2hlZWxFdmVudC53aGVlbERlbHRhLFxuICAgICAgICAgICAgY29vcmQueCxcbiAgICAgICAgICAgIGNvb3JkLnlcbiAgICAgICAgXSk7XG4gICAgICAgIHdoZWVsRXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGUgdGhlIG1vdXNlIGRvdWJsZSBjbGljayBldmVudCwgc2VuZHMgdGhlIG1vdXNlIGRhdGEgdG8gdGhlIFVFIEluc3RhbmNlXG4gICAgICogQHBhcmFtIG1vdXNlRXZlbnQgLSBNb3VzZSBFdmVudFxuICAgICAqL1xuICAgIGhhbmRsZU1vdXNlRG91YmxlKG1vdXNlRXZlbnQ6IE1vdXNlRXZlbnQpIHtcbiAgICAgICAgaWYgKCF0aGlzLm1vdXNlQ29udHJvbGxlci52aWRlb0VsZW1lbnRQcm92aWRlci5pc1ZpZGVvUmVhZHkoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGNvb3JkID1cbiAgICAgICAgICAgIHRoaXMubW91c2VDb250cm9sbGVyLmNvb3JkaW5hdGVDb252ZXJ0ZXIubm9ybWFsaXplQW5kUXVhbnRpemVVbnNpZ25lZChcbiAgICAgICAgICAgICAgICBtb3VzZUV2ZW50Lm9mZnNldFgsXG4gICAgICAgICAgICAgICAgbW91c2VFdmVudC5vZmZzZXRZXG4gICAgICAgICAgICApO1xuICAgICAgICBjb25zdCB0b1N0cmVhbWVySGFuZGxlcnMgPVxuICAgICAgICAgICAgdGhpcy5tb3VzZUNvbnRyb2xsZXIudG9TdHJlYW1lck1lc3NhZ2VzUHJvdmlkZXIudG9TdHJlYW1lckhhbmRsZXJzO1xuICAgICAgICB0b1N0cmVhbWVySGFuZGxlcnMuZ2V0KCdNb3VzZURvdWJsZScpKFtcbiAgICAgICAgICAgIG1vdXNlRXZlbnQuYnV0dG9uLFxuICAgICAgICAgICAgY29vcmQueCxcbiAgICAgICAgICAgIGNvb3JkLnlcbiAgICAgICAgXSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlIHRoZSBwcmVzcyBtb3VzZSBidXR0b25zIGV2ZW50LCBzZW5kcyB0aGUgbW91c2UgZGF0YSB0byB0aGUgVUUgSW5zdGFuY2VcbiAgICAgKiBAcGFyYW0gbW91c2VFdmVudCAtIE1vdXNlIEV2ZW50XG4gICAgICovXG4gICAgaGFuZGxlUHJlc3NNb3VzZUJ1dHRvbnMobW91c2VFdmVudDogTW91c2VFdmVudCkge1xuICAgICAgICBpZiAoIXRoaXMubW91c2VDb250cm9sbGVyLnZpZGVvRWxlbWVudFByb3ZpZGVyLmlzVmlkZW9SZWFkeSgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgTG9nZ2VyLkxvZyhMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLCAnb25Nb3VzZSBwcmVzcycsIDYpO1xuICAgICAgICB0aGlzLm1vdXNlQ29udHJvbGxlci5wcmVzc01vdXNlQnV0dG9ucyhcbiAgICAgICAgICAgIG1vdXNlRXZlbnQuYnV0dG9ucyxcbiAgICAgICAgICAgIG1vdXNlRXZlbnQub2Zmc2V0WCxcbiAgICAgICAgICAgIG1vdXNlRXZlbnQub2Zmc2V0WVxuICAgICAgICApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZSB0aGUgcmVsZWFzZSBtb3VzZSBidXR0b25zIGV2ZW50LCBzZW5kcyB0aGUgbW91c2UgZGF0YSB0byB0aGUgVUUgSW5zdGFuY2VcbiAgICAgKiBAcGFyYW0gbW91c2VFdmVudCAtIE1vdXNlIEV2ZW50XG4gICAgICovXG4gICAgaGFuZGxlUmVsZWFzZU1vdXNlQnV0dG9ucyhtb3VzZUV2ZW50OiBNb3VzZUV2ZW50KSB7XG4gICAgICAgIGlmICghdGhpcy5tb3VzZUNvbnRyb2xsZXIudmlkZW9FbGVtZW50UHJvdmlkZXIuaXNWaWRlb1JlYWR5KCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBMb2dnZXIuTG9nKExvZ2dlci5HZXRTdGFja1RyYWNlKCksICdvbk1vdXNlIHJlbGVhc2UnLCA2KTtcbiAgICAgICAgdGhpcy5tb3VzZUNvbnRyb2xsZXIucmVsZWFzZU1vdXNlQnV0dG9ucyhcbiAgICAgICAgICAgIG1vdXNlRXZlbnQuYnV0dG9ucyxcbiAgICAgICAgICAgIG1vdXNlRXZlbnQub2Zmc2V0WCxcbiAgICAgICAgICAgIG1vdXNlRXZlbnQub2Zmc2V0WVxuICAgICAgICApO1xuICAgIH1cbn1cbiIsIi8vIENvcHlyaWdodCBFcGljIEdhbWVzLCBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG5cbmltcG9ydCB7IEZha2VUb3VjaENvbnRyb2xsZXIgfSBmcm9tICcuL0Zha2VUb3VjaENvbnRyb2xsZXInO1xuaW1wb3J0IHsgS2V5Ym9hcmRDb250cm9sbGVyIH0gZnJvbSAnLi9LZXlib2FyZENvbnRyb2xsZXInO1xuaW1wb3J0IHsgTW91c2VDb250cm9sbGVyIH0gZnJvbSAnLi9Nb3VzZUNvbnRyb2xsZXInO1xuaW1wb3J0IHsgVG91Y2hDb250cm9sbGVyIH0gZnJvbSAnLi9Ub3VjaENvbnRyb2xsZXInO1xuaW1wb3J0IHsgR2FtZVBhZENvbnRyb2xsZXIgfSBmcm9tICcuL0dhbWVwYWRDb250cm9sbGVyJztcbmltcG9ydCB7IENvbmZpZywgQ29udHJvbFNjaGVtZVR5cGUgfSBmcm9tICcuLi9Db25maWcvQ29uZmlnJztcbmltcG9ydCB7IExvZ2dlciB9IGZyb20gJy4uL0xvZ2dlci9Mb2dnZXInO1xuaW1wb3J0IHsgQ29vcmRpbmF0ZUNvbnZlcnRlciB9IGZyb20gJy4uL1V0aWwvQ29vcmRpbmF0ZUNvbnZlcnRlcic7XG5pbXBvcnQgeyBTdHJlYW1NZXNzYWdlQ29udHJvbGxlciB9IGZyb20gJy4uL1VlSW5zdGFuY2VNZXNzYWdlL1N0cmVhbU1lc3NhZ2VDb250cm9sbGVyJztcbmltcG9ydCB7IFZpZGVvUGxheWVyIH0gZnJvbSAnLi4vVmlkZW9QbGF5ZXIvVmlkZW9QbGF5ZXInO1xuXG4vKipcbiAqIENsYXNzIGZvciBtYWtpbmcgYW5kIHNldHRpbmcgdXAgaW5wdXQgY2xhc3MgdHlwZXNcbiAqL1xuZXhwb3J0IGNsYXNzIElucHV0Q2xhc3Nlc0ZhY3Rvcnkge1xuICAgIHRvU3RyZWFtZXJNZXNzYWdlc1Byb3ZpZGVyOiBTdHJlYW1NZXNzYWdlQ29udHJvbGxlcjtcbiAgICB2aWRlb0VsZW1lbnRQcm92aWRlcjogVmlkZW9QbGF5ZXI7XG4gICAgY29vcmRpbmF0ZUNvbnZlcnRlcjogQ29vcmRpbmF0ZUNvbnZlcnRlcjtcbiAgICBhY3RpdmVLZXlzOiBBY3RpdmVLZXlzID0gbmV3IEFjdGl2ZUtleXMoKTtcblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB0b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlciAtIFN0cmVhbSBtZXNzYWdlIGluc3RhbmNlXG4gICAgICogQHBhcmFtIHZpZGVvRWxlbWVudFByb3ZpZGVyIC0gVmlkZW8gUGxheWVyIGluc3RhbmNlXG4gICAgICogQHBhcmFtIGNvb3JkaW5hdGVDb252ZXJ0ZXIgLSBBIGNvb3JkaW5hdGVDb252ZXJ0ZXIgaW5zdGFuY2VcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgdG9TdHJlYW1lck1lc3NhZ2VzUHJvdmlkZXI6IFN0cmVhbU1lc3NhZ2VDb250cm9sbGVyLFxuICAgICAgICB2aWRlb0VsZW1lbnRQcm92aWRlcjogVmlkZW9QbGF5ZXIsXG4gICAgICAgIGNvb3JkaW5hdGVDb252ZXJ0ZXI6IENvb3JkaW5hdGVDb252ZXJ0ZXJcbiAgICApIHtcbiAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlciA9IHRvU3RyZWFtZXJNZXNzYWdlc1Byb3ZpZGVyO1xuICAgICAgICB0aGlzLnZpZGVvRWxlbWVudFByb3ZpZGVyID0gdmlkZW9FbGVtZW50UHJvdmlkZXI7XG4gICAgICAgIHRoaXMuY29vcmRpbmF0ZUNvbnZlcnRlciA9IGNvb3JkaW5hdGVDb252ZXJ0ZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVnaXN0ZXJzIGJyb3dzZXIga2V5IGV2ZW50cy5cbiAgICAgKi9cbiAgICByZWdpc3RlcktleUJvYXJkKGNvbmZpZzogQ29uZmlnKSB7XG4gICAgICAgIExvZ2dlci5Mb2coTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSwgJ1JlZ2lzdGVyIEtleWJvYXJkIEV2ZW50cycsIDcpO1xuICAgICAgICBjb25zdCBrZXlib2FyZENvbnRyb2xsZXIgPSBuZXcgS2V5Ym9hcmRDb250cm9sbGVyKFxuICAgICAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlcixcbiAgICAgICAgICAgIGNvbmZpZyxcbiAgICAgICAgICAgIHRoaXMuYWN0aXZlS2V5c1xuICAgICAgICApO1xuICAgICAgICBrZXlib2FyZENvbnRyb2xsZXIucmVnaXN0ZXJLZXlCb2FyZEV2ZW50cygpO1xuICAgICAgICByZXR1cm4ga2V5Ym9hcmRDb250cm9sbGVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIHJlZ2lzdGVyIG1vdXNlIGV2ZW50cyBiYXNlZCBvbiBhIGNvbnRyb2wgdHlwZVxuICAgICAqIEBwYXJhbSBjb250cm9sU2NoZW1lIC0gaWYgdGhlIG1vdXNlIGlzIGVpdGhlciBob3ZlcmluZyBvciBsb2NrZWRcbiAgICAgKi9cbiAgICByZWdpc3Rlck1vdXNlKGNvbnRyb2xTY2hlbWU6IENvbnRyb2xTY2hlbWVUeXBlKSB7XG4gICAgICAgIExvZ2dlci5Mb2coTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSwgJ1JlZ2lzdGVyIE1vdXNlIEV2ZW50cycsIDcpO1xuICAgICAgICBjb25zdCBtb3VzZUNvbnRyb2xsZXIgPSBuZXcgTW91c2VDb250cm9sbGVyKFxuICAgICAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlcixcbiAgICAgICAgICAgIHRoaXMudmlkZW9FbGVtZW50UHJvdmlkZXIsXG4gICAgICAgICAgICB0aGlzLmNvb3JkaW5hdGVDb252ZXJ0ZXIsXG4gICAgICAgICAgICB0aGlzLmFjdGl2ZUtleXNcbiAgICAgICAgKTtcblxuICAgICAgICBzd2l0Y2ggKGNvbnRyb2xTY2hlbWUpIHtcbiAgICAgICAgICAgIGNhc2UgQ29udHJvbFNjaGVtZVR5cGUuTG9ja2VkTW91c2U6XG4gICAgICAgICAgICAgICAgbW91c2VDb250cm9sbGVyLnJlZ2lzdGVyTG9ja2VkTW91c2VFdmVudHMobW91c2VDb250cm9sbGVyKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgQ29udHJvbFNjaGVtZVR5cGUuSG92ZXJpbmdNb3VzZTpcbiAgICAgICAgICAgICAgICBtb3VzZUNvbnRyb2xsZXIucmVnaXN0ZXJIb3ZlcmluZ01vdXNlRXZlbnRzKG1vdXNlQ29udHJvbGxlcik7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIExvZ2dlci5JbmZvKFxuICAgICAgICAgICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgICAgICAgICAndW5rbm93biBDb250cm9sIFNjaGVtZSBUeXBlIERlZmF1bHRpbmcgdG8gTG9ja2VkIE1vdXNlIEV2ZW50cydcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIG1vdXNlQ29udHJvbGxlci5yZWdpc3RlckxvY2tlZE1vdXNlRXZlbnRzKG1vdXNlQ29udHJvbGxlcik7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbW91c2VDb250cm9sbGVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIHJlZ2lzdGVyIHRvdWNoIGV2ZW50c1xuICAgICAqIEBwYXJhbSBmYWtlTW91c2VUb3VjaCAtIHRoZSBmYWtlZCBtb3VzZSB0b3VjaCBldmVudFxuICAgICAqL1xuICAgIHJlZ2lzdGVyVG91Y2goXG4gICAgICAgIGZha2VNb3VzZVRvdWNoOiBib29sZWFuLFxuICAgICAgICB2aWRlb0VsZW1lbnRQYXJlbnRDbGllbnRSZWN0OiBET01SZWN0XG4gICAgKSB7XG4gICAgICAgIExvZ2dlci5Mb2coTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSwgJ1JlZ2lzdGVyaW5nIFRvdWNoJywgNik7XG4gICAgICAgIGlmIChmYWtlTW91c2VUb3VjaCkge1xuICAgICAgICAgICAgY29uc3QgZmFrZVRvdWNoQ29udHJvbGxlciA9IG5ldyBGYWtlVG91Y2hDb250cm9sbGVyKFxuICAgICAgICAgICAgICAgIHRoaXMudG9TdHJlYW1lck1lc3NhZ2VzUHJvdmlkZXIsXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb0VsZW1lbnRQcm92aWRlcixcbiAgICAgICAgICAgICAgICB0aGlzLmNvb3JkaW5hdGVDb252ZXJ0ZXJcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBmYWtlVG91Y2hDb250cm9sbGVyLnNldFZpZGVvRWxlbWVudFBhcmVudENsaWVudFJlY3QoXG4gICAgICAgICAgICAgICAgdmlkZW9FbGVtZW50UGFyZW50Q2xpZW50UmVjdFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJldHVybiBmYWtlVG91Y2hDb250cm9sbGVyO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBUb3VjaENvbnRyb2xsZXIoXG4gICAgICAgICAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlcixcbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvRWxlbWVudFByb3ZpZGVyLFxuICAgICAgICAgICAgICAgIHRoaXMuY29vcmRpbmF0ZUNvbnZlcnRlclxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIHJlZ2lzdGVycyBhIGdhbWVwYWRcbiAgICAgKi9cbiAgICByZWdpc3RlckdhbWVQYWQoKSB7XG4gICAgICAgIExvZ2dlci5Mb2coTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSwgJ1JlZ2lzdGVyIEdhbWUgUGFkJywgNyk7XG4gICAgICAgIGNvbnN0IGdhbWVQYWRDb250cm9sbGVyID0gbmV3IEdhbWVQYWRDb250cm9sbGVyKFxuICAgICAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlclxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gZ2FtZVBhZENvbnRyb2xsZXI7XG4gICAgfVxufVxuXG4vKipcbiAqIEEgY2xhc3MgdGhhdCBrZWVwcyB0cmFjayBvZiBjdXJyZW50IGFjdGl2ZSBrZXlzXG4gKi9cbmV4cG9ydCBjbGFzcyBBY3RpdmVLZXlzIHtcbiAgICBhY3RpdmVLZXlzOiBBcnJheTxudW1iZXI+ID0gW107XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMuYWN0aXZlS2V5cyA9IFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgY3VycmVudCBhcnJheSBvZiBhY3RpdmUga2V5c1xuICAgICAqIEByZXR1cm5zIC0gYW4gYXJyYXkgb2YgYWN0aXZlIGtleXNcbiAgICAgKi9cbiAgICBnZXRBY3RpdmVLZXlzKCk6IG51bWJlcltdIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYWN0aXZlS2V5cztcbiAgICB9XG59XG4iLCIvLyBDb3B5cmlnaHQgRXBpYyBHYW1lcywgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuXG5pbXBvcnQgeyBTcGVjaWFsS2V5Q29kZXMgfSBmcm9tICcuL1NwZWNpYWxLZXlDb2Rlcyc7XG5pbXBvcnQgeyBMb2dnZXIgfSBmcm9tICcuLi9Mb2dnZXIvTG9nZ2VyJztcbmltcG9ydCB7IEFjdGl2ZUtleXMgfSBmcm9tICcuL0lucHV0Q2xhc3Nlc0ZhY3RvcnknO1xuaW1wb3J0IHsgU3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIgfSBmcm9tICcuLi9VZUluc3RhbmNlTWVzc2FnZS9TdHJlYW1NZXNzYWdlQ29udHJvbGxlcic7XG5pbXBvcnQgeyBDb25maWcsIEZsYWdzIH0gZnJvbSAnLi4vQ29uZmlnL0NvbmZpZyc7XG5pbXBvcnQgeyBFdmVudExpc3RlbmVyVHJhY2tlciB9IGZyb20gJy4uL1V0aWwvRXZlbnRMaXN0ZW5lclRyYWNrZXInO1xuXG5pbnRlcmZhY2UgSUNvZGVUb0tleUNvZGUge1xuICAgIFtrZXk6IHN0cmluZ106IG51bWJlcjtcbn1cblxuLyoqXG4gKiBIYW5kbGVzIHRoZSBLZXlib2FyZCBJbnB1dHMgZm9yIHRoZSBkb2N1bWVudFxuICovXG5leHBvcnQgY2xhc3MgS2V5Ym9hcmRDb250cm9sbGVyIHtcbiAgICB0b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlcjogU3RyZWFtTWVzc2FnZUNvbnRyb2xsZXI7XG4gICAgYWN0aXZlS2V5c1Byb3ZpZGVyOiBBY3RpdmVLZXlzO1xuICAgIGNvbmZpZzogQ29uZmlnO1xuXG4gICAgLy8gVXRpbGl0eSBmb3Iga2VlcGluZyB0cmFjayBvZiBldmVudCBoYW5kbGVycyBhbmQgdW5yZWdpc3RlcmluZyB0aGVtXG4gICAgcHJpdmF0ZSBrZXlib2FyZEV2ZW50TGlzdGVuZXJUcmFja2VyID0gbmV3IEV2ZW50TGlzdGVuZXJUcmFja2VyKCk7XG5cbiAgICAvKlxuICAgICAqIE5ldyBicm93c2VyIEFQSXMgaGF2ZSBtb3ZlZCBhd2F5IGZyb20gS2V5Ym9hcmRFdmVudC5rZXlDb2RlIHRvIEtleWJvYXJkRXZlbnQuQ29kZS5cbiAgICAgKiBGb3IgZGV0YWlscyBzZWU6IGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9LZXlib2FyZEV2ZW50L2tleUNvZGUjY29uc3RhbnRzX2Zvcl9rZXljb2RlX3ZhbHVlXG4gICAgICogV2Ugc3RpbGwgdXNlIG9sZCBLZXlib2FyZEV2ZW50LmtleUNvZGUgaW50ZWdlcnMgaW4gdGhlIFVFIEMrKyBzaWRlLCBzbyB3ZSBuZWVkIGEgd2F5IHRvIG1hcCB0aGUgbmV3XG4gICAgICogc3RyaW5nLWJhc2VkIEtleWJvYXJkRXZlbnQuQ29kZSB0byB0aGUgb2xkIGludGVnZXJzLlxuICAgICAqL1xuICAgIENvZGVUb0tleUNvZGU6IElDb2RlVG9LZXlDb2RlID0ge1xuICAgICAgICBFc2NhcGU6IDI3LFxuICAgICAgICBEaWdpdDA6IDQ4LFxuICAgICAgICBEaWdpdDE6IDQ5LFxuICAgICAgICBEaWdpdDI6IDUwLFxuICAgICAgICBEaWdpdDM6IDUxLFxuICAgICAgICBEaWdpdDQ6IDUyLFxuICAgICAgICBEaWdpdDU6IDUzLFxuICAgICAgICBEaWdpdDY6IDU0LFxuICAgICAgICBEaWdpdDc6IDU1LFxuICAgICAgICBEaWdpdDg6IDU2LFxuICAgICAgICBEaWdpdDk6IDU3LFxuICAgICAgICBNaW51czogMTczLFxuICAgICAgICBFcXVhbDogMTg3LFxuICAgICAgICBCYWNrc3BhY2U6IDgsXG4gICAgICAgIFRhYjogOSxcbiAgICAgICAgS2V5UTogODEsXG4gICAgICAgIEtleVc6IDg3LFxuICAgICAgICBLZXlFOiA2OSxcbiAgICAgICAgS2V5UjogODIsXG4gICAgICAgIEtleVQ6IDg0LFxuICAgICAgICBLZXlZOiA4OSxcbiAgICAgICAgS2V5VTogODUsXG4gICAgICAgIEtleUk6IDczLFxuICAgICAgICBLZXlPOiA3OSxcbiAgICAgICAgS2V5UDogODAsXG4gICAgICAgIEJyYWNrZXRMZWZ0OiAyMTksXG4gICAgICAgIEJyYWNrZXRSaWdodDogMjIxLFxuICAgICAgICBFbnRlcjogMTMsXG4gICAgICAgIENvbnRyb2xMZWZ0OiAxNyxcbiAgICAgICAgS2V5QTogNjUsXG4gICAgICAgIEtleVM6IDgzLFxuICAgICAgICBLZXlEOiA2OCxcbiAgICAgICAgS2V5RjogNzAsXG4gICAgICAgIEtleUc6IDcxLFxuICAgICAgICBLZXlIOiA3MixcbiAgICAgICAgS2V5SjogNzQsXG4gICAgICAgIEtleUs6IDc1LFxuICAgICAgICBLZXlMOiA3NixcbiAgICAgICAgU2VtaWNvbG9uOiAxODYsXG4gICAgICAgIFF1b3RlOiAyMjIsXG4gICAgICAgIEJhY2txdW90ZTogMTkyLFxuICAgICAgICBTaGlmdExlZnQ6IDE2LFxuICAgICAgICBCYWNrc2xhc2g6IDIyMCxcbiAgICAgICAgS2V5WjogOTAsXG4gICAgICAgIEtleVg6IDg4LFxuICAgICAgICBLZXlDOiA2NyxcbiAgICAgICAgS2V5VjogODYsXG4gICAgICAgIEtleUI6IDY2LFxuICAgICAgICBLZXlOOiA3OCxcbiAgICAgICAgS2V5TTogNzcsXG4gICAgICAgIENvbW1hOiAxODgsXG4gICAgICAgIFBlcmlvZDogMTkwLFxuICAgICAgICBTbGFzaDogMTkxLFxuICAgICAgICBTaGlmdFJpZ2h0OiAyNTMsXG4gICAgICAgIEFsdExlZnQ6IDE4LFxuICAgICAgICBTcGFjZTogMzIsXG4gICAgICAgIENhcHNMb2NrOiAyMCxcbiAgICAgICAgRjE6IDExMixcbiAgICAgICAgRjI6IDExMyxcbiAgICAgICAgRjM6IDExNCxcbiAgICAgICAgRjQ6IDExNSxcbiAgICAgICAgRjU6IDExNixcbiAgICAgICAgRjY6IDExNyxcbiAgICAgICAgRjc6IDExOCxcbiAgICAgICAgRjg6IDExOSxcbiAgICAgICAgRjk6IDEyMCxcbiAgICAgICAgRjEwOiAxMjEsXG4gICAgICAgIEYxMTogMTIyLFxuICAgICAgICBGMTI6IDEyMyxcbiAgICAgICAgUGF1c2U6IDE5LFxuICAgICAgICBTY3JvbGxMb2NrOiAxNDUsXG4gICAgICAgIE51bXBhZERpdmlkZTogMTExLFxuICAgICAgICBOdW1wYWRNdWx0aXBseTogMTA2LFxuICAgICAgICBOdW1wYWRTdWJ0cmFjdDogMTA5LFxuICAgICAgICBOdW1wYWRBZGQ6IDEwNyxcbiAgICAgICAgTnVtcGFkRGVjaW1hbDogMTEwLFxuICAgICAgICBOdW1wYWQ5OiAxMDUsXG4gICAgICAgIE51bXBhZDg6IDEwNCxcbiAgICAgICAgTnVtcGFkNzogMTAzLFxuICAgICAgICBOdW1wYWQ2OiAxMDIsXG4gICAgICAgIE51bXBhZDU6IDEwMSxcbiAgICAgICAgTnVtcGFkNDogMTAwLFxuICAgICAgICBOdW1wYWQzOiA5OSxcbiAgICAgICAgTnVtcGFkMjogOTgsXG4gICAgICAgIE51bXBhZDE6IDk3LFxuICAgICAgICBOdW1wYWQwOiA5NixcbiAgICAgICAgTnVtTG9jazogMTQ0LFxuICAgICAgICBDb250cm9sUmlnaHQ6IDI1NCxcbiAgICAgICAgQWx0UmlnaHQ6IDI1NSxcbiAgICAgICAgSG9tZTogMzYsXG4gICAgICAgIEVuZDogMzUsXG4gICAgICAgIEFycm93VXA6IDM4LFxuICAgICAgICBBcnJvd0xlZnQ6IDM3LFxuICAgICAgICBBcnJvd1JpZ2h0OiAzOSxcbiAgICAgICAgQXJyb3dEb3duOiA0MCxcbiAgICAgICAgUGFnZVVwOiAzMyxcbiAgICAgICAgUGFnZURvd246IDM0LFxuICAgICAgICBJbnNlcnQ6IDQ1LFxuICAgICAgICBEZWxldGU6IDQ2LFxuICAgICAgICBDb250ZXh0TWVudTogOTNcbiAgICB9O1xuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIHRvU3RyZWFtZXJNZXNzYWdlc1Byb3ZpZGVyIFN0cmVhbSBtZXNzYWdlIHByb3ZpZGVyIGNsYXNzIG9iamVjdFxuICAgICAqIEBwYXJhbSBjb25maWcgVGhlIGFwcGxpY2F0aW9ucyBjb25maWd1cmF0aW9uLiBXZSdyZSBpbnRlcmVzdGVkIGluIHRoZSBzdXBwcmVzcyBicm93c2VyIGtleXMgb3B0aW9uXG4gICAgICogQHBhcmFtIGFjdGl2ZUtleXNQcm92aWRlciBBY3RpdmUga2V5cyBwcm92aWRlciBjbGFzcyBvYmplY3RcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgdG9TdHJlYW1lck1lc3NhZ2VzUHJvdmlkZXI6IFN0cmVhbU1lc3NhZ2VDb250cm9sbGVyLFxuICAgICAgICBjb25maWc6IENvbmZpZyxcbiAgICAgICAgYWN0aXZlS2V5c1Byb3ZpZGVyOiBBY3RpdmVLZXlzXG4gICAgKSB7XG4gICAgICAgIHRoaXMudG9TdHJlYW1lck1lc3NhZ2VzUHJvdmlkZXIgPSB0b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlcjtcbiAgICAgICAgdGhpcy5jb25maWcgPSBjb25maWc7XG4gICAgICAgIHRoaXMuYWN0aXZlS2V5c1Byb3ZpZGVyID0gYWN0aXZlS2V5c1Byb3ZpZGVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlZ2lzdGVycyBkb2N1bWVudCBrZXlib2FyZCBldmVudHMgd2l0aCB0aGUgY29udHJvbGxlclxuICAgICAqL1xuICAgIHJlZ2lzdGVyS2V5Qm9hcmRFdmVudHMoKSB7XG4gICAgICAgIGNvbnN0IGtleURvd25IYW5kbGVyID0gKGV2OiBLZXlib2FyZEV2ZW50KSA9PiB0aGlzLmhhbmRsZU9uS2V5RG93bihldik7XG4gICAgICAgIGNvbnN0IGtleVVwSGFuZGxlciA9IChldjogS2V5Ym9hcmRFdmVudCkgPT4gdGhpcy5oYW5kbGVPbktleVVwKGV2KTtcbiAgICAgICAgY29uc3Qga2V5UHJlc3NIYW5kbGVyID0gKGV2OiBLZXlib2FyZEV2ZW50KSA9PiB0aGlzLmhhbmRsZU9uS2V5UHJlc3MoZXYpO1xuXG4gICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoXCJrZXlkb3duXCIsIGtleURvd25IYW5kbGVyKTtcbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihcImtleXVwXCIsIGtleVVwSGFuZGxlcik7XG5cbiAgICAgICAgLy9UaGlzIGhhcyBiZWVuIGRlcHJlY2F0ZWQgYXMgYXQgSnVuIDEzIDIwMjFcbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcihcImtleXByZXNzXCIsIGtleVByZXNzSGFuZGxlcik7XG5cbiAgICAgICAgdGhpcy5rZXlib2FyZEV2ZW50TGlzdGVuZXJUcmFja2VyLmFkZFVucmVnaXN0ZXJDYWxsYmFjayhcbiAgICAgICAgICAgICgpID0+IGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJrZXlkb3duXCIsIGtleURvd25IYW5kbGVyKVxuICAgICAgICApO1xuICAgICAgICB0aGlzLmtleWJvYXJkRXZlbnRMaXN0ZW5lclRyYWNrZXIuYWRkVW5yZWdpc3RlckNhbGxiYWNrKFxuICAgICAgICAgICAgKCkgPT4gZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihcImtleXVwXCIsIGtleVVwSGFuZGxlcilcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5rZXlib2FyZEV2ZW50TGlzdGVuZXJUcmFja2VyLmFkZFVucmVnaXN0ZXJDYWxsYmFjayhcbiAgICAgICAgICAgICgpID0+IGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJrZXlwcmVzc1wiLCBrZXlQcmVzc0hhbmRsZXIpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVW5yZWdpc3RlcnMgZG9jdW1lbnQga2V5Ym9hcmQgZXZlbnRzXG4gICAgICovXG4gICAgdW5yZWdpc3RlcktleUJvYXJkRXZlbnRzKCkge1xuICAgICAgICB0aGlzLmtleWJvYXJkRXZlbnRMaXN0ZW5lclRyYWNrZXIudW5yZWdpc3RlckFsbCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXMgV2hlbiBhIGtleSBpcyBkb3duXG4gICAgICogQHBhcmFtIGtleWJvYXJkRXZlbnQgLSBLZXlib2FyZCBldmVudFxuICAgICAqL1xuICAgIGhhbmRsZU9uS2V5RG93bihrZXlib2FyZEV2ZW50OiBLZXlib2FyZEV2ZW50KSB7XG4gICAgICAgIGNvbnN0IGtleUNvZGUgPSB0aGlzLmdldEtleWNvZGUoa2V5Ym9hcmRFdmVudCk7XG4gICAgICAgIGlmICgha2V5Q29kZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgTG9nZ2VyLkxvZyhcbiAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICBga2V5IGRvd24gJHtrZXlDb2RlfSwgcmVwZWF0ID0gJHtrZXlib2FyZEV2ZW50LnJlcGVhdH1gLFxuICAgICAgICAgICAgNlxuICAgICAgICApO1xuICAgICAgICBjb25zdCB0b1N0cmVhbWVySGFuZGxlcnMgPVxuICAgICAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlci50b1N0cmVhbWVySGFuZGxlcnM7XG4gICAgICAgIHRvU3RyZWFtZXJIYW5kbGVycy5nZXQoJ0tleURvd24nKShbXG4gICAgICAgICAgICB0aGlzLmdldEtleWNvZGUoa2V5Ym9hcmRFdmVudCksXG4gICAgICAgICAgICBrZXlib2FyZEV2ZW50LnJlcGVhdCA/IDEgOiAwXG4gICAgICAgIF0pO1xuICAgICAgICBjb25zdCBhY3RpdmVLZXlzID0gdGhpcy5hY3RpdmVLZXlzUHJvdmlkZXIuZ2V0QWN0aXZlS2V5cygpO1xuICAgICAgICBhY3RpdmVLZXlzLnB1c2goa2V5Q29kZSk7XG4gICAgICAgIC8vIEJhY2tzcGFjZSBpcyBub3QgY29uc2lkZXJlZCBhIGtleXByZXNzIGluIEphdmFTY3JpcHQgYnV0IHdlIG5lZWQgaXRcbiAgICAgICAgLy8gdG8gYmUgc28gY2hhcmFjdGVycyBtYXkgYmUgZGVsZXRlZCBpbiBhIFVFIHRleHQgZW50cnkgZmllbGQuXG4gICAgICAgIGlmIChrZXlDb2RlID09PSBTcGVjaWFsS2V5Q29kZXMuYmFja1NwYWNlKSB7XG4gICAgICAgICAgICBkb2N1bWVudC5kaXNwYXRjaEV2ZW50KFxuICAgICAgICAgICAgICAgIG5ldyBLZXlib2FyZEV2ZW50KCdrZXlwcmVzcycsIHtcbiAgICAgICAgICAgICAgICAgICAgY2hhckNvZGU6IFNwZWNpYWxLZXlDb2Rlcy5iYWNrU3BhY2VcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLmlzRmxhZ0VuYWJsZWQoRmxhZ3MuU3VwcHJlc3NCcm93c2VyS2V5cykgJiZcbiAgICAgICAgICAgIHRoaXMuaXNLZXlDb2RlQnJvd3NlcktleShrZXlDb2RlKVxuICAgICAgICApIHtcbiAgICAgICAgICAgIGtleWJvYXJkRXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIGhhbmRsZXMgd2hlbiBhIGtleSBpcyB1cFxuICAgICAqIEBwYXJhbSBrZXlib2FyZEV2ZW50IC0gS2V5Ym9hcmQgZXZlbnRcbiAgICAgKi9cbiAgICBoYW5kbGVPbktleVVwKGtleWJvYXJkRXZlbnQ6IEtleWJvYXJkRXZlbnQpIHtcbiAgICAgICAgY29uc3Qga2V5Q29kZSA9IHRoaXMuZ2V0S2V5Y29kZShrZXlib2FyZEV2ZW50KTtcbiAgICAgICAgaWYgKCFrZXlDb2RlKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBMb2dnZXIuTG9nKExvZ2dlci5HZXRTdGFja1RyYWNlKCksIGBrZXkgdXAgJHtrZXlDb2RlfWAsIDYpO1xuICAgICAgICBjb25zdCB0b1N0cmVhbWVySGFuZGxlcnMgPVxuICAgICAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlci50b1N0cmVhbWVySGFuZGxlcnM7XG4gICAgICAgIHRvU3RyZWFtZXJIYW5kbGVycy5nZXQoJ0tleVVwJykoWyBrZXlDb2RlIF0pO1xuXG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLmlzRmxhZ0VuYWJsZWQoRmxhZ3MuU3VwcHJlc3NCcm93c2VyS2V5cykgJiZcbiAgICAgICAgICAgIHRoaXMuaXNLZXlDb2RlQnJvd3NlcktleShrZXlDb2RlKVxuICAgICAgICApIHtcbiAgICAgICAgICAgIGtleWJvYXJkRXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXMgd2hlbiBhIGtleSBpcyBwcmVzc1xuICAgICAqIEBwYXJhbSBrZXlib2FyZCAtIEtleWJvYXJkIEV2ZW50XG4gICAgICovXG4gICAgaGFuZGxlT25LZXlQcmVzcyhrZXlib2FyZDogS2V5Ym9hcmRFdmVudCkge1xuICAgICAgICBpZiAoISgnY2hhckNvZGUnIGluIGtleWJvYXJkKSkge1xuICAgICAgICAgICAgTG9nZ2VyLldhcm5pbmcoXG4gICAgICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICAgICAnS2V5Ym9hcmRFdmVudC5jaGFyQ29kZSBpcyBkZXByZWNhdGVkIGluIHRoaXMgYnJvd3NlciwgY2Fubm90IHNlbmQga2V5IHByZXNzLidcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjaGFyQ29kZSA9IGtleWJvYXJkLmNoYXJDb2RlO1xuICAgICAgICBMb2dnZXIuTG9nKExvZ2dlci5HZXRTdGFja1RyYWNlKCksIGBrZXkgcHJlc3MgJHtjaGFyQ29kZX1gLCA2KTtcblxuICAgICAgICBjb25zdCB0b1N0cmVhbWVySGFuZGxlcnMgPVxuICAgICAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlci50b1N0cmVhbWVySGFuZGxlcnM7XG4gICAgICAgIHRvU3RyZWFtZXJIYW5kbGVycy5nZXQoJ0tleVByZXNzJykoW2NoYXJDb2RlXSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0cyB0aGUgS2V5Y29kZSBvZiB0aGUgS2V5IHByZXNzZWRcbiAgICAgKiBAcGFyYW0ga2V5Ym9hcmRFdmVudCAtIEtleSBib2FyZCBFdmVudFxuICAgICAqIEByZXR1cm5zIC0gdGhlIGtleSBjb2RlIG9mIHRoZSBLZXlcbiAgICAgKi9cbiAgICBnZXRLZXljb2RlKGtleWJvYXJkRXZlbnQ6IEtleWJvYXJkRXZlbnQpIHtcbiAgICAgICAgLy8gSWYgd2UgZG9uJ3QgaGF2ZSBrZXlDb2RlIHByb3BlcnR5IGJlY2F1c2UgYnJvd3NlciBBUEkgaXMgZGVwcmVjYXRlZCB0aGVuIHVzZSBLZXlib2FyZEV2ZW50LmNvZGUgaW5zdGVhZC5cbiAgICAgICAgLy8gU2VlOiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvS2V5Ym9hcmRFdmVudC9rZXlDb2RlI2NvbnN0YW50c19mb3Jfa2V5Y29kZV92YWx1ZVxuICAgICAgICBpZiAoISgna2V5Q29kZScgaW4ga2V5Ym9hcmRFdmVudCkpIHtcbiAgICAgICAgICAgIC8vIENvbnZlcnQgS2V5Ym9hcmRFdmVudC5jb2RlIHN0cmluZyBpbnRvIGludGVnZXItYmFzZWQga2V5IGNvZGUgZm9yIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5IHJlYXNvbnMuXG4gICAgICAgICAgICBjb25zdCBldmVudCA9IGtleWJvYXJkRXZlbnQgYXMgS2V5Ym9hcmRFdmVudDtcbiAgICAgICAgICAgIGlmIChldmVudC5jb2RlIGluIHRoaXMuQ29kZVRvS2V5Q29kZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLkNvZGVUb0tleUNvZGVbZXZlbnQuY29kZV07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIExvZ2dlci5XYXJuaW5nKFxuICAgICAgICAgICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgICAgICAgICBgS2V5Ym9hcmQgY29kZSBvZiAke2V2ZW50LmNvZGV9IGlzIG5vdCBzdXBwb3J0ZWQgaW4gb3VyIG1hcHBpbmcsIGlnbm9yaW5nIHRoaXMga2V5LmBcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gSWYgd2UgbWFkZSBpdCBoZXJlIEtleWJvYXJkRXZlbnQua2V5Q29kZSBpcyBzdGlsbCBzdXBwb3J0ZWQgc28gd2UgY2FuIHNhZmVseSB1c2UgaXQuXG5cbiAgICAgICAgaWYgKFxuICAgICAgICAgICAga2V5Ym9hcmRFdmVudC5rZXlDb2RlID09PSBTcGVjaWFsS2V5Q29kZXMuc2hpZnQgJiZcbiAgICAgICAgICAgIGtleWJvYXJkRXZlbnQuY29kZSA9PT0gJ1NoaWZ0UmlnaHQnXG4gICAgICAgICkge1xuICAgICAgICAgICAgcmV0dXJuIFNwZWNpYWxLZXlDb2Rlcy5yaWdodFNoaWZ0O1xuICAgICAgICB9IGVsc2UgaWYgKFxuICAgICAgICAgICAga2V5Ym9hcmRFdmVudC5rZXlDb2RlID09PSBTcGVjaWFsS2V5Q29kZXMuY29udHJvbCAmJlxuICAgICAgICAgICAga2V5Ym9hcmRFdmVudC5jb2RlID09PSAnQ29udHJvbFJpZ2h0J1xuICAgICAgICApIHtcbiAgICAgICAgICAgIHJldHVybiBTcGVjaWFsS2V5Q29kZXMucmlnaHRDb250cm9sO1xuICAgICAgICB9IGVsc2UgaWYgKFxuICAgICAgICAgICAga2V5Ym9hcmRFdmVudC5rZXlDb2RlID09PSBTcGVjaWFsS2V5Q29kZXMuYWx0ICYmXG4gICAgICAgICAgICBrZXlib2FyZEV2ZW50LmNvZGUgPT09ICdBbHRSaWdodCdcbiAgICAgICAgKSB7XG4gICAgICAgICAgICByZXR1cm4gU3BlY2lhbEtleUNvZGVzLnJpZ2h0QWx0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGtleWJvYXJkRXZlbnQua2V5Q29kZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEJyb3dzZXIga2V5cyBkbyBub3QgaGF2ZSBhIGNoYXJDb2RlIHNvIHdlIG9ubHkgbmVlZCB0byB0ZXN0IGtleUNvZGUuXG4gICAgICogQHBhcmFtIGtleUNvZGUgLSB0aGUgYnJvd3NlciBrZXljb2RlIG51bWJlclxuICAgICAqL1xuICAgIGlzS2V5Q29kZUJyb3dzZXJLZXkoa2V5Q29kZTogbnVtYmVyKSB7XG4gICAgICAgIC8vIEZ1bmN0aW9uIGtleXMgb3IgdGFiIGtleSBhcmUgY29uc2lkZXJlZCBcImJyb3dzZXIga2V5c1wiIHRoYXQgd2UgbWF5IHdpc2ggdG8gc3VwcHJlc3MgYnkgcHJldmVudGluZyB0aGVtIGJlaW5nIHByb2Nlc3MgYnkgYnJvd3Nlci5cbiAgICAgICAgcmV0dXJuIChrZXlDb2RlID49IDExMiAmJiBrZXlDb2RlIDw9IDEyMykgfHwga2V5Q29kZSA9PT0gOTtcbiAgICB9XG59XG4iLCIvLyBDb3B5cmlnaHQgRXBpYyBHYW1lcywgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuXG5pbXBvcnQgeyBNb3VzZUNvbnRyb2xsZXIgfSBmcm9tICcuL01vdXNlQ29udHJvbGxlcic7XG5pbXBvcnQgeyBMb2dnZXIgfSBmcm9tICcuLi9Mb2dnZXIvTG9nZ2VyJztcbmltcG9ydCB7IElNb3VzZUV2ZW50cyB9IGZyb20gJy4vSU1vdXNlRXZlbnRzJztcbmltcG9ydCB7IE5vcm1hbGl6ZWRRdWFudGl6ZWRVbnNpZ25lZENvb3JkIH0gZnJvbSAnLi4vVXRpbC9Db29yZGluYXRlQ29udmVydGVyJztcbmltcG9ydCB7IEFjdGl2ZUtleXMgfSBmcm9tICcuL0lucHV0Q2xhc3Nlc0ZhY3RvcnknO1xuaW1wb3J0IHsgVmlkZW9QbGF5ZXIgfSBmcm9tICcuLi9WaWRlb1BsYXllci9WaWRlb1BsYXllcic7XG5pbXBvcnQgeyBFdmVudExpc3RlbmVyVHJhY2tlciB9IGZyb20gJy4uL1V0aWwvRXZlbnRMaXN0ZW5lclRyYWNrZXInO1xuXG4vKipcbiAqIEhhbmRsZSB0aGUgbW91c2UgbG9ja2VkIGV2ZW50c1xuICovXG5leHBvcnQgY2xhc3MgTG9ja2VkTW91c2VFdmVudHMgaW1wbGVtZW50cyBJTW91c2VFdmVudHMge1xuICAgIHggPSAwO1xuICAgIHkgPSAwO1xuICAgIGNvb3JkOiBOb3JtYWxpemVkUXVhbnRpemVkVW5zaWduZWRDb29yZDtcbiAgICB2aWRlb0VsZW1lbnRQcm92aWRlcjogVmlkZW9QbGF5ZXI7XG4gICAgbW91c2VDb250cm9sbGVyOiBNb3VzZUNvbnRyb2xsZXI7XG4gICAgYWN0aXZlS2V5c1Byb3ZpZGVyOiBBY3RpdmVLZXlzO1xuICAgIHVwZGF0ZU1vdXNlTW92ZVBvc2l0aW9uRXZlbnQgPSAobW91c2VFdmVudDogTW91c2VFdmVudCkgPT4ge1xuICAgICAgICB0aGlzLnVwZGF0ZU1vdXNlTW92ZVBvc2l0aW9uKG1vdXNlRXZlbnQpO1xuICAgIH07XG5cbiAgICAvLyBVdGlsaXR5IGZvciBrZWVwaW5nIHRyYWNrIG9mIGV2ZW50IGhhbmRsZXJzIGFuZCB1bnJlZ2lzdGVyaW5nIHRoZW1cbiAgICBwcml2YXRlIG1vdXNlRXZlbnRMaXN0ZW5lclRyYWNrZXIgPSBuZXcgRXZlbnRMaXN0ZW5lclRyYWNrZXIoKTtcblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB2aWRlb0VsZW1lbnRQcm92aWRlciAtIFZpZGVvIFBsYXllciBpbnN0YW5jZVxuICAgICAqIEBwYXJhbSBtb3VzZUNvbnRyb2xsZXIgLSBNb3VzZSBjb250cm9sbGVyIGluc3RhbmNlXG4gICAgICogQHBhcmFtIGFjdGl2ZUtleXNQcm92aWRlciAtIEFjdGl2ZSBrZXlzIHByb3ZpZGVyIGluc3RhbmNlXG4gICAgICogQHBhcmFtIHBsYXllclN0eWxlQXR0cmlidXRlc1Byb3ZpZGVyIC0gUGxheWVyIHN0eWxlIGF0dHJpYnV0ZXMgaW5zdGFuY2VcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgdmlkZW9FbGVtZW50UHJvdmlkZXI6IFZpZGVvUGxheWVyLFxuICAgICAgICBtb3VzZUNvbnRyb2xsZXI6IE1vdXNlQ29udHJvbGxlcixcbiAgICAgICAgYWN0aXZlS2V5c1Byb3ZpZGVyOiBBY3RpdmVLZXlzXG4gICAgKSB7XG4gICAgICAgIHRoaXMudmlkZW9FbGVtZW50UHJvdmlkZXIgPSB2aWRlb0VsZW1lbnRQcm92aWRlcjtcbiAgICAgICAgdGhpcy5tb3VzZUNvbnRyb2xsZXIgPSBtb3VzZUNvbnRyb2xsZXI7XG4gICAgICAgIHRoaXMuYWN0aXZlS2V5c1Byb3ZpZGVyID0gYWN0aXZlS2V5c1Byb3ZpZGVyO1xuICAgICAgICBjb25zdCB2aWRlb0VsZW1lbnRQYXJlbnQgPVxuICAgICAgICAgICAgdGhpcy52aWRlb0VsZW1lbnRQcm92aWRlci5nZXRWaWRlb1BhcmVudEVsZW1lbnQoKTtcbiAgICAgICAgdGhpcy54ID0gdmlkZW9FbGVtZW50UGFyZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLndpZHRoIC8gMjtcbiAgICAgICAgdGhpcy55ID0gdmlkZW9FbGVtZW50UGFyZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmhlaWdodCAvIDI7XG4gICAgICAgIHRoaXMuY29vcmQgPVxuICAgICAgICAgICAgdGhpcy5tb3VzZUNvbnRyb2xsZXIuY29vcmRpbmF0ZUNvbnZlcnRlci5ub3JtYWxpemVBbmRRdWFudGl6ZVVuc2lnbmVkKFxuICAgICAgICAgICAgICAgIHRoaXMueCxcbiAgICAgICAgICAgICAgICB0aGlzLnlcbiAgICAgICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVW5yZWdpc3RlcnMgYWxsIGV2ZW50IGhhbmRsZXJzXG4gICAgICovXG4gICAgdW5yZWdpc3Rlck1vdXNlRXZlbnRzKCkge1xuICAgICAgICB0aGlzLm1vdXNlRXZlbnRMaXN0ZW5lclRyYWNrZXIudW5yZWdpc3RlckFsbCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZSB3aGVuIHRoZSBsb2NrZWQgc3RhdGUgQ2hhbmdlZFxuICAgICAqL1xuICAgIGxvY2tTdGF0ZUNoYW5nZSgpIHtcbiAgICAgICAgY29uc3QgdmlkZW9FbGVtZW50UGFyZW50ID1cbiAgICAgICAgICAgIHRoaXMudmlkZW9FbGVtZW50UHJvdmlkZXIuZ2V0VmlkZW9QYXJlbnRFbGVtZW50KCk7XG4gICAgICAgIGNvbnN0IHRvU3RyZWFtZXJIYW5kbGVycyA9XG4gICAgICAgICAgICB0aGlzLm1vdXNlQ29udHJvbGxlci50b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlci50b1N0cmVhbWVySGFuZGxlcnM7XG5cbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgZG9jdW1lbnQucG9pbnRlckxvY2tFbGVtZW50ID09PSB2aWRlb0VsZW1lbnRQYXJlbnQgfHxcbiAgICAgICAgICAgIGRvY3VtZW50Lm1velBvaW50ZXJMb2NrRWxlbWVudCA9PT0gdmlkZW9FbGVtZW50UGFyZW50XG4gICAgICAgICkge1xuICAgICAgICAgICAgTG9nZ2VyLkxvZyhMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLCAnUG9pbnRlciBsb2NrZWQnLCA2KTtcbiAgICAgICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoXG4gICAgICAgICAgICAgICAgJ21vdXNlbW92ZScsXG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGVNb3VzZU1vdmVQb3NpdGlvbkV2ZW50LFxuICAgICAgICAgICAgICAgIGZhbHNlXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgdGhpcy5tb3VzZUV2ZW50TGlzdGVuZXJUcmFja2VyLmFkZFVucmVnaXN0ZXJDYWxsYmFjayhcbiAgICAgICAgICAgICAgICAoKSA9PiBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKFxuICAgICAgICAgICAgICAgICAgICAnbW91c2Vtb3ZlJyxcbiAgICAgICAgICAgICAgICAgICAgdGhpcy51cGRhdGVNb3VzZU1vdmVQb3NpdGlvbkV2ZW50LFxuICAgICAgICAgICAgICAgICAgICBmYWxzZVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBMb2dnZXIuTG9nKFxuICAgICAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAgICAgJ1RoZSBwb2ludGVyIGxvY2sgc3RhdHVzIGlzIG5vdyB1bmxvY2tlZCcsXG4gICAgICAgICAgICAgICAgNlxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIC8vICFhIG5ldyBhcnJvdyBmdW5jdGlvbiBtdXN0IG5vdCBiZSB1c2VkIGhlcmUgYXMgaXQgd2lsbCBiZSBjb3VudGVkIGFzIGEgbmV3IGZ1bmN0aW9uIHRoYXQgY2Fubm90IGJlIHJlbW92ZWRcbiAgICAgICAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoXG4gICAgICAgICAgICAgICAgJ21vdXNlbW92ZScsXG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGVNb3VzZU1vdmVQb3NpdGlvbkV2ZW50LFxuICAgICAgICAgICAgICAgIGZhbHNlXG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAvLyBJZiBtb3VzZSBsb3NlcyBmb2N1cywgc2VuZCBhIGtleSB1cCBmb3IgYWxsIG9mIHRoZSBjdXJyZW50bHkgaGVsZC1kb3duIGtleXNcbiAgICAgICAgICAgIC8vIFRoaXMgaXMgbmVjZXNzYXJ5IGFzIHdoZW4gdGhlIG1vdXNlIGxvc2VzIGZvY3VzLCB0aGUgd2luZG93cyBzdG9wcyBsaXN0ZW5pbmcgZm9yIGV2ZW50cyBhbmQgYXMgc3VjaFxuICAgICAgICAgICAgLy8gdGhlIGtleXVwIGxpc3RlbmVyIHdvbid0IGdldCBmaXJlZFxuICAgICAgICAgICAgbGV0IGFjdGl2ZUtleXMgPSB0aGlzLmFjdGl2ZUtleXNQcm92aWRlci5nZXRBY3RpdmVLZXlzKCk7XG4gICAgICAgICAgICBjb25zdCBzZXRLZXlzID0gbmV3IFNldChhY3RpdmVLZXlzKTtcbiAgICAgICAgICAgIGNvbnN0IG5ld0tleXNJdGVyYWJsZTogQXJyYXk8bnVtYmVyPiA9IFtdO1xuXG4gICAgICAgICAgICBzZXRLZXlzLmZvckVhY2goKHNldEtleTogbnVtYmVyKSA9PiB7XG4gICAgICAgICAgICAgICAgbmV3S2V5c0l0ZXJhYmxlW3NldEtleV07XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgbmV3S2V5c0l0ZXJhYmxlLmZvckVhY2goKHVuaXF1ZUtleWNvZGUpID0+IHtcbiAgICAgICAgICAgICAgICB0b1N0cmVhbWVySGFuZGxlcnMuZ2V0KCdLZXlVcCcpKFt1bmlxdWVLZXljb2RlXSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIC8vIFJlc2V0IHRoZSBhY3RpdmUga2V5cyBiYWNrIHRvIG5vdGhpbmdcbiAgICAgICAgICAgIGFjdGl2ZUtleXMgPSBbXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZSB0aGUgbW91c2UgbW92ZSBldmVudCwgc2VuZHMgdGhlIG1vdXNlIGRhdGEgdG8gdGhlIFVFIEluc3RhbmNlXG4gICAgICogQHBhcmFtIG1vdXNlRXZlbnQgLSBNb3VzZSBFdmVudFxuICAgICAqL1xuICAgIHVwZGF0ZU1vdXNlTW92ZVBvc2l0aW9uKG1vdXNlRXZlbnQ6IE1vdXNlRXZlbnQpIHtcbiAgICAgICAgaWYgKCF0aGlzLnZpZGVvRWxlbWVudFByb3ZpZGVyLmlzVmlkZW9SZWFkeSgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgdG9TdHJlYW1lckhhbmRsZXJzID1cbiAgICAgICAgICAgIHRoaXMubW91c2VDb250cm9sbGVyLnRvU3RyZWFtZXJNZXNzYWdlc1Byb3ZpZGVyLnRvU3RyZWFtZXJIYW5kbGVycztcbiAgICAgICAgY29uc3Qgc3R5bGVXaWR0aCA9XG4gICAgICAgICAgICB0aGlzLnZpZGVvRWxlbWVudFByb3ZpZGVyLmdldFZpZGVvUGFyZW50RWxlbWVudCgpLmNsaWVudFdpZHRoO1xuICAgICAgICBjb25zdCBzdHlsZUhlaWdodCA9XG4gICAgICAgICAgICB0aGlzLnZpZGVvRWxlbWVudFByb3ZpZGVyLmdldFZpZGVvUGFyZW50RWxlbWVudCgpLmNsaWVudEhlaWdodDtcblxuICAgICAgICB0aGlzLnggKz0gbW91c2VFdmVudC5tb3ZlbWVudFg7XG4gICAgICAgIHRoaXMueSArPSBtb3VzZUV2ZW50Lm1vdmVtZW50WTtcblxuICAgICAgICBpZiAodGhpcy54ID4gc3R5bGVXaWR0aCkge1xuICAgICAgICAgICAgdGhpcy54IC09IHN0eWxlV2lkdGg7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMueSA+IHN0eWxlSGVpZ2h0KSB7XG4gICAgICAgICAgICB0aGlzLnkgLT0gc3R5bGVIZWlnaHQ7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMueCA8IDApIHtcbiAgICAgICAgICAgIHRoaXMueCA9IHN0eWxlV2lkdGggKyB0aGlzLng7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMueSA8IDApIHtcbiAgICAgICAgICAgIHRoaXMueSA9IHN0eWxlSGVpZ2h0IC0gdGhpcy55O1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5jb29yZCA9XG4gICAgICAgICAgICB0aGlzLm1vdXNlQ29udHJvbGxlci5jb29yZGluYXRlQ29udmVydGVyLm5vcm1hbGl6ZUFuZFF1YW50aXplVW5zaWduZWQoXG4gICAgICAgICAgICAgICAgdGhpcy54LFxuICAgICAgICAgICAgICAgIHRoaXMueVxuICAgICAgICAgICAgKTtcbiAgICAgICAgY29uc3QgZGVsdGEgPVxuICAgICAgICAgICAgdGhpcy5tb3VzZUNvbnRyb2xsZXIuY29vcmRpbmF0ZUNvbnZlcnRlci5ub3JtYWxpemVBbmRRdWFudGl6ZVNpZ25lZChcbiAgICAgICAgICAgICAgICBtb3VzZUV2ZW50Lm1vdmVtZW50WCxcbiAgICAgICAgICAgICAgICBtb3VzZUV2ZW50Lm1vdmVtZW50WVxuICAgICAgICAgICAgKTtcbiAgICAgICAgdG9TdHJlYW1lckhhbmRsZXJzLmdldCgnTW91c2VNb3ZlJykoW1xuICAgICAgICAgICAgdGhpcy5jb29yZC54LFxuICAgICAgICAgICAgdGhpcy5jb29yZC55LFxuICAgICAgICAgICAgZGVsdGEueCxcbiAgICAgICAgICAgIGRlbHRhLnlcbiAgICAgICAgXSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlIHRoZSBtb3VzZSBEb3duIGV2ZW50LCBzZW5kcyB0aGUgbW91c2UgZGF0YSB0byB0aGUgVUUgSW5zdGFuY2VcbiAgICAgKiBAcGFyYW0gbW91c2VFdmVudCAtIE1vdXNlIEV2ZW50XG4gICAgICovXG4gICAgaGFuZGxlTW91c2VEb3duKG1vdXNlRXZlbnQ6IE1vdXNlRXZlbnQpIHtcbiAgICAgICAgaWYgKCF0aGlzLnZpZGVvRWxlbWVudFByb3ZpZGVyLmlzVmlkZW9SZWFkeSgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB0b1N0cmVhbWVySGFuZGxlcnMgPVxuICAgICAgICAgICAgdGhpcy5tb3VzZUNvbnRyb2xsZXIudG9TdHJlYW1lck1lc3NhZ2VzUHJvdmlkZXIudG9TdHJlYW1lckhhbmRsZXJzO1xuICAgICAgICB0b1N0cmVhbWVySGFuZGxlcnMuZ2V0KCdNb3VzZURvd24nKShbXG4gICAgICAgICAgICBtb3VzZUV2ZW50LmJ1dHRvbixcbiAgICAgICAgICAgIC8vIFdlIHVzZSB0aGUgc3RvcmUgdmFsdWUgb2YgdGhpcy5jb29yZCBhcyBvcHBvc2VkIHRvIHRoZSBtb3VzZUV2ZW50LngveSBhcyB0aGUgbW91c2VFdmVudCBsb2NhdGlvblxuICAgICAgICAgICAgLy8gdXNlcyB0aGUgc3lzdGVtIGN1cnNvciBsb2NhdGlvbiB3aGljaCBoYXNuJ3QgbW92ZWRcbiAgICAgICAgICAgIHRoaXMuY29vcmQueCxcbiAgICAgICAgICAgIHRoaXMuY29vcmQueVxuICAgICAgICBdKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGUgdGhlIG1vdXNlIFVwIGV2ZW50LCBzZW5kcyB0aGUgbW91c2UgZGF0YSB0byB0aGUgVUUgSW5zdGFuY2VcbiAgICAgKiBAcGFyYW0gbW91c2VFdmVudCAtIE1vdXNlIEV2ZW50XG4gICAgICovXG4gICAgaGFuZGxlTW91c2VVcChtb3VzZUV2ZW50OiBNb3VzZUV2ZW50KSB7XG4gICAgICAgIGlmICghdGhpcy52aWRlb0VsZW1lbnRQcm92aWRlci5pc1ZpZGVvUmVhZHkoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHRvU3RyZWFtZXJIYW5kbGVycyA9XG4gICAgICAgICAgICB0aGlzLm1vdXNlQ29udHJvbGxlci50b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlci50b1N0cmVhbWVySGFuZGxlcnM7XG4gICAgICAgIHRvU3RyZWFtZXJIYW5kbGVycy5nZXQoJ01vdXNlVXAnKShbXG4gICAgICAgICAgICBtb3VzZUV2ZW50LmJ1dHRvbixcbiAgICAgICAgICAgIC8vIFdlIHVzZSB0aGUgc3RvcmUgdmFsdWUgb2YgdGhpcy5jb29yZCBhcyBvcHBvc2VkIHRvIHRoZSBtb3VzZUV2ZW50LngveSBhcyB0aGUgbW91c2VFdmVudCBsb2NhdGlvblxuICAgICAgICAgICAgLy8gdXNlcyB0aGUgc3lzdGVtIGN1cnNvciBsb2NhdGlvbiB3aGljaCBoYXNuJ3QgbW92ZWRcbiAgICAgICAgICAgIHRoaXMuY29vcmQueCxcbiAgICAgICAgICAgIHRoaXMuY29vcmQueVxuICAgICAgICBdKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGUgdGhlIG1vdXNlIHdoZWVsIGV2ZW50LCBzZW5kcyB0aGUgbW91c2Ugd2hlZWwgZGF0YSB0byB0aGUgVUUgSW5zdGFuY2VcbiAgICAgKiBAcGFyYW0gd2hlZWxFdmVudCAtIE1vdXNlIEV2ZW50XG4gICAgICovXG4gICAgaGFuZGxlTW91c2VXaGVlbCh3aGVlbEV2ZW50OiBXaGVlbEV2ZW50KSB7XG4gICAgICAgIGlmICghdGhpcy52aWRlb0VsZW1lbnRQcm92aWRlci5pc1ZpZGVvUmVhZHkoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHRvU3RyZWFtZXJIYW5kbGVycyA9XG4gICAgICAgICAgICB0aGlzLm1vdXNlQ29udHJvbGxlci50b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlci50b1N0cmVhbWVySGFuZGxlcnM7XG4gICAgICAgIHRvU3RyZWFtZXJIYW5kbGVycy5nZXQoJ01vdXNlV2hlZWwnKShbXG4gICAgICAgICAgICB3aGVlbEV2ZW50LndoZWVsRGVsdGEsXG4gICAgICAgICAgICAvLyBXZSB1c2UgdGhlIHN0b3JlIHZhbHVlIG9mIHRoaXMuY29vcmQgYXMgb3Bwb3NlZCB0byB0aGUgbW91c2VFdmVudC54L3kgYXMgdGhlIG1vdXNlRXZlbnQgbG9jYXRpb25cbiAgICAgICAgICAgIC8vIHVzZXMgdGhlIHN5c3RlbSBjdXJzb3IgbG9jYXRpb24gd2hpY2ggaGFzbid0IG1vdmVkXG4gICAgICAgICAgICB0aGlzLmNvb3JkLngsXG4gICAgICAgICAgICB0aGlzLmNvb3JkLnlcbiAgICAgICAgXSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlIHRoZSBtb3VzZSBkb3VibGUgY2xpY2sgZXZlbnQsIHNlbmRzIHRoZSBtb3VzZSBkYXRhIHRvIHRoZSBVRSBJbnN0YW5jZVxuICAgICAqIEBwYXJhbSBtb3VzZUV2ZW50IC0gTW91c2UgRXZlbnRcbiAgICAgKi9cbiAgICBoYW5kbGVNb3VzZURvdWJsZShtb3VzZUV2ZW50OiBNb3VzZUV2ZW50KSB7XG4gICAgICAgIGlmICghdGhpcy52aWRlb0VsZW1lbnRQcm92aWRlci5pc1ZpZGVvUmVhZHkoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHRvU3RyZWFtZXJIYW5kbGVycyA9XG4gICAgICAgICAgICB0aGlzLm1vdXNlQ29udHJvbGxlci50b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlci50b1N0cmVhbWVySGFuZGxlcnM7XG4gICAgICAgIHRvU3RyZWFtZXJIYW5kbGVycy5nZXQoJ01vdXNlRG91YmxlJykoW1xuICAgICAgICAgICAgbW91c2VFdmVudC5idXR0b24sXG4gICAgICAgICAgICAvLyBXZSB1c2UgdGhlIHN0b3JlIHZhbHVlIG9mIHRoaXMuY29vcmQgYXMgb3Bwb3NlZCB0byB0aGUgbW91c2VFdmVudC54L3kgYXMgdGhlIG1vdXNlRXZlbnQgbG9jYXRpb25cbiAgICAgICAgICAgIC8vIHVzZXMgdGhlIHN5c3RlbSBjdXJzb3IgbG9jYXRpb24gd2hpY2ggaGFzbid0IG1vdmVkXG4gICAgICAgICAgICB0aGlzLmNvb3JkLngsXG4gICAgICAgICAgICB0aGlzLmNvb3JkLnlcbiAgICAgICAgXSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlIHRoZSBwcmVzcyBtb3VzZSBidXR0b25zIGV2ZW50LCBzZW5kcyB0aGUgbW91c2UgZGF0YSB0byB0aGUgVUUgSW5zdGFuY2VcbiAgICAgKiBAcGFyYW0gbW91c2VFdmVudCAtIE1vdXNlIEV2ZW50XG4gICAgICovXG4gICAgaGFuZGxlUHJlc3NNb3VzZUJ1dHRvbnMobW91c2VFdmVudDogTW91c2VFdmVudCkge1xuICAgICAgICBpZiAoIXRoaXMudmlkZW9FbGVtZW50UHJvdmlkZXIuaXNWaWRlb1JlYWR5KCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLm1vdXNlQ29udHJvbGxlci5wcmVzc01vdXNlQnV0dG9ucyhcbiAgICAgICAgICAgIG1vdXNlRXZlbnQuYnV0dG9ucyxcbiAgICAgICAgICAgIHRoaXMueCxcbiAgICAgICAgICAgIHRoaXMueVxuICAgICAgICApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZSB0aGUgcmVsZWFzZSBtb3VzZSBidXR0b25zIGV2ZW50LCBzZW5kcyB0aGUgbW91c2UgZGF0YSB0byB0aGUgVUUgSW5zdGFuY2VcbiAgICAgKiBAcGFyYW0gbW91c2VFdmVudCAtIE1vdXNlIEV2ZW50XG4gICAgICovXG4gICAgaGFuZGxlUmVsZWFzZU1vdXNlQnV0dG9ucyhtb3VzZUV2ZW50OiBNb3VzZUV2ZW50KSB7XG4gICAgICAgIGlmICghdGhpcy52aWRlb0VsZW1lbnRQcm92aWRlci5pc1ZpZGVvUmVhZHkoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubW91c2VDb250cm9sbGVyLnJlbGVhc2VNb3VzZUJ1dHRvbnMoXG4gICAgICAgICAgICBtb3VzZUV2ZW50LmJ1dHRvbnMsXG4gICAgICAgICAgICB0aGlzLngsXG4gICAgICAgICAgICB0aGlzLnlcbiAgICAgICAgKTtcbiAgICB9XG59XG5cbi8qKlxuICogRXh0cmEgdHlwZXMgZm9yIERvY3VtZW50IGFuZCBXaGVlbEV2ZW50XG4gKi9cbmRlY2xhcmUgZ2xvYmFsIHtcbiAgICBpbnRlcmZhY2UgRG9jdW1lbnQge1xuICAgICAgICBtb3pQb2ludGVyTG9ja0VsZW1lbnQ6IHVua25vd247XG4gICAgICAgIG1vekV4aXRQb2ludGVyTG9jaz8oKTogdm9pZDtcbiAgICB9XG5cbiAgICBpbnRlcmZhY2UgV2hlZWxFdmVudCB7XG4gICAgICAgIHdoZWVsRGVsdGE6IG51bWJlcjtcbiAgICB9XG59XG4iLCIvLyBDb3B5cmlnaHQgRXBpYyBHYW1lcywgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuXG4vKipcbiAqIE1vdXNlIEJ1dHRvbiBEYXRhXG4gKiB7QGxpbmsgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL01vdXNlRXZlbnQvYnV0dG9ufVxuICovXG5leHBvcnQgY2xhc3MgTW91c2VCdXR0b24ge1xuICAgIHN0YXRpYyBtYWluQnV0dG9uID0gMDsgLy8gTGVmdCBidXR0b24uXG4gICAgc3RhdGljIGF1eGlsaWFyeUJ1dHRvbiA9IDE7IC8vIFdoZWVsIGJ1dHRvbi5cbiAgICBzdGF0aWMgc2Vjb25kYXJ5QnV0dG9uID0gMjsgLy8gUmlnaHQgYnV0dG9uLlxuICAgIHN0YXRpYyBmb3VydGhCdXR0b24gPSAzOyAvLyBCcm93c2VyIEJhY2sgYnV0dG9uLlxuICAgIHN0YXRpYyBmaWZ0aEJ1dHRvbiA9IDQ7IC8vIEJyb3dzZXIgRm9yd2FyZCBidXR0b24uXG59XG5cbi8qKlxuICogTW91c2UgQnV0dG9uIE1hc2sgRGF0YVxuICoge0BsaW5rIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9Nb3VzZUV2ZW50L2J1dHRvbnN9XG4gKi9cbmV4cG9ydCBjbGFzcyBNb3VzZUJ1dHRvbnNNYXNrIHtcbiAgICBzdGF0aWMgcHJpbWFyeUJ1dHRvbiA9IDE7IC8vIExlZnQgYnV0dG9uLlxuICAgIHN0YXRpYyBzZWNvbmRhcnlCdXR0b24gPSAyOyAvLyBSaWdodCBidXR0b24uXG4gICAgc3RhdGljIGF1eGlsaWFyeUJ1dHRvbiA9IDQ7IC8vIFdoZWVsIGJ1dHRvbi5cbiAgICBzdGF0aWMgZm91cnRoQnV0dG9uID0gODsgLy8gQnJvd3NlciBCYWNrIGJ1dHRvbi5cbiAgICBzdGF0aWMgZmlmdGhCdXR0b24gPSAxNjsgLy8gQnJvd3NlciBGb3J3YXJkIGJ1dHRvbi5cbn1cbiIsIi8vIENvcHlyaWdodCBFcGljIEdhbWVzLCBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG5cbmltcG9ydCB7IE1vdXNlQnV0dG9uc01hc2ssIE1vdXNlQnV0dG9uIH0gZnJvbSAnLi9Nb3VzZUJ1dHRvbnMnO1xuaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSAnLi4vTG9nZ2VyL0xvZ2dlcic7XG5pbXBvcnQgeyBTdHJlYW1NZXNzYWdlQ29udHJvbGxlciB9IGZyb20gJy4uL1VlSW5zdGFuY2VNZXNzYWdlL1N0cmVhbU1lc3NhZ2VDb250cm9sbGVyJztcbmltcG9ydCB7IENvb3JkaW5hdGVDb252ZXJ0ZXIgfSBmcm9tICcuLi9VdGlsL0Nvb3JkaW5hdGVDb252ZXJ0ZXInO1xuaW1wb3J0IHsgVmlkZW9QbGF5ZXIgfSBmcm9tICcuLi9WaWRlb1BsYXllci9WaWRlb1BsYXllcic7XG5pbXBvcnQgeyBJTW91c2VFdmVudHMgfSBmcm9tICcuL0lNb3VzZUV2ZW50cyc7XG5pbXBvcnQgeyBMb2NrZWRNb3VzZUV2ZW50cyB9IGZyb20gJy4vTG9ja2VkTW91c2VFdmVudHMnO1xuaW1wb3J0IHsgSG92ZXJpbmdNb3VzZUV2ZW50cyB9IGZyb20gJy4vSG92ZXJpbmdNb3VzZUV2ZW50cyc7XG5pbXBvcnQgdHlwZSB7IEFjdGl2ZUtleXMgfSBmcm9tICcuL0lucHV0Q2xhc3Nlc0ZhY3RvcnknO1xuaW1wb3J0IHsgRXZlbnRMaXN0ZW5lclRyYWNrZXIgfSBmcm9tICcuLi9VdGlsL0V2ZW50TGlzdGVuZXJUcmFja2VyJztcblxuLyoqXG4gKiBIYW5kbGVzIHRoZSBNb3VzZSBJbnB1dHMgZm9yIHRoZSBkb2N1bWVudFxuICovXG5leHBvcnQgY2xhc3MgTW91c2VDb250cm9sbGVyIHtcbiAgICB2aWRlb0VsZW1lbnRQcm92aWRlcjogVmlkZW9QbGF5ZXI7XG4gICAgdG9TdHJlYW1lck1lc3NhZ2VzUHJvdmlkZXI6IFN0cmVhbU1lc3NhZ2VDb250cm9sbGVyO1xuICAgIGNvb3JkaW5hdGVDb252ZXJ0ZXI6IENvb3JkaW5hdGVDb252ZXJ0ZXI7XG4gICAgYWN0aXZlS2V5c1Byb3ZpZGVyOiBBY3RpdmVLZXlzO1xuXG4gICAgLy8gVXRpbGl0eSBmb3Iga2VlcGluZyB0cmFjayBvZiBldmVudCBoYW5kbGVycyBhbmQgdW5yZWdpc3RlcmluZyB0aGVtXG4gICAgcHJpdmF0ZSBtb3VzZUV2ZW50TGlzdGVuZXJUcmFja2VyID0gbmV3IEV2ZW50TGlzdGVuZXJUcmFja2VyKCk7XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gdG9TdHJlYW1lck1lc3NhZ2VzUHJvdmlkZXIgLSBTdHJlYW0gbWVzc2FnZSBpbnN0YW5jZVxuICAgICAqIEBwYXJhbSB2aWRlb0VsZW1lbnRQcm92aWRlciAtIFZpZGVvIFBsYXllciBpbnN0YW5jZVxuICAgICAqIEBwYXJhbSBub3JtYWxpemVBbmRRdWFudGl6ZSAtIEEgbm9ybWFsaXplIGFuZCBxdWFudGl6ZSBpbnN0YW5jZVxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICB0b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlcjogU3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIsXG4gICAgICAgIHZpZGVvRWxlbWVudFByb3ZpZGVyOiBWaWRlb1BsYXllcixcbiAgICAgICAgY29vcmRpbmF0ZUNvbnZlcnRlcjogQ29vcmRpbmF0ZUNvbnZlcnRlcixcbiAgICAgICAgYWN0aXZlS2V5c1Byb3ZpZGVyOiBBY3RpdmVLZXlzXG4gICAgKSB7XG4gICAgICAgIHRoaXMudG9TdHJlYW1lck1lc3NhZ2VzUHJvdmlkZXIgPSB0b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlcjtcbiAgICAgICAgdGhpcy5jb29yZGluYXRlQ29udmVydGVyID0gY29vcmRpbmF0ZUNvbnZlcnRlcjtcbiAgICAgICAgdGhpcy52aWRlb0VsZW1lbnRQcm92aWRlciA9IHZpZGVvRWxlbWVudFByb3ZpZGVyO1xuICAgICAgICB0aGlzLmFjdGl2ZUtleXNQcm92aWRlciA9IGFjdGl2ZUtleXNQcm92aWRlcjtcbiAgICAgICAgdGhpcy5yZWdpc3Rlck1vdXNlRW50ZXJBbmRMZWF2ZUV2ZW50cygpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENsZWFycyBhbGwgdGhlIGNsaWNrIGV2ZW50cyBvbiB0aGUgY3VycmVudCB2aWRlbyBlbGVtZW50IHBhcmVudCBkaXZcbiAgICAgKi9cbiAgICB1bnJlZ2lzdGVyTW91c2VFdmVudHMoKSB7XG4gICAgICAgIHRoaXMubW91c2VFdmVudExpc3RlbmVyVHJhY2tlci51bnJlZ2lzdGVyQWxsKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVnaXN0ZXIgYSBsb2NrZWQgbW91c2UgY2xhc3NcbiAgICAgKiBAcGFyYW0gbW91c2VDb250cm9sbGVyIC0gYSBtb3VzZSBjb250cm9sbGVyIGluc3RhbmNlXG4gICAgICogQHBhcmFtIHBsYXllclN0eWxlQXR0cmlidXRlc1Byb3ZpZGVyIC0gYSBwbGF5ZXIgc3R5bGUgYXR0cmlidXRlcyBpbnN0YW5jZVxuICAgICAqL1xuICAgIHJlZ2lzdGVyTG9ja2VkTW91c2VFdmVudHMobW91c2VDb250cm9sbGVyOiBNb3VzZUNvbnRyb2xsZXIpIHtcbiAgICAgICAgY29uc3QgdmlkZW9FbGVtZW50UGFyZW50ID1cbiAgICAgICAgICAgIHRoaXMudmlkZW9FbGVtZW50UHJvdmlkZXIuZ2V0VmlkZW9QYXJlbnRFbGVtZW50KCkgYXMgSFRNTERpdkVsZW1lbnQ7XG4gICAgICAgIGNvbnN0IGxvY2tlZE1vdXNlRXZlbnRzOiBJTW91c2VFdmVudHMgPSBuZXcgTG9ja2VkTW91c2VFdmVudHMoXG4gICAgICAgICAgICB0aGlzLnZpZGVvRWxlbWVudFByb3ZpZGVyLFxuICAgICAgICAgICAgbW91c2VDb250cm9sbGVyLFxuICAgICAgICAgICAgdGhpcy5hY3RpdmVLZXlzUHJvdmlkZXJcbiAgICAgICAgKTtcblxuICAgICAgICB2aWRlb0VsZW1lbnRQYXJlbnQucmVxdWVzdFBvaW50ZXJMb2NrID1cbiAgICAgICAgICAgIHZpZGVvRWxlbWVudFBhcmVudC5yZXF1ZXN0UG9pbnRlckxvY2sgfHxcbiAgICAgICAgICAgIHZpZGVvRWxlbWVudFBhcmVudC5tb3pSZXF1ZXN0UG9pbnRlckxvY2s7XG4gICAgICAgIGRvY3VtZW50LmV4aXRQb2ludGVyTG9jayA9XG4gICAgICAgICAgICBkb2N1bWVudC5leGl0UG9pbnRlckxvY2sgfHwgZG9jdW1lbnQubW96RXhpdFBvaW50ZXJMb2NrO1xuXG4gICAgICAgIC8vIG1pbm9yIGhhY2sgdG8gYWxsZXZpYXRlIGlvcyBub3Qgc3VwcG9ydGluZyBwb2ludGVybG9ja1xuICAgICAgICBpZiAodmlkZW9FbGVtZW50UGFyZW50LnJlcXVlc3RQb2ludGVyTG9jaykge1xuICAgICAgICAgICAgY29uc3Qgb25jbGljayA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICB2aWRlb0VsZW1lbnRQYXJlbnQucmVxdWVzdFBvaW50ZXJMb2NrKCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdmlkZW9FbGVtZW50UGFyZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgb25jbGljayk7XG4gICAgICAgICAgICB0aGlzLm1vdXNlRXZlbnRMaXN0ZW5lclRyYWNrZXIuYWRkVW5yZWdpc3RlckNhbGxiYWNrKFxuICAgICAgICAgICAgICAgICgpID0+IHZpZGVvRWxlbWVudFBhcmVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdjbGljaycsIG9uY2xpY2spXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgbG9ja1N0YXRlQ2hhbmdlTGlzdGVuZXIgPSAoKSA9PlxuICAgICAgICAgICAgbG9ja2VkTW91c2VFdmVudHMubG9ja1N0YXRlQ2hhbmdlKCk7XG4gICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoXG4gICAgICAgICAgICAncG9pbnRlcmxvY2tjaGFuZ2UnLFxuICAgICAgICAgICAgbG9ja1N0YXRlQ2hhbmdlTGlzdGVuZXIsXG4gICAgICAgICAgICBmYWxzZVxuICAgICAgICApO1xuICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKFxuICAgICAgICAgICAgJ21venBvaW50ZXJsb2NrY2hhbmdlJyxcbiAgICAgICAgICAgIGxvY2tTdGF0ZUNoYW5nZUxpc3RlbmVyLFxuICAgICAgICAgICAgZmFsc2VcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5tb3VzZUV2ZW50TGlzdGVuZXJUcmFja2VyLmFkZFVucmVnaXN0ZXJDYWxsYmFjayhcbiAgICAgICAgICAgICgpID0+IGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoXG4gICAgICAgICAgICAgICAgJ3BvaW50ZXJsb2NrY2hhbmdlJyxcbiAgICAgICAgICAgICAgICBsb2NrU3RhdGVDaGFuZ2VMaXN0ZW5lcixcbiAgICAgICAgICAgICAgICBmYWxzZVxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgICAgICB0aGlzLm1vdXNlRXZlbnRMaXN0ZW5lclRyYWNrZXIuYWRkVW5yZWdpc3RlckNhbGxiYWNrKFxuICAgICAgICAgICAgKCkgPT4gZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcihcbiAgICAgICAgICAgICAgICAnbW96cG9pbnRlcmxvY2tjaGFuZ2UnLFxuICAgICAgICAgICAgICAgIGxvY2tTdGF0ZUNoYW5nZUxpc3RlbmVyLFxuICAgICAgICAgICAgICAgIGZhbHNlXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG5cbiAgICAgICAgY29uc3Qgb25tb3VzZWRvd24gPSAobW91c2VFdmVudDogTW91c2VFdmVudCkgPT5cbiAgICAgICAgICAgIGxvY2tlZE1vdXNlRXZlbnRzLmhhbmRsZU1vdXNlRG93bihtb3VzZUV2ZW50KTtcbiAgICAgICAgY29uc3Qgb25tb3VzZXVwID0gKG1vdXNlRXZlbnQ6IE1vdXNlRXZlbnQpID0+XG4gICAgICAgICAgICBsb2NrZWRNb3VzZUV2ZW50cy5oYW5kbGVNb3VzZVVwKG1vdXNlRXZlbnQpO1xuICAgICAgICBjb25zdCBvbndoZWVsID0gKHdoZWVsRXZlbnQ6IFdoZWVsRXZlbnQpID0+XG4gICAgICAgICAgICBsb2NrZWRNb3VzZUV2ZW50cy5oYW5kbGVNb3VzZVdoZWVsKHdoZWVsRXZlbnQpO1xuICAgICAgICBjb25zdCBvbmRibGNsaWNrID0gKG1vdXNlRXZlbnQ6IE1vdXNlRXZlbnQpID0+XG4gICAgICAgICAgICBsb2NrZWRNb3VzZUV2ZW50cy5oYW5kbGVNb3VzZURvdWJsZShtb3VzZUV2ZW50KTtcbiAgICAgICAgdmlkZW9FbGVtZW50UGFyZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIG9ubW91c2Vkb3duKTtcbiAgICAgICAgdmlkZW9FbGVtZW50UGFyZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCBvbm1vdXNldXApO1xuICAgICAgICB2aWRlb0VsZW1lbnRQYXJlbnQuYWRkRXZlbnRMaXN0ZW5lcignd2hlZWwnLCBvbndoZWVsKTtcbiAgICAgICAgdmlkZW9FbGVtZW50UGFyZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2RibGNsaWNrJywgb25kYmxjbGljayk7XG5cbiAgICAgICAgdGhpcy5tb3VzZUV2ZW50TGlzdGVuZXJUcmFja2VyLmFkZFVucmVnaXN0ZXJDYWxsYmFjayhcbiAgICAgICAgICAgICgpID0+IHZpZGVvRWxlbWVudFBhcmVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCBvbm1vdXNlZG93bilcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5tb3VzZUV2ZW50TGlzdGVuZXJUcmFja2VyLmFkZFVucmVnaXN0ZXJDYWxsYmFjayhcbiAgICAgICAgICAgICgpID0+IHZpZGVvRWxlbWVudFBhcmVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgb25tb3VzZXVwKVxuICAgICAgICApO1xuICAgICAgICB0aGlzLm1vdXNlRXZlbnRMaXN0ZW5lclRyYWNrZXIuYWRkVW5yZWdpc3RlckNhbGxiYWNrKFxuICAgICAgICAgICAgKCkgPT4gdmlkZW9FbGVtZW50UGFyZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3doZWVsJywgb253aGVlbClcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5tb3VzZUV2ZW50TGlzdGVuZXJUcmFja2VyLmFkZFVucmVnaXN0ZXJDYWxsYmFjayhcbiAgICAgICAgICAgICgpID0+IHZpZGVvRWxlbWVudFBhcmVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdkYmxjbGljaycsIG9uZGJsY2xpY2spXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMubW91c2VFdmVudExpc3RlbmVyVHJhY2tlci5hZGRVbnJlZ2lzdGVyQ2FsbGJhY2soXG4gICAgICAgICAgICAoKSA9PiBsb2NrZWRNb3VzZUV2ZW50cy51bnJlZ2lzdGVyTW91c2VFdmVudHMoKVxuICAgICAgICApO1xuICAgICAgICB0aGlzLm1vdXNlRXZlbnRMaXN0ZW5lclRyYWNrZXIuYWRkVW5yZWdpc3RlckNhbGxiYWNrKCgpID0+IHtcbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICBkb2N1bWVudC5leGl0UG9pbnRlckxvY2sgJiZcbiAgICAgICAgICAgICAgICAoZG9jdW1lbnQucG9pbnRlckxvY2tFbGVtZW50ID09PSB2aWRlb0VsZW1lbnRQYXJlbnQgfHxcbiAgICAgICAgICAgICAgICAgICAgZG9jdW1lbnQubW96UG9pbnRlckxvY2tFbGVtZW50ID09PSB2aWRlb0VsZW1lbnRQYXJlbnQpXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICBkb2N1bWVudC5leGl0UG9pbnRlckxvY2soKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVnaXN0ZXIgYSBob3ZlcmluZyBtb3VzZSBjbGFzc1xuICAgICAqIEBwYXJhbSBtb3VzZUNvbnRyb2xsZXIgLSBBIG1vdXNlIGNvbnRyb2xsZXIgb2JqZWN0XG4gICAgICovXG4gICAgcmVnaXN0ZXJIb3ZlcmluZ01vdXNlRXZlbnRzKG1vdXNlQ29udHJvbGxlcjogTW91c2VDb250cm9sbGVyKSB7XG4gICAgICAgIGNvbnN0IHZpZGVvRWxlbWVudFBhcmVudCA9XG4gICAgICAgICAgICB0aGlzLnZpZGVvRWxlbWVudFByb3ZpZGVyLmdldFZpZGVvUGFyZW50RWxlbWVudCgpIGFzIEhUTUxEaXZFbGVtZW50O1xuICAgICAgICBjb25zdCBob3ZlcmluZ01vdXNlRXZlbnRzID0gbmV3IEhvdmVyaW5nTW91c2VFdmVudHMobW91c2VDb250cm9sbGVyKTtcblxuICAgICAgICBjb25zdCBvbm1vdXNlbW92ZSA9IChtb3VzZUV2ZW50OiBNb3VzZUV2ZW50KSA9PlxuICAgICAgICAgICAgaG92ZXJpbmdNb3VzZUV2ZW50cy51cGRhdGVNb3VzZU1vdmVQb3NpdGlvbihtb3VzZUV2ZW50KTtcbiAgICAgICAgY29uc3Qgb25tb3VzZWRvd24gPSAobW91c2VFdmVudDogTW91c2VFdmVudCkgPT5cbiAgICAgICAgICAgIGhvdmVyaW5nTW91c2VFdmVudHMuaGFuZGxlTW91c2VEb3duKG1vdXNlRXZlbnQpO1xuICAgICAgICBjb25zdCBvbm1vdXNldXAgPSAobW91c2VFdmVudDogTW91c2VFdmVudCkgPT5cbiAgICAgICAgICAgIGhvdmVyaW5nTW91c2VFdmVudHMuaGFuZGxlTW91c2VVcChtb3VzZUV2ZW50KTtcbiAgICAgICAgY29uc3Qgb25jb250ZXh0bWVudSA9IChtb3VzZUV2ZW50OiBNb3VzZUV2ZW50KSA9PlxuICAgICAgICAgICAgaG92ZXJpbmdNb3VzZUV2ZW50cy5oYW5kbGVDb250ZXh0TWVudShtb3VzZUV2ZW50KTtcbiAgICAgICAgY29uc3Qgb253aGVlbCA9ICh3aGVlbEV2ZW50OiBXaGVlbEV2ZW50KSA9PlxuICAgICAgICAgICAgaG92ZXJpbmdNb3VzZUV2ZW50cy5oYW5kbGVNb3VzZVdoZWVsKHdoZWVsRXZlbnQpO1xuICAgICAgICBjb25zdCBvbmRibGNsaWNrID0gKG1vdXNlRXZlbnQ6IE1vdXNlRXZlbnQpID0+XG4gICAgICAgICAgICBob3ZlcmluZ01vdXNlRXZlbnRzLmhhbmRsZU1vdXNlRG91YmxlKG1vdXNlRXZlbnQpO1xuICAgICAgICB2aWRlb0VsZW1lbnRQYXJlbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgb25tb3VzZW1vdmUpO1xuICAgICAgICB2aWRlb0VsZW1lbnRQYXJlbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgb25tb3VzZWRvd24pO1xuICAgICAgICB2aWRlb0VsZW1lbnRQYXJlbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIG9ubW91c2V1cCk7XG4gICAgICAgIHZpZGVvRWxlbWVudFBhcmVudC5hZGRFdmVudExpc3RlbmVyKCdjb250ZXh0bWVudScsIG9uY29udGV4dG1lbnUpO1xuICAgICAgICB2aWRlb0VsZW1lbnRQYXJlbnQuYWRkRXZlbnRMaXN0ZW5lcignd2hlZWwnLCBvbndoZWVsKTtcbiAgICAgICAgdmlkZW9FbGVtZW50UGFyZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2RibGNsaWNrJywgb25kYmxjbGljayk7XG5cbiAgICAgICAgdGhpcy5tb3VzZUV2ZW50TGlzdGVuZXJUcmFja2VyLmFkZFVucmVnaXN0ZXJDYWxsYmFjayhcbiAgICAgICAgICAgICgpID0+IHZpZGVvRWxlbWVudFBhcmVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCBvbm1vdXNlbW92ZSlcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5tb3VzZUV2ZW50TGlzdGVuZXJUcmFja2VyLmFkZFVucmVnaXN0ZXJDYWxsYmFjayhcbiAgICAgICAgICAgICgpID0+IHZpZGVvRWxlbWVudFBhcmVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCBvbm1vdXNlZG93bilcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5tb3VzZUV2ZW50TGlzdGVuZXJUcmFja2VyLmFkZFVucmVnaXN0ZXJDYWxsYmFjayhcbiAgICAgICAgICAgICgpID0+IHZpZGVvRWxlbWVudFBhcmVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgb25tb3VzZXVwKVxuICAgICAgICApO1xuICAgICAgICB0aGlzLm1vdXNlRXZlbnRMaXN0ZW5lclRyYWNrZXIuYWRkVW5yZWdpc3RlckNhbGxiYWNrKFxuICAgICAgICAgICAgKCkgPT4gdmlkZW9FbGVtZW50UGFyZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2NvbnRleHRtZW51Jywgb25jb250ZXh0bWVudSlcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5tb3VzZUV2ZW50TGlzdGVuZXJUcmFja2VyLmFkZFVucmVnaXN0ZXJDYWxsYmFjayhcbiAgICAgICAgICAgICgpID0+IHZpZGVvRWxlbWVudFBhcmVudC5yZW1vdmVFdmVudExpc3RlbmVyKCd3aGVlbCcsIG9ud2hlZWwpXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMubW91c2VFdmVudExpc3RlbmVyVHJhY2tlci5hZGRVbnJlZ2lzdGVyQ2FsbGJhY2soXG4gICAgICAgICAgICAoKSA9PiB2aWRlb0VsZW1lbnRQYXJlbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignZGJsY2xpY2snLCBvbmRibGNsaWNrKVxuICAgICAgICApO1xuICAgICAgICB0aGlzLm1vdXNlRXZlbnRMaXN0ZW5lclRyYWNrZXIuYWRkVW5yZWdpc3RlckNhbGxiYWNrKFxuICAgICAgICAgICAgKCkgPT4gaG92ZXJpbmdNb3VzZUV2ZW50cy51bnJlZ2lzdGVyTW91c2VFdmVudHMoKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgbW91c2UgZW50ZXIgYW5kIG1vdXNlIGxlYXZlIGV2ZW50c1xuICAgICAqL1xuICAgIHJlZ2lzdGVyTW91c2VFbnRlckFuZExlYXZlRXZlbnRzKCkge1xuICAgICAgICBjb25zdCB2aWRlb0VsZW1lbnRQYXJlbnQgPVxuICAgICAgICAgICAgdGhpcy52aWRlb0VsZW1lbnRQcm92aWRlci5nZXRWaWRlb1BhcmVudEVsZW1lbnQoKSBhcyBIVE1MRGl2RWxlbWVudDtcblxuICAgICAgICAvLyBIYW5kbGUgd2hlbiB0aGUgTW91c2UgaGFzIGVudGVyZWQgdGhlIGVsZW1lbnRcbiAgICAgICAgY29uc3Qgb25tb3VzZWVudGVyID0gKGV2ZW50OiBNb3VzZUV2ZW50KSA9PiB7XG4gICAgICAgICAgICBpZiAoIXRoaXMudmlkZW9FbGVtZW50UHJvdmlkZXIuaXNWaWRlb1JlYWR5KCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBMb2dnZXIuTG9nKExvZ2dlci5HZXRTdGFja1RyYWNlKCksICdNb3VzZSBFbnRlcmVkJywgNik7XG4gICAgICAgICAgICB0aGlzLnNlbmRNb3VzZUVudGVyKCk7XG4gICAgICAgICAgICB0aGlzLnByZXNzTW91c2VCdXR0b25zKGV2ZW50LmJ1dHRvbnMsIGV2ZW50LngsIGV2ZW50LnkpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIEhhbmRsZXMgd2hlbiB0aGUgbW91c2UgaGFzIGxlZnQgdGhlIGVsZW1lbnRcbiAgICAgICAgY29uc3Qgb25tb3VzZWxlYXZlID0gKGV2ZW50OiBNb3VzZUV2ZW50KSA9PiB7XG4gICAgICAgICAgICBpZiAoIXRoaXMudmlkZW9FbGVtZW50UHJvdmlkZXIuaXNWaWRlb1JlYWR5KCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBMb2dnZXIuTG9nKExvZ2dlci5HZXRTdGFja1RyYWNlKCksICdNb3VzZSBMZWZ0JywgNik7XG4gICAgICAgICAgICB0aGlzLnNlbmRNb3VzZUxlYXZlKCk7XG4gICAgICAgICAgICB0aGlzLnJlbGVhc2VNb3VzZUJ1dHRvbnMoZXZlbnQuYnV0dG9ucywgZXZlbnQueCwgZXZlbnQueSk7XG4gICAgICAgIH07XG4gICAgICAgIHZpZGVvRWxlbWVudFBhcmVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWVudGVyJywgb25tb3VzZWVudGVyKTtcbiAgICAgICAgdmlkZW9FbGVtZW50UGFyZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbGVhdmUnLCBvbm1vdXNlbGVhdmUpO1xuXG4gICAgICAgIHRoaXMubW91c2VFdmVudExpc3RlbmVyVHJhY2tlci5hZGRVbnJlZ2lzdGVyQ2FsbGJhY2soXG4gICAgICAgICAgICAoKSA9PiB2aWRlb0VsZW1lbnRQYXJlbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2VlbnRlcicsIG9ubW91c2VlbnRlcilcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5tb3VzZUV2ZW50TGlzdGVuZXJUcmFja2VyLmFkZFVucmVnaXN0ZXJDYWxsYmFjayhcbiAgICAgICAgICAgICgpID0+IHZpZGVvRWxlbWVudFBhcmVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZWxlYXZlJywgb25tb3VzZWxlYXZlKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZSB3aGVuIGEgbW91c2UgYnV0dG9uIGlzIHJlbGVhc2VkXG4gICAgICogQHBhcmFtIGJ1dHRvbnMgLSBNb3VzZSBCdXR0b25cbiAgICAgKiBAcGFyYW0gWCAtIE1vdXNlIHBvaW50ZXIgWCBjb29yZGluYXRlXG4gICAgICogQHBhcmFtIFkgLSBNb3VzZSBwb2ludGVyIFkgY29vcmRpbmF0ZVxuICAgICAqL1xuICAgIHJlbGVhc2VNb3VzZUJ1dHRvbnMoYnV0dG9uczogbnVtYmVyLCBYOiBudW1iZXIsIFk6IG51bWJlcikge1xuICAgICAgICBjb25zdCBjb29yZCA9IHRoaXMuY29vcmRpbmF0ZUNvbnZlcnRlci5ub3JtYWxpemVBbmRRdWFudGl6ZVVuc2lnbmVkKFxuICAgICAgICAgICAgWCxcbiAgICAgICAgICAgIFlcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKGJ1dHRvbnMgJiBNb3VzZUJ1dHRvbnNNYXNrLnByaW1hcnlCdXR0b24pIHtcbiAgICAgICAgICAgIHRoaXMuc2VuZE1vdXNlVXAoTW91c2VCdXR0b24ubWFpbkJ1dHRvbiwgY29vcmQueCwgY29vcmQueSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGJ1dHRvbnMgJiBNb3VzZUJ1dHRvbnNNYXNrLnNlY29uZGFyeUJ1dHRvbikge1xuICAgICAgICAgICAgdGhpcy5zZW5kTW91c2VVcChNb3VzZUJ1dHRvbi5zZWNvbmRhcnlCdXR0b24sIGNvb3JkLngsIGNvb3JkLnkpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChidXR0b25zICYgTW91c2VCdXR0b25zTWFzay5hdXhpbGlhcnlCdXR0b24pIHtcbiAgICAgICAgICAgIHRoaXMuc2VuZE1vdXNlVXAoTW91c2VCdXR0b24uYXV4aWxpYXJ5QnV0dG9uLCBjb29yZC54LCBjb29yZC55KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYnV0dG9ucyAmIE1vdXNlQnV0dG9uc01hc2suZm91cnRoQnV0dG9uKSB7XG4gICAgICAgICAgICB0aGlzLnNlbmRNb3VzZVVwKE1vdXNlQnV0dG9uLmZvdXJ0aEJ1dHRvbiwgY29vcmQueCwgY29vcmQueSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGJ1dHRvbnMgJiBNb3VzZUJ1dHRvbnNNYXNrLmZpZnRoQnV0dG9uKSB7XG4gICAgICAgICAgICB0aGlzLnNlbmRNb3VzZVVwKE1vdXNlQnV0dG9uLmZpZnRoQnV0dG9uLCBjb29yZC54LCBjb29yZC55KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZSB3aGVuIGEgbW91c2UgYnV0dG9uIGlzIHByZXNzZWRcbiAgICAgKiBAcGFyYW0gYnV0dG9ucyAtIE1vdXNlIEJ1dHRvblxuICAgICAqIEBwYXJhbSBYIC0gTW91c2UgcG9pbnRlciBYIGNvb3JkaW5hdGVcbiAgICAgKiBAcGFyYW0gWSAtIE1vdXNlIHBvaW50ZXIgWSBjb29yZGluYXRlXG4gICAgICovXG4gICAgcHJlc3NNb3VzZUJ1dHRvbnMoYnV0dG9uczogbnVtYmVyLCBYOiBudW1iZXIsIFk6IG51bWJlcikge1xuICAgICAgICBpZiAoIXRoaXMudmlkZW9FbGVtZW50UHJvdmlkZXIuaXNWaWRlb1JlYWR5KCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBjb29yZCA9IHRoaXMuY29vcmRpbmF0ZUNvbnZlcnRlci5ub3JtYWxpemVBbmRRdWFudGl6ZVVuc2lnbmVkKFxuICAgICAgICAgICAgWCxcbiAgICAgICAgICAgIFlcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKGJ1dHRvbnMgJiBNb3VzZUJ1dHRvbnNNYXNrLnByaW1hcnlCdXR0b24pIHtcbiAgICAgICAgICAgIHRoaXMuc2VuZE1vdXNlRG93bihNb3VzZUJ1dHRvbi5tYWluQnV0dG9uLCBjb29yZC54LCBjb29yZC55KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYnV0dG9ucyAmIE1vdXNlQnV0dG9uc01hc2suc2Vjb25kYXJ5QnV0dG9uKSB7XG4gICAgICAgICAgICB0aGlzLnNlbmRNb3VzZURvd24oTW91c2VCdXR0b24uc2Vjb25kYXJ5QnV0dG9uLCBjb29yZC54LCBjb29yZC55KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYnV0dG9ucyAmIE1vdXNlQnV0dG9uc01hc2suYXV4aWxpYXJ5QnV0dG9uKSB7XG4gICAgICAgICAgICB0aGlzLnNlbmRNb3VzZURvd24oTW91c2VCdXR0b24uYXV4aWxpYXJ5QnV0dG9uLCBjb29yZC54LCBjb29yZC55KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYnV0dG9ucyAmIE1vdXNlQnV0dG9uc01hc2suZm91cnRoQnV0dG9uKSB7XG4gICAgICAgICAgICB0aGlzLnNlbmRNb3VzZURvd24oTW91c2VCdXR0b24uZm91cnRoQnV0dG9uLCBjb29yZC54LCBjb29yZC55KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYnV0dG9ucyAmIE1vdXNlQnV0dG9uc01hc2suZmlmdGhCdXR0b24pIHtcbiAgICAgICAgICAgIHRoaXMuc2VuZE1vdXNlRG93bihNb3VzZUJ1dHRvbi5maWZ0aEJ1dHRvbiwgY29vcmQueCwgY29vcmQueSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVzIG1vdXNlIGVudGVyXG4gICAgICovXG4gICAgc2VuZE1vdXNlRW50ZXIoKSB7XG4gICAgICAgIGlmICghdGhpcy52aWRlb0VsZW1lbnRQcm92aWRlci5pc1ZpZGVvUmVhZHkoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHRvU3RyZWFtZXJIYW5kbGVycyA9XG4gICAgICAgICAgICB0aGlzLnRvU3RyZWFtZXJNZXNzYWdlc1Byb3ZpZGVyLnRvU3RyZWFtZXJIYW5kbGVycztcbiAgICAgICAgdG9TdHJlYW1lckhhbmRsZXJzLmdldCgnTW91c2VFbnRlcicpKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlcyBtb3VzZSBMZWF2ZVxuICAgICAqL1xuICAgIHNlbmRNb3VzZUxlYXZlKCkge1xuICAgICAgICBpZiAoIXRoaXMudmlkZW9FbGVtZW50UHJvdmlkZXIuaXNWaWRlb1JlYWR5KCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCB0b1N0cmVhbWVySGFuZGxlcnMgPVxuICAgICAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlci50b1N0cmVhbWVySGFuZGxlcnM7XG4gICAgICAgIHRvU3RyZWFtZXJIYW5kbGVycy5nZXQoJ01vdXNlTGVhdmUnKSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXMgd2hlbiBhIG1vdXNlIGJ1dHRvbiBpcyBwcmVzc2VkIGRvd25cbiAgICAgKiBAcGFyYW0gYnV0dG9uIC0gTW91c2UgQnV0dG9uIFByZXNzZWRcbiAgICAgKiBAcGFyYW0gWCAgLSBNb3VzZSBYIENvb3JkaW5hdGVcbiAgICAgKiBAcGFyYW0gWSAgLSBNb3VzZSBZIENvb3JkaW5hdGVcbiAgICAgKi9cbiAgICBzZW5kTW91c2VEb3duKGJ1dHRvbjogbnVtYmVyLCBYOiBudW1iZXIsIFk6IG51bWJlcikge1xuICAgICAgICBpZiAoIXRoaXMudmlkZW9FbGVtZW50UHJvdmlkZXIuaXNWaWRlb1JlYWR5KCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBMb2dnZXIuTG9nKFxuICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgIGBtb3VzZSBidXR0b24gJHtidXR0b259IGRvd24gYXQgKCR7WH0sICR7WX0pYCxcbiAgICAgICAgICAgIDZcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgdG9TdHJlYW1lckhhbmRsZXJzID1cbiAgICAgICAgICAgIHRoaXMudG9TdHJlYW1lck1lc3NhZ2VzUHJvdmlkZXIudG9TdHJlYW1lckhhbmRsZXJzO1xuICAgICAgICB0b1N0cmVhbWVySGFuZGxlcnMuZ2V0KCdNb3VzZURvd24nKShbYnV0dG9uLCBYLCBZXSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlcyB3aGVuIGEgbW91c2UgYnV0dG9uIGlzIHByZXNzZWQgdXBcbiAgICAgKiBAcGFyYW0gYnV0dG9uIC0gTW91c2UgQnV0dG9uIFByZXNzZWRcbiAgICAgKiBAcGFyYW0gWCAgLSBNb3VzZSBYIENvb3JkaW5hdGVcbiAgICAgKiBAcGFyYW0gWSAgLSBNb3VzZSBZIENvb3JkaW5hdGVcbiAgICAgKi9cbiAgICBzZW5kTW91c2VVcChidXR0b246IG51bWJlciwgWDogbnVtYmVyLCBZOiBudW1iZXIpIHtcbiAgICAgICAgaWYgKCF0aGlzLnZpZGVvRWxlbWVudFByb3ZpZGVyLmlzVmlkZW9SZWFkeSgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgTG9nZ2VyLkxvZyhcbiAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICBgbW91c2UgYnV0dG9uICR7YnV0dG9ufSB1cCBhdCAoJHtYfSwgJHtZfSlgLFxuICAgICAgICAgICAgNlxuICAgICAgICApO1xuICAgICAgICBjb25zdCBjb29yZCA9IHRoaXMuY29vcmRpbmF0ZUNvbnZlcnRlci5ub3JtYWxpemVBbmRRdWFudGl6ZVVuc2lnbmVkKFxuICAgICAgICAgICAgWCxcbiAgICAgICAgICAgIFlcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgdG9TdHJlYW1lckhhbmRsZXJzID1cbiAgICAgICAgICAgIHRoaXMudG9TdHJlYW1lck1lc3NhZ2VzUHJvdmlkZXIudG9TdHJlYW1lckhhbmRsZXJzO1xuICAgICAgICB0b1N0cmVhbWVySGFuZGxlcnMuZ2V0KCdNb3VzZVVwJykoW2J1dHRvbiwgY29vcmQueCwgY29vcmQueV0pO1xuICAgIH1cbn1cbiIsIi8vIENvcHlyaWdodCBFcGljIEdhbWVzLCBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG5cbi8qKlxuICogUmVnaXN0ZXJzIHRoZSBTcGVjaWFsIEtleSBjb2Rlc1xuICogIE11c3QgYmUga2VwdCBpbiBzeW5jIHdpdGggSmF2YVNjcmlwdEtleUNvZGVUb0ZLZXkgQysrIGFycmF5LlxuICogVGhlIGluZGV4IG9mIHRoZSBlbnRyeSBpbiB0aGUgYXJyYXkgaXMgdGhlIHNwZWNpYWwga2V5IGNvZGUgZ2l2ZW4gYmVsb3cuXG4gKi9cbmV4cG9ydCBjbGFzcyBTcGVjaWFsS2V5Q29kZXMge1xuICAgIHN0YXRpYyBiYWNrU3BhY2UgPSA4O1xuICAgIHN0YXRpYyBzaGlmdCA9IDE2O1xuICAgIHN0YXRpYyBjb250cm9sID0gMTc7XG4gICAgc3RhdGljIGFsdCA9IDE4O1xuICAgIHN0YXRpYyByaWdodFNoaWZ0ID0gMjUzO1xuICAgIHN0YXRpYyByaWdodENvbnRyb2wgPSAyNTQ7XG4gICAgc3RhdGljIHJpZ2h0QWx0ID0gMjU1O1xufVxuIiwiLy8gQ29weXJpZ2h0IEVwaWMgR2FtZXMsIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cblxuaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSAnLi4vTG9nZ2VyL0xvZ2dlcic7XG5pbXBvcnQgeyBDb29yZGluYXRlQ29udmVydGVyIH0gZnJvbSAnLi4vVXRpbC9Db29yZGluYXRlQ29udmVydGVyJztcbmltcG9ydCB7IFN0cmVhbU1lc3NhZ2VDb250cm9sbGVyIH0gZnJvbSAnLi4vVWVJbnN0YW5jZU1lc3NhZ2UvU3RyZWFtTWVzc2FnZUNvbnRyb2xsZXInO1xuaW1wb3J0IHsgVmlkZW9QbGF5ZXIgfSBmcm9tICcuLi9WaWRlb1BsYXllci9WaWRlb1BsYXllcic7XG5pbXBvcnQgeyBJVG91Y2hDb250cm9sbGVyIH0gZnJvbSAnLi9JVG91Y2hDb250cm9sbGVyJztcbmltcG9ydCB7IEV2ZW50TGlzdGVuZXJUcmFja2VyIH0gZnJvbSAnLi4vVXRpbC9FdmVudExpc3RlbmVyVHJhY2tlcic7XG4vKipcbiAqIEhhbmRsZXMgdGhlIFRvdWNoIGlucHV0IEV2ZW50c1xuICovXG5leHBvcnQgY2xhc3MgVG91Y2hDb250cm9sbGVyIGltcGxlbWVudHMgSVRvdWNoQ29udHJvbGxlciB7XG4gICAgdG9TdHJlYW1lck1lc3NhZ2VzUHJvdmlkZXI6IFN0cmVhbU1lc3NhZ2VDb250cm9sbGVyO1xuICAgIHZpZGVvRWxlbWVudFByb3ZpZGVyOiBWaWRlb1BsYXllcjtcbiAgICBjb29yZGluYXRlQ29udmVydGVyOiBDb29yZGluYXRlQ29udmVydGVyO1xuICAgIHZpZGVvRWxlbWVudFBhcmVudDogSFRNTFZpZGVvRWxlbWVudDtcbiAgICBmaW5nZXJzID0gWzksIDgsIDcsIDYsIDUsIDQsIDMsIDIsIDEsIDBdO1xuICAgIGZpbmdlcklkcyA9IG5ldyBNYXAoKTtcbiAgICBtYXhCeXRlVmFsdWUgPSAyNTU7XG5cbiAgICAvLyBVdGlsaXR5IGZvciBrZWVwaW5nIHRyYWNrIG9mIGV2ZW50IGhhbmRsZXJzIGFuZCB1bnJlZ2lzdGVyaW5nIHRoZW1cbiAgICBwcml2YXRlIHRvdWNoRXZlbnRMaXN0ZW5lclRyYWNrZXIgPSBuZXcgRXZlbnRMaXN0ZW5lclRyYWNrZXIoKTtcblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB0b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlciAtIFN0cmVhbSBtZXNzYWdlIGluc3RhbmNlXG4gICAgICogQHBhcmFtIHZpZGVvRWxlbWVudFByb3ZpZGVyIC0gVmlkZW8gUGxheWVyIGluc3RhbmNlXG4gICAgICogQHBhcmFtIGNvb3JkaW5hdGVDb252ZXJ0ZXIgLSBBIGNvb3JkaW5hdGUgY29udmVydGVyIGluc3RhbmNlXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIHRvU3RyZWFtZXJNZXNzYWdlc1Byb3ZpZGVyOiBTdHJlYW1NZXNzYWdlQ29udHJvbGxlcixcbiAgICAgICAgdmlkZW9FbGVtZW50UHJvdmlkZXI6IFZpZGVvUGxheWVyLFxuICAgICAgICBjb29yZGluYXRlQ29udmVydGVyOiBDb29yZGluYXRlQ29udmVydGVyXG4gICAgKSB7XG4gICAgICAgIHRoaXMudG9TdHJlYW1lck1lc3NhZ2VzUHJvdmlkZXIgPSB0b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlcjtcbiAgICAgICAgdGhpcy52aWRlb0VsZW1lbnRQcm92aWRlciA9IHZpZGVvRWxlbWVudFByb3ZpZGVyO1xuICAgICAgICB0aGlzLmNvb3JkaW5hdGVDb252ZXJ0ZXIgPSBjb29yZGluYXRlQ29udmVydGVyO1xuICAgICAgICB0aGlzLnZpZGVvRWxlbWVudFBhcmVudCA9IHZpZGVvRWxlbWVudFByb3ZpZGVyLmdldFZpZGVvRWxlbWVudCgpO1xuICAgICAgICBjb25zdCBvbnRvdWNoc3RhcnQgPSAoZXY6IFRvdWNoRXZlbnQpID0+XG4gICAgICAgICAgICB0aGlzLm9uVG91Y2hTdGFydChldik7XG4gICAgICAgIGNvbnN0IG9udG91Y2hlbmQgPSAoZXY6IFRvdWNoRXZlbnQpID0+XG4gICAgICAgICAgICB0aGlzLm9uVG91Y2hFbmQoZXYpO1xuICAgICAgICBjb25zdCBvbnRvdWNobW92ZSA9IChldjogVG91Y2hFdmVudCkgPT5cbiAgICAgICAgICAgIHRoaXMub25Ub3VjaE1vdmUoZXYpO1xuICAgICAgICB0aGlzLnZpZGVvRWxlbWVudFBhcmVudC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaHN0YXJ0Jywgb250b3VjaHN0YXJ0KTtcbiAgICAgICAgdGhpcy52aWRlb0VsZW1lbnRQYXJlbnQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCBvbnRvdWNoZW5kKTtcbiAgICAgICAgdGhpcy52aWRlb0VsZW1lbnRQYXJlbnQuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgb250b3VjaG1vdmUpO1xuICAgICAgICB0aGlzLnRvdWNoRXZlbnRMaXN0ZW5lclRyYWNrZXIuYWRkVW5yZWdpc3RlckNhbGxiYWNrKFxuICAgICAgICAgICAgKCkgPT4gdGhpcy52aWRlb0VsZW1lbnRQYXJlbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2hzdGFydCcsIG9udG91Y2hzdGFydClcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy50b3VjaEV2ZW50TGlzdGVuZXJUcmFja2VyLmFkZFVucmVnaXN0ZXJDYWxsYmFjayhcbiAgICAgICAgICAgICgpID0+IHRoaXMudmlkZW9FbGVtZW50UGFyZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNoZW5kJywgb250b3VjaGVuZClcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy50b3VjaEV2ZW50TGlzdGVuZXJUcmFja2VyLmFkZFVucmVnaXN0ZXJDYWxsYmFjayhcbiAgICAgICAgICAgICgpID0+IHRoaXMudmlkZW9FbGVtZW50UGFyZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIG9udG91Y2htb3ZlKVxuICAgICAgICApO1xuICAgICAgICBMb2dnZXIuTG9nKExvZ2dlci5HZXRTdGFja1RyYWNlKCksICdUb3VjaCBFdmVudHMgUmVnaXN0ZXJlZCcsIDYpO1xuXG4gICAgICAgIC8vIGlzIHRoaXMgc3RyaWN0bHkgbmVjZXNzYXJ5P1xuICAgICAgICBjb25zdCBwcmV2ZW50T25Ub3VjaE1vdmUgPSAoZXZlbnQ6IFRvdWNoRXZlbnQpID0+IHtcbiAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH07XG4gICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIHByZXZlbnRPblRvdWNoTW92ZSk7XG4gICAgICAgIHRoaXMudG91Y2hFdmVudExpc3RlbmVyVHJhY2tlci5hZGRVbnJlZ2lzdGVyQ2FsbGJhY2soXG4gICAgICAgICAgICAoKSA9PiBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCd0b3VjaG1vdmUnLCBwcmV2ZW50T25Ub3VjaE1vdmUpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVW5yZWdpc3RlciBhbGwgdG91Y2ggZXZlbnRzXG4gICAgICovXG4gICAgdW5yZWdpc3RlclRvdWNoRXZlbnRzKCkge1xuICAgICAgICB0aGlzLnRvdWNoRXZlbnRMaXN0ZW5lclRyYWNrZXIudW5yZWdpc3RlckFsbCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbWVtYmVyIGEgdG91Y2ggY29tbWFuZFxuICAgICAqIEBwYXJhbSB0b3VjaCAtIHRoZSB0b3VjaCBjb21tYW5kXG4gICAgICovXG4gICAgcmVtZW1iZXJUb3VjaCh0b3VjaDogVG91Y2gpIHtcbiAgICAgICAgY29uc3QgZmluZ2VyID0gdGhpcy5maW5nZXJzLnBvcCgpO1xuICAgICAgICBpZiAoZmluZ2VyID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIExvZ2dlci5Mb2coXG4gICAgICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICAgICAnZXhoYXVzdGVkIHRvdWNoIGlkZW50aWZpZXJzJyxcbiAgICAgICAgICAgICAgICA2XG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZmluZ2VySWRzLnNldCh0b3VjaC5pZGVudGlmaWVyLCBmaW5nZXIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZvcmdldHMgYSB0b3VjaCBjb21tYW5kXG4gICAgICogQHBhcmFtIHRvdWNoIC0gdGhlIHRvdWNoIGNvbW1hbmRcbiAgICAgKi9cbiAgICBmb3JnZXRUb3VjaCh0b3VjaDogVG91Y2gpIHtcbiAgICAgICAgdGhpcy5maW5nZXJzLnB1c2godGhpcy5maW5nZXJJZHMuZ2V0KHRvdWNoLmlkZW50aWZpZXIpKTtcbiAgICAgICAgLy8gU29ydCBhcnJheSBiYWNrIGludG8gZGVzY2VuZGluZyBvcmRlci4gVGhpcyBtZWFucyBpZiBmaW5nZXIgJzEnIHdlcmUgdG8gbGlmdCBhZnRlciBmaW5nZXIgJzAnLCB3ZSB3b3VsZCBlbnN1cmUgdGhhdCAwIHdpbGwgYmUgdGhlIGZpcnN0IGluZGV4IHRvIHBvcFxuICAgICAgICB0aGlzLmZpbmdlcnMuc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICAgICAgcmV0dXJuIGIgLSBhO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5maW5nZXJJZHMuZGVsZXRlKHRvdWNoLmlkZW50aWZpZXIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFdoZW4gYSB0b3VjaCBldmVudCBzdGFydHNcbiAgICAgKiBAcGFyYW0gdG91Y2hFdmVudCAtIHRoZSB0b3VjaCBldmVudCBiZWluZyBpbnRlcmNlcHRlZFxuICAgICAqL1xuICAgIG9uVG91Y2hTdGFydCh0b3VjaEV2ZW50OiBUb3VjaEV2ZW50KSB7XG4gICAgICAgIGlmICghdGhpcy52aWRlb0VsZW1lbnRQcm92aWRlci5pc1ZpZGVvUmVhZHkoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGZvciAobGV0IHQgPSAwOyB0IDwgdG91Y2hFdmVudC5jaGFuZ2VkVG91Y2hlcy5sZW5ndGg7IHQrKykge1xuICAgICAgICAgICAgdGhpcy5yZW1lbWJlclRvdWNoKHRvdWNoRXZlbnQuY2hhbmdlZFRvdWNoZXNbdF0pO1xuICAgICAgICB9XG4gICAgICAgIExvZ2dlci5Mb2coTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSwgJ3RvdWNoIHN0YXJ0JywgNik7XG5cbiAgICAgICAgdGhpcy5lbWl0VG91Y2hEYXRhKCdUb3VjaFN0YXJ0JywgdG91Y2hFdmVudC5jaGFuZ2VkVG91Y2hlcyk7XG4gICAgICAgIHRvdWNoRXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBXaGVuIGEgdG91Y2ggZXZlbnQgZW5kc1xuICAgICAqIEBwYXJhbSB0b3VjaEV2ZW50IC0gdGhlIHRvdWNoIGV2ZW50IGJlaW5nIGludGVyY2VwdGVkXG4gICAgICovXG4gICAgb25Ub3VjaEVuZCh0b3VjaEV2ZW50OiBUb3VjaEV2ZW50KSB7XG4gICAgICAgIGlmICghdGhpcy52aWRlb0VsZW1lbnRQcm92aWRlci5pc1ZpZGVvUmVhZHkoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIExvZ2dlci5Mb2coTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSwgJ3RvdWNoIGVuZCcsIDYpO1xuICAgICAgICB0aGlzLmVtaXRUb3VjaERhdGEoJ1RvdWNoRW5kJywgdG91Y2hFdmVudC5jaGFuZ2VkVG91Y2hlcyk7XG4gICAgICAgIC8vIFJlLWN5Y2xlIHVuaXF1ZSBpZGVudGlmaWVycyBwcmV2aW91c2x5IGFzc2lnbmVkIHRvIGVhY2ggdG91Y2guXG4gICAgICAgIGZvciAobGV0IHQgPSAwOyB0IDwgdG91Y2hFdmVudC5jaGFuZ2VkVG91Y2hlcy5sZW5ndGg7IHQrKykge1xuICAgICAgICAgICAgdGhpcy5mb3JnZXRUb3VjaCh0b3VjaEV2ZW50LmNoYW5nZWRUb3VjaGVzW3RdKTtcbiAgICAgICAgfVxuICAgICAgICB0b3VjaEV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogd2hlbiBhIG1vdmluZyB0b3VjaCBldmVudCBvY2N1cnNcbiAgICAgKiBAcGFyYW0gdG91Y2hFdmVudCAtIHRoZSB0b3VjaCBldmVudCBiZWluZyBpbnRlcmNlcHRlZFxuICAgICAqL1xuICAgIG9uVG91Y2hNb3ZlKHRvdWNoRXZlbnQ6IFRvdWNoRXZlbnQpIHtcbiAgICAgICAgaWYgKCF0aGlzLnZpZGVvRWxlbWVudFByb3ZpZGVyLmlzVmlkZW9SZWFkeSgpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgTG9nZ2VyLkxvZyhMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLCAndG91Y2ggbW92ZScsIDYpO1xuICAgICAgICB0aGlzLmVtaXRUb3VjaERhdGEoJ1RvdWNoTW92ZScsIHRvdWNoRXZlbnQudG91Y2hlcyk7XG4gICAgICAgIHRvdWNoRXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG5cbiAgICBlbWl0VG91Y2hEYXRhKHR5cGU6IHN0cmluZywgdG91Y2hlczogVG91Y2hMaXN0KSB7XG4gICAgICAgIGlmICghdGhpcy52aWRlb0VsZW1lbnRQcm92aWRlci5pc1ZpZGVvUmVhZHkoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IG9mZnNldCA9IHRoaXMudmlkZW9FbGVtZW50UHJvdmlkZXIuZ2V0VmlkZW9QYXJlbnRFbGVtZW50KCkuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIGNvbnN0IHRvU3RyZWFtZXJIYW5kbGVycyA9XG4gICAgICAgICAgICB0aGlzLnRvU3RyZWFtZXJNZXNzYWdlc1Byb3ZpZGVyLnRvU3RyZWFtZXJIYW5kbGVycztcblxuICAgICAgICBmb3IgKGxldCB0ID0gMDsgdCA8IHRvdWNoZXMubGVuZ3RoOyB0KyspIHtcbiAgICAgICAgICAgIGNvbnN0IG51bVRvdWNoZXMgPSAxOyAvLyB0aGUgbnVtYmVyIG9mIHRvdWNoZXMgdG8gYmUgc2VudCB0aGlzIG1lc3NhZ2VcbiAgICAgICAgICAgIGNvbnN0IHRvdWNoID0gdG91Y2hlc1t0XTtcbiAgICAgICAgICAgIGNvbnN0IHggPSB0b3VjaC5jbGllbnRYIC0gb2Zmc2V0LmxlZnQ7XG4gICAgICAgICAgICBjb25zdCB5ID0gdG91Y2guY2xpZW50WSAtIG9mZnNldC50b3A7XG4gICAgICAgICAgICBMb2dnZXIuTG9nKFxuICAgICAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAgICAgYEYke3RoaXMuZmluZ2VySWRzLmdldCh0b3VjaC5pZGVudGlmaWVyKX09KCR7eH0sICR7eX0pYCxcbiAgICAgICAgICAgICAgICA2XG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICBjb25zdCBjb29yZCA9IHRoaXMuY29vcmRpbmF0ZUNvbnZlcnRlci5ub3JtYWxpemVBbmRRdWFudGl6ZVVuc2lnbmVkKFxuICAgICAgICAgICAgICAgIHgsXG4gICAgICAgICAgICAgICAgeVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ1RvdWNoU3RhcnQnOlxuICAgICAgICAgICAgICAgICAgICB0b1N0cmVhbWVySGFuZGxlcnMuZ2V0KCdUb3VjaFN0YXJ0JykoW1xuICAgICAgICAgICAgICAgICAgICAgICAgbnVtVG91Y2hlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLngsXG4gICAgICAgICAgICAgICAgICAgICAgICBjb29yZC55LFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5maW5nZXJJZHMuZ2V0KHRvdWNoLmlkZW50aWZpZXIpLFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5tYXhCeXRlVmFsdWUgKiB0b3VjaC5mb3JjZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvb3JkLmluUmFuZ2UgPyAxIDogMFxuICAgICAgICAgICAgICAgICAgICBdKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnVG91Y2hFbmQnOlxuICAgICAgICAgICAgICAgICAgICB0b1N0cmVhbWVySGFuZGxlcnMuZ2V0KCdUb3VjaEVuZCcpKFtcbiAgICAgICAgICAgICAgICAgICAgICAgIG51bVRvdWNoZXMsXG4gICAgICAgICAgICAgICAgICAgICAgICBjb29yZC54LFxuICAgICAgICAgICAgICAgICAgICAgICAgY29vcmQueSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZmluZ2VySWRzLmdldCh0b3VjaC5pZGVudGlmaWVyKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubWF4Qnl0ZVZhbHVlICogdG91Y2guZm9yY2UsXG4gICAgICAgICAgICAgICAgICAgICAgICBjb29yZC5pblJhbmdlID8gMSA6IDBcbiAgICAgICAgICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ1RvdWNoTW92ZSc6XG4gICAgICAgICAgICAgICAgICAgIHRvU3RyZWFtZXJIYW5kbGVycy5nZXQoJ1RvdWNoTW92ZScpKFtcbiAgICAgICAgICAgICAgICAgICAgICAgIG51bVRvdWNoZXMsXG4gICAgICAgICAgICAgICAgICAgICAgICBjb29yZC54LFxuICAgICAgICAgICAgICAgICAgICAgICAgY29vcmQueSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZmluZ2VySWRzLmdldCh0b3VjaC5pZGVudGlmaWVyKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubWF4Qnl0ZVZhbHVlICogdG91Y2guZm9yY2UsXG4gICAgICAgICAgICAgICAgICAgICAgICBjb29yZC5pblJhbmdlID8gMSA6IDBcbiAgICAgICAgICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxufVxuIiwiLy8gQ29weXJpZ2h0IEVwaWMgR2FtZXMsIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cblxuaW1wb3J0IHsgU3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIgfSBmcm9tICcuLi9VZUluc3RhbmNlTWVzc2FnZS9TdHJlYW1NZXNzYWdlQ29udHJvbGxlcic7XG5pbXBvcnQgeyBDb250cm9sbGVyIH0gZnJvbSAnLi9HYW1lcGFkVHlwZXMnO1xuaW1wb3J0IHsgV2ViWFJVdGlscyB9IGZyb20gJy4uL1V0aWwvV2ViWFJVdGlscyc7XG5cbi8qKlxuICogVGhlIGNsYXNzIHRoYXQgaGFuZGxlcyB0aGUgZnVuY3Rpb25hbGl0eSBvZiB4cmdhbWVwYWRzIGFuZCBjb250cm9sbGVyc1xuICovXG5leHBvcnQgY2xhc3MgWFJHYW1lcGFkQ29udHJvbGxlciB7XG4gICAgY29udHJvbGxlcnM6IEFycmF5PENvbnRyb2xsZXI+O1xuICAgIHRvU3RyZWFtZXJNZXNzYWdlc1Byb3ZpZGVyOiBTdHJlYW1NZXNzYWdlQ29udHJvbGxlcjtcblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB0b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlciAtIFN0cmVhbSBtZXNzYWdlIGluc3RhbmNlXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodG9TdHJlYW1lck1lc3NhZ2VzUHJvdmlkZXI6IFN0cmVhbU1lc3NhZ2VDb250cm9sbGVyKSB7XG4gICAgICAgIHRoaXMudG9TdHJlYW1lck1lc3NhZ2VzUHJvdmlkZXIgPSB0b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlcjtcbiAgICAgICAgdGhpcy5jb250cm9sbGVycyA9IFtdO1xuICAgIH1cblxuICAgIHVwZGF0ZVN0YXR1cyhcbiAgICAgICAgc291cmNlOiBYUklucHV0U291cmNlLFxuICAgICAgICBmcmFtZTogWFJGcmFtZSxcbiAgICAgICAgcmVmU3BhY2U6IFhSUmVmZXJlbmNlU3BhY2VcbiAgICApIHtcbiAgICAgICAgaWYgKHNvdXJjZS5nYW1lcGFkKSB7XG4gICAgICAgICAgICBjb25zdCBnYW1lcGFkUG9zZSA9IGZyYW1lLmdldFBvc2Uoc291cmNlLmdyaXBTcGFjZSwgcmVmU3BhY2UpO1xuICAgICAgICAgICAgaWYgKCFnYW1lcGFkUG9zZSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGV0IHN5c3RlbSA9IDA7XG4gICAgICAgICAgICBpZiAoc291cmNlLnByb2ZpbGVzLmluY2x1ZGVzKCdodGMtdml2ZScpKSB7XG4gICAgICAgICAgICAgICAgc3lzdGVtID0gMTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoc291cmNlLnByb2ZpbGVzLmluY2x1ZGVzKCdvY3VsdXMtdG91Y2gnKSkge1xuICAgICAgICAgICAgICAgIHN5c3RlbSA9IDI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBUT0RPICh3aWxsaWFtLmJlbGNoZXIpOiBBZGQgb3RoZXIgcHJvZmlsZXMgKFF1ZXN0LCBNaWNyb3NvZnQgTWl4ZWQgUmVhbGl0eSwgZXRjKVxuICAgICAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlci50b1N0cmVhbWVySGFuZGxlcnMuZ2V0KCdYUlN5c3RlbScpKFtcbiAgICAgICAgICAgICAgICBzeXN0ZW1cbiAgICAgICAgICAgIF0pO1xuXG4gICAgICAgICAgICAvLyBEZWZhdWx0OiBBbnlIYW5kICgyKVxuICAgICAgICAgICAgbGV0IGhhbmRlZG5lc3MgPSAyO1xuICAgICAgICAgICAgc3dpdGNoIChzb3VyY2UuaGFuZGVkbmVzcykge1xuICAgICAgICAgICAgICAgIGNhc2UgJ2xlZnQnOlxuICAgICAgICAgICAgICAgICAgICBoYW5kZWRuZXNzID0gMDtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAncmlnaHQnOlxuICAgICAgICAgICAgICAgICAgICBoYW5kZWRuZXNzID0gMTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFNlbmQgY29udHJvbGxlciB0cmFuc2Zvcm1cbiAgICAgICAgICAgIGNvbnN0IG1hdHJpeCA9IGdhbWVwYWRQb3NlLnRyYW5zZm9ybS5tYXRyaXg7XG4gICAgICAgICAgICBjb25zdCBtYXQgPSBbXTtcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgMTY7IGkrKykge1xuICAgICAgICAgICAgICAgIG1hdFtpXSA9IG5ldyBGbG9hdDMyQXJyYXkoW21hdHJpeFtpXV0pWzBdO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBwcmV0dGllci1pZ25vcmVcbiAgICAgICAgICAgIHRoaXMudG9TdHJlYW1lck1lc3NhZ2VzUHJvdmlkZXIudG9TdHJlYW1lckhhbmRsZXJzLmdldCgnWFJDb250cm9sbGVyVHJhbnNmb3JtJykoW1xuICAgICAgICAgICAgICAgIG1hdFswXSwgbWF0WzRdLCBtYXRbOF0sIG1hdFsxMl0sXG4gICAgICAgICAgICAgICAgbWF0WzFdLCBtYXRbNV0sIG1hdFs5XSwgbWF0WzEzXSxcbiAgICAgICAgICAgICAgICBtYXRbMl0sIG1hdFs2XSwgbWF0WzEwXSwgbWF0WzE0XSxcbiAgICAgICAgICAgICAgICBtYXRbM10sIG1hdFs3XSwgbWF0WzExXSwgbWF0WzE1XSxcbiAgICAgICAgICAgICAgICBoYW5kZWRuZXNzXG4gICAgICAgICAgICBdKTtcblxuICAgICAgICAgICAgLy8gSGFuZGxlIGNvbnRyb2xsZXIgYnV0dG9ucyBhbmQgYXhlc1xuICAgICAgICAgICAgaWYgKHRoaXMuY29udHJvbGxlcnNbaGFuZGVkbmVzc10gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuY29udHJvbGxlcnNbaGFuZGVkbmVzc10gPSB7XG4gICAgICAgICAgICAgICAgICAgIHByZXZTdGF0ZTogdW5kZWZpbmVkLFxuICAgICAgICAgICAgICAgICAgICBjdXJyZW50U3RhdGU6IHVuZGVmaW5lZCxcblx0XHRcdFx0XHRpZDogdW5kZWZpbmVkXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbnRyb2xsZXJzW2hhbmRlZG5lc3NdLnByZXZTdGF0ZSA9XG4gICAgICAgICAgICAgICAgICAgIFdlYlhSVXRpbHMuZGVlcENvcHlHYW1lcGFkKHNvdXJjZS5nYW1lcGFkKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5jb250cm9sbGVyc1toYW5kZWRuZXNzXS5jdXJyZW50U3RhdGUgPVxuICAgICAgICAgICAgICAgIFdlYlhSVXRpbHMuZGVlcENvcHlHYW1lcGFkKHNvdXJjZS5nYW1lcGFkKTtcblxuICAgICAgICAgICAgY29uc3QgY29udHJvbGxlciA9IHRoaXMuY29udHJvbGxlcnNbaGFuZGVkbmVzc107XG4gICAgICAgICAgICBjb25zdCBjdXJyU3RhdGUgPSBjb250cm9sbGVyLmN1cnJlbnRTdGF0ZTtcbiAgICAgICAgICAgIGNvbnN0IHByZXZTdGF0ZSA9IGNvbnRyb2xsZXIucHJldlN0YXRlO1xuICAgICAgICAgICAgLy8gSXRlcmF0ZSBvdmVyIGJ1dHRvbnNcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY3VyclN0YXRlLmJ1dHRvbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCBjdXJyQnV0dG9uID0gY3VyclN0YXRlLmJ1dHRvbnNbaV07XG4gICAgICAgICAgICAgICAgY29uc3QgcHJldkJ1dHRvbiA9IHByZXZTdGF0ZS5idXR0b25zW2ldO1xuXG4gICAgICAgICAgICAgICAgaWYgKGN1cnJCdXR0b24ucHJlc3NlZCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBwcmVzc1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnRvU3RyZWFtZXJNZXNzYWdlc1Byb3ZpZGVyLnRvU3RyZWFtZXJIYW5kbGVycy5nZXQoXG4gICAgICAgICAgICAgICAgICAgICAgICAnWFJCdXR0b25QcmVzc2VkJ1xuICAgICAgICAgICAgICAgICAgICApKFtoYW5kZWRuZXNzLCBpLCBwcmV2QnV0dG9uLnByZXNzZWQgPyAxIDogMF0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoIWN1cnJCdXR0b24ucHJlc3NlZCAmJiBwcmV2QnV0dG9uLnByZXNzZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlci50b1N0cmVhbWVySGFuZGxlcnMuZ2V0KFxuICAgICAgICAgICAgICAgICAgICAgICAgJ1hSQnV0dG9uUmVsZWFzZWQnXG4gICAgICAgICAgICAgICAgICAgICkoW2hhbmRlZG5lc3MsIGksIDBdKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAoY3VyckJ1dHRvbi50b3VjaGVkICYmICFjdXJyQnV0dG9uLnByZXNzZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gcHJlc3NcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlci50b1N0cmVhbWVySGFuZGxlcnMuZ2V0KFxuICAgICAgICAgICAgICAgICAgICAgICAgJ1hSQnV0dG9uUHJlc3NlZCdcbiAgICAgICAgICAgICAgICAgICAgKShbaGFuZGVkbmVzcywgMywgcHJldkJ1dHRvbi50b3VjaGVkID8gMSA6IDBdKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCFjdXJyQnV0dG9uLnRvdWNoZWQgJiYgcHJldkJ1dHRvbi50b3VjaGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudG9TdHJlYW1lck1lc3NhZ2VzUHJvdmlkZXIudG9TdHJlYW1lckhhbmRsZXJzLmdldChcbiAgICAgICAgICAgICAgICAgICAgICAgICdYUkJ1dHRvblJlbGVhc2VkJ1xuICAgICAgICAgICAgICAgICAgICApKFtoYW5kZWRuZXNzLCAzLCAwXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBJdGVyYXRlIG92ZXIgZ2FtZXBhZCBheGVzXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGN1cnJTdGF0ZS5heGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXNQcm92aWRlci50b1N0cmVhbWVySGFuZGxlcnMuZ2V0KFxuICAgICAgICAgICAgICAgICAgICAnWFJBbmFsb2cnXG4gICAgICAgICAgICAgICAgKShbaGFuZGVkbmVzcywgaSwgY3VyclN0YXRlLmF4ZXNbaV1dKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5jb250cm9sbGVyc1toYW5kZWRuZXNzXS5wcmV2U3RhdGUgPSBjdXJyU3RhdGU7XG4gICAgICAgIH1cbiAgICB9XG59XG4iLCIvLyBDb3B5cmlnaHQgRXBpYyBHYW1lcywgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuXG5leHBvcnQgY2xhc3MgTG9nZ2VyIHtcbiAgICBzdGF0aWMgdmVyYm9zZUxvZ0xldmVsID0gNTtcblxuICAgIC8qKlxuICAgICAqIENhcHR1cmVzIHRoZSBzdGFjayBhbmQgcmV0dXJucyBpdFxuICAgICAqIEByZXR1cm5zIHRoZSBjdXJyZW50IHN0YWNrXG4gICAgICovXG4gICAgc3RhdGljIEdldFN0YWNrVHJhY2UoKSB7XG4gICAgICAgIGNvbnN0IGVycm9yID0gbmV3IEVycm9yKCk7XG4gICAgICAgIGxldCBmb3JtYXR0ZWRTdGFjayA9ICdObyBTdGFjayBBdmFpbGFibGUgZm9yIHRoaXMgYnJvd3Nlcic7XG5cbiAgICAgICAgLy8gZm9ybWF0IHRoZSBlcnJvclxuICAgICAgICBpZiAoZXJyb3Iuc3RhY2spIHtcbiAgICAgICAgICAgIGZvcm1hdHRlZFN0YWNrID0gZXJyb3Iuc3RhY2sudG9TdHJpbmcoKS5yZXBsYWNlKC9FcnJvci9nLCAnJyk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZm9ybWF0dGVkU3RhY2s7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSBsb2cgdmVyYm9zaXR5IGxldmVsXG4gICAgICovXG4gICAgc3RhdGljIFNldExvZ2dlclZlcmJvc2l0eSh2ZXJib3NlTG9nTGV2ZWw6IG51bWJlcikge1xuICAgICAgICBpZiAodGhpcy52ZXJib3NlTG9nTGV2ZWwgIT0gbnVsbCkge1xuICAgICAgICAgICAgdGhpcy52ZXJib3NlTG9nTGV2ZWwgPSB2ZXJib3NlTG9nTGV2ZWw7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgc3RhbmRhcmQgbG9nZ2luZyBvdXRwdXRcbiAgICAgKiBAcGFyYW0gc3RhY2sgLSB0aGUgc3RhY2sgdHJhY2VcbiAgICAgKiBAcGFyYW0gbWVzc2FnZSAtIHRoZSBtZXNzYWdlIHRvIGJlIGxvZ2dlZFxuICAgICAqIEBwYXJhbSB2ZXJib3NpdHkgLSB0aGUgdmVyYm9zaXR5IGxldmVsXG4gICAgICovXG4gICAgc3RhdGljIExvZyhzdGFjazogc3RyaW5nLCBtZXNzYWdlOiBzdHJpbmcsIHZlcmJvc2l0eT86IG51bWJlcikge1xuICAgICAgICBpZiAodmVyYm9zaXR5ID4gdGhpcy52ZXJib3NlTG9nTGV2ZWwpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHJldHVyblN0cmluZyA9IGBMZXZlbDogTG9nXFxuTXNnOiAke21lc3NhZ2V9XFxuQ2FsbGVyOiAke3N0YWNrfWA7XG4gICAgICAgIGNvbnNvbGUubG9nKHJldHVyblN0cmluZyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIHN0YW5kYXJkIGxvZ2dpbmcgb3V0cHV0XG4gICAgICogQHBhcmFtIHN0YWNrIC0gdGhlIHN0YWNrIHRyYWNlXG4gICAgICogQHBhcmFtIG1lc3NhZ2UgLSB0aGUgbWVzc2FnZSB0byBiZSBsb2dnZWRcbiAgICAgKiBAcGFyYW0gdmVyYm9zaXR5IC0gdGhlIHZlcmJvc2l0eSBsZXZlbFxuICAgICAqL1xuICAgIHN0YXRpYyBJbmZvKHN0YWNrOiBzdHJpbmcsIG1lc3NhZ2U6IHN0cmluZywgdmVyYm9zaXR5PzogbnVtYmVyKSB7XG4gICAgICAgIGlmICh2ZXJib3NpdHkgPiB0aGlzLnZlcmJvc2VMb2dMZXZlbCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmV0dXJuU3RyaW5nID0gYExldmVsOiBJbmZvXFxuTXNnOiAke21lc3NhZ2V9YDtcbiAgICAgICAgY29uc29sZS5pbmZvKHJldHVyblN0cmluZyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIHN0YW5kYXJkIGxvZ2dpbmcgb3V0cHV0XG4gICAgICogQHBhcmFtIHN0YWNrIC0gdGhlIHN0YWNrIHRyYWNlXG4gICAgICogQHBhcmFtIG1lc3NhZ2UgLSB0aGUgbWVzc2FnZSB0byBiZSBsb2dnZWRcbiAgICAgKi9cbiAgICBzdGF0aWMgRXJyb3Ioc3RhY2s6IHN0cmluZywgbWVzc2FnZTogc3RyaW5nKSB7XG4gICAgICAgIGNvbnN0IHJldHVyblN0cmluZyA9IGBMZXZlbDogRXJyb3JcXG5Nc2c6ICR7bWVzc2FnZX1cXG5DYWxsZXI6ICR7c3RhY2t9YDtcbiAgICAgICAgY29uc29sZS5lcnJvcihyZXR1cm5TdHJpbmcpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBzdGFuZGFyZCBsb2dnaW5nIG91dHB1dFxuICAgICAqIEBwYXJhbSBzdGFjayAtIHRoZSBzdGFjayB0cmFjZVxuICAgICAqIEBwYXJhbSBtZXNzYWdlIC0gdGhlIG1lc3NhZ2UgdG8gYmUgbG9nZ2VkXG4gICAgICovXG4gICAgc3RhdGljIFdhcm5pbmcoc3RhY2s6IHN0cmluZywgbWVzc2FnZTogc3RyaW5nKSB7XG4gICAgICAgIGNvbnN0IHJldHVyblN0cmluZyA9IGBMZXZlbDogV2FybmluZ1xcbkNhbGxlcjogJHtzdGFja31cXG5Nc2c6ICR7bWVzc2FnZX1gO1xuICAgICAgICBjb25zb2xlLndhcm4ocmV0dXJuU3RyaW5nKTtcbiAgICB9XG59XG4iLCIvLyBDb3B5cmlnaHQgRXBpYyBHYW1lcywgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuXG5pbXBvcnQge1xuICAgIEluYm91bmRSVFBTdGF0cyxcbiAgICBJbmJvdW5kVmlkZW9TdGF0cyxcbiAgICBJbmJvdW5kQXVkaW9TdGF0c1xufSBmcm9tICcuL0luYm91bmRSVFBTdGF0cyc7XG5pbXBvcnQgeyBJbmJvdW5kVHJhY2tTdGF0cyB9IGZyb20gJy4vSW5ib3VuZFRyYWNrU3RhdHMnO1xuaW1wb3J0IHsgRGF0YUNoYW5uZWxTdGF0cyB9IGZyb20gJy4vRGF0YUNoYW5uZWxTdGF0cyc7XG5pbXBvcnQgeyBDYW5kaWRhdGVTdGF0IH0gZnJvbSAnLi9DYW5kaWRhdGVTdGF0JztcbmltcG9ydCB7IENhbmRpZGF0ZVBhaXJTdGF0cyB9IGZyb20gJy4vQ2FuZGlkYXRlUGFpclN0YXRzJztcbmltcG9ydCB7IE91dEJvdW5kUlRQU3RhdHMsIE91dEJvdW5kVmlkZW9TdGF0cyB9IGZyb20gJy4vT3V0Qm91bmRSVFBTdGF0cyc7XG5pbXBvcnQgeyBTZXNzaW9uU3RhdHMgfSBmcm9tICcuL1Nlc3Npb25TdGF0cyc7XG5pbXBvcnQgeyBTdHJlYW1TdGF0cyB9IGZyb20gJy4vU3RyZWFtU3RhdHMnO1xuaW1wb3J0IHsgQ29kZWNTdGF0cyB9IGZyb20gJy4vQ29kZWNTdGF0cyc7XG5pbXBvcnQgeyBMb2dnZXIgfSBmcm9tICcuLi9Mb2dnZXIvTG9nZ2VyJztcblxuLyoqXG4gKiBUaGUgQWdncmVnYXRlZCBTdGF0cyB0aGF0IGlzIGdlbmVyYXRlZCBmcm9tIHRoZSBSVEMgU3RhdHMgUmVwb3J0XG4gKi9cblxudHlwZSBSVENTdGF0c1R5cGVQUyA9IFJUQ1N0YXRzVHlwZSB8ICdzdHJlYW0nIHwgJ21lZGlhLXBsYXlvdXQnO1xuZXhwb3J0IGNsYXNzIEFnZ3JlZ2F0ZWRTdGF0cyB7XG4gICAgaW5ib3VuZFZpZGVvU3RhdHM6IEluYm91bmRWaWRlb1N0YXRzO1xuICAgIGluYm91bmRBdWRpb1N0YXRzOiBJbmJvdW5kQXVkaW9TdGF0cztcbiAgICBsYXN0VmlkZW9TdGF0czogSW5ib3VuZFZpZGVvU3RhdHM7XG4gICAgbGFzdEF1ZGlvU3RhdHM6IEluYm91bmRBdWRpb1N0YXRzO1xuICAgIGNhbmRpZGF0ZVBhaXI6IENhbmRpZGF0ZVBhaXJTdGF0cztcbiAgICBEYXRhQ2hhbm5lbFN0YXRzOiBEYXRhQ2hhbm5lbFN0YXRzO1xuICAgIGxvY2FsQ2FuZGlkYXRlczogQXJyYXk8Q2FuZGlkYXRlU3RhdD47XG4gICAgcmVtb3RlQ2FuZGlkYXRlczogQXJyYXk8Q2FuZGlkYXRlU3RhdD47XG4gICAgb3V0Qm91bmRWaWRlb1N0YXRzOiBPdXRCb3VuZFZpZGVvU3RhdHM7XG4gICAgc2Vzc2lvblN0YXRzOiBTZXNzaW9uU3RhdHM7XG4gICAgc3RyZWFtU3RhdHM6IFN0cmVhbVN0YXRzO1xuICAgIGNvZGVjczogTWFwPHN0cmluZywgc3RyaW5nPjtcblxuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLmluYm91bmRWaWRlb1N0YXRzID0gbmV3IEluYm91bmRWaWRlb1N0YXRzKCk7XG4gICAgICAgIHRoaXMuaW5ib3VuZEF1ZGlvU3RhdHMgPSBuZXcgSW5ib3VuZEF1ZGlvU3RhdHMoKTtcbiAgICAgICAgdGhpcy5jYW5kaWRhdGVQYWlyID0gbmV3IENhbmRpZGF0ZVBhaXJTdGF0cygpO1xuICAgICAgICB0aGlzLkRhdGFDaGFubmVsU3RhdHMgPSBuZXcgRGF0YUNoYW5uZWxTdGF0cygpO1xuICAgICAgICB0aGlzLm91dEJvdW5kVmlkZW9TdGF0cyA9IG5ldyBPdXRCb3VuZFZpZGVvU3RhdHMoKTtcbiAgICAgICAgdGhpcy5zZXNzaW9uU3RhdHMgPSBuZXcgU2Vzc2lvblN0YXRzKCk7XG4gICAgICAgIHRoaXMuc3RyZWFtU3RhdHMgPSBuZXcgU3RyZWFtU3RhdHMoKTtcbiAgICAgICAgdGhpcy5jb2RlY3MgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nPigpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdhdGhlciBhbGwgdGhlIGluZm9ybWF0aW9uIGZyb20gdGhlIFJUQyBQZWVyIENvbm5lY3Rpb24gUmVwb3J0XG4gICAgICogQHBhcmFtIHJ0Y1N0YXRzUmVwb3J0IC0gUlRDIFN0YXRzIFJlcG9ydFxuICAgICAqL1xuICAgIHByb2Nlc3NTdGF0cyhydGNTdGF0c1JlcG9ydDogUlRDU3RhdHNSZXBvcnQpIHtcbiAgICAgICAgdGhpcy5sb2NhbENhbmRpZGF0ZXMgPSBuZXcgQXJyYXk8Q2FuZGlkYXRlU3RhdD4oKTtcbiAgICAgICAgdGhpcy5yZW1vdGVDYW5kaWRhdGVzID0gbmV3IEFycmF5PENhbmRpZGF0ZVN0YXQ+KCk7XG5cbiAgICAgICAgcnRjU3RhdHNSZXBvcnQuZm9yRWFjaCgoc3RhdCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgdHlwZTogUlRDU3RhdHNUeXBlUFMgPSBzdGF0LnR5cGU7XG5cbiAgICAgICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ2NhbmRpZGF0ZS1wYWlyJzpcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5oYW5kbGVDYW5kaWRhdGVQYWlyKHN0YXQpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdjZXJ0aWZpY2F0ZSc6XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ2NvZGVjJzpcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5oYW5kbGVDb2RlYyhzdGF0KTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnZGF0YS1jaGFubmVsJzpcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5oYW5kbGVEYXRhQ2hhbm5lbChzdGF0KTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnaW5ib3VuZC1ydHAnOlxuICAgICAgICAgICAgICAgICAgICB0aGlzLmhhbmRsZUluQm91bmRSVFAoc3RhdCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ2xvY2FsLWNhbmRpZGF0ZSc6XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaGFuZGxlTG9jYWxDYW5kaWRhdGUoc3RhdCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ21lZGlhLXNvdXJjZSc6XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ21lZGlhLXBsYXlvdXQnOlxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdvdXRib3VuZC1ydHAnOlxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdwZWVyLWNvbm5lY3Rpb24nOlxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdyZW1vdGUtY2FuZGlkYXRlJzpcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5oYW5kbGVSZW1vdGVDYW5kaWRhdGUoc3RhdCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3JlbW90ZS1pbmJvdW5kLXJ0cCc6XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3JlbW90ZS1vdXRib3VuZC1ydHAnOlxuICAgICAgICAgICAgICAgICAgICB0aGlzLmhhbmRsZVJlbW90ZU91dEJvdW5kKHN0YXQpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICd0cmFjayc6XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaGFuZGxlVHJhY2soc3RhdCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3RyYW5zcG9ydCc6XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3N0cmVhbSc6XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaGFuZGxlU3RyZWFtKHN0YXQpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBMb2dnZXIuRXJyb3IoTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSwgJ3VuaGFuZGxlZCBTdGF0IFR5cGUnKTtcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLkxvZyhMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLCBzdGF0KTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFByb2Nlc3Mgc3RyZWFtIHN0YXRzIGRhdGEgZnJvbSB3ZWJydGNcbiAgICAgKlxuICAgICAqIEBwYXJhbSBzdGF0IC0gdGhlIHN0YXRzIGNvbWluZyBpbiBmcm9tIHdlYnJ0Y1xuICAgICAqL1xuICAgIGhhbmRsZVN0cmVhbShzdGF0OiBTdHJlYW1TdGF0cykge1xuICAgICAgICB0aGlzLnN0cmVhbVN0YXRzID0gc3RhdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQcm9jZXNzIHRoZSBJY2UgQ2FuZGlkYXRlIFBhaXIgRGF0YVxuICAgICAqIEBwYXJhbSBzdGF0IC0gdGhlIHN0YXRzIGNvbWluZyBpbiBmcm9tIGljZSBjYW5kaWRhdGVzXG4gICAgICovXG4gICAgaGFuZGxlQ2FuZGlkYXRlUGFpcihzdGF0OiBDYW5kaWRhdGVQYWlyU3RhdHMpIHtcbiAgICAgICAgdGhpcy5jYW5kaWRhdGVQYWlyLmJ5dGVzUmVjZWl2ZWQgPSBzdGF0LmJ5dGVzUmVjZWl2ZWQ7XG4gICAgICAgIHRoaXMuY2FuZGlkYXRlUGFpci5ieXRlc1NlbnQgPSBzdGF0LmJ5dGVzU2VudDtcbiAgICAgICAgdGhpcy5jYW5kaWRhdGVQYWlyLmxvY2FsQ2FuZGlkYXRlSWQgPSBzdGF0LmxvY2FsQ2FuZGlkYXRlSWQ7XG4gICAgICAgIHRoaXMuY2FuZGlkYXRlUGFpci5yZW1vdGVDYW5kaWRhdGVJZCA9IHN0YXQucmVtb3RlQ2FuZGlkYXRlSWQ7XG4gICAgICAgIHRoaXMuY2FuZGlkYXRlUGFpci5ub21pbmF0ZWQgPSBzdGF0Lm5vbWluYXRlZDtcbiAgICAgICAgdGhpcy5jYW5kaWRhdGVQYWlyLnJlYWRhYmxlID0gc3RhdC5yZWFkYWJsZTtcbiAgICAgICAgdGhpcy5jYW5kaWRhdGVQYWlyLnNlbGVjdGVkID0gc3RhdC5zZWxlY3RlZDtcbiAgICAgICAgdGhpcy5jYW5kaWRhdGVQYWlyLndyaXRhYmxlID0gc3RhdC53cml0YWJsZTtcbiAgICAgICAgdGhpcy5jYW5kaWRhdGVQYWlyLnN0YXRlID0gc3RhdC5zdGF0ZTtcbiAgICAgICAgdGhpcy5jYW5kaWRhdGVQYWlyLmN1cnJlbnRSb3VuZFRyaXBUaW1lID0gc3RhdC5jdXJyZW50Um91bmRUcmlwVGltZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQcm9jZXNzIHRoZSBEYXRhIENoYW5uZWwgRGF0YVxuICAgICAqIEBwYXJhbSBzdGF0IC0gdGhlIHN0YXRzIGNvbWluZyBpbiBmcm9tIHRoZSBkYXRhIGNoYW5uZWxcbiAgICAgKi9cbiAgICBoYW5kbGVEYXRhQ2hhbm5lbChzdGF0OiBEYXRhQ2hhbm5lbFN0YXRzKSB7XG4gICAgICAgIHRoaXMuRGF0YUNoYW5uZWxTdGF0cy5ieXRlc1JlY2VpdmVkID0gc3RhdC5ieXRlc1JlY2VpdmVkO1xuICAgICAgICB0aGlzLkRhdGFDaGFubmVsU3RhdHMuYnl0ZXNTZW50ID0gc3RhdC5ieXRlc1NlbnQ7XG4gICAgICAgIHRoaXMuRGF0YUNoYW5uZWxTdGF0cy5kYXRhQ2hhbm5lbElkZW50aWZpZXIgPVxuICAgICAgICAgICAgc3RhdC5kYXRhQ2hhbm5lbElkZW50aWZpZXI7XG4gICAgICAgIHRoaXMuRGF0YUNoYW5uZWxTdGF0cy5pZCA9IHN0YXQuaWQ7XG4gICAgICAgIHRoaXMuRGF0YUNoYW5uZWxTdGF0cy5sYWJlbCA9IHN0YXQubGFiZWw7XG4gICAgICAgIHRoaXMuRGF0YUNoYW5uZWxTdGF0cy5tZXNzYWdlc1JlY2VpdmVkID0gc3RhdC5tZXNzYWdlc1JlY2VpdmVkO1xuICAgICAgICB0aGlzLkRhdGFDaGFubmVsU3RhdHMubWVzc2FnZXNTZW50ID0gc3RhdC5tZXNzYWdlc1NlbnQ7XG4gICAgICAgIHRoaXMuRGF0YUNoYW5uZWxTdGF0cy5wcm90b2NvbCA9IHN0YXQucHJvdG9jb2w7XG4gICAgICAgIHRoaXMuRGF0YUNoYW5uZWxTdGF0cy5zdGF0ZSA9IHN0YXQuc3RhdGU7XG4gICAgICAgIHRoaXMuRGF0YUNoYW5uZWxTdGF0cy50aW1lc3RhbXAgPSBzdGF0LnRpbWVzdGFtcDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQcm9jZXNzIHRoZSBMb2NhbCBJY2UgQ2FuZGlkYXRlIERhdGFcbiAgICAgKiBAcGFyYW0gc3RhdCAtIGxvY2FsIHN0YXRzXG4gICAgICovXG4gICAgaGFuZGxlTG9jYWxDYW5kaWRhdGUoc3RhdDogQ2FuZGlkYXRlU3RhdCkge1xuICAgICAgICBjb25zdCBsb2NhbENhbmRpZGF0ZSA9IG5ldyBDYW5kaWRhdGVTdGF0KCk7XG4gICAgICAgIGxvY2FsQ2FuZGlkYXRlLmxhYmVsID0gJ2xvY2FsLWNhbmRpZGF0ZSc7XG4gICAgICAgIGxvY2FsQ2FuZGlkYXRlLmFkZHJlc3MgPSBzdGF0LmFkZHJlc3M7XG4gICAgICAgIGxvY2FsQ2FuZGlkYXRlLnBvcnQgPSBzdGF0LnBvcnQ7XG4gICAgICAgIGxvY2FsQ2FuZGlkYXRlLnByb3RvY29sID0gc3RhdC5wcm90b2NvbDtcbiAgICAgICAgbG9jYWxDYW5kaWRhdGUuY2FuZGlkYXRlVHlwZSA9IHN0YXQuY2FuZGlkYXRlVHlwZTtcbiAgICAgICAgbG9jYWxDYW5kaWRhdGUuaWQgPSBzdGF0LmlkO1xuICAgICAgICB0aGlzLmxvY2FsQ2FuZGlkYXRlcy5wdXNoKGxvY2FsQ2FuZGlkYXRlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQcm9jZXNzIHRoZSBSZW1vdGUgSWNlIENhbmRpZGF0ZSBEYXRhXG4gICAgICogQHBhcmFtIHN0YXQgLSBpY2UgY2FuZGlkYXRlIHN0YXRzXG4gICAgICovXG4gICAgaGFuZGxlUmVtb3RlQ2FuZGlkYXRlKHN0YXQ6IENhbmRpZGF0ZVN0YXQpIHtcbiAgICAgICAgY29uc3QgUmVtb3RlQ2FuZGlkYXRlID0gbmV3IENhbmRpZGF0ZVN0YXQoKTtcbiAgICAgICAgUmVtb3RlQ2FuZGlkYXRlLmxhYmVsID0gJ2xvY2FsLWNhbmRpZGF0ZSc7XG4gICAgICAgIFJlbW90ZUNhbmRpZGF0ZS5hZGRyZXNzID0gc3RhdC5hZGRyZXNzO1xuICAgICAgICBSZW1vdGVDYW5kaWRhdGUucG9ydCA9IHN0YXQucG9ydDtcbiAgICAgICAgUmVtb3RlQ2FuZGlkYXRlLnByb3RvY29sID0gc3RhdC5wcm90b2NvbDtcbiAgICAgICAgUmVtb3RlQ2FuZGlkYXRlLmlkID0gc3RhdC5pZDtcbiAgICAgICAgUmVtb3RlQ2FuZGlkYXRlLmNhbmRpZGF0ZVR5cGUgPSBzdGF0LmNhbmRpZGF0ZVR5cGU7XG4gICAgICAgIHRoaXMucmVtb3RlQ2FuZGlkYXRlcy5wdXNoKFJlbW90ZUNhbmRpZGF0ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUHJvY2VzcyB0aGUgSW5ib3VuZCBSVFAgQXVkaW8gYW5kIFZpZGVvIERhdGFcbiAgICAgKiBAcGFyYW0gc3RhdCAtIGluYm91bmQgcnRwIHN0YXRzXG4gICAgICovXG4gICAgaGFuZGxlSW5Cb3VuZFJUUChzdGF0OiBJbmJvdW5kUlRQU3RhdHMpIHtcbiAgICAgICAgc3dpdGNoIChzdGF0LmtpbmQpIHtcbiAgICAgICAgICAgIGNhc2UgJ3ZpZGVvJzpcbiAgICAgICAgICAgICAgICAvLyBOZWVkIHRvIGNvbnZlcnQgdG8gdW5rbm93biBmaXJzdCB0byByZW1vdmUgYW4gZXJyb3IgYXJvdW5kXG4gICAgICAgICAgICAgICAgLy8gSW5ib3VuZFZpZGVvU3RhdHMgaGF2aW5nIHRoZSBiaXRyYXRlIG1lbWJlciB3aGljaCBpc24ndCBmb3VuZCBvblxuICAgICAgICAgICAgICAgIC8vIHRoZSBJbmJvdW5kUlRQU3RhdHNcbiAgICAgICAgICAgICAgICB0aGlzLmluYm91bmRWaWRlb1N0YXRzID0gc3RhdCBhcyB1bmtub3duIGFzIEluYm91bmRWaWRlb1N0YXRzO1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMubGFzdFZpZGVvU3RhdHMgIT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaW5ib3VuZFZpZGVvU3RhdHMuYml0cmF0ZSA9XG4gICAgICAgICAgICAgICAgICAgICAgICAoOCAqXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKHRoaXMuaW5ib3VuZFZpZGVvU3RhdHMuYnl0ZXNSZWNlaXZlZCAtXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubGFzdFZpZGVvU3RhdHMuYnl0ZXNSZWNlaXZlZCkpIC9cbiAgICAgICAgICAgICAgICAgICAgICAgICh0aGlzLmluYm91bmRWaWRlb1N0YXRzLnRpbWVzdGFtcCAtXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sYXN0VmlkZW9TdGF0cy50aW1lc3RhbXApO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmluYm91bmRWaWRlb1N0YXRzLmJpdHJhdGUgPSBNYXRoLmZsb29yKFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pbmJvdW5kVmlkZW9TdGF0cy5iaXRyYXRlXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMubGFzdFZpZGVvU3RhdHMgPSB7IC4uLnRoaXMuaW5ib3VuZFZpZGVvU3RhdHMgfTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ2F1ZGlvJzpcbiAgICAgICAgICAgICAgICAvLyBOZWVkIHRvIGNvbnZlcnQgdG8gdW5rbm93biBmaXJzdCB0byByZW1vdmUgYW4gZXJyb3IgYXJvdW5kXG4gICAgICAgICAgICAgICAgLy8gSW5ib3VuZEF1ZGlvU3RhdHMgaGF2aW5nIHRoZSBiaXRyYXRlIG1lbWJlciB3aGljaCBpc24ndCBmb3VuZCBvblxuICAgICAgICAgICAgICAgIC8vIHRoZSBJbmJvdW5kUlRQU3RhdHNcbiAgICAgICAgICAgICAgICB0aGlzLmluYm91bmRBdWRpb1N0YXRzID0gc3RhdCBhcyB1bmtub3duIGFzIEluYm91bmRBdWRpb1N0YXRzO1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMubGFzdEF1ZGlvU3RhdHMgIT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaW5ib3VuZEF1ZGlvU3RhdHMuYml0cmF0ZSA9XG4gICAgICAgICAgICAgICAgICAgICAgICAoOCAqXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKHRoaXMuaW5ib3VuZEF1ZGlvU3RhdHMuYnl0ZXNSZWNlaXZlZCAtXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubGFzdEF1ZGlvU3RhdHMuYnl0ZXNSZWNlaXZlZCkpIC9cbiAgICAgICAgICAgICAgICAgICAgICAgICh0aGlzLmluYm91bmRBdWRpb1N0YXRzLnRpbWVzdGFtcCAtXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5sYXN0QXVkaW9TdGF0cy50aW1lc3RhbXApO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmluYm91bmRBdWRpb1N0YXRzLmJpdHJhdGUgPSBNYXRoLmZsb29yKFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pbmJvdW5kQXVkaW9TdGF0cy5iaXRyYXRlXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMubGFzdEF1ZGlvU3RhdHMgPSB7IC4uLnRoaXMuaW5ib3VuZEF1ZGlvU3RhdHMgfTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgTG9nZ2VyLkxvZyhMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLCAnS2luZCBpcyBub3QgaGFuZGxlZCcpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUHJvY2VzcyB0aGUgb3V0Ym91bmQgUlRQIEF1ZGlvIGFuZCBWaWRlbyBEYXRhXG4gICAgICogQHBhcmFtIHN0YXQgLSByZW1vdGUgb3V0Ym91bmQgc3RhdHNcbiAgICAgKi9cbiAgICBoYW5kbGVSZW1vdGVPdXRCb3VuZChzdGF0OiBPdXRCb3VuZFJUUFN0YXRzKSB7XG4gICAgICAgIHN3aXRjaCAoc3RhdC5raW5kKSB7XG4gICAgICAgICAgICBjYXNlICd2aWRlbyc6XG4gICAgICAgICAgICAgICAgdGhpcy5vdXRCb3VuZFZpZGVvU3RhdHMuYnl0ZXNTZW50ID0gc3RhdC5ieXRlc1NlbnQ7XG4gICAgICAgICAgICAgICAgdGhpcy5vdXRCb3VuZFZpZGVvU3RhdHMuaWQgPSBzdGF0LmlkO1xuICAgICAgICAgICAgICAgIHRoaXMub3V0Qm91bmRWaWRlb1N0YXRzLmxvY2FsSWQgPSBzdGF0LmxvY2FsSWQ7XG4gICAgICAgICAgICAgICAgdGhpcy5vdXRCb3VuZFZpZGVvU3RhdHMucGFja2V0c1NlbnQgPSBzdGF0LnBhY2tldHNTZW50O1xuICAgICAgICAgICAgICAgIHRoaXMub3V0Qm91bmRWaWRlb1N0YXRzLnJlbW90ZVRpbWVzdGFtcCA9IHN0YXQucmVtb3RlVGltZXN0YW1wO1xuICAgICAgICAgICAgICAgIHRoaXMub3V0Qm91bmRWaWRlb1N0YXRzLnRpbWVzdGFtcCA9IHN0YXQudGltZXN0YW1wO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnYXVkaW8nOlxuICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUHJvY2VzcyB0aGUgSW5ib3VuZCBWaWRlbyBUcmFjayBEYXRhXG4gICAgICogQHBhcmFtIHN0YXQgLSB2aWRlbyB0cmFjayBzdGF0c1xuICAgICAqL1xuICAgIGhhbmRsZVRyYWNrKHN0YXQ6IEluYm91bmRUcmFja1N0YXRzKSB7XG4gICAgICAgIC8vIHdlIG9ubHkgd2FudCB0byBleHRyYWN0IHN0YXRzIGZyb20gdGhlIHZpZGVvIHRyYWNrXG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIHN0YXQudHlwZSA9PT0gJ3RyYWNrJyAmJlxuICAgICAgICAgICAgKHN0YXQudHJhY2tJZGVudGlmaWVyID09PSAndmlkZW9fbGFiZWwnIHx8IHN0YXQua2luZCA9PT0gJ3ZpZGVvJylcbiAgICAgICAgKSB7XG4gICAgICAgICAgICB0aGlzLmluYm91bmRWaWRlb1N0YXRzLmZyYW1lc0Ryb3BwZWQgPSBzdGF0LmZyYW1lc0Ryb3BwZWQ7XG4gICAgICAgICAgICB0aGlzLmluYm91bmRWaWRlb1N0YXRzLmZyYW1lc1JlY2VpdmVkID0gc3RhdC5mcmFtZXNSZWNlaXZlZDtcbiAgICAgICAgICAgIHRoaXMuaW5ib3VuZFZpZGVvU3RhdHMuZnJhbWVIZWlnaHQgPSBzdGF0LmZyYW1lSGVpZ2h0O1xuICAgICAgICAgICAgdGhpcy5pbmJvdW5kVmlkZW9TdGF0cy5mcmFtZVdpZHRoID0gc3RhdC5mcmFtZVdpZHRoO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaGFuZGxlQ29kZWMoc3RhdDogQ29kZWNTdGF0cykge1xuICAgICAgICBjb25zdCBjb2RlY0lkID0gc3RhdC5pZDtcbiAgICAgICAgY29uc3QgY29kZWNUeXBlID0gYCR7c3RhdC5taW1lVHlwZVxuICAgICAgICAgICAgLnJlcGxhY2UoJ3ZpZGVvLycsICcnKVxuICAgICAgICAgICAgLnJlcGxhY2UoJ2F1ZGlvLycsICcnKX0ke1xuICAgICAgICAgICAgc3RhdC5zZHBGbXRwTGluZSA/IGAgJHtzdGF0LnNkcEZtdHBMaW5lfWAgOiAnJ1xuICAgICAgICB9YDtcbiAgICAgICAgdGhpcy5jb2RlY3Muc2V0KGNvZGVjSWQsIGNvZGVjVHlwZSk7XG4gICAgfVxuXG4gICAgaGFuZGxlU2Vzc2lvblN0YXRpc3RpY3MoXG4gICAgICAgIHZpZGVvU3RhcnRUaW1lOiBudW1iZXIsXG4gICAgICAgIGlucHV0Q29udHJvbGxlcjogYm9vbGVhbiB8IG51bGwsXG4gICAgICAgIHZpZGVvRW5jb2RlckF2Z1FQOiBudW1iZXJcbiAgICApIHtcbiAgICAgICAgY29uc3QgZGVsdGFUaW1lID0gRGF0ZS5ub3coKSAtIHZpZGVvU3RhcnRUaW1lO1xuICAgICAgICB0aGlzLnNlc3Npb25TdGF0cy5ydW5UaW1lID0gbmV3IERhdGUoZGVsdGFUaW1lKVxuICAgICAgICAgICAgLnRvSVNPU3RyaW5nKClcbiAgICAgICAgICAgIC5zdWJzdHIoMTEsIDgpXG4gICAgICAgICAgICAudG9TdHJpbmcoKTtcblxuICAgICAgICBjb25zdCBjb250cm9sc1N0cmVhbUlucHV0ID1cbiAgICAgICAgICAgIGlucHV0Q29udHJvbGxlciA9PT0gbnVsbFxuICAgICAgICAgICAgICAgID8gJ05vdCBzZW50IHlldCdcbiAgICAgICAgICAgICAgICA6IGlucHV0Q29udHJvbGxlclxuICAgICAgICAgICAgICAgID8gJ3RydWUnXG4gICAgICAgICAgICAgICAgOiAnZmFsc2UnO1xuICAgICAgICB0aGlzLnNlc3Npb25TdGF0cy5jb250cm9sc1N0cmVhbUlucHV0ID0gY29udHJvbHNTdHJlYW1JbnB1dDtcblxuICAgICAgICB0aGlzLnNlc3Npb25TdGF0cy52aWRlb0VuY29kZXJBdmdRUCA9IHZpZGVvRW5jb2RlckF2Z1FQO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrIGlmIGEgdmFsdWUgY29taW5nIGluIGZyb20gb3VyIHN0YXRzIGlzIGFjdHVhbGx5IGEgbnVtYmVyXG4gICAgICogQHBhcmFtIHZhbHVlIC0gdGhlIG51bWJlciB0byBiZSBjaGVja2VkXG4gICAgICovXG4gICAgaXNOdW1iZXIodmFsdWU6IHVua25vd24pOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicgJiYgaXNGaW5pdGUodmFsdWUpO1xuICAgIH1cbn1cbiIsIi8vIENvcHlyaWdodCBFcGljIEdhbWVzLCBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG5cbi8qKlxuICogSUNFIENhbmRpZGF0ZSBQYWlyIFN0YXRzIGNvbGxlY3RlZCBmcm9tIHRoZSBSVEMgU3RhdHMgUmVwb3J0XG4gKi9cbmV4cG9ydCBjbGFzcyBDYW5kaWRhdGVQYWlyU3RhdHMge1xuICAgIGJ5dGVzUmVjZWl2ZWQ6IG51bWJlcjtcbiAgICBieXRlc1NlbnQ6IG51bWJlcjtcbiAgICBsb2NhbENhbmRpZGF0ZUlkOiBzdHJpbmc7XG4gICAgcmVtb3RlQ2FuZGlkYXRlSWQ6IHN0cmluZztcbiAgICBub21pbmF0ZWQ6IGJvb2xlYW47XG4gICAgcmVhZGFibGU6IGJvb2xlYW47XG4gICAgd3JpdGFibGU6IGJvb2xlYW47XG4gICAgc2VsZWN0ZWQ6IGJvb2xlYW47XG4gICAgc3RhdGU6IHN0cmluZztcbiAgICBjdXJyZW50Um91bmRUcmlwVGltZTogbnVtYmVyO1xufVxuIiwiLy8gQ29weXJpZ2h0IEVwaWMgR2FtZXMsIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cblxuLyoqXG4gKiBJQ0UgQ2FuZGlkYXRlIFN0YXQgY29sbGVjdGVkIGZyb20gdGhlIFJUQyBTdGF0cyBSZXBvcnRcbiAqL1xuZXhwb3J0IGNsYXNzIENhbmRpZGF0ZVN0YXQge1xuICAgIGxhYmVsOiBzdHJpbmc7XG4gICAgaWQ6IHN0cmluZztcbiAgICBhZGRyZXNzOiBzdHJpbmc7XG4gICAgY2FuZGlkYXRlVHlwZTogc3RyaW5nO1xuICAgIHBvcnQ6IG51bWJlcjtcbiAgICBwcm90b2NvbDogJ3RjcCcgfCAndWRwJztcbn1cbiIsIi8vIENvcHlyaWdodCBFcGljIEdhbWVzLCBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG5cbi8qKlxuICogRGF0YSBDaGFubmVsIFN0YXRzIGNvbGxlY3RlZCBmcm9tIHRoZSBSVEMgU3RhdHMgUmVwb3J0XG4gKi9cbmV4cG9ydCBjbGFzcyBEYXRhQ2hhbm5lbFN0YXRzIHtcbiAgICBieXRlc1JlY2VpdmVkOiBudW1iZXI7XG4gICAgYnl0ZXNTZW50OiBudW1iZXI7XG4gICAgZGF0YUNoYW5uZWxJZGVudGlmaWVyOiBudW1iZXI7XG4gICAgaWQ6IHN0cmluZztcbiAgICBsYWJlbDogc3RyaW5nO1xuICAgIG1lc3NhZ2VzUmVjZWl2ZWQ6IG51bWJlcjtcbiAgICBtZXNzYWdlc1NlbnQ6IG51bWJlcjtcbiAgICBwcm90b2NvbDogc3RyaW5nO1xuICAgIHN0YXRlOiBzdHJpbmc7XG4gICAgdGltZXN0YW1wOiBudW1iZXI7XG59XG4iLCIvLyBDb3B5cmlnaHQgRXBpYyBHYW1lcywgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuXG4vKipcbiAqIEluYm91bmQgQXVkaW8gU3RhdHMgY29sbGVjdGVkIGZyb20gdGhlIFJUQyBTdGF0cyBSZXBvcnRcbiAqL1xuZXhwb3J0IGNsYXNzIEluYm91bmRBdWRpb1N0YXRzIHtcbiAgICBhdWRpb0xldmVsOiBudW1iZXI7XG4gICAgYnl0ZXNSZWNlaXZlZDogbnVtYmVyO1xuICAgIGNvZGVjSWQ6IHN0cmluZztcbiAgICBjb25jZWFsZWRTYW1wbGVzOiBudW1iZXI7XG4gICAgY29uY2VhbG1lbnRFdmVudHM6IG51bWJlcjtcbiAgICBmZWNQYWNrZXRzRGlzY2FyZGVkOiBudW1iZXI7XG4gICAgZmVjUGFja2V0c1JlY2VpdmVkOiBudW1iZXI7XG4gICAgaGVhZGVyQnl0ZXNSZWNlaXZlZDogbnVtYmVyO1xuICAgIGlkOiBzdHJpbmc7XG4gICAgaW5zZXJ0ZWRTYW1wbGVzRm9yRGVjZWxlcmF0aW9uOiBudW1iZXI7XG4gICAgaml0dGVyOiBudW1iZXI7XG4gICAgaml0dGVyQnVmZmVyRGVsYXk6IG51bWJlcjtcbiAgICBqaXR0ZXJCdWZmZXJFbWl0dGVkQ291bnQ6IG51bWJlcjtcbiAgICBqaXR0ZXJCdWZmZXJNaW5pbXVtRGVsYXk6IG51bWJlcjtcbiAgICBqaXR0ZXJCdWZmZXJUYXJnZXREZWxheTogbnVtYmVyO1xuICAgIGtpbmQ6IHN0cmluZztcbiAgICBsYXN0UGFja2V0UmVjZWl2ZWRUaW1lc3RhbXA6IG51bWJlcjtcbiAgICBtZWRpYVR5cGU6IHN0cmluZztcbiAgICBtaWQ6IHN0cmluZztcbiAgICBwYWNrZXRzRGlzY2FyZGVkOiBudW1iZXI7XG4gICAgcGFja2V0c0xvc3Q6IG51bWJlcjtcbiAgICBwYWNrZXRzUmVjZWl2ZWQ6IG51bWJlcjtcbiAgICByZW1vdmVkU2FtcGxlc0ZvckFjY2VsZXJhdGlvbjogbnVtYmVyO1xuICAgIHNpbGVudENvbmNlYWxlZFNhbXBsZXM6IG51bWJlcjtcbiAgICBzc3JjOiBudW1iZXI7XG4gICAgdGltZXN0YW1wOiBudW1iZXI7XG4gICAgdG90YWxBdWRpb0VuZXJneTogbnVtYmVyO1xuICAgIHRvdGFsU2FtcGxlc0R1cmF0aW9uOiBudW1iZXI7XG4gICAgdG90YWxTYW1wbGVzUmVjZWl2ZWQ6IG51bWJlcjtcbiAgICB0cmFja0lkZW50aWZpZXI6IHN0cmluZztcbiAgICB0cmFuc3BvcnRJZDogc3RyaW5nO1xuICAgIHR5cGU6IHN0cmluZztcblxuICAgIC8qIGFkZGl0aW9uYWwsIGN1c3RvbSBzdGF0cyAqL1xuICAgIGJpdHJhdGU6IG51bWJlcjtcbn1cblxuLyoqXG4gKiBJbmJvdW5kIFZpZGVvIFN0YXRzIGNvbGxlY3RlZCBmcm9tIHRoZSBSVEMgU3RhdHMgUmVwb3J0XG4gKi9cbmV4cG9ydCBjbGFzcyBJbmJvdW5kVmlkZW9TdGF0cyB7XG4gICAgYnl0ZXNSZWNlaXZlZDogbnVtYmVyO1xuICAgIGNvZGVjSWQ6IHN0cmluZztcbiAgICBmaXJDb3VudDogbnVtYmVyO1xuICAgIGZyYW1lSGVpZ2h0OiBudW1iZXI7XG4gICAgZnJhbWVXaWR0aDogbnVtYmVyO1xuICAgIGZyYW1lc0Fzc2VtYmxlZEZyb21NdWx0aXBsZVBhY2tldHM6IG51bWJlcjtcbiAgICBmcmFtZXNEZWNvZGVkOiBudW1iZXI7XG4gICAgZnJhbWVzRHJvcHBlZDogbnVtYmVyO1xuICAgIGZyYW1lc1BlclNlY29uZDogbnVtYmVyO1xuICAgIGZyYW1lc1JlY2VpdmVkOiBudW1iZXI7XG4gICAgZnJlZXplQ291bnQ6IG51bWJlcjtcbiAgICBnb29nVGltaW5nRnJhbWVJbmZvOiBzdHJpbmc7XG4gICAgaGVhZGVyQnl0ZXNSZWNlaXZlZDogbnVtYmVyO1xuICAgIGlkOiBzdHJpbmc7XG4gICAgaml0dGVyOiBudW1iZXI7XG4gICAgaml0dGVyQnVmZmVyRGVsYXk6IG51bWJlcjtcbiAgICBqaXR0ZXJCdWZmZXJFbWl0dGVkQ291bnQ6IG51bWJlcjtcbiAgICBrZXlGcmFtZXNEZWNvZGVkOiBudW1iZXI7XG4gICAga2luZDogc3RyaW5nO1xuICAgIGxhc3RQYWNrZXRSZWNlaXZlZFRpbWVzdGFtcDogbnVtYmVyO1xuICAgIG1lZGlhVHlwZTogc3RyaW5nO1xuICAgIG1pZDogc3RyaW5nO1xuICAgIG5hY2tDb3VudDogbnVtYmVyO1xuICAgIHBhY2tldHNMb3N0OiBudW1iZXI7XG4gICAgcGFja2V0c1JlY2VpdmVkOiBudW1iZXI7XG4gICAgcGF1c2VDb3VudDogbnVtYmVyO1xuICAgIHBsaUNvdW50OiBudW1iZXI7XG4gICAgc3NyYzogbnVtYmVyO1xuICAgIHRpbWVzdGFtcDogbnVtYmVyO1xuICAgIHRvdGFsQXNzZW1ibHlUaW1lOiBudW1iZXI7XG4gICAgdG90YWxEZWNvZGVUaW1lOiBudW1iZXI7XG4gICAgdG90YWxGcmVlemVzRHVyYXRpb246IG51bWJlcjtcbiAgICB0b3RhbEludGVyRnJhbWVEZWxheTogbnVtYmVyO1xuICAgIHRvdGFsUGF1c2VzRHVyYXRpb246IG51bWJlcjtcbiAgICB0b3RhbFByb2Nlc3NpbmdEZWxheTogbnVtYmVyO1xuICAgIHRvdGFsU3F1YXJlZEludGVyRnJhbWVEZWxheTogbnVtYmVyO1xuICAgIHRyYWNrSWRlbnRpZmllcjogc3RyaW5nO1xuICAgIHRyYW5zcG9ydElkOiBzdHJpbmc7XG4gICAgdHlwZTogc3RyaW5nO1xuXG4gICAgLyogYWRkaXRpb25hbCwgY3VzdG9tIHN0YXRzICovXG4gICAgYml0cmF0ZTogbnVtYmVyO1xufVxuXG4vKipcbiAqIEluYm91bmQgU3RhdHMgY29sbGVjdGVkIGZyb20gdGhlIFJUQyBTdGF0cyBSZXBvcnRcbiAqL1xuZXhwb3J0IGNsYXNzIEluYm91bmRSVFBTdGF0cyB7XG4gICAgLyogY29tbW9uIHN0YXRzICovXG4gICAgYnl0ZXNSZWNlaXZlZDogbnVtYmVyO1xuICAgIGNvZGVjSWQ6IHN0cmluZztcbiAgICBoZWFkZXJCeXRlc1JlY2VpdmVkOiBudW1iZXI7XG4gICAgaWQ6IHN0cmluZztcbiAgICBqaXR0ZXI6IG51bWJlcjtcbiAgICBqaXR0ZXJCdWZmZXJEZWxheTogbnVtYmVyO1xuICAgIGppdHRlckJ1ZmZlckVtaXR0ZWRDb3VudDogbnVtYmVyO1xuICAgIGtpbmQ6IHN0cmluZztcbiAgICBsYXN0UGFja2V0UmVjZWl2ZWRUaW1lc3RhbXA6IG51bWJlcjtcbiAgICBtZWRpYVR5cGU6IHN0cmluZztcbiAgICBtaWQ6IHN0cmluZztcbiAgICBwYWNrZXRzTG9zdDogbnVtYmVyO1xuICAgIHBhY2tldHNSZWNlaXZlZDogbnVtYmVyO1xuICAgIHNzcmM6IG51bWJlcjtcbiAgICB0aW1lc3RhbXA6IG51bWJlcjtcbiAgICB0cmFja0lkZW50aWZpZXI6IHN0cmluZztcbiAgICB0cmFuc3BvcnRJZDogc3RyaW5nO1xuICAgIHR5cGU6IHN0cmluZztcblxuICAgIC8qIGF1ZGlvIHNwZWNpZmljIHN0YXRzICovXG4gICAgYXVkaW9MZXZlbDogbnVtYmVyO1xuICAgIGNvbmNlYWxlZFNhbXBsZXM6IG51bWJlcjtcbiAgICBjb25jZWFsbWVudEV2ZW50czogbnVtYmVyO1xuICAgIGZlY1BhY2tldHNEaXNjYXJkZWQ6IG51bWJlcjtcbiAgICBmZWNQYWNrZXRzUmVjZWl2ZWQ6IG51bWJlcjtcbiAgICBpbnNlcnRlZFNhbXBsZXNGb3JEZWNlbGVyYXRpb246IG51bWJlcjtcbiAgICBqaXR0ZXJCdWZmZXJNaW5pbXVtRGVsYXk6IG51bWJlcjtcbiAgICBqaXR0ZXJCdWZmZXJUYXJnZXREZWxheTogbnVtYmVyO1xuICAgIHBhY2tldHNEaXNjYXJkZWQ6IG51bWJlcjtcbiAgICByZW1vdmVkU2FtcGxlc0ZvckFjY2VsZXJhdGlvbjogbnVtYmVyO1xuICAgIHNpbGVudENvbmNlYWxlZFNhbXBsZXM6IG51bWJlcjtcbiAgICB0b3RhbEF1ZGlvRW5lcmd5OiBudW1iZXI7XG4gICAgdG90YWxTYW1wbGVzRHVyYXRpb246IG51bWJlcjtcbiAgICB0b3RhbFNhbXBsZXNSZWNlaXZlZDogbnVtYmVyO1xuXG4gICAgLyogdmlkZW8gc3BlY2lmaWMgc3RhdHMgKi9cbiAgICBmaXJDb3VudDogbnVtYmVyO1xuICAgIGZyYW1lSGVpZ2h0OiBudW1iZXI7XG4gICAgZnJhbWVXaWR0aDogbnVtYmVyO1xuICAgIGZyYW1lc0Fzc2VtYmxlZEZyb21NdWx0aXBsZVBhY2tldHM6IG51bWJlcjtcbiAgICBmcmFtZXNEZWNvZGVkOiBudW1iZXI7XG4gICAgZnJhbWVzRHJvcHBlZDogbnVtYmVyO1xuICAgIGZyYW1lc1BlclNlY29uZDogbnVtYmVyO1xuICAgIGZyYW1lc1JlY2VpdmVkOiBudW1iZXI7XG4gICAgZnJlZXplQ291bnQ6IG51bWJlcjtcbiAgICBnb29nVGltaW5nRnJhbWVJbmZvOiBzdHJpbmc7XG4gICAga2V5RnJhbWVzRGVjb2RlZDogbnVtYmVyO1xuICAgIG5hY2tDb3VudDogbnVtYmVyO1xuICAgIHBhdXNlQ291bnQ6IG51bWJlcjtcbiAgICBwbGlDb3VudDogbnVtYmVyO1xuICAgIHRvdGFsQXNzZW1ibHlUaW1lOiBudW1iZXI7XG4gICAgdG90YWxEZWNvZGVUaW1lOiBudW1iZXI7XG4gICAgdG90YWxGcmVlemVzRHVyYXRpb246IG51bWJlcjtcbiAgICB0b3RhbEludGVyRnJhbWVEZWxheTogbnVtYmVyO1xuICAgIHRvdGFsUGF1c2VzRHVyYXRpb246IG51bWJlcjtcbiAgICB0b3RhbFByb2Nlc3NpbmdEZWxheTogbnVtYmVyO1xuICAgIHRvdGFsU3F1YXJlZEludGVyRnJhbWVEZWxheTogbnVtYmVyO1xufVxuIiwiLy8gQ29weXJpZ2h0IEVwaWMgR2FtZXMsIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cblxuLyoqXG4gKiBPdXRib3VuZCBWaWRlbyBTdGF0cyBjb2xsZWN0ZWQgZnJvbSB0aGUgUlRDIFN0YXRzIFJlcG9ydFxuICovXG5leHBvcnQgY2xhc3MgT3V0Qm91bmRWaWRlb1N0YXRzIHtcbiAgICBieXRlc1NlbnQ6IG51bWJlcjtcbiAgICBpZDogc3RyaW5nO1xuICAgIGxvY2FsSWQ6IHN0cmluZztcbiAgICBwYWNrZXRzU2VudDogbnVtYmVyO1xuICAgIHJlbW90ZVRpbWVzdGFtcDogbnVtYmVyO1xuICAgIHRpbWVzdGFtcDogbnVtYmVyO1xufVxuXG4vKipcbiAqIE91dGJvdW5kIFN0YXRzIGNvbGxlY3RlZCBmcm9tIHRoZSBSVEMgU3RhdHMgUmVwb3J0XG4gKi9cbmV4cG9ydCBjbGFzcyBPdXRCb3VuZFJUUFN0YXRzIHtcbiAgICBraW5kOiBzdHJpbmc7XG4gICAgYnl0ZXNTZW50OiBudW1iZXI7XG4gICAgaWQ6IHN0cmluZztcbiAgICBsb2NhbElkOiBzdHJpbmc7XG4gICAgcGFja2V0c1NlbnQ6IG51bWJlcjtcbiAgICByZW1vdGVUaW1lc3RhbXA6IG51bWJlcjtcbiAgICB0aW1lc3RhbXA6IG51bWJlcjtcbn1cbiIsIi8vIENvcHlyaWdodCBFcGljIEdhbWVzLCBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG5cbmltcG9ydCB7IExvZ2dlciB9IGZyb20gJy4uL0xvZ2dlci9Mb2dnZXInO1xuaW1wb3J0IHsgQ29uZmlnLCBPcHRpb25QYXJhbWV0ZXJzLCBGbGFncyB9IGZyb20gJy4uL0NvbmZpZy9Db25maWcnO1xuaW1wb3J0IHsgQWdncmVnYXRlZFN0YXRzIH0gZnJvbSAnLi9BZ2dyZWdhdGVkU3RhdHMnO1xuaW1wb3J0IHsgcGFyc2VSdHBQYXJhbWV0ZXJzLCBzcGxpdFNlY3Rpb25zIH0gZnJvbSAnc2RwJztcbmltcG9ydCB7IFJUQ1V0aWxzIH0gZnJvbSAnLi4vVXRpbC9SVENVdGlscyc7XG5cbi8qKlxuICogSGFuZGxlcyB0aGUgUGVlciBDb25uZWN0aW9uXG4gKi9cbmV4cG9ydCBjbGFzcyBQZWVyQ29ubmVjdGlvbkNvbnRyb2xsZXIge1xuICAgIHBlZXJDb25uZWN0aW9uOiBSVENQZWVyQ29ubmVjdGlvbjtcbiAgICBhZ2dyZWdhdGVkU3RhdHM6IEFnZ3JlZ2F0ZWRTdGF0cztcbiAgICBjb25maWc6IENvbmZpZztcbiAgICBwcmVmZXJyZWRDb2RlYzogc3RyaW5nO1xuICAgIHVwZGF0ZUNvZGVjU2VsZWN0aW9uOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlIGEgbmV3IFJUQyBQZWVyIENvbm5lY3Rpb24gY2xpZW50XG4gICAgICogQHBhcmFtIG9wdGlvbnMgLSBQZWVyIGNvbm5lY3Rpb24gT3B0aW9uc1xuICAgICAqIEBwYXJhbSBjb25maWcgLSBUaGUgY29uZmlnIGZvciBvdXIgUFMgZXhwZXJpZW5jZS5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgb3B0aW9uczogUlRDQ29uZmlndXJhdGlvbixcbiAgICAgICAgY29uZmlnOiBDb25maWcsXG4gICAgICAgIHByZWZlcnJlZENvZGVjOiBzdHJpbmdcbiAgICApIHtcbiAgICAgICAgdGhpcy5jb25maWcgPSBjb25maWc7XG4gICAgICAgIHRoaXMuY3JlYXRlUGVlckNvbm5lY3Rpb24ob3B0aW9ucywgcHJlZmVycmVkQ29kZWMpO1xuICAgIH1cblxuICAgIGNyZWF0ZVBlZXJDb25uZWN0aW9uKG9wdGlvbnM6IFJUQ0NvbmZpZ3VyYXRpb24sIHByZWZlcnJlZENvZGVjOiBzdHJpbmcpIHtcbiAgICAgICAgLy8gU2V0IHRoZSBJQ0UgdHJhbnNwb3J0IHRvIHJlbGF5IGlmIFRVUk4gZW5hYmxlZFxuICAgICAgICBpZiAodGhpcy5jb25maWcuaXNGbGFnRW5hYmxlZChGbGFncy5Gb3JjZVRVUk4pKSB7XG4gICAgICAgICAgICBvcHRpb25zLmljZVRyYW5zcG9ydFBvbGljeSA9ICdyZWxheSc7XG4gICAgICAgICAgICBMb2dnZXIuTG9nKFxuICAgICAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAgICAgJ0ZvcmNpbmcgVFVSTiB1c2FnZSBieSBzZXR0aW5nIElDRSBUcmFuc3BvcnQgUG9saWN5IGluIHBlZXIgY29ubmVjdGlvbiBjb25maWcuJ1xuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGJ1aWxkIGEgbmV3IHBlZXIgY29ubmVjdGlvbiB3aXRoIHRoZSBvcHRpb25zXG4gICAgICAgIHRoaXMucGVlckNvbm5lY3Rpb24gPSBuZXcgUlRDUGVlckNvbm5lY3Rpb24ob3B0aW9ucyk7XG4gICAgICAgIHRoaXMucGVlckNvbm5lY3Rpb24ub25zaWduYWxpbmdzdGF0ZWNoYW5nZSA9IChldjogRXZlbnQpID0+XG4gICAgICAgICAgICB0aGlzLmhhbmRsZVNpZ25hbFN0YXRlQ2hhbmdlKGV2KTtcbiAgICAgICAgdGhpcy5wZWVyQ29ubmVjdGlvbi5vbmljZWNvbm5lY3Rpb25zdGF0ZWNoYW5nZSA9IChldjogRXZlbnQpID0+XG4gICAgICAgICAgICB0aGlzLmhhbmRsZUljZUNvbm5lY3Rpb25TdGF0ZUNoYW5nZShldik7XG4gICAgICAgIHRoaXMucGVlckNvbm5lY3Rpb24ub25pY2VnYXRoZXJpbmdzdGF0ZWNoYW5nZSA9IChldjogRXZlbnQpID0+XG4gICAgICAgICAgICB0aGlzLmhhbmRsZUljZUdhdGhlcmluZ1N0YXRlQ2hhbmdlKGV2KTtcbiAgICAgICAgdGhpcy5wZWVyQ29ubmVjdGlvbi5vbnRyYWNrID0gKGV2OiBSVENUcmFja0V2ZW50KSA9PlxuICAgICAgICAgICAgdGhpcy5oYW5kbGVPblRyYWNrKGV2KTtcbiAgICAgICAgdGhpcy5wZWVyQ29ubmVjdGlvbi5vbmljZWNhbmRpZGF0ZSA9IChldjogUlRDUGVlckNvbm5lY3Rpb25JY2VFdmVudCkgPT5cbiAgICAgICAgICAgIHRoaXMuaGFuZGxlSWNlQ2FuZGlkYXRlKGV2KTtcbiAgICAgICAgdGhpcy5wZWVyQ29ubmVjdGlvbi5vbmRhdGFjaGFubmVsID0gKGV2OiBSVENEYXRhQ2hhbm5lbEV2ZW50KSA9PlxuICAgICAgICAgICAgdGhpcy5oYW5kbGVEYXRhQ2hhbm5lbChldik7XG4gICAgICAgIHRoaXMuYWdncmVnYXRlZFN0YXRzID0gbmV3IEFnZ3JlZ2F0ZWRTdGF0cygpO1xuICAgICAgICB0aGlzLnByZWZlcnJlZENvZGVjID0gcHJlZmVycmVkQ29kZWM7XG4gICAgICAgIHRoaXMudXBkYXRlQ29kZWNTZWxlY3Rpb24gPSB0cnVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZSBhbiBvZmZlciBmb3IgdGhlIFdlYiBSVEMgaGFuZHNoYWtlIGFuZCBzZW5kIHRoZSBvZmZlciB0byB0aGUgc2lnbmFsaW5nIHNlcnZlciB2aWEgd2Vic29ja2V0XG4gICAgICogQHBhcmFtIG9mZmVyT3B0aW9ucyAtIFJUQyBPZmZlciBPcHRpb25zXG4gICAgICovXG4gICAgYXN5bmMgY3JlYXRlT2ZmZXIob2ZmZXJPcHRpb25zOiBSVENPZmZlck9wdGlvbnMsIGNvbmZpZzogQ29uZmlnKSB7XG4gICAgICAgIExvZ2dlci5Mb2coTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSwgJ0NyZWF0ZSBPZmZlcicsIDYpO1xuXG4gICAgICAgIGNvbnN0IGlzTG9jYWxob3N0Q29ubmVjdGlvbiA9XG4gICAgICAgICAgICBsb2NhdGlvbi5ob3N0bmFtZSA9PT0gJ2xvY2FsaG9zdCcgfHxcbiAgICAgICAgICAgIGxvY2F0aW9uLmhvc3RuYW1lID09PSAnMTI3LjAuMC4xJztcbiAgICAgICAgY29uc3QgaXNIdHRwc0Nvbm5lY3Rpb24gPSBsb2NhdGlvbi5wcm90b2NvbCA9PT0gJ2h0dHBzOic7XG4gICAgICAgIGxldCB1c2VNaWMgPSBjb25maWcuaXNGbGFnRW5hYmxlZChGbGFncy5Vc2VNaWMpO1xuICAgICAgICBpZiAodXNlTWljICYmICEoaXNMb2NhbGhvc3RDb25uZWN0aW9uIHx8IGlzSHR0cHNDb25uZWN0aW9uKSkge1xuICAgICAgICAgICAgdXNlTWljID0gZmFsc2U7XG4gICAgICAgICAgICBMb2dnZXIuRXJyb3IoXG4gICAgICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICAgICAnTWljcm9waG9uZSBhY2Nlc3MgaW4gdGhlIGJyb3dzZXIgd2lsbCBub3Qgd29yayBpZiB5b3UgYXJlIG5vdCBvbiBIVFRQUyBvciBsb2NhbGhvc3QuIERpc2FibGluZyBtaWMgYWNjZXNzLidcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBMb2dnZXIuRXJyb3IoXG4gICAgICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICAgICBcIkZvciB0ZXN0aW5nIHlvdSBjYW4gZW5hYmxlIEhUVFAgbWljcm9waG9uZSBhY2Nlc3MgQ2hyb21lIGJ5IHZpc2l0aW5nIGNocm9tZTovL2ZsYWdzLyBhbmQgZW5hYmxpbmcgJ3Vuc2FmZWx5LXRyZWF0LWluc2VjdXJlLW9yaWdpbi1hcy1zZWN1cmUnXCJcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnNldHVwVHJhbnNjZWl2ZXJzQXN5bmModXNlTWljKS5maW5hbGx5KCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMucGVlckNvbm5lY3Rpb25cbiAgICAgICAgICAgICAgICA/LmNyZWF0ZU9mZmVyKG9mZmVyT3B0aW9ucylcbiAgICAgICAgICAgICAgICAudGhlbigob2ZmZXI6IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbkluaXQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zaG93VGV4dE92ZXJsYXlDb25uZWN0aW5nKCk7XG4gICAgICAgICAgICAgICAgICAgIG9mZmVyLnNkcCA9IHRoaXMubXVuZ2VTRFAob2ZmZXIuc2RwLCB1c2VNaWMpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnBlZXJDb25uZWN0aW9uPy5zZXRMb2NhbERlc2NyaXB0aW9uKG9mZmVyKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vblNlbmRXZWJSVENPZmZlcihvZmZlcik7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2goKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNob3dUZXh0T3ZlcmxheVNldHVwRmFpbHVyZSgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKlxuICAgICAqL1xuICAgIGFzeW5jIHJlY2VpdmVPZmZlcihvZmZlcjogUlRDU2Vzc2lvbkRlc2NyaXB0aW9uSW5pdCwgY29uZmlnOiBDb25maWcpIHtcbiAgICAgICAgTG9nZ2VyLkxvZyhMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLCAnUmVjZWl2ZSBPZmZlcicsIDYpO1xuXG4gICAgICAgIHRoaXMucGVlckNvbm5lY3Rpb24/LnNldFJlbW90ZURlc2NyaXB0aW9uKG9mZmVyKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGlzTG9jYWxob3N0Q29ubmVjdGlvbiA9XG4gICAgICAgICAgICAgICAgbG9jYXRpb24uaG9zdG5hbWUgPT09ICdsb2NhbGhvc3QnIHx8XG4gICAgICAgICAgICAgICAgbG9jYXRpb24uaG9zdG5hbWUgPT09ICcxMjcuMC4wLjEnO1xuICAgICAgICAgICAgY29uc3QgaXNIdHRwc0Nvbm5lY3Rpb24gPSBsb2NhdGlvbi5wcm90b2NvbCA9PT0gJ2h0dHBzOic7XG4gICAgICAgICAgICBsZXQgdXNlTWljID0gY29uZmlnLmlzRmxhZ0VuYWJsZWQoRmxhZ3MuVXNlTWljKTtcbiAgICAgICAgICAgIGlmICh1c2VNaWMgJiYgIShpc0xvY2FsaG9zdENvbm5lY3Rpb24gfHwgaXNIdHRwc0Nvbm5lY3Rpb24pKSB7XG4gICAgICAgICAgICAgICAgdXNlTWljID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLkVycm9yKFxuICAgICAgICAgICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgICAgICAgICAnTWljcm9waG9uZSBhY2Nlc3MgaW4gdGhlIGJyb3dzZXIgd2lsbCBub3Qgd29yayBpZiB5b3UgYXJlIG5vdCBvbiBIVFRQUyBvciBsb2NhbGhvc3QuIERpc2FibGluZyBtaWMgYWNjZXNzLidcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIExvZ2dlci5FcnJvcihcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICAgICAgICAgXCJGb3IgdGVzdGluZyB5b3UgY2FuIGVuYWJsZSBIVFRQIG1pY3JvcGhvbmUgYWNjZXNzIENocm9tZSBieSB2aXNpdGluZyBjaHJvbWU6Ly9mbGFncy8gYW5kIGVuYWJsaW5nICd1bnNhZmVseS10cmVhdC1pbnNlY3VyZS1vcmlnaW4tYXMtc2VjdXJlJ1wiXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5zZXR1cFRyYW5zY2VpdmVyc0FzeW5jKHVzZU1pYykuZmluYWxseSgoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5wZWVyQ29ubmVjdGlvblxuICAgICAgICAgICAgICAgICAgICA/LmNyZWF0ZUFuc3dlcigpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKChBbnN3ZXI6IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbkluaXQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIEFuc3dlci5zZHAgPSB0aGlzLm11bmdlU0RQKEFuc3dlci5zZHAsIHVzZU1pYyk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5wZWVyQ29ubmVjdGlvbj8uc2V0TG9jYWxEZXNjcmlwdGlvbihBbnN3ZXIpO1xuICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm9uU2VuZFdlYlJUQ0Fuc3dlcihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBlZXJDb25uZWN0aW9uPy5jdXJyZW50TG9jYWxEZXNjcmlwdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgLmNhdGNoKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIExvZ2dlci5FcnJvcihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICdjcmVhdGVBbnN3ZXIoKSBmYWlsZWQnXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcblxuICAgICAgICAvLyBVZ2x5IHN5bnRheCwgYnV0IHRoaXMgYWNoaWV2ZXMgdGhlIGludGVyc2VjdGlvbiBvZiB0aGUgYnJvd3NlciBzdXBwb3J0ZWQgbGlzdCBhbmQgdGhlIFVFIHN1cHBvcnRlZCBsaXN0XG4gICAgICAgIHRoaXMuY29uZmlnLnNldE9wdGlvblNldHRpbmdPcHRpb25zKFxuICAgICAgICAgICAgT3B0aW9uUGFyYW1ldGVycy5QcmVmZXJyZWRDb2RlYyxcbiAgICAgICAgICAgIHRoaXMucGFyc2VBdmFpbGFibGVDb2RlY3Mob2ZmZXIpLmZpbHRlcigodmFsdWUpID0+XG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWdcbiAgICAgICAgICAgICAgICAgICAgLmdldFNldHRpbmdPcHRpb24oT3B0aW9uUGFyYW1ldGVycy5QcmVmZXJyZWRDb2RlYylcbiAgICAgICAgICAgICAgICAgICAgLm9wdGlvbnMuaW5jbHVkZXModmFsdWUpXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSBSZW1vdGUgRGVzY3JpcHRvciBmcm9tIHRoZSBzaWduYWxpbmcgc2VydmVyIHRvIHRoZSBSVEMgUGVlciBDb25uZWN0aW9uXG4gICAgICogQHBhcmFtIGFuc3dlciAtIFJUQyBTZXNzaW9uIERlc2NyaXB0b3IgZnJvbSB0aGUgU2lnbmFsaW5nIFNlcnZlclxuICAgICAqL1xuICAgIHJlY2VpdmVBbnN3ZXIoYW5zd2VyOiBSVENTZXNzaW9uRGVzY3JpcHRpb25Jbml0KSB7XG4gICAgICAgIHRoaXMucGVlckNvbm5lY3Rpb24/LnNldFJlbW90ZURlc2NyaXB0aW9uKGFuc3dlcik7XG4gICAgICAgIC8vIFVnbHkgc3ludGF4LCBidXQgdGhpcyBhY2hpZXZlcyB0aGUgaW50ZXJzZWN0aW9uIG9mIHRoZSBicm93c2VyIHN1cHBvcnRlZCBsaXN0IGFuZCB0aGUgVUUgc3VwcG9ydGVkIGxpc3RcbiAgICAgICAgdGhpcy5jb25maWcuc2V0T3B0aW9uU2V0dGluZ09wdGlvbnMoXG4gICAgICAgICAgICBPcHRpb25QYXJhbWV0ZXJzLlByZWZlcnJlZENvZGVjLFxuICAgICAgICAgICAgdGhpcy5wYXJzZUF2YWlsYWJsZUNvZGVjcyhhbnN3ZXIpLmZpbHRlcigodmFsdWUpID0+XG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWdcbiAgICAgICAgICAgICAgICAgICAgLmdldFNldHRpbmdPcHRpb24oT3B0aW9uUGFyYW1ldGVycy5QcmVmZXJyZWRDb2RlYylcbiAgICAgICAgICAgICAgICAgICAgLm9wdGlvbnMuaW5jbHVkZXModmFsdWUpXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2VuZXJhdGUgQWdncmVnYXRlZCBTdGF0cyBhbmQgdGhlbiBmaXJlIGEgb25WaWRlbyBTdGF0cyBldmVudFxuICAgICAqL1xuICAgIGdlbmVyYXRlU3RhdHMoKSB7XG4gICAgICAgIHRoaXMucGVlckNvbm5lY3Rpb24/LmdldFN0YXRzKG51bGwpLnRoZW4oKFN0YXRzRGF0YTogUlRDU3RhdHNSZXBvcnQpID0+IHtcbiAgICAgICAgICAgIHRoaXMuYWdncmVnYXRlZFN0YXRzLnByb2Nlc3NTdGF0cyhTdGF0c0RhdGEpO1xuICAgICAgICAgICAgdGhpcy5vblZpZGVvU3RhdHModGhpcy5hZ2dyZWdhdGVkU3RhdHMpO1xuXG4gICAgICAgICAgICAvLyBVcGRhdGUgdGhlIHByZWZlcnJlZCBjb2RlYyBzZWxlY3Rpb24gYmFzZWQgb24gd2hhdCB3YXMgYWN0dWFsbHkgbmVnb3RpYXRlZFxuICAgICAgICAgICAgaWYgKHRoaXMudXBkYXRlQ29kZWNTZWxlY3Rpb24pIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZy5zZXRPcHRpb25TZXR0aW5nVmFsdWUoXG4gICAgICAgICAgICAgICAgICAgIE9wdGlvblBhcmFtZXRlcnMuUHJlZmVycmVkQ29kZWMsXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuYWdncmVnYXRlZFN0YXRzLmNvZGVjcy5nZXQoXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmFnZ3JlZ2F0ZWRTdGF0cy5pbmJvdW5kVmlkZW9TdGF0cy5jb2RlY0lkXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDbG9zZSBUaGUgUGVlciBDb25uZWN0aW9uXG4gICAgICovXG4gICAgY2xvc2UoKSB7XG4gICAgICAgIGlmICh0aGlzLnBlZXJDb25uZWN0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLnBlZXJDb25uZWN0aW9uLmNsb3NlKCk7XG4gICAgICAgICAgICB0aGlzLnBlZXJDb25uZWN0aW9uID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1vZGlmeSB0aGUgU2Vzc2lvbiBEZXNjcmlwdG9yXG4gICAgICogQHBhcmFtIHNkcCAtIFNlc3Npb24gRGVzY3JpcHRvciBhcyBhIHN0cmluZ1xuICAgICAqIEBwYXJhbSB1c2VNaWMgLSBJcyB0aGUgbWljcm9waG9uZSBpbiB1c2VcbiAgICAgKiBAcmV0dXJucyBBIG1vZGlmaWVkIFNlc3Npb24gRGVzY3JpcHRvclxuICAgICAqL1xuICAgIG11bmdlU0RQKHNkcDogc3RyaW5nLCB1c2VNaWM6IGJvb2xlYW4pIHtcbiAgICAgICAgbGV0IG11bmdlZFNEUCA9IHNkcC5yZXBsYWNlKFxuICAgICAgICAgICAgLyhhPWZtdHA6XFxkKyAuKmxldmVsLWFzeW1tZXRyeS1hbGxvd2VkPS4qKVxcclxcbi9nbSxcbiAgICAgICAgICAgICckMTt4LWdvb2dsZS1zdGFydC1iaXRyYXRlPTEwMDAwO3gtZ29vZ2xlLW1heC1iaXRyYXRlPTEwMDAwMFxcclxcbidcbiAgICAgICAgKTtcblxuICAgICAgICAvLyBzZXQgbWF4IGJpdHJhdGUgdG8gaGlnaGVzdCBiaXRyYXRlIE9wdXMgc3VwcG9ydHNcbiAgICAgICAgbGV0IGF1ZGlvU0RQID0gJ21heGF2ZXJhZ2ViaXRyYXRlPTUxMDAwMDsnO1xuXG4gICAgICAgIGlmICh1c2VNaWMpIHtcbiAgICAgICAgICAgIC8vIHNldCB0aGUgbWF4IGNhcHR1cmUgcmF0ZSB0byA0OGtoeiAoc28gd2UgY2FuIHNlbmQgaGlnaCBxdWFsaXR5IGF1ZGlvIGZyb20gbWljKVxuICAgICAgICAgICAgYXVkaW9TRFAgKz0gJ3Nwcm9wLW1heGNhcHR1cmVyYXRlPTQ4MDAwOyc7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBGb3JjZSBtb25vIG9yIHN0ZXJlbyBiYXNlZCBvbiB3aGV0aGVyID9mb3JjZU1vbm8gd2FzIHBhc3NlZCBvciBub3RcbiAgICAgICAgYXVkaW9TRFAgKz0gdGhpcy5jb25maWcuaXNGbGFnRW5hYmxlZChGbGFncy5Gb3JjZU1vbm9BdWRpbylcbiAgICAgICAgICAgID8gJ3N0ZXJlbz0wOydcbiAgICAgICAgICAgIDogJ3N0ZXJlbz0xOyc7XG5cbiAgICAgICAgLy8gZW5hYmxlIGluLWJhbmQgZm9yd2FyZCBlcnJvciBjb3JyZWN0aW9uIGZvciBvcHVzIGF1ZGlvXG4gICAgICAgIGF1ZGlvU0RQICs9ICd1c2VpbmJhbmRmZWM9MSc7XG5cbiAgICAgICAgLy8gV2UgdXNlIHRoZSBsaW5lICd1c2VpbmJhbmRmZWM9MScgKHdoaWNoIE9wdXMgdXNlcykgdG8gc2V0IG91ciBPcHVzIHNwZWNpZmljIGF1ZGlvIHBhcmFtZXRlcnMuXG4gICAgICAgIG11bmdlZFNEUCA9IG11bmdlZFNEUC5yZXBsYWNlKCd1c2VpbmJhbmRmZWM9MScsIGF1ZGlvU0RQKTtcblxuICAgICAgICByZXR1cm4gbXVuZ2VkU0RQO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFdoZW4gYSBJY2UgQ2FuZGlkYXRlIGlzIHJlY2VpdmVkIGFkZCB0byB0aGUgUlRDIFBlZXIgQ29ubmVjdGlvblxuICAgICAqIEBwYXJhbSBpY2VDYW5kaWRhdGUgLSBSVEMgSWNlIENhbmRpZGF0ZSBmcm9tIHRoZSBTaWduYWxpbmcgU2VydmVyXG4gICAgICovXG4gICAgaGFuZGxlT25JY2UoaWNlQ2FuZGlkYXRlOiBSVENJY2VDYW5kaWRhdGUpIHtcbiAgICAgICAgTG9nZ2VyLkxvZyhMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLCAncGVlcmNvbm5lY3Rpb24gaGFuZGxlT25JY2UnLCA2KTtcblxuICAgICAgICAvLyAvLyBpZiBmb3JjaW5nIFRVUk4sIHJlamVjdCBhbnkgY2FuZGlkYXRlcyBub3QgcmVsYXlcbiAgICAgICAgaWYgKHRoaXMuY29uZmlnLmlzRmxhZ0VuYWJsZWQoRmxhZ3MuRm9yY2VUVVJOKSkge1xuICAgICAgICAgICAgLy8gY2hlY2sgaWYgbm8gcmVsYXkgYWRkcmVzcyBpcyBmb3VuZCwgaWYgc28sIHdlIGFyZSBhc3N1bWluZyBpdCBtZWFucyBubyBUVVJOIHNlcnZlclxuICAgICAgICAgICAgaWYgKGljZUNhbmRpZGF0ZS5jYW5kaWRhdGUuaW5kZXhPZigncmVsYXknKSA8IDApIHtcbiAgICAgICAgICAgICAgICBMb2dnZXIuSW5mbyhcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICAgICAgICAgYERyb3BwaW5nIGNhbmRpZGF0ZSBiZWNhdXNlIGl0IHdhcyBub3QgVFVSTiByZWxheS4gfCBUeXBlPSAke2ljZUNhbmRpZGF0ZS50eXBlfSB8IFByb3RvY29sPSAke2ljZUNhbmRpZGF0ZS5wcm90b2NvbH0gfCBBZGRyZXNzPSR7aWNlQ2FuZGlkYXRlLmFkZHJlc3N9IHwgUG9ydD0ke2ljZUNhbmRpZGF0ZS5wb3J0fSB8YCxcbiAgICAgICAgICAgICAgICAgICAgNlxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5wZWVyQ29ubmVjdGlvbj8uYWRkSWNlQ2FuZGlkYXRlKGljZUNhbmRpZGF0ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogV2hlbiB0aGUgUlRDIFBlZXIgQ29ubmVjdGlvbiBTaWduYWxpbmcgc2VydmVyIHN0YXRlIENoYW5nZXNcbiAgICAgKiBAcGFyYW0gc3RhdGUgLSBTaWduYWxpbmcgU2VydmVyIFN0YXRlIENoYW5nZSBFdmVudFxuICAgICAqL1xuICAgIGhhbmRsZVNpZ25hbFN0YXRlQ2hhbmdlKHN0YXRlOiBFdmVudCkge1xuICAgICAgICBMb2dnZXIuTG9nKFxuICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICdzaWduYWxpbmcgc3RhdGUgY2hhbmdlOiAnICsgc3RhdGUsXG4gICAgICAgICAgICA2XG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlIHdoZW4gdGhlIEljZSBDb25uZWN0aW9uIFN0YXRlIENoYW5nZXNcbiAgICAgKiBAcGFyYW0gc3RhdGUgLSBJY2UgQ29ubmVjdGlvbiBTdGF0ZVxuICAgICAqL1xuICAgIGhhbmRsZUljZUNvbm5lY3Rpb25TdGF0ZUNoYW5nZShzdGF0ZTogRXZlbnQpIHtcbiAgICAgICAgTG9nZ2VyLkxvZyhcbiAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAnaWNlIGNvbm5lY3Rpb24gc3RhdGUgY2hhbmdlOiAnICsgc3RhdGUsXG4gICAgICAgICAgICA2XG4gICAgICAgICk7XG4gICAgICAgIHRoaXMub25JY2VDb25uZWN0aW9uU3RhdGVDaGFuZ2Uoc3RhdGUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZSB3aGVuIHRoZSBJY2UgR2F0aGVyaW5nIFN0YXRlIENoYW5nZXNcbiAgICAgKiBAcGFyYW0gc3RhdGUgLSBJY2UgR2F0aGVyaW5nIFN0YXRlIENoYW5nZVxuICAgICAqL1xuICAgIGhhbmRsZUljZUdhdGhlcmluZ1N0YXRlQ2hhbmdlKHN0YXRlOiBFdmVudCkge1xuICAgICAgICBMb2dnZXIuTG9nKFxuICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICdpY2UgZ2F0aGVyaW5nIHN0YXRlIGNoYW5nZTogJyArIEpTT04uc3RyaW5naWZ5KHN0YXRlKSxcbiAgICAgICAgICAgIDZcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBY3RpdmF0ZXMgdGhlIG9uVHJhY2sgbWV0aG9kXG4gICAgICogQHBhcmFtIGV2ZW50IC0gVGhlIHdlYlJ0YyB0cmFjayBldmVudFxuICAgICAqL1xuICAgIGhhbmRsZU9uVHJhY2soZXZlbnQ6IFJUQ1RyYWNrRXZlbnQpIHtcbiAgICAgICAgdGhpcy5vblRyYWNrKGV2ZW50KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBY3RpdmF0ZXMgdGhlIG9uUGVlckljZUNhbmRpZGF0ZVxuICAgICAqIEBwYXJhbSBldmVudCAtIFRoZSBwZWVyIGljZSBjYW5kaWRhdGVcbiAgICAgKi9cbiAgICBoYW5kbGVJY2VDYW5kaWRhdGUoZXZlbnQ6IFJUQ1BlZXJDb25uZWN0aW9uSWNlRXZlbnQpIHtcbiAgICAgICAgdGhpcy5vblBlZXJJY2VDYW5kaWRhdGUoZXZlbnQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFjdGl2YXRlcyB0aGUgb25EYXRhQ2hhbm5lbFxuICAgICAqIEBwYXJhbSBldmVudCAtIFRoZSBwZWVyJ3MgZGF0YSBjaGFubmVsXG4gICAgICovXG4gICAgaGFuZGxlRGF0YUNoYW5uZWwoZXZlbnQ6IFJUQ0RhdGFDaGFubmVsRXZlbnQpIHtcbiAgICAgICAgdGhpcy5vbkRhdGFDaGFubmVsKGV2ZW50KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBbiBvdmVycmlkZSBtZXRob2QgZm9yIG9uVHJhY2sgZm9yIHVzZSBvdXRzaWRlIG9mIHRoZSBQZWVyQ29ubmVjdGlvbkNvbnRyb2xsZXJcbiAgICAgKiBAcGFyYW0gdHJhY2tFdmVudCAtIFRoZSB3ZWJSdGMgdHJhY2sgZXZlbnRcbiAgICAgKi9cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgb25UcmFjayh0cmFja0V2ZW50OiBSVENUcmFja0V2ZW50KSB7XG4gICAgICAgIC8vIERlZmF1bHQgRnVuY3Rpb25hbGl0eTogRG8gTm90aGluZ1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFuIG92ZXJyaWRlIG1ldGhvZCBmb3Igb25JY2VDb25uZWN0aW9uU3RhdGVDaGFuZ2UgZm9yIHVzZSBvdXRzaWRlIG9mIHRoZSBQZWVyQ29ubmVjdGlvbkNvbnRyb2xsZXJcbiAgICAgKiBAcGFyYW0gZXZlbnQgLSBUaGUgd2ViUnRjIGljZWNvbm5lY3Rpb25zdGF0ZWNoYW5nZSBldmVudFxuICAgICAqL1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICBvbkljZUNvbm5lY3Rpb25TdGF0ZUNoYW5nZShldmVudDogRXZlbnQpIHtcbiAgICAgICAgLy8gRGVmYXVsdCBGdW5jdGlvbmFsaXR5OiBEbyBOb3RoaW5nXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQW4gb3ZlcnJpZGUgbWV0aG9kIGZvciBvblBlZXJJY2VDYW5kaWRhdGUgZm9yIHVzZSBvdXRzaWRlIG9mIHRoZSBQZWVyQ29ubmVjdGlvbkNvbnRyb2xsZXJcbiAgICAgKiBAcGFyYW0gcGVlckNvbm5lY3Rpb25JY2VFdmVudCAtIFRoZSBwZWVyIGljZSBjYW5kaWRhdGVcbiAgICAgKi9cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgb25QZWVySWNlQ2FuZGlkYXRlKHBlZXJDb25uZWN0aW9uSWNlRXZlbnQ6IFJUQ1BlZXJDb25uZWN0aW9uSWNlRXZlbnQpIHtcbiAgICAgICAgLy8gRGVmYXVsdCBGdW5jdGlvbmFsaXR5OiBEbyBOb3RoaW5nXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQW4gb3ZlcnJpZGUgbWV0aG9kIGZvciBvbkRhdGFDaGFubmVsIGZvciB1c2Ugb3V0c2lkZSBvZiB0aGUgUGVlckNvbm5lY3Rpb25Db250cm9sbGVyXG4gICAgICogQHBhcmFtIGRhdGFjaGFubmVsRXZlbnQgLSBUaGUgcGVlcidzIGRhdGEgY2hhbm5lbFxuICAgICAqL1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICBvbkRhdGFDaGFubmVsKGRhdGFjaGFubmVsRXZlbnQ6IFJUQ0RhdGFDaGFubmVsRXZlbnQpIHtcbiAgICAgICAgLy8gRGVmYXVsdCBGdW5jdGlvbmFsaXR5OiBEbyBOb3RoaW5nXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0dXAgdHJhY2tzIG9uIHRoZSBSVEMgUGVlciBDb25uZWN0aW9uXG4gICAgICogQHBhcmFtIHVzZU1pYyAtIGlzIG1pYyBpbiB1c2VcbiAgICAgKi9cbiAgICBhc3luYyBzZXR1cFRyYW5zY2VpdmVyc0FzeW5jKHVzZU1pYzogYm9vbGVhbikge1xuICAgICAgICBjb25zdCBoYXNUcmFuc2NlaXZlcnMgPVxuICAgICAgICAgICAgdGhpcy5wZWVyQ29ubmVjdGlvbj8uZ2V0VHJhbnNjZWl2ZXJzKCkubGVuZ3RoID4gMDtcblxuICAgICAgICAvLyBTZXR1cCBhIHRyYW5zY2VpdmVyIGZvciBnZXR0aW5nIFVFIHZpZGVvXG4gICAgICAgIHRoaXMucGVlckNvbm5lY3Rpb24/LmFkZFRyYW5zY2VpdmVyKCd2aWRlbycsIHsgZGlyZWN0aW9uOiAncmVjdm9ubHknIH0pO1xuXG4gICAgICAgIC8vIFdlIGNhbiBvbmx5IHNldCBwcmVmZXJyZWMgY29kZWMgb24gQ2hyb21lXG4gICAgICAgIGlmIChSVENSdHBSZWNlaXZlci5nZXRDYXBhYmlsaXRpZXMgJiYgdGhpcy5wcmVmZXJyZWRDb2RlYyAhPSAnJykge1xuICAgICAgICAgICAgZm9yIChjb25zdCB0cmFuc2NlaXZlciBvZiB0aGlzLnBlZXJDb25uZWN0aW9uPy5nZXRUcmFuc2NlaXZlcnMoKSA/PyBbXSkge1xuICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgdHJhbnNjZWl2ZXIgJiYgIFxuICAgICAgICAgICAgICAgICAgICB0cmFuc2NlaXZlci5yZWNlaXZlciAmJlxuICAgICAgICAgICAgICAgICAgICB0cmFuc2NlaXZlci5yZWNlaXZlci50cmFjayAmJlxuICAgICAgICAgICAgICAgICAgICB0cmFuc2NlaXZlci5yZWNlaXZlci50cmFjay5raW5kID09PSAndmlkZW8nICYmXG4gICAgICAgICAgICAgICAgICAgIC8vIEFzIG9mIDA2LzIwMjMsIEZpcmVGb3ggaGFzIGFkZGVkIFJUQ1J0cFJlY2VpdmVyLmdldENhcGFiaWxpdGllcywgYnV0IGhhc24ndCBhZGRlZCB0aGUgYWJpbGl0eSB0byBzZXQgY29kZWMgcHJlZmVyZW5jZXNcbiAgICAgICAgICAgICAgICAgICAgdHJhbnNjZWl2ZXIuc2V0Q29kZWNQcmVmZXJlbmNlc1xuICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBwcmVmZXJyZWRSVFBDb2RlYyA9IHRoaXMucHJlZmVycmVkQ29kZWMuc3BsaXQoJyAnKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY29kZWNzID0gW1xuICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbWVUeXBlOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAndmlkZW8vJyArIHByZWZlcnJlZFJUUENvZGVjWzBdIC8qIE5hbWUgKi8sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvY2tSYXRlOiA5MDAwMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZHBGbXRwTGluZTogcHJlZmVycmVkUlRQQ29kZWNbMV0gLyogc2RwRm10cExpbmUgKi9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPyBwcmVmZXJyZWRSVFBDb2RlY1sxXVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6ICcnXG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIF07XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jb25maWdcbiAgICAgICAgICAgICAgICAgICAgICAgIC5nZXRTZXR0aW5nT3B0aW9uKE9wdGlvblBhcmFtZXRlcnMuUHJlZmVycmVkQ29kZWMpXG4gICAgICAgICAgICAgICAgICAgICAgICAub3B0aW9ucy5maWx0ZXIoKG9wdGlvbikgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJlbW92ZSB0aGUgcHJlZmVycmVkIGNvZGVjIGZyb20gdGhlIGxpc3Qgb2YgcG9zc2libGUgY29kZWNzIGFzIHdlJ3ZlIHNldCBpdCBhbHJlYWR5XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9wdGlvbiAhPSB0aGlzLnByZWZlcnJlZENvZGVjO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC5mb3JFYWNoKChvcHRpb24pID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBBbW1lbmQgdGhlIHJlc3Qgb2YgdGhlIGJyb3dzZXJzIHN1cHBvcnRlZCBjb2RlY3NcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBhbHRDb2RlYyA9IG9wdGlvbi5zcGxpdCgnICcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvZGVjcy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWltZVR5cGU6ICd2aWRlby8nICsgYWx0Q29kZWNbMF0gLyogTmFtZSAqLyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvY2tSYXRlOiA5MDAwMCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2RwRm10cExpbmU6IGFsdENvZGVjWzFdIC8qIHNkcEZtdHBMaW5lICovXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IGFsdENvZGVjWzFdXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6ICcnXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGNvZGVjIG9mIGNvZGVjcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGNvZGVjLnNkcEZtdHBMaW5lID09PSAnJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdlIGNhbid0IGR5bmFtaWNhbGx5IGFkZCBtZW1iZXJzIHRvIHRoZSBjb2RlYywgc28gaW5zdGVhZCByZW1vdmUgdGhlIGZpZWxkIGlmIGl0J3MgZW1wdHlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgY29kZWMuc2RwRm10cExpbmU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB0cmFuc2NlaXZlci5zZXRDb2RlY1ByZWZlcmVuY2VzKGNvZGVjcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gU2V0dXAgYSB0cmFuc2NlaXZlciBmb3Igc2VuZGluZyBtaWMgYXVkaW8gdG8gVUUgYW5kIHJlY2VpdmluZyBhdWRpbyBmcm9tIFVFXG4gICAgICAgIGlmICghdXNlTWljKSB7XG4gICAgICAgICAgICB0aGlzLnBlZXJDb25uZWN0aW9uPy5hZGRUcmFuc2NlaXZlcignYXVkaW8nLCB7XG4gICAgICAgICAgICAgICAgZGlyZWN0aW9uOiAncmVjdm9ubHknXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIHNldCB0aGUgYXVkaW8gb3B0aW9ucyBiYXNlZCBvbiBtaWMgdXNhZ2VcbiAgICAgICAgICAgIGNvbnN0IGF1ZGlvT3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICBhdXRvR2FpbkNvbnRyb2w6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGNoYW5uZWxDb3VudDogMSxcbiAgICAgICAgICAgICAgICBlY2hvQ2FuY2VsbGF0aW9uOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBsYXRlbmN5OiAwLFxuICAgICAgICAgICAgICAgIG5vaXNlU3VwcHJlc3Npb246IGZhbHNlLFxuICAgICAgICAgICAgICAgIHNhbXBsZVJhdGU6IDQ4MDAwLFxuICAgICAgICAgICAgICAgIHNhbXBsZVNpemU6IDE2LFxuICAgICAgICAgICAgICAgIHZvbHVtZTogMS4wXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIHNldCB0aGUgbWVkaWEgc2VuZCBvcHRpb25zXG4gICAgICAgICAgICBjb25zdCBtZWRpYVNlbmRPcHRpb25zOiBNZWRpYVN0cmVhbUNvbnN0cmFpbnRzID0ge1xuICAgICAgICAgICAgICAgIHZpZGVvOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBhdWRpbzogYXVkaW9PcHRpb25zXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAvLyBOb3RlIHVzaW5nIG1pYyBvbiBhbmRyb2lkIGNocm9tZSByZXF1aXJlcyBTU0wgb3IgY2hyb21lOi8vZmxhZ3MvIFwidW5zYWZlbHktdHJlYXQtaW5zZWN1cmUtb3JpZ2luLWFzLXNlY3VyZVwiXG4gICAgICAgICAgICBjb25zdCBzdHJlYW0gPSBhd2FpdCBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShcbiAgICAgICAgICAgICAgICBtZWRpYVNlbmRPcHRpb25zXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgaWYgKHN0cmVhbSkge1xuICAgICAgICAgICAgICAgIGlmIChoYXNUcmFuc2NlaXZlcnMpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCB0cmFuc2NlaXZlciBvZiB0aGlzLnBlZXJDb25uZWN0aW9uPy5nZXRUcmFuc2NlaXZlcnMoKSA/PyBbXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFJUQ1V0aWxzLmNhblRyYW5zY2VpdmVyUmVjZWl2ZUF1ZGlvKHRyYW5zY2VpdmVyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3QgdHJhY2sgb2Ygc3RyZWFtLmdldFRyYWNrcygpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0cmFjay5raW5kICYmIHRyYWNrLmtpbmQgPT0gJ2F1ZGlvJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNjZWl2ZXIuc2VuZGVyLnJlcGxhY2VUcmFjayh0cmFjayk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2NlaXZlci5kaXJlY3Rpb24gPSAnc2VuZHJlY3YnO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCB0cmFjayBvZiBzdHJlYW0uZ2V0VHJhY2tzKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0cmFjay5raW5kICYmIHRyYWNrLmtpbmQgPT0gJ2F1ZGlvJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGVlckNvbm5lY3Rpb24/LmFkZFRyYW5zY2VpdmVyKHRyYWNrLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpcmVjdGlvbjogJ3NlbmRyZWN2J1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnBlZXJDb25uZWN0aW9uPy5hZGRUcmFuc2NlaXZlcignYXVkaW8nLCB7XG4gICAgICAgICAgICAgICAgICAgIGRpcmVjdGlvbjogJ3JlY3Zvbmx5J1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQW5kIG92ZXJyaWRlIGV2ZW50IGZvciB3aGVuIHRoZSB2aWRlbyBzdGF0cyBhcmUgZmlyZWRcbiAgICAgKiBAcGFyYW0gZXZlbnQgLSBBZ2dyZWdhdGVkIFN0YXRzXG4gICAgICovXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFyc1xuICAgIG9uVmlkZW9TdGF0cyhldmVudDogQWdncmVnYXRlZFN0YXRzKSB7XG4gICAgICAgIC8vIERlZmF1bHQgRnVuY3Rpb25hbGl0eTogRG8gTm90aGluZ1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEV2ZW50IHRvIHNlbmQgdGhlIFJUQyBvZmZlciB0byB0aGUgU2lnbmFsaW5nIHNlcnZlclxuICAgICAqIEBwYXJhbSBvZmZlciAtIFJUQyBPZmZlclxuICAgICAqL1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICBvblNlbmRXZWJSVENPZmZlcihvZmZlcjogUlRDU2Vzc2lvbkRlc2NyaXB0aW9uSW5pdCkge1xuICAgICAgICAvLyBEZWZhdWx0IEZ1bmN0aW9uYWxpdHk6IERvIE5vdGhpbmdcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFdmVudCB0byBzZW5kIHRoZSBSVEMgQW5zd2VyIHRvIHRoZSBTaWduYWxpbmcgc2VydmVyXG4gICAgICogQHBhcmFtIGFuc3dlciAtIFJUQyBBbnN3ZXJcbiAgICAgKi9cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgb25TZW5kV2ViUlRDQW5zd2VyKGFuc3dlcjogUlRDU2Vzc2lvbkRlc2NyaXB0aW9uSW5pdCkge1xuICAgICAgICAvLyBEZWZhdWx0IEZ1bmN0aW9uYWxpdHk6IERvIE5vdGhpbmdcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBbiBvdmVycmlkZSBmb3Igc2hvd2luZyB0aGUgUGVlciBjb25uZWN0aW9uIGNvbm5lY3RpbmcgT3ZlcmxheVxuICAgICAqL1xuICAgIHNob3dUZXh0T3ZlcmxheUNvbm5lY3RpbmcoKSB7XG4gICAgICAgIC8vIERlZmF1bHQgRnVuY3Rpb25hbGl0eTogRG8gTm90aGluZ1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFuIG92ZXJyaWRlIGZvciBzaG93aW5nIHRoZSBQZWVyIGNvbm5lY3Rpb24gRmFpbGVkIG92ZXJsYXlcbiAgICAgKi9cbiAgICBzaG93VGV4dE92ZXJsYXlTZXR1cEZhaWx1cmUoKSB7XG4gICAgICAgIC8vIERlZmF1bHQgRnVuY3Rpb25hbGl0eTogRG8gTm90aGluZ1xuICAgIH1cblxuICAgIHBhcnNlQXZhaWxhYmxlQ29kZWNzKFxuICAgICAgICBydGNTZXNzaW9uRGVzY3JpcHRpb246IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbkluaXRcbiAgICApOiBBcnJheTxzdHJpbmc+IHtcbiAgICAgICAgLy8gTm8gcG9pbnQgaW4gdXBkYXRpbmcgdGhlIGF2YWlsYWJsZSBjb2RlY3MgaWYgb24gRkZcbiAgICAgICAgaWYgKCFSVENSdHBSZWNlaXZlci5nZXRDYXBhYmlsaXRpZXMpXG4gICAgICAgICAgICByZXR1cm4gWydPbmx5IGF2YWlsYWJsZSBvbiBDaHJvbWUnXTtcblxuICAgICAgICBjb25zdCB1ZVN1cHBvcnRlZENvZGVjczogQXJyYXk8c3RyaW5nPiA9IFtdO1xuICAgICAgICBjb25zdCBzZWN0aW9ucyA9IHNwbGl0U2VjdGlvbnMocnRjU2Vzc2lvbkRlc2NyaXB0aW9uLnNkcCk7XG4gICAgICAgIC8vIGRpc2NhcmQgdGhlIHNlc3Npb24gaW5mb3JtYXRpb24gYXMgd2Ugb25seSB3YW50IG1lZGlhIHJlbGF0ZWQgaW5mb1xuICAgICAgICBzZWN0aW9ucy5zaGlmdCgpO1xuICAgICAgICBzZWN0aW9ucy5mb3JFYWNoKChtZWRpYVNlY3Rpb24pID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHsgY29kZWNzIH0gPSBwYXJzZVJ0cFBhcmFtZXRlcnMobWVkaWFTZWN0aW9uKTtcbiAgICAgICAgICAgIC8vIEZpbHRlciBvbmx5IGZvciBWUFggLyBIMjZYIC8gQVYxXG4gICAgICAgICAgICBjb25zdCBtYXRjaGVyID0gLyhWUFxcZHxIMjZcXGR8QVYxKS4qLztcbiAgICAgICAgICAgIGNvZGVjcy5mb3JFYWNoKChjKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RyID1cbiAgICAgICAgICAgICAgICAgICAgYy5uYW1lICtcbiAgICAgICAgICAgICAgICAgICAgJyAnICtcbiAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmtleXMoYy5wYXJhbWV0ZXJzIHx8IHt9KVxuICAgICAgICAgICAgICAgICAgICAgICAgLm1hcCgocCkgPT4gcCArICc9JyArIGMucGFyYW1ldGVyc1twXSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC5qb2luKCc7Jyk7XG4gICAgICAgICAgICAgICAgY29uc3QgbWF0Y2ggPSBtYXRjaGVyLmV4ZWMoc3RyKTtcbiAgICAgICAgICAgICAgICBpZiAobWF0Y2ggIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGMubmFtZSA9PSAnVlA5Jykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVUUgYW5zd2VycyBkb24ndCBzcGVjaWZ5IHByb2ZpbGUgYnV0IHdlIGtub3cgd2Ugd2FudCBwcm9maWxlIDBcbiAgICAgICAgICAgICAgICAgICAgICAgIGMucGFyYW1ldGVycyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAncHJvZmlsZS1pZCc6ICcwJ1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBjb25zdCBjb2RlY1N0cjogc3RyaW5nID1cbiAgICAgICAgICAgICAgICAgICAgICAgIGMubmFtZSArXG4gICAgICAgICAgICAgICAgICAgICAgICAnICcgK1xuICAgICAgICAgICAgICAgICAgICAgICAgT2JqZWN0LmtleXMoYy5wYXJhbWV0ZXJzIHx8IHt9KVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5tYXAoKHApID0+IHAgKyAnPScgKyBjLnBhcmFtZXRlcnNbcF0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmpvaW4oJzsnKTtcbiAgICAgICAgICAgICAgICAgICAgdWVTdXBwb3J0ZWRDb2RlY3MucHVzaChjb2RlY1N0cik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiB1ZVN1cHBvcnRlZENvZGVjcztcbiAgICB9XG59XG4iLCIvLyBDb3B5cmlnaHQgRXBpYyBHYW1lcywgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuXG4vKipcbiAqIFNlc3Npb24gc3RhdGlzdGljc1xuICovXG5leHBvcnQgY2xhc3MgU2Vzc2lvblN0YXRzIHtcbiAgICBydW5UaW1lOiBzdHJpbmc7XG4gICAgY29udHJvbHNTdHJlYW1JbnB1dDogc3RyaW5nO1xuICAgIHZpZGVvRW5jb2RlckF2Z1FQOiBudW1iZXI7XG59XG4iLCIvLyBDb3B5cmlnaHQgRXBpYyBHYW1lcywgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuXG4vKipcbiAqIENsYXNzIHRvIGhvbGQgdGhlIHN0cmVhbSBzdGF0cyBkYXRhIGNvbWluZyBpbiBmcm9tIHdlYlJ0Y1xuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtU3RhdHMge1xuICAgIGlkOiBzdHJpbmc7XG4gICAgc3RyZWFtSWRlbnRpZmllcjogc3RyaW5nO1xuICAgIHRpbWVzdGFtcDogbnVtYmVyO1xuICAgIHRyYWNrSWRzOiBzdHJpbmdbXTtcbn1cbiIsIi8vIENvcHlyaWdodCBFcGljIEdhbWVzLCBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG5cbmltcG9ydCB7IENvbmZpZywgT3B0aW9uUGFyYW1ldGVycyB9IGZyb20gJy4uL0NvbmZpZy9Db25maWcnO1xuaW1wb3J0IHsgTGF0ZW5jeVRlc3RSZXN1bHRzIH0gZnJvbSAnLi4vRGF0YUNoYW5uZWwvTGF0ZW5jeVRlc3RSZXN1bHRzJztcbmltcG9ydCB7IEFnZ3JlZ2F0ZWRTdGF0cyB9IGZyb20gJy4uL1BlZXJDb25uZWN0aW9uQ29udHJvbGxlci9BZ2dyZWdhdGVkU3RhdHMnO1xuaW1wb3J0IHsgV2ViUnRjUGxheWVyQ29udHJvbGxlciB9IGZyb20gJy4uL1dlYlJ0Y1BsYXllci9XZWJSdGNQbGF5ZXJDb250cm9sbGVyJztcbmltcG9ydCB7IEZsYWdzLCBOdW1lcmljUGFyYW1ldGVycyB9IGZyb20gJy4uL0NvbmZpZy9Db25maWcnO1xuaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSAnLi4vTG9nZ2VyL0xvZ2dlcic7XG5pbXBvcnQgeyBJbml0aWFsU2V0dGluZ3MgfSBmcm9tICcuLi9EYXRhQ2hhbm5lbC9Jbml0aWFsU2V0dGluZ3MnO1xuaW1wb3J0IHsgT25TY3JlZW5LZXlib2FyZCB9IGZyb20gJy4uL1VJL09uU2NyZWVuS2V5Ym9hcmQnO1xuaW1wb3J0IHtcbiAgICBFdmVudEVtaXR0ZXIsXG4gICAgSW5pdGlhbFNldHRpbmdzRXZlbnQsXG4gICAgTGF0ZW5jeVRlc3RSZXN1bHRFdmVudCxcbiAgICBQaXhlbFN0cmVhbWluZ0V2ZW50LFxuICAgIFN0YXRzUmVjZWl2ZWRFdmVudCxcbiAgICBTdHJlYW1Mb2FkaW5nRXZlbnQsXG4gICAgU3RyZWFtUHJlQ29ubmVjdEV2ZW50LFxuICAgIFN0cmVhbVJlY29ubmVjdEV2ZW50LFxuICAgIFN0cmVhbVByZURpc2Nvbm5lY3RFdmVudCxcbiAgICBWaWRlb0VuY29kZXJBdmdRUEV2ZW50LFxuICAgIFZpZGVvSW5pdGlhbGl6ZWRFdmVudCxcbiAgICBXZWJSdGNBdXRvQ29ubmVjdEV2ZW50LFxuICAgIFdlYlJ0Y0Nvbm5lY3RlZEV2ZW50LFxuICAgIFdlYlJ0Y0Nvbm5lY3RpbmdFdmVudCxcbiAgICBXZWJSdGNEaXNjb25uZWN0ZWRFdmVudCxcbiAgICBXZWJSdGNGYWlsZWRFdmVudCxcbiAgICBXZWJSdGNTZHBFdmVudCxcbiAgICBEYXRhQ2hhbm5lbExhdGVuY3lUZXN0UmVzcG9uc2VFdmVudCxcbiAgICBEYXRhQ2hhbm5lbExhdGVuY3lUZXN0UmVzdWx0RXZlbnQsXG4gICAgUGxheWVyQ291bnRFdmVudFxufSBmcm9tICcuLi9VdGlsL0V2ZW50RW1pdHRlcic7XG5pbXBvcnQgeyBNZXNzYWdlT25TY3JlZW5LZXlib2FyZCB9IGZyb20gJy4uL1dlYlNvY2tldHMvTWVzc2FnZVJlY2VpdmUnO1xuaW1wb3J0IHsgV2ViWFJDb250cm9sbGVyIH0gZnJvbSAnLi4vV2ViWFIvV2ViWFJDb250cm9sbGVyJztcbmltcG9ydCB7IE1lc3NhZ2VEaXJlY3Rpb24gfSBmcm9tICcuLi9VZUluc3RhbmNlTWVzc2FnZS9TdHJlYW1NZXNzYWdlQ29udHJvbGxlcic7XG5pbXBvcnQge1xuICAgIERhdGFDaGFubmVsTGF0ZW5jeVRlc3RDb25maWcsXG4gICAgRGF0YUNoYW5uZWxMYXRlbmN5VGVzdENvbnRyb2xsZXJcbn0gZnJvbSBcIi4uL0RhdGFDaGFubmVsL0RhdGFDaGFubmVsTGF0ZW5jeVRlc3RDb250cm9sbGVyXCI7XG5pbXBvcnQge1xuICAgIERhdGFDaGFubmVsTGF0ZW5jeVRlc3RSZXNwb25zZSxcbiAgICBEYXRhQ2hhbm5lbExhdGVuY3lUZXN0UmVzdWx0XG59IGZyb20gXCIuLi9EYXRhQ2hhbm5lbC9EYXRhQ2hhbm5lbExhdGVuY3lUZXN0UmVzdWx0c1wiO1xuaW1wb3J0IHsgUlRDVXRpbHMgfSBmcm9tICcuLi9VdGlsL1JUQ1V0aWxzJztcblxuXG5leHBvcnQgaW50ZXJmYWNlIFBpeGVsU3RyZWFtaW5nT3ZlcnJpZGVzIHtcbiAgICAvKiogVGhlIERPTSBlbG1lbnQgd2hlcmUgUGl4ZWwgU3RyZWFtaW5nIHZpZGVvIGFuZCB1c2VyIGlucHV0IGV2ZW50IGhhbmRsZXJzIGFyZSBhdHRhY2hlZCB0by5cbiAgICAgKiBZb3UgY2FuIGdpdmUgYW4gZXhpc3RpbmcgRE9NIGVsZW1lbnQgaGVyZS4gSWYgbm90IGdpdmVuLCB0aGUgbGlicmFyeSB3aWxsIGNyZWF0ZSBhIG5ldyBkaXYgZWxlbWVudFxuICAgICAqIHRoYXQgaXMgbm90IGF0dGFjaGVkIGFueXdoZXJlLiBJbiB0aGlzIGNhc2UgeW91IGNhbiBsYXRlciBnZXQgYWNjZXNzIHRvIHRoaXMgbmV3IGVsZW1lbnQgYW5kXG4gICAgICogYXR0YWNoIGl0IHRvIHlvdXIgd2ViIHBhZ2UuICovXG4gICAgdmlkZW9FbGVtZW50UGFyZW50PzogSFRNTEVsZW1lbnQ7XG59XG5cbi8qKlxuICogVGhlIGtleSBjbGFzcyBmb3IgdGhlIGJyb3dzZXIgc2lkZSBvZiBhIFBpeGVsIFN0cmVhbWluZyBhcHBsaWNhdGlvbiwgaXQgaW5jbHVkZXM6XG4gKiBXZWJSVEMgaGFuZGxpbmcsIFhSIHN1cHBvcnQsIGlucHV0IGhhbmRsaW5nLCBhbmQgZW1pdHRlcnMgZm9yIGxpZmV0aW1lIGFuZCBzdGF0ZSBjaGFuZ2UgZXZlbnRzLlxuICogVXNlcnMgYXJlIGVuY291cmFnZWQgdG8gdXNlIHRoaXMgY2xhc3MgYXMgaXMsIHRocm91Z2ggY29tcG9zaXRpb24sIG9yIGV4dGVuZCBpdC4gSW4gYW55IGNhc2UsIFxuICogdGhpcyB3aWxsIGxpa2VseSBiZSB0aGUgY29yZSBvZiB5b3VyIFBpeGVsIFN0cmVhbWluZyBleHBlcmllbmNlIGluIHRlcm1zIG9mIGZ1bmN0aW9uYWxpdHkuXG4gKi9cbmV4cG9ydCBjbGFzcyBQaXhlbFN0cmVhbWluZyB7XG4gICAgcHJvdGVjdGVkIF93ZWJSdGNDb250cm9sbGVyOiBXZWJSdGNQbGF5ZXJDb250cm9sbGVyO1xuICAgIHByb3RlY3RlZCBfd2ViWHJDb250cm9sbGVyOiBXZWJYUkNvbnRyb2xsZXI7XG4gICAgcHJvdGVjdGVkIF9kYXRhQ2hhbm5lbExhdGVuY3lUZXN0Q29udHJvbGxlcjogRGF0YUNoYW5uZWxMYXRlbmN5VGVzdENvbnRyb2xsZXI7XG4gICAgLyoqXG4gICAgICogQ29uZmlndXJhdGlvbiBvYmplY3QuIFlvdSBjYW4gcmVhZCBvciBtb2RpZnkgY29uZmlnIHRocm91Z2ggdGhpcyBvYmplY3QuIFdoZW5ldmVyXG4gICAgICogdGhlIGNvbmZpZ3VyYXRpb24gaXMgY2hhbmdlZCwgdGhlIGxpYnJhcnkgd2lsbCBlbWl0IGEgYHNldHRpbmdzQ2hhbmdlZGAgZXZlbnQuXG4gICAgICovXG4gICAgcHVibGljIGNvbmZpZzogQ29uZmlnO1xuXG4gICAgcHJpdmF0ZSBfdmlkZW9FbGVtZW50UGFyZW50OiBIVE1MRWxlbWVudDtcblxuICAgIHByaXZhdGUgYWxsb3dDb25zb2xlQ29tbWFuZHMgPSBmYWxzZTtcblxuICAgIHByaXZhdGUgb25TY3JlZW5LZXlib2FyZEhlbHBlcjogT25TY3JlZW5LZXlib2FyZDtcblxuICAgIHByaXZhdGUgX3ZpZGVvU3RhcnRUaW1lOiBudW1iZXI7XG4gICAgcHJpdmF0ZSBfaW5wdXRDb250cm9sbGVyOiBib29sZWFuO1xuXG4gICAgcHJpdmF0ZSBfZXZlbnRFbWl0dGVyOiBFdmVudEVtaXR0ZXI7XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gY29uZmlnIC0gQSBuZXdseSBpbnN0YW50aWF0ZWQgY29uZmlnIG9iamVjdFxuICAgICAqIEBwYXJhbSBvdmVycmlkZXMgLSBQYXJhbWV0ZXJzIHRvIG92ZXJyaWRlIGRlZmF1bHQgYmVoYXZpb3VyXG4gICAgICogcmV0dXJucyB0aGUgYmFzZSBQaXhlbCBzdHJlYW1pbmcgb2JqZWN0XG4gICAgICovXG4gICAgY29uc3RydWN0b3IoY29uZmlnOiBDb25maWcsIG92ZXJyaWRlcz86IFBpeGVsU3RyZWFtaW5nT3ZlcnJpZGVzKSB7XG4gICAgICAgIHRoaXMuY29uZmlnID0gY29uZmlnO1xuXG4gICAgICAgIGlmIChvdmVycmlkZXM/LnZpZGVvRWxlbWVudFBhcmVudCkge1xuICAgICAgICAgICAgdGhpcy5fdmlkZW9FbGVtZW50UGFyZW50ID0gb3ZlcnJpZGVzLnZpZGVvRWxlbWVudFBhcmVudDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX2V2ZW50RW1pdHRlciA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICAgICAgICB0aGlzLmNvbmZpZ3VyZVNldHRpbmdzKCk7XG5cbiAgICAgICAgLy8gc2V0dXAgV2ViUlRDXG4gICAgICAgIHRoaXMuc2V0V2ViUnRjUGxheWVyQ29udHJvbGxlcihcbiAgICAgICAgICAgIG5ldyBXZWJSdGNQbGF5ZXJDb250cm9sbGVyKHRoaXMuY29uZmlnLCB0aGlzKVxuICAgICAgICApO1xuXG4gICAgICAgIC8vIE9uc2NyZWVuIGtleWJvYXJkXG4gICAgICAgIHRoaXMub25TY3JlZW5LZXlib2FyZEhlbHBlciA9IG5ldyBPblNjcmVlbktleWJvYXJkKFxuICAgICAgICAgICAgdGhpcy52aWRlb0VsZW1lbnRQYXJlbnRcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5vblNjcmVlbktleWJvYXJkSGVscGVyLnVucXVhbnRpemVBbmREZW5vcm1hbGl6ZVVuc2lnbmVkID0gKFxuICAgICAgICAgICAgeDogbnVtYmVyLFxuICAgICAgICAgICAgeTogbnVtYmVyXG4gICAgICAgICkgPT5cbiAgICAgICAgICAgIHRoaXMuX3dlYlJ0Y0NvbnRyb2xsZXIucmVxdWVzdFVucXVhbnRpemVkQW5kRGVub3JtYWxpemVVbnNpZ25lZChcbiAgICAgICAgICAgICAgICB4LFxuICAgICAgICAgICAgICAgIHlcbiAgICAgICAgICAgICk7XG4gICAgICAgIHRoaXMuX2FjdGl2YXRlT25TY3JlZW5LZXlib2FyZCA9IChjb21tYW5kOiBNZXNzYWdlT25TY3JlZW5LZXlib2FyZCkgPT5cbiAgICAgICAgICAgIHRoaXMub25TY3JlZW5LZXlib2FyZEhlbHBlci5zaG93T25TY3JlZW5LZXlib2FyZChjb21tYW5kKTtcblxuICAgICAgICB0aGlzLl93ZWJYckNvbnRyb2xsZXIgPSBuZXcgV2ViWFJDb250cm9sbGVyKHRoaXMuX3dlYlJ0Y0NvbnRyb2xsZXIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGVsZW1lbnQgdGhhdCBjb250YWlucyB0aGUgdmlkZW8gc3RyZWFtIGVsZW1lbnQuXG4gICAgICovXG4gICAgcHVibGljIGdldCB2aWRlb0VsZW1lbnRQYXJlbnQoKTogSFRNTEVsZW1lbnQge1xuICAgICAgICBpZiAoIXRoaXMuX3ZpZGVvRWxlbWVudFBhcmVudCkge1xuICAgICAgICAgICAgdGhpcy5fdmlkZW9FbGVtZW50UGFyZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICAgICAgICB0aGlzLl92aWRlb0VsZW1lbnRQYXJlbnQuaWQgPSAndmlkZW9FbGVtZW50UGFyZW50JztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5fdmlkZW9FbGVtZW50UGFyZW50O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbmZpZ3VyZSB0aGUgc2V0dGluZ3Mgd2l0aCBvbiBjaGFuZ2UgbGlzdGVuZXJzIGFuZCBhbnkgYWRkaXRpb25hbCBwZXIgZXhwZXJpZW5jZSBzZXR0aW5ncy5cbiAgICAgKi9cbiAgICBwcml2YXRlIGNvbmZpZ3VyZVNldHRpbmdzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLmNvbmZpZy5fYWRkT25TZXR0aW5nQ2hhbmdlZExpc3RlbmVyKFxuICAgICAgICAgICAgRmxhZ3MuSXNRdWFsaXR5Q29udHJvbGxlcixcbiAgICAgICAgICAgICh3YW50c1F1YWxpdHlDb250cm9sbGVyOiBib29sZWFuKSA9PiB7XG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIHNldHRpbmcgaGFzIGJlZW4gc2V0IHRvIHRydWUgKGVpdGhlciBwcm9ncmFtYXRpY2FsbHkgb3IgdGhlIHVzZXIgaGFzIGZsaWNrZWQgdGhlIHRvZ2dsZSlcbiAgICAgICAgICAgICAgICAvLyBhbmQgd2UgYXJlbid0IGN1cnJlbnRseSBxdWFsaXR5IGNvbnRyb2xsZXIsIHNlbmQgdGhlIHJlcXVlc3RcbiAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgIHdhbnRzUXVhbGl0eUNvbnRyb2xsZXIgPT09IHRydWUgJiZcbiAgICAgICAgICAgICAgICAgICAgIXRoaXMuX3dlYlJ0Y0NvbnRyb2xsZXIuaXNRdWFsaXR5Q29udHJvbGxlclxuICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl93ZWJSdGNDb250cm9sbGVyLnNlbmRSZXF1ZXN0UXVhbGl0eUNvbnRyb2xPd25lcnNoaXAoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICk7XG5cbiAgICAgICAgdGhpcy5jb25maWcuX2FkZE9uU2V0dGluZ0NoYW5nZWRMaXN0ZW5lcihcbiAgICAgICAgICAgIEZsYWdzLkFGS0RldGVjdGlvbixcbiAgICAgICAgICAgIChpc0FGS0VuYWJsZWQ6IGJvb2xlYW4pID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLl93ZWJSdGNDb250cm9sbGVyLnNldEFma0VuYWJsZWQoaXNBRktFbmFibGVkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgKTtcblxuICAgICAgICB0aGlzLmNvbmZpZy5fYWRkT25TZXR0aW5nQ2hhbmdlZExpc3RlbmVyKFxuICAgICAgICAgICAgRmxhZ3MuTWF0Y2hWaWV3cG9ydFJlc29sdXRpb24sXG4gICAgICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5fd2ViUnRjQ29udHJvbGxlci52aWRlb1BsYXllci51cGRhdGVWaWRlb1N0cmVhbVNpemUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgKTtcblxuICAgICAgICB0aGlzLmNvbmZpZy5fYWRkT25TZXR0aW5nQ2hhbmdlZExpc3RlbmVyKFxuICAgICAgICAgICAgRmxhZ3MuSG92ZXJpbmdNb3VzZU1vZGUsXG4gICAgICAgICAgICAoaXNIb3ZlcmluZ01vdXNlOiBib29sZWFuKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWcuc2V0RmxhZ0xhYmVsKFxuICAgICAgICAgICAgICAgICAgICBGbGFncy5Ib3ZlcmluZ01vdXNlTW9kZSxcbiAgICAgICAgICAgICAgICAgICAgYENvbnRyb2wgU2NoZW1lOiAke1xuICAgICAgICAgICAgICAgICAgICAgICAgaXNIb3ZlcmluZ01vdXNlID8gJ0hvdmVyaW5nJyA6ICdMb2NrZWQnXG4gICAgICAgICAgICAgICAgICAgIH0gTW91c2VgXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB0aGlzLl93ZWJSdGNDb250cm9sbGVyLnNldE1vdXNlSW5wdXRFbmFibGVkKHRoaXMuY29uZmlnLmlzRmxhZ0VuYWJsZWQoRmxhZ3MuTW91c2VJbnB1dCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICApO1xuXG4gICAgICAgIC8vIHVzZXIgaW5wdXRcbiAgICAgICAgdGhpcy5jb25maWcuX2FkZE9uU2V0dGluZ0NoYW5nZWRMaXN0ZW5lcihcbiAgICAgICAgICAgIEZsYWdzLktleWJvYXJkSW5wdXQsXG4gICAgICAgICAgICAoaXNFbmFibGVkOiBib29sZWFuKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5fd2ViUnRjQ29udHJvbGxlci5zZXRLZXlib2FyZElucHV0RW5hYmxlZChpc0VuYWJsZWQpO1xuICAgICAgICAgICAgfVxuICAgICAgICApO1xuXG4gICAgICAgIHRoaXMuY29uZmlnLl9hZGRPblNldHRpbmdDaGFuZ2VkTGlzdGVuZXIoXG4gICAgICAgICAgICBGbGFncy5Nb3VzZUlucHV0LFxuICAgICAgICAgICAgKGlzRW5hYmxlZDogYm9vbGVhbikgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuX3dlYlJ0Y0NvbnRyb2xsZXIuc2V0TW91c2VJbnB1dEVuYWJsZWQoaXNFbmFibGVkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgKTtcblxuICAgICAgICB0aGlzLmNvbmZpZy5fYWRkT25TZXR0aW5nQ2hhbmdlZExpc3RlbmVyKFxuICAgICAgICAgICAgRmxhZ3MuVG91Y2hJbnB1dCxcbiAgICAgICAgICAgIChpc0VuYWJsZWQ6IGJvb2xlYW4pID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLl93ZWJSdGNDb250cm9sbGVyLnNldFRvdWNoSW5wdXRFbmFibGVkKGlzRW5hYmxlZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICk7XG5cbiAgICAgICAgdGhpcy5jb25maWcuX2FkZE9uU2V0dGluZ0NoYW5nZWRMaXN0ZW5lcihcbiAgICAgICAgICAgIEZsYWdzLkdhbWVwYWRJbnB1dCxcbiAgICAgICAgICAgIChpc0VuYWJsZWQ6IGJvb2xlYW4pID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLl93ZWJSdGNDb250cm9sbGVyLnNldEdhbWVQYWRJbnB1dEVuYWJsZWQoaXNFbmFibGVkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgKTtcblxuICAgICAgICAvLyBlbmNvZGVyIHNldHRpbmdzXG4gICAgICAgIHRoaXMuY29uZmlnLl9hZGRPbk51bWVyaWNTZXR0aW5nQ2hhbmdlZExpc3RlbmVyKFxuICAgICAgICAgICAgTnVtZXJpY1BhcmFtZXRlcnMuTWluUVAsXG4gICAgICAgICAgICAobmV3VmFsdWU6IG51bWJlcikgPT4ge1xuICAgICAgICAgICAgICAgIExvZ2dlci5Mb2coXG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAgICAgICAgICctLS0tLS0tLSAgU2VuZGluZyBNaW5RUCAgLS0tLS0tLS0nLFxuICAgICAgICAgICAgICAgICAgICA3XG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB0aGlzLl93ZWJSdGNDb250cm9sbGVyLnNlbmRFbmNvZGVyTWluUVAobmV3VmFsdWUpO1xuICAgICAgICAgICAgICAgIExvZ2dlci5Mb2coXG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAgICAgICAgICctLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tJyxcbiAgICAgICAgICAgICAgICAgICAgN1xuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICk7XG5cbiAgICAgICAgdGhpcy5jb25maWcuX2FkZE9uTnVtZXJpY1NldHRpbmdDaGFuZ2VkTGlzdGVuZXIoXG4gICAgICAgICAgICBOdW1lcmljUGFyYW1ldGVycy5NYXhRUCxcbiAgICAgICAgICAgIChuZXdWYWx1ZTogbnVtYmVyKSA9PiB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLkxvZyhcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICAgICAgICAgJy0tLS0tLS0tICBTZW5kaW5nIGVuY29kZXIgc2V0dGluZ3MgIC0tLS0tLS0tJyxcbiAgICAgICAgICAgICAgICAgICAgN1xuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgdGhpcy5fd2ViUnRjQ29udHJvbGxlci5zZW5kRW5jb2Rlck1heFFQKG5ld1ZhbHVlKTtcbiAgICAgICAgICAgICAgICBMb2dnZXIuTG9nKFxuICAgICAgICAgICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgICAgICAgICAnLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLScsXG4gICAgICAgICAgICAgICAgICAgIDdcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICApO1xuXG4gICAgICAgIC8vIFdlYlJUQyBzZXR0aW5nc1xuICAgICAgICB0aGlzLmNvbmZpZy5fYWRkT25OdW1lcmljU2V0dGluZ0NoYW5nZWRMaXN0ZW5lcihcbiAgICAgICAgICAgIE51bWVyaWNQYXJhbWV0ZXJzLldlYlJUQ01pbkJpdHJhdGUsXG4gICAgICAgICAgICAobmV3VmFsdWU6IG51bWJlcikgPT4ge1xuICAgICAgICAgICAgICAgIExvZ2dlci5Mb2coXG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAgICAgICAgICctLS0tLS0tLSAgU2VuZGluZyB3ZWIgcnRjIHNldHRpbmdzICAtLS0tLS0tLScsXG4gICAgICAgICAgICAgICAgICAgIDdcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIHRoaXMuX3dlYlJ0Y0NvbnRyb2xsZXIuc2VuZFdlYlJUQ01pbkJpdHJhdGUobmV3VmFsdWUgKiAxMDAwIC8qIGticHMgdG8gYnBzICovKTtcbiAgICAgICAgICAgICAgICBMb2dnZXIuTG9nKFxuICAgICAgICAgICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgICAgICAgICAnLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLScsXG4gICAgICAgICAgICAgICAgICAgIDdcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICApO1xuXG4gICAgICAgIHRoaXMuY29uZmlnLl9hZGRPbk51bWVyaWNTZXR0aW5nQ2hhbmdlZExpc3RlbmVyKFxuICAgICAgICAgICAgTnVtZXJpY1BhcmFtZXRlcnMuV2ViUlRDTWF4Qml0cmF0ZSxcbiAgICAgICAgICAgIChuZXdWYWx1ZTogbnVtYmVyKSA9PiB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLkxvZyhcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICAgICAgICAgJy0tLS0tLS0tICBTZW5kaW5nIHdlYiBydGMgc2V0dGluZ3MgIC0tLS0tLS0tJyxcbiAgICAgICAgICAgICAgICAgICAgN1xuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgdGhpcy5fd2ViUnRjQ29udHJvbGxlci5zZW5kV2ViUlRDTWF4Qml0cmF0ZShuZXdWYWx1ZSAqIDEwMDAgLyoga2JwcyB0byBicHMgKi8pO1xuICAgICAgICAgICAgICAgIExvZ2dlci5Mb2coXG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAgICAgICAgICctLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tJyxcbiAgICAgICAgICAgICAgICAgICAgN1xuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICk7XG5cbiAgICAgICAgdGhpcy5jb25maWcuX2FkZE9uTnVtZXJpY1NldHRpbmdDaGFuZ2VkTGlzdGVuZXIoXG4gICAgICAgICAgICBOdW1lcmljUGFyYW1ldGVycy5XZWJSVENGUFMsXG4gICAgICAgICAgICAobmV3VmFsdWU6IG51bWJlcikgPT4ge1xuICAgICAgICAgICAgICAgIExvZ2dlci5Mb2coXG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAgICAgICAgICctLS0tLS0tLSAgU2VuZGluZyB3ZWIgcnRjIHNldHRpbmdzICAtLS0tLS0tLScsXG4gICAgICAgICAgICAgICAgICAgIDdcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIHRoaXMuX3dlYlJ0Y0NvbnRyb2xsZXIuc2VuZFdlYlJUQ0ZwcyhuZXdWYWx1ZSk7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLkxvZyhcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICAgICAgICAgJy0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0nLFxuICAgICAgICAgICAgICAgICAgICA3XG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgKTtcblxuICAgICAgICB0aGlzLmNvbmZpZy5fYWRkT25PcHRpb25TZXR0aW5nQ2hhbmdlZExpc3RlbmVyKFxuICAgICAgICAgICAgT3B0aW9uUGFyYW1ldGVycy5QcmVmZXJyZWRDb2RlYyxcbiAgICAgICAgICAgIChuZXdWYWx1ZTogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX3dlYlJ0Y0NvbnRyb2xsZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fd2ViUnRjQ29udHJvbGxlci5zZXRQcmVmZXJyZWRDb2RlYyhuZXdWYWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICApO1xuXG4gICAgICAgIHRoaXMuY29uZmlnLl9yZWdpc3Rlck9uQ2hhbmdlRXZlbnRzKHRoaXMuX2V2ZW50RW1pdHRlcik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWN0aXZhdGUgdGhlIG9uIHNjcmVlbiBrZXlib2FyZCB3aGVuIHJlY2VpdmluZyB0aGUgY29tbWFuZCBmcm9tIHRoZSBzdHJlYW1lclxuICAgICAqIEBwYXJhbSBjb21tYW5kIC0gdGhlIGtleWJvYXJkIGNvbW1hbmRcbiAgICAgKi9cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgX2FjdGl2YXRlT25TY3JlZW5LZXlib2FyZChjb21tYW5kOiBNZXNzYWdlT25TY3JlZW5LZXlib2FyZCk6IHZvaWQge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ01ldGhvZCBub3QgaW1wbGVtZW50ZWQuJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSBpbnB1dCBjb250cm9sIG93bmVyc2hpcFxuICAgICAqIEBwYXJhbSBpbnB1dENvbnRyb2xPd25lcnNoaXAgLSBkb2VzIHRoZSB1c2VyIGhhdmUgaW5wdXQgY29udHJvbCBvd25lcnNoaXBcbiAgICAgKi9cbiAgICBfb25JbnB1dENvbnRyb2xPd25lcnNoaXAoaW5wdXRDb250cm9sT3duZXJzaGlwOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIHRoaXMuX2lucHV0Q29udHJvbGxlciA9IGlucHV0Q29udHJvbE93bmVyc2hpcDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbnN0YW50aWF0ZSB0aGUgV2ViUlRDUGxheWVyQ29udHJvbGxlciBpbnRlcmZhY2UgdG8gcHJvdmlkZSBXZWJSVENQbGF5ZXJDb250cm9sbGVyIGZ1bmN0aW9uYWxpdHkgd2l0aGluIHRoaXMgY2xhc3MgYW5kIHNldCB1cCBhbnl0aGluZyB0aGF0IHJlcXVpcmVzIGl0XG4gICAgICogQHBhcmFtIHdlYlJ0Y1BsYXllckNvbnRyb2xsZXIgLSBhIFdlYlJ0Y1BsYXllckNvbnRyb2xsZXIgY29udHJvbGxlciBpbnN0YW5jZVxuICAgICAqL1xuICAgIHByaXZhdGUgc2V0V2ViUnRjUGxheWVyQ29udHJvbGxlcihcbiAgICAgICAgd2ViUnRjUGxheWVyQ29udHJvbGxlcjogV2ViUnRjUGxheWVyQ29udHJvbGxlclxuICAgICkge1xuICAgICAgICB0aGlzLl93ZWJSdGNDb250cm9sbGVyID0gd2ViUnRjUGxheWVyQ29udHJvbGxlcjtcblxuICAgICAgICB0aGlzLl93ZWJSdGNDb250cm9sbGVyLnNldFByZWZlcnJlZENvZGVjKFxuICAgICAgICAgICAgdGhpcy5jb25maWcuZ2V0U2V0dGluZ09wdGlvbihPcHRpb25QYXJhbWV0ZXJzLlByZWZlcnJlZENvZGVjKVxuICAgICAgICAgICAgICAgIC5zZWxlY3RlZFxuICAgICAgICApO1xuICAgICAgICB0aGlzLl93ZWJSdGNDb250cm9sbGVyLnJlc2l6ZVBsYXllclN0eWxlKCk7XG5cbiAgICAgICAgLy8gY29ubmVjdCBpZiBhdXRvIGNvbm5lY3QgZmxhZyBpcyBlbmFibGVkXG4gICAgICAgIHRoaXMuY2hlY2tGb3JBdXRvQ29ubmVjdCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbm5lY3QgdG8gc2lnbmFsaW5nIHNlcnZlci5cbiAgICAgKi9cbiAgICBwdWJsaWMgY29ubmVjdCgpIHtcbiAgICAgICAgdGhpcy5fZXZlbnRFbWl0dGVyLmRpc3BhdGNoRXZlbnQobmV3IFN0cmVhbVByZUNvbm5lY3RFdmVudCgpKTtcbiAgICAgICAgdGhpcy5fd2ViUnRjQ29udHJvbGxlci5jb25uZWN0VG9TaWduYWxsaW5nU2VydmVyKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVjb25uZWN0cyB0byB0aGUgc2lnbmFsaW5nIHNlcnZlci4gSWYgY29ubmVjdGlvbiBpcyB1cCwgZGlzY29ubmVjdHMgZmlyc3RcbiAgICAgKiBiZWZvcmUgZXN0YWJsaXNoaW5nIGEgbmV3IGNvbm5lY3Rpb25cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVjb25uZWN0KCkge1xuICAgICAgICB0aGlzLl9ldmVudEVtaXR0ZXIuZGlzcGF0Y2hFdmVudChuZXcgU3RyZWFtUmVjb25uZWN0RXZlbnQoKSk7XG4gICAgICAgIHRoaXMuX3dlYlJ0Y0NvbnRyb2xsZXIudHJ5UmVjb25uZWN0KFwiUmVjb25uZWN0aW5nLi4uXCIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERpc2Nvbm5lY3QgZnJvbSB0aGUgc2lnbmFsaW5nIHNlcnZlciBhbmQgY2xvc2Ugb3BlbiBwZWVyIGNvbm5lY3Rpb25zLlxuICAgICAqL1xuICAgIHB1YmxpYyBkaXNjb25uZWN0KCkge1xuICAgICAgICB0aGlzLl9ldmVudEVtaXR0ZXIuZGlzcGF0Y2hFdmVudChuZXcgU3RyZWFtUHJlRGlzY29ubmVjdEV2ZW50KCkpO1xuICAgICAgICB0aGlzLl93ZWJSdGNDb250cm9sbGVyLmNsb3NlKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGxheSB0aGUgc3RyZWFtLiBDYW4gYmUgY2FsbGVkIG9ubHkgYWZ0ZXIgYSBwZWVyIGNvbm5lY3Rpb24gaGFzIGJlZW4gZXN0YWJsaXNoZWQuXG4gICAgICovXG4gICAgcHVibGljIHBsYXkoKSB7XG4gICAgICAgIHRoaXMuX29uU3RyZWFtTG9hZGluZygpO1xuICAgICAgICB0aGlzLl93ZWJSdGNDb250cm9sbGVyLnBsYXlTdHJlYW0oKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBdXRvIGNvbm5lY3QgaWYgQXV0b0Nvbm5lY3QgZmxhZyBpcyBlbmFibGVkXG4gICAgICovXG4gICAgcHJpdmF0ZSBjaGVja0ZvckF1dG9Db25uZWN0KCkge1xuICAgICAgICAvLyBzZXQgdXAgaWYgdGhlIGF1dG8gcGxheSB3aWxsIGJlIHVzZWQgb3IgcmVndWxhciBjbGljayB0byBzdGFydFxuICAgICAgICBpZiAodGhpcy5jb25maWcuaXNGbGFnRW5hYmxlZChGbGFncy5BdXRvQ29ubmVjdCkpIHtcbiAgICAgICAgICAgIC8vIGlmIGF1dG9wbGF5aW5nIHNob3cgYW4gaW5mbyBvdmVybGF5IHdoaWxlIHdoaWxlIHdhaXRpbmcgZm9yIHRoZSBjb25uZWN0aW9uIHRvIGJlZ2luXG4gICAgICAgICAgICB0aGlzLl9vbldlYlJ0Y0F1dG9Db25uZWN0KCk7XG4gICAgICAgICAgICB0aGlzLl93ZWJSdGNDb250cm9sbGVyLmNvbm5lY3RUb1NpZ25hbGxpbmdTZXJ2ZXIoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKiBcbiAgICAgKiBXaWxsIHVubXV0ZSB0aGUgbWljcm9waG9uZSB0cmFjayB3aGljaCBpcyBzZW50IHRvIFVucmVhbCBFbmdpbmUuXG4gICAgICogQnkgZGVmYXVsdCwgd2lsbCBvbmx5IHVubXV0ZSBhbiBleGlzdGluZyBtaWMgdHJhY2suXG4gICAgICogXG4gICAgICogQHBhcmFtIGZvcmNlRW5hYmxlIENhbiBiZSB1c2VkIGZvciBjYXNlcyB3aGVuIHRoaXMgb2JqZWN0IHdhc24ndCBpbml0aWFsaXplZCB3aXRoIGEgbWljIHRyYWNrLlxuICAgICAqIElmIHRoaXMgcGFyYW1ldGVyIGlzIHRydWUsIHRoZSBjb25uZWN0aW9uIHdpbGwgYmUgcmVzdGFydGVkIHdpdGggYSBtaWNyb3Bob25lLlxuICAgICAqIFdhcm5pbmc6IHRoaXMgdGFrZXMgc29tZSB0aW1lLCBhcyBhIGZ1bGwgcmVuZWdvdGlhdGlvbiBhbmQgcmVjb25uZWN0aW9uIHdpbGwgaGFwcGVuLlxuICAgICAqL1xuICAgIHB1YmxpYyB1bm11dGVNaWNyb3Bob25lKGZvcmNlRW5hYmxlID0gZmFsc2UpIDogdm9pZCB7XG4gICAgICAgIC8vIElmIHRoZXJlJ3MgYW4gZXhpc3RpbmcgbWljIHRyYWNrLCB3ZSBqdXN0IHNldCBtdXRlZCBzdGF0ZVxuICAgICAgICBpZiAodGhpcy5jb25maWcuaXNGbGFnRW5hYmxlZCgnVXNlTWljJykpIHtcbiAgICAgICAgICAgIHRoaXMuc2V0TWljcm9waG9uZU11dGVkKGZhbHNlKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgLy8gSWYgdGhlcmUncyBubyBwcmUtZXhpc3RpbmcgbWljIHRyYWNrLCBhbmQgY2FsbGVyIGlzIG9rIHdpdGggZnVsbCByZXNldCwgd2UgZW5hYmxlIGFuZCByZXNldFxuICAgICAgICBpZiAoZm9yY2VFbmFibGUpIHtcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLnNldEZsYWdFbmFibGVkKFwiVXNlTWljXCIsIHRydWUpO1xuICAgICAgICAgICAgdGhpcy5yZWNvbm5lY3QoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICAgIFxuICAgICAgICAvLyBJZiB3ZSBwcmVmZXIgbm90IHRvIGZvcmNlIGEgcmVjb25uZWN0aW9uLCBqdXN0IHdhcm4gdGhlIHVzZXIgdGhhdCB0aGlzIG9wZXJhdGlvbiBkaWRuJ3QgaGFwcGVuXG4gICAgICAgIExvZ2dlci5XYXJuaW5nKFxuICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICdUcnlpbmcgdG8gdW5tdXRlIG1pYywgYnV0IFBpeGVsU3RyZWFtaW5nIHdhcyBpbml0aWFsaXplZCB3aXRoIG5vIG1pY3JvcGhvbmUgdHJhY2suIENhbGwgd2l0aCBmb3JjZUVuYWJsZSA9PSB0cnVlIHRvIHJlLWNvbm5lY3Qgd2l0aCBhIG1pYyB0cmFjay4nXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHVibGljIG11dGVNaWNyb3Bob25lKCkgOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuY29uZmlnLmlzRmxhZ0VuYWJsZWQoJ1VzZU1pYycpKSB7XG4gICAgICAgICAgICB0aGlzLnNldE1pY3JvcGhvbmVNdXRlZCh0cnVlKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIElmIHRoZXJlIHdhc24ndCBhIG1pYyB0cmFjaywganVzdCBsZXQgdXNlciBrbm93IHRoZXJlJ3Mgbm90aGluZyB0byBtdXRlXG4gICAgICAgIExvZ2dlci5JbmZvKFxuICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICdUcnlpbmcgdG8gbXV0ZSBtaWMsIGJ1dCBQaXhlbFN0cmVhbWluZyBoYXMgbm8gbWljcm9waG9uZSB0cmFjaywgc28gc2VuZGluZyBzb3VuZCBpcyBhbHJlYWR5IGRpc2FibGVkLidcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIHNldE1pY3JvcGhvbmVNdXRlZChtdXRlOiBib29sZWFuKSA6IHZvaWRcbiAgICB7XG4gICAgICAgIGZvciAoY29uc3QgdHJhbnNjZWl2ZXIgb2YgdGhpcy5fd2ViUnRjQ29udHJvbGxlcj8ucGVlckNvbm5lY3Rpb25Db250cm9sbGVyPy5wZWVyQ29ubmVjdGlvbj8uZ2V0VHJhbnNjZWl2ZXJzKCkgPz8gW10pIHtcbiAgICAgICAgICAgIGlmIChSVENVdGlscy5jYW5UcmFuc2NlaXZlclNlbmRBdWRpbyh0cmFuc2NlaXZlcikpIHtcbiAgICAgICAgICAgICAgICB0cmFuc2NlaXZlci5zZW5kZXIudHJhY2suZW5hYmxlZCA9ICFtdXRlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRW1pdCBhbiBldmVudCBvbiBhdXRvIGNvbm5lY3RpbmdcbiAgICAgKi9cbiAgICBfb25XZWJSdGNBdXRvQ29ubmVjdCgpIHtcbiAgICAgICAgdGhpcy5fZXZlbnRFbWl0dGVyLmRpc3BhdGNoRXZlbnQobmV3IFdlYlJ0Y0F1dG9Db25uZWN0RXZlbnQoKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHVwIGZ1bmN0aW9uYWxpdHkgdG8gaGFwcGVuIHdoZW4gcmVjZWl2aW5nIGEgd2ViUlRDIGFuc3dlclxuICAgICAqL1xuICAgIF9vbldlYlJ0Y1NkcCgpIHtcbiAgICAgICAgdGhpcy5fZXZlbnRFbWl0dGVyLmRpc3BhdGNoRXZlbnQobmV3IFdlYlJ0Y1NkcEV2ZW50KCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEVtaXRzIGEgU3RyZWFtTG9hZGluZyBldmVudFxuICAgICAqL1xuICAgIF9vblN0cmVhbUxvYWRpbmcoKSB7XG4gICAgICAgIHRoaXMuX2V2ZW50RW1pdHRlci5kaXNwYXRjaEV2ZW50KG5ldyBTdHJlYW1Mb2FkaW5nRXZlbnQoKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRXZlbnQgZmlyZWQgd2hlbiB0aGUgdmlkZW8gaXMgZGlzY29ubmVjdGVkIC0gZW1pdHMgZ2l2ZW4gZXZlbnRTdHJpbmcgb3IgYW4gb3ZlcnJpZGVcbiAgICAgKiBtZXNzYWdlIGZyb20gd2ViUnRjQ29udHJvbGxlciBpZiBvbmUgaGFzIGJlZW4gc2V0XG4gICAgICogQHBhcmFtIGV2ZW50U3RyaW5nIC0gYSBzdHJpbmcgZGVzY3JpYmluZyB3aHkgdGhlIGNvbm5lY3Rpb24gY2xvc2VkXG4gICAgICogQHBhcmFtIGFsbG93Q2xpY2tUb1JlY29ubmVjdCAtIHRydWUgaWYgd2Ugd2FudCB0byBhbGxvdyB0aGUgdXNlciB0byByZXRyeSB0aGUgY29ubmVjdGlvbiB3aXRoIGEgY2xpY2tcbiAgICAgKi9cbiAgICBfb25EaXNjb25uZWN0KGV2ZW50U3RyaW5nOiBzdHJpbmcsIGFsbG93Q2xpY2tUb1JlY29ubmVjdDogYm9vbGVhbikge1xuICAgICAgICB0aGlzLl9ldmVudEVtaXR0ZXIuZGlzcGF0Y2hFdmVudChcbiAgICAgICAgICAgIG5ldyBXZWJSdGNEaXNjb25uZWN0ZWRFdmVudCh7XG4gICAgICAgICAgICAgICAgZXZlbnRTdHJpbmc6IGV2ZW50U3RyaW5nLFxuICAgICAgICAgICAgICAgIGFsbG93Q2xpY2tUb1JlY29ubmVjdDogYWxsb3dDbGlja1RvUmVjb25uZWN0XG4gICAgICAgICAgICB9KVxuICAgICAgICApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXMgd2hlbiBXZWIgUnRjIGlzIGNvbm5lY3RpbmdcbiAgICAgKi9cbiAgICBfb25XZWJSdGNDb25uZWN0aW5nKCkge1xuICAgICAgICB0aGlzLl9ldmVudEVtaXR0ZXIuZGlzcGF0Y2hFdmVudChuZXcgV2ViUnRjQ29ubmVjdGluZ0V2ZW50KCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXMgd2hlbiBXZWIgUnRjIGhhcyBjb25uZWN0ZWRcbiAgICAgKi9cbiAgICBfb25XZWJSdGNDb25uZWN0ZWQoKSB7XG4gICAgICAgIHRoaXMuX2V2ZW50RW1pdHRlci5kaXNwYXRjaEV2ZW50KG5ldyBXZWJSdGNDb25uZWN0ZWRFdmVudCgpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVzIHdoZW4gV2ViIFJ0YyBmYWlscyB0byBjb25uZWN0XG4gICAgICovXG4gICAgX29uV2ViUnRjRmFpbGVkKCkge1xuICAgICAgICB0aGlzLl9ldmVudEVtaXR0ZXIuZGlzcGF0Y2hFdmVudChuZXcgV2ViUnRjRmFpbGVkRXZlbnQoKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlIHdoZW4gdGhlIFZpZGVvIGhhcyBiZWVuIEluaXRpYWxpemVkXG4gICAgICovXG4gICAgX29uVmlkZW9Jbml0aWFsaXplZCgpIHtcbiAgICAgICAgdGhpcy5fZXZlbnRFbWl0dGVyLmRpc3BhdGNoRXZlbnQobmV3IFZpZGVvSW5pdGlhbGl6ZWRFdmVudCgpKTtcbiAgICAgICAgdGhpcy5fdmlkZW9TdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCB1cCBmdW5jdGlvbmFsaXR5IHRvIGhhcHBlbiB3aGVuIHJlY2VpdmluZyBsYXRlbmN5IHRlc3QgcmVzdWx0c1xuICAgICAqIEBwYXJhbSBsYXRlbmN5IC0gbGF0ZW5jeSB0ZXN0IHJlc3VsdHMgb2JqZWN0XG4gICAgICovXG4gICAgX29uTGF0ZW5jeVRlc3RSZXN1bHQobGF0ZW5jeVRpbWluZ3M6IExhdGVuY3lUZXN0UmVzdWx0cykge1xuICAgICAgICB0aGlzLl9ldmVudEVtaXR0ZXIuZGlzcGF0Y2hFdmVudChcbiAgICAgICAgICAgIG5ldyBMYXRlbmN5VGVzdFJlc3VsdEV2ZW50KHsgbGF0ZW5jeVRpbWluZ3MgfSlcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBfb25EYXRhQ2hhbm5lbExhdGVuY3lUZXN0UmVzcG9uc2UocmVzcG9uc2U6IERhdGFDaGFubmVsTGF0ZW5jeVRlc3RSZXNwb25zZSkge1xuICAgICAgICB0aGlzLl9ldmVudEVtaXR0ZXIuZGlzcGF0Y2hFdmVudChcbiAgICAgICAgICAgIG5ldyBEYXRhQ2hhbm5lbExhdGVuY3lUZXN0UmVzcG9uc2VFdmVudCh7IHJlc3BvbnNlIH0pXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHVwIGZ1bmN0aW9uYWxpdHkgdG8gaGFwcGVuIHdoZW4gcmVjZWl2aW5nIHZpZGVvIHN0YXRpc3RpY3NcbiAgICAgKiBAcGFyYW0gdmlkZW9TdGF0cyAtIHZpZGVvIHN0YXRpc3RpY3MgYXMgYSBhZ2dyZWdhdGUgc3RhdHMgb2JqZWN0XG4gICAgICovXG4gICAgX29uVmlkZW9TdGF0cyh2aWRlb1N0YXRzOiBBZ2dyZWdhdGVkU3RhdHMpIHtcbiAgICAgICAgLy8gRHVyYXRpb25cbiAgICAgICAgaWYgKCF0aGlzLl92aWRlb1N0YXJ0VGltZSB8fCB0aGlzLl92aWRlb1N0YXJ0VGltZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aGlzLl92aWRlb1N0YXJ0VGltZSA9IERhdGUubm93KCk7XG4gICAgICAgIH1cbiAgICAgICAgdmlkZW9TdGF0cy5oYW5kbGVTZXNzaW9uU3RhdGlzdGljcyhcbiAgICAgICAgICAgIHRoaXMuX3ZpZGVvU3RhcnRUaW1lLFxuICAgICAgICAgICAgdGhpcy5faW5wdXRDb250cm9sbGVyLFxuICAgICAgICAgICAgdGhpcy5fd2ViUnRjQ29udHJvbGxlci52aWRlb0F2Z1FwXG4gICAgICAgICk7XG5cbiAgICAgICAgdGhpcy5fZXZlbnRFbWl0dGVyLmRpc3BhdGNoRXZlbnQoXG4gICAgICAgICAgICBuZXcgU3RhdHNSZWNlaXZlZEV2ZW50KHsgYWdncmVnYXRlZFN0YXRzOiB2aWRlb1N0YXRzIH0pXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHVwIGZ1bmN0aW9uYWxpdHkgdG8gaGFwcGVuIHdoZW4gY2FsY3VsYXRpbmcgdGhlIGF2ZXJhZ2UgdmlkZW8gZW5jb2RlciBxcFxuICAgICAqIEBwYXJhbSBRUCAtIHRoZSBxdWFsaXR5IG51bWJlciBvZiB0aGUgc3RyZWFtXG4gICAgICovXG4gICAgX29uVmlkZW9FbmNvZGVyQXZnUVAoUVA6IG51bWJlcikge1xuICAgICAgICB0aGlzLl9ldmVudEVtaXR0ZXIuZGlzcGF0Y2hFdmVudChcbiAgICAgICAgICAgIG5ldyBWaWRlb0VuY29kZXJBdmdRUEV2ZW50KHsgYXZnUVA6IFFQIH0pXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHVwIGZ1bmN0aW9uYWxpdHkgdG8gaGFwcGVuIHdoZW4gcmVjZWl2aW5nIGFuZCBoYW5kbGluZyBpbml0aWFsIHNldHRpbmdzIGZvciB0aGUgVUUgYXBwXG4gICAgICogQHBhcmFtIHNldHRpbmdzIC0gaW5pdGlhbCBVRSBhcHAgc2V0dGluZ3NcbiAgICAgKi9cbiAgICBfb25Jbml0aWFsU2V0dGluZ3Moc2V0dGluZ3M6IEluaXRpYWxTZXR0aW5ncykge1xuICAgICAgICB0aGlzLl9ldmVudEVtaXR0ZXIuZGlzcGF0Y2hFdmVudChcbiAgICAgICAgICAgIG5ldyBJbml0aWFsU2V0dGluZ3NFdmVudCh7IHNldHRpbmdzIH0pXG4gICAgICAgICk7XG4gICAgICAgIGlmIChzZXR0aW5ncy5QaXhlbFN0cmVhbWluZ1NldHRpbmdzKSB7XG4gICAgICAgICAgICB0aGlzLmFsbG93Q29uc29sZUNvbW1hbmRzID1cbiAgICAgICAgICAgICAgICBzZXR0aW5ncy5QaXhlbFN0cmVhbWluZ1NldHRpbmdzLkFsbG93UGl4ZWxTdHJlYW1pbmdDb21tYW5kcyA/PyBmYWxzZTtcbiAgICAgICAgICAgIGlmICh0aGlzLmFsbG93Q29uc29sZUNvbW1hbmRzID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgIExvZ2dlci5JbmZvKFxuICAgICAgICAgICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgICAgICAgICAnLUFsbG93UGl4ZWxTdHJlYW1pbmdDb21tYW5kcz1mYWxzZSwgc2VuZGluZyBhcmJpdHJhcnkgY29uc29sZSBjb21tYW5kcyBmcm9tIGJyb3dzZXIgdG8gVUUgaXMgZGlzYWJsZWQuJ1xuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB1c2VVcmxQYXJhbXMgPSB0aGlzLmNvbmZpZy51c2VVcmxQYXJhbXM7XG4gICAgICAgIGNvbnN0IHVybFBhcmFtcyA9IG5ldyBVUkxTZWFyY2hQYXJhbXMod2luZG93LmxvY2F0aW9uLnNlYXJjaCk7XG4gICAgICAgIGlmIChzZXR0aW5ncy5FbmNvZGVyU2V0dGluZ3MpIHtcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLnNldE51bWVyaWNTZXR0aW5nKFxuICAgICAgICAgICAgICAgIE51bWVyaWNQYXJhbWV0ZXJzLk1pblFQLFxuICAgICAgICAgICAgICAgIC8vIElmIGEgc2V0dGluZyBpcyBzZXQgaW4gdGhlIFVSTCwgbWFrZSBzdXJlIHdlIHJlc3BlY3QgdGhhdCB2YWx1ZSBhcyBvcHBvc2VkIHRvIHdoYXQgdGhlIGFwcGxpY2F0aW9uIHNlbmRzIHVzXG4gICAgICAgICAgICAgICAgKHVzZVVybFBhcmFtcyAmJiB1cmxQYXJhbXMuaGFzKE51bWVyaWNQYXJhbWV0ZXJzLk1pblFQKSkgXG4gICAgICAgICAgICAgICAgICAgID8gTnVtYmVyLnBhcnNlSW50KHVybFBhcmFtcy5nZXQoTnVtZXJpY1BhcmFtZXRlcnMuTWluUVApKSBcbiAgICAgICAgICAgICAgICAgICAgOiBzZXR0aW5ncy5FbmNvZGVyU2V0dGluZ3MuTWluUVBcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIFxuICAgICAgICAgICAgdGhpcy5jb25maWcuc2V0TnVtZXJpY1NldHRpbmcoXG4gICAgICAgICAgICAgICAgTnVtZXJpY1BhcmFtZXRlcnMuTWF4UVAsXG4gICAgICAgICAgICAgICAgKHVzZVVybFBhcmFtcyAmJiB1cmxQYXJhbXMuaGFzKE51bWVyaWNQYXJhbWV0ZXJzLk1heFFQKSkgXG4gICAgICAgICAgICAgICAgICAgID8gTnVtYmVyLnBhcnNlSW50KHVybFBhcmFtcy5nZXQoTnVtZXJpY1BhcmFtZXRlcnMuTWF4UVApKSBcbiAgICAgICAgICAgICAgICAgICAgOiBzZXR0aW5ncy5FbmNvZGVyU2V0dGluZ3MuTWF4UVBcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHNldHRpbmdzLldlYlJUQ1NldHRpbmdzKSB7XG4gICAgICAgICAgICB0aGlzLmNvbmZpZy5zZXROdW1lcmljU2V0dGluZyhcbiAgICAgICAgICAgICAgICBOdW1lcmljUGFyYW1ldGVycy5XZWJSVENNaW5CaXRyYXRlLFxuICAgICAgICAgICAgICAgICh1c2VVcmxQYXJhbXMgJiYgdXJsUGFyYW1zLmhhcyhOdW1lcmljUGFyYW1ldGVycy5XZWJSVENNaW5CaXRyYXRlKSkgXG4gICAgICAgICAgICAgICAgICAgID8gTnVtYmVyLnBhcnNlSW50KHVybFBhcmFtcy5nZXQoTnVtZXJpY1BhcmFtZXRlcnMuV2ViUlRDTWluQml0cmF0ZSkpXG4gICAgICAgICAgICAgICAgICAgIDogc2V0dGluZ3MuV2ViUlRDU2V0dGluZ3MuTWluQml0cmF0ZSAvIDEwMDAgLyogYnBzIHRvIGticHMgKi9cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICB0aGlzLmNvbmZpZy5zZXROdW1lcmljU2V0dGluZyhcbiAgICAgICAgICAgICAgICBOdW1lcmljUGFyYW1ldGVycy5XZWJSVENNYXhCaXRyYXRlLFxuICAgICAgICAgICAgICAgICh1c2VVcmxQYXJhbXMgJiYgdXJsUGFyYW1zLmhhcyhOdW1lcmljUGFyYW1ldGVycy5XZWJSVENNYXhCaXRyYXRlKSkgXG4gICAgICAgICAgICAgICAgICAgID8gTnVtYmVyLnBhcnNlSW50KHVybFBhcmFtcy5nZXQoTnVtZXJpY1BhcmFtZXRlcnMuV2ViUlRDTWF4Qml0cmF0ZSkpXG4gICAgICAgICAgICAgICAgICAgIDogc2V0dGluZ3MuV2ViUlRDU2V0dGluZ3MuTWF4Qml0cmF0ZSAvIDEwMDAgLyogYnBzIHRvIGticHMgKi9cbiAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICB0aGlzLmNvbmZpZy5zZXROdW1lcmljU2V0dGluZyhcbiAgICAgICAgICAgICAgICBOdW1lcmljUGFyYW1ldGVycy5XZWJSVENGUFMsXG4gICAgICAgICAgICAgICAgKHVzZVVybFBhcmFtcyAmJiB1cmxQYXJhbXMuaGFzKE51bWVyaWNQYXJhbWV0ZXJzLldlYlJUQ0ZQUykpIFxuICAgICAgICAgICAgICAgICAgICA/IE51bWJlci5wYXJzZUludCh1cmxQYXJhbXMuZ2V0KE51bWVyaWNQYXJhbWV0ZXJzLldlYlJUQ0ZQUykpXG4gICAgICAgICAgICAgICAgICAgIDogc2V0dGluZ3MuV2ViUlRDU2V0dGluZ3MuRlBTXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHVwIGZ1bmN0aW9uYWxpdHkgdG8gaGFwcGVuIHdoZW4gc2V0dGluZyBxdWFsaXR5IGNvbnRyb2wgb3duZXJzaGlwIG9mIGEgc3RyZWFtXG4gICAgICogQHBhcmFtIGhhc1F1YWxpdHlPd25lcnNoaXAgLSBkb2VzIHRoaXMgdXNlciBoYXZlIHF1YWxpdHkgb3duZXJzaGlwIG9mIHRoZSBzdHJlYW0gdHJ1ZSAvIGZhbHNlXG4gICAgICovXG4gICAgX29uUXVhbGl0eUNvbnRyb2xPd25lcnNoaXAoaGFzUXVhbGl0eU93bmVyc2hpcDogYm9vbGVhbikge1xuICAgICAgICB0aGlzLmNvbmZpZy5zZXRGbGFnRW5hYmxlZChcbiAgICAgICAgICAgIEZsYWdzLklzUXVhbGl0eUNvbnRyb2xsZXIsXG4gICAgICAgICAgICBoYXNRdWFsaXR5T3duZXJzaGlwXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgX29uUGxheWVyQ291bnQocGxheWVyQ291bnQ6IG51bWJlcikge1xuICAgICAgICB0aGlzLl9ldmVudEVtaXR0ZXIuZGlzcGF0Y2hFdmVudChcbiAgICAgICAgICAgIG5ldyBQbGF5ZXJDb3VudEV2ZW50KHsgY291bnQ6IHBsYXllckNvdW50IH0pXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVxdWVzdCBhIGNvbm5lY3Rpb24gbGF0ZW5jeSB0ZXN0LlxuICAgICAqIE5PVEU6IFRoZXJlIGFyZSBwbGFucyB0byByZWZhY3RvciBhbGwgcmVxdWVzdCogZnVuY3Rpb25zLiBFeHBlY3QgY2hhbmdlcyBpZiB5b3UgdXNlIHRoaXMhXG4gICAgICogQHJldHVybnNcbiAgICAgKi9cbiAgICBwdWJsaWMgcmVxdWVzdExhdGVuY3lUZXN0KCkge1xuICAgICAgICBpZiAoIXRoaXMuX3dlYlJ0Y0NvbnRyb2xsZXIudmlkZW9QbGF5ZXIuaXNWaWRlb1JlYWR5KCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl93ZWJSdGNDb250cm9sbGVyLnNlbmRMYXRlbmN5VGVzdCgpO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXF1ZXN0IGEgZGF0YSBjaGFubmVsIGxhdGVuY3kgdGVzdC5cbiAgICAgKiBOT1RFOiBUaGVyZSBhcmUgcGxhbnMgdG8gcmVmYWN0b3IgYWxsIHJlcXVlc3QqIGZ1bmN0aW9ucy4gRXhwZWN0IGNoYW5nZXMgaWYgeW91IHVzZSB0aGlzIVxuICAgICAqL1xuICAgIHB1YmxpYyByZXF1ZXN0RGF0YUNoYW5uZWxMYXRlbmN5VGVzdChjb25maWc6IERhdGFDaGFubmVsTGF0ZW5jeVRlc3RDb25maWcpIHtcbiAgICAgICAgaWYgKCF0aGlzLl93ZWJSdGNDb250cm9sbGVyLnZpZGVvUGxheWVyLmlzVmlkZW9SZWFkeSgpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLl9kYXRhQ2hhbm5lbExhdGVuY3lUZXN0Q29udHJvbGxlcikge1xuICAgICAgICAgICAgdGhpcy5fZGF0YUNoYW5uZWxMYXRlbmN5VGVzdENvbnRyb2xsZXIgPSBuZXcgRGF0YUNoYW5uZWxMYXRlbmN5VGVzdENvbnRyb2xsZXIoXG4gICAgICAgICAgICAgICAgdGhpcy5fd2ViUnRjQ29udHJvbGxlci5zZW5kRGF0YUNoYW5uZWxMYXRlbmN5VGVzdC5iaW5kKHRoaXMuX3dlYlJ0Y0NvbnRyb2xsZXIpLFxuICAgICAgICAgICAgICAgIChyZXN1bHQ6IERhdGFDaGFubmVsTGF0ZW5jeVRlc3RSZXN1bHQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fZXZlbnRFbWl0dGVyLmRpc3BhdGNoRXZlbnQobmV3IERhdGFDaGFubmVsTGF0ZW5jeVRlc3RSZXN1bHRFdmVudCggeyByZXN1bHQgfSkpXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB0aGlzLmFkZEV2ZW50TGlzdGVuZXIoXG4gICAgICAgICAgICAgICAgXCJkYXRhQ2hhbm5lbExhdGVuY3lUZXN0UmVzcG9uc2VcIixcbiAgICAgICAgICAgICAgICAoe2RhdGE6IHtyZXNwb25zZX0gfSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9kYXRhQ2hhbm5lbExhdGVuY3lUZXN0Q29udHJvbGxlci5yZWNlaXZlKHJlc3BvbnNlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApXG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuX2RhdGFDaGFubmVsTGF0ZW5jeVRlc3RDb250cm9sbGVyLnN0YXJ0KGNvbmZpZyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVxdWVzdCBmb3IgdGhlIFVFIGFwcGxpY2F0aW9uIHRvIHNob3cgRlBTIGNvdW50ZXIuXG4gICAgICogTk9URTogVGhlcmUgYXJlIHBsYW5zIHRvIHJlZmFjdG9yIGFsbCByZXF1ZXN0KiBmdW5jdGlvbnMuIEV4cGVjdCBjaGFuZ2VzIGlmIHlvdSB1c2UgdGhpcyFcbiAgICAgKiBAcmV0dXJuc1xuICAgICAqL1xuICAgIHB1YmxpYyByZXF1ZXN0U2hvd0ZwcygpIHtcbiAgICAgICAgaWYgKCF0aGlzLl93ZWJSdGNDb250cm9sbGVyLnZpZGVvUGxheWVyLmlzVmlkZW9SZWFkeSgpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fd2ViUnRjQ29udHJvbGxlci5zZW5kU2hvd0ZwcygpO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXF1ZXN0IGZvciBhIG5ldyBJRnJhbWUgZnJvbSB0aGUgVUUgYXBwbGljYXRpb24uXG4gICAgICogTk9URTogVGhlcmUgYXJlIHBsYW5zIHRvIHJlZmFjdG9yIGFsbCByZXF1ZXN0KiBmdW5jdGlvbnMuIEV4cGVjdCBjaGFuZ2VzIGlmIHlvdSB1c2UgdGhpcyFcbiAgICAgKiBAcmV0dXJuc1xuICAgICAqL1xuICAgIHB1YmxpYyByZXF1ZXN0SWZyYW1lKCkge1xuICAgICAgICBpZiAoIXRoaXMuX3dlYlJ0Y0NvbnRyb2xsZXIudmlkZW9QbGF5ZXIuaXNWaWRlb1JlYWR5KCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl93ZWJSdGNDb250cm9sbGVyLnNlbmRJZnJhbWVSZXF1ZXN0KCk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlbmQgZGF0YSB0byBVRSBhcHBsaWNhdGlvbi4gVGhlIGRhdGEgd2lsbCBiZSBydW4gdGhyb3VnaCBKU09OLnN0cmluZ2lmeSgpIHNvIGUuZy4gc3RyaW5nc1xuICAgICAqIGFuZCBhbnkgc2VyaWFsaXphYmxlIHBsYWluIEpTT04gb2JqZWN0cyB3aXRoIG5vIHJlY3VycmVuY2UgY2FuIGJlIHNlbnQuXG4gICAgICogQHJldHVybnMgdHJ1ZSBpZiBzdWNjZWVkZWQsIGZhbHNlIGlmIHJlamVjdGVkXG4gICAgICovXG4gICAgcHVibGljIGVtaXRVSUludGVyYWN0aW9uKGRlc2NyaXB0b3I6IG9iamVjdCB8IHN0cmluZykge1xuICAgICAgICBpZiAoIXRoaXMuX3dlYlJ0Y0NvbnRyb2xsZXIudmlkZW9QbGF5ZXIuaXNWaWRlb1JlYWR5KCkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl93ZWJSdGNDb250cm9sbGVyLmVtaXRVSUludGVyYWN0aW9uKGRlc2NyaXB0b3IpO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZW5kIGEgY29tbWFuZCB0byBVRSBhcHBsaWNhdGlvbi4gQmxvY2tzIENvbnNvbGVDb21tYW5kIGRlc2NyaXB0b3JzIHVubGVzcyBVRVxuICAgICAqIGhhcyBzaWduYWxlZCB0aGF0IGl0IGFsbG93cyBjb25zb2xlIGNvbW1hbmRzLlxuICAgICAqIEByZXR1cm5zIHRydWUgaWYgc3VjY2VlZGVkLCBmYWxzZSBpZiByZWplY3RlZFxuICAgICAqL1xuICAgIHB1YmxpYyBlbWl0Q29tbWFuZChkZXNjcmlwdG9yOiBvYmplY3QpIHtcbiAgICAgICAgaWYgKCF0aGlzLl93ZWJSdGNDb250cm9sbGVyLnZpZGVvUGxheWVyLmlzVmlkZW9SZWFkeSgpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLmFsbG93Q29uc29sZUNvbW1hbmRzICYmICdDb25zb2xlQ29tbWFuZCcgaW4gZGVzY3JpcHRvcikge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3dlYlJ0Y0NvbnRyb2xsZXIuZW1pdENvbW1hbmQoZGVzY3JpcHRvcik7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlbmQgYSBjb25zb2xlIGNvbW1hbmQgdG8gVUUgYXBwbGljYXRpb24uIE9ubHkgYWxsb3dlZCBpZiBVRSBoYXMgc2lnbmFsZWQgdGhhdCBpdCBhbGxvd3NcbiAgICAgKiBjb25zb2xlIGNvbW1hbmRzLlxuICAgICAqIEByZXR1cm5zIHRydWUgaWYgc3VjY2VlZGVkLCBmYWxzZSBpZiByZWplY3RlZFxuICAgICAqL1xuICAgIHB1YmxpYyBlbWl0Q29uc29sZUNvbW1hbmQoY29tbWFuZDogc3RyaW5nKSB7XG4gICAgICAgIGlmICghdGhpcy5hbGxvd0NvbnNvbGVDb21tYW5kcyB8fCAhdGhpcy5fd2ViUnRjQ29udHJvbGxlci52aWRlb1BsYXllci5pc1ZpZGVvUmVhZHkoKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3dlYlJ0Y0NvbnRyb2xsZXIuZW1pdENvbnNvbGVDb21tYW5kKGNvbW1hbmQpO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGQgYSBVRSAtPiBicm93c2VyIHJlc3BvbnNlIGV2ZW50IGxpc3RlbmVyXG4gICAgICogQHBhcmFtIG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgcmVzcG9uc2UgaGFuZGxlclxuICAgICAqIEBwYXJhbSBsaXN0ZW5lciAtIFRoZSBtZXRob2QgdG8gYmUgYWN0aXZhdGVkIHdoZW4gYSBtZXNzYWdlIGlzIHJlY2VpdmVkXG4gICAgICovXG4gICAgcHVibGljIGFkZFJlc3BvbnNlRXZlbnRMaXN0ZW5lcihcbiAgICAgICAgbmFtZTogc3RyaW5nLFxuICAgICAgICBsaXN0ZW5lcjogKHJlc3BvbnNlOiBzdHJpbmcpID0+IHZvaWRcbiAgICApIHtcbiAgICAgICAgdGhpcy5fd2ViUnRjQ29udHJvbGxlci5yZXNwb25zZUNvbnRyb2xsZXIuYWRkUmVzcG9uc2VFdmVudExpc3RlbmVyKG5hbWUsIGxpc3RlbmVyKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgYSBVRSAtPiBicm93c2VyIHJlc3BvbnNlIGV2ZW50IGxpc3RlbmVyXG4gICAgICogQHBhcmFtIG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgcmVzcG9uc2UgaGFuZGxlclxuICAgICAqL1xuICAgIHB1YmxpYyByZW1vdmVSZXNwb25zZUV2ZW50TGlzdGVuZXIobmFtZTogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMuX3dlYlJ0Y0NvbnRyb2xsZXIucmVzcG9uc2VDb250cm9sbGVyLnJlbW92ZVJlc3BvbnNlRXZlbnRMaXN0ZW5lcihuYW1lKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEaXNwYXRjaCBhIG5ldyBldmVudC5cbiAgICAgKiBAcGFyYW0gZSBldmVudFxuICAgICAqIEByZXR1cm5zXG4gICAgICovXG4gICAgcHVibGljIGRpc3BhdGNoRXZlbnQoZTogUGl4ZWxTdHJlYW1pbmdFdmVudCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5fZXZlbnRFbWl0dGVyLmRpc3BhdGNoRXZlbnQoZSk7XG4gICAgfVxuICAgIFxuICAgIC8qKlxuICAgICAqIFJlZ2lzdGVyIGFuIGV2ZW50IGhhbmRsZXIuXG4gICAgICogQHBhcmFtIHR5cGUgZXZlbnQgbmFtZVxuICAgICAqIEBwYXJhbSBsaXN0ZW5lciBldmVudCBoYW5kbGVyIGZ1bmN0aW9uXG4gICAgICovXG4gICAgcHVibGljIGFkZEV2ZW50TGlzdGVuZXI8XG4gICAgICAgIFQgZXh0ZW5kcyBQaXhlbFN0cmVhbWluZ0V2ZW50Wyd0eXBlJ10sXG4gICAgICAgIEUgZXh0ZW5kcyBQaXhlbFN0cmVhbWluZ0V2ZW50ICYgeyB0eXBlOiBUIH1cbiAgICA+KHR5cGU6IFQsIGxpc3RlbmVyOiAoZTogRXZlbnQgJiBFKSA9PiB2b2lkKSB7XG4gICAgICAgIHRoaXMuX2V2ZW50RW1pdHRlci5hZGRFdmVudExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgYW4gZXZlbnQgaGFuZGxlci5cbiAgICAgKiBAcGFyYW0gdHlwZSBldmVudCBuYW1lXG4gICAgICogQHBhcmFtIGxpc3RlbmVyIGV2ZW50IGhhbmRsZXIgZnVuY3Rpb25cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVtb3ZlRXZlbnRMaXN0ZW5lcjxcbiAgICAgICAgVCBleHRlbmRzIFBpeGVsU3RyZWFtaW5nRXZlbnRbJ3R5cGUnXSxcbiAgICAgICAgRSBleHRlbmRzIFBpeGVsU3RyZWFtaW5nRXZlbnQgJiB7IHR5cGU6IFQgfVxuICAgID4odHlwZTogVCwgbGlzdGVuZXI6IChlOiBFdmVudCAmIEUpID0+IHZvaWQpIHtcbiAgICAgICAgdGhpcy5fZXZlbnRFbWl0dGVyLnJlbW92ZUV2ZW50TGlzdGVuZXIodHlwZSwgbGlzdGVuZXIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEVuYWJsZS9kaXNhYmxlIFhSIG1vZGUuXG4gICAgICovXG4gICAgcHVibGljIHRvZ2dsZVhSKCkge1xuICAgICAgICB0aGlzLndlYlhyQ29udHJvbGxlci54ckNsaWNrZWQoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQYXNzIGluIGEgZnVuY3Rpb24gdG8gZ2VuZXJhdGUgYSBzaWduYWxsaW5nIHNlcnZlciBVUkwuXG4gICAgICogVGhpcyBmdW5jdGlvbiBpcyB1c2VmdWwgaWYgeW91IG5lZWQgdG8gcHJvZ3JhbW1hdGljYWxseSBjb25zdHJ1Y3QgeW91ciBzaWduYWxsaW5nIHNlcnZlciBVUkwuXG4gICAgICogQHBhcmFtIHNpZ25hbGxpbmdVcmxCdWlsZGVyRnVuYyBBIGZ1bmN0aW9uIHRoYXQgZ2VuZXJhdGVzIGEgc2lnbmFsbGluZyBzZXJ2ZXIgdXJsLlxuICAgICAqL1xuICAgIHB1YmxpYyBzZXRTaWduYWxsaW5nVXJsQnVpbGRlcihzaWduYWxsaW5nVXJsQnVpbGRlckZ1bmM6ICgpPT5zdHJpbmcpIHtcbiAgICAgICAgdGhpcy5fd2ViUnRjQ29udHJvbGxlci5zaWduYWxsaW5nVXJsQnVpbGRlciA9IHNpZ25hbGxpbmdVcmxCdWlsZGVyRnVuYztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQdWJsaWMgZ2V0dGVyIGZvciB0aGUgd2Vic29ja2V0IGNvbnRyb2xsZXIuIEFjY2VzcyB0byB0aGlzIHByb3BlcnR5IGFsbG93cyB5b3UgdG8gc2VuZFxuICAgICAqIGN1c3RvbSB3ZWJzb2NrZXQgbWVzc2FnZXMuXG4gICAgICovXG4gICAgcHVibGljIGdldCB3ZWJTb2NrZXRDb250cm9sbGVyKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fd2ViUnRjQ29udHJvbGxlci53ZWJTb2NrZXRDb250cm9sbGVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFB1YmxpYyBnZXR0ZXIgZm9yIHRoZSB3ZWJYckNvbnRyb2xsZXIgY29udHJvbGxlci4gVXNlZCBmb3IgYWxsIFhSIGZlYXR1cmVzLlxuICAgICAqL1xuICAgIHB1YmxpYyBnZXQgd2ViWHJDb250cm9sbGVyKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fd2ViWHJDb250cm9sbGVyO1xuICAgIH1cblxuICAgIHB1YmxpYyByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKG5hbWU6IHN0cmluZywgZGlyZWN0aW9uOiBNZXNzYWdlRGlyZWN0aW9uLCBoYW5kbGVyPzogKGRhdGE6IEFycmF5QnVmZmVyIHwgQXJyYXk8bnVtYmVyIHwgc3RyaW5nPikgPT4gdm9pZCkge1xuICAgICAgICBpZihkaXJlY3Rpb24gPT09IE1lc3NhZ2VEaXJlY3Rpb24uRnJvbVN0cmVhbWVyICYmIHR5cGVvZiBoYW5kbGVyID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgTG9nZ2VyLldhcm5pbmcoTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSwgYFVuYWJsZSB0byByZWdpc3RlciBhbiB1bmRlZmluZWQgaGFuZGxlciBmb3IgJHtuYW1lfWApXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZihkaXJlY3Rpb24gPT09IE1lc3NhZ2VEaXJlY3Rpb24uVG9TdHJlYW1lciAmJiB0eXBlb2YgaGFuZGxlciA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIHRoaXMuX3dlYlJ0Y0NvbnRyb2xsZXIuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIucmVnaXN0ZXJNZXNzYWdlSGFuZGxlcihcbiAgICAgICAgICAgICAgICBkaXJlY3Rpb24sXG4gICAgICAgICAgICAgICAgbmFtZSxcbiAgICAgICAgICAgICAgICAoZGF0YTogQXJyYXk8bnVtYmVyIHwgc3RyaW5nPikgPT5cbiAgICAgICAgICAgICAgICB0aGlzLl93ZWJSdGNDb250cm9sbGVyLnNlbmRNZXNzYWdlQ29udHJvbGxlci5zZW5kTWVzc2FnZVRvU3RyZWFtZXIoXG4gICAgICAgICAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICAgICAgICAgIGRhdGFcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5fd2ViUnRjQ29udHJvbGxlci5zdHJlYW1NZXNzYWdlQ29udHJvbGxlci5yZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKFxuICAgICAgICAgICAgICAgIGRpcmVjdGlvbixcbiAgICAgICAgICAgICAgICBuYW1lLFxuICAgICAgICAgICAgICAgIChkYXRhOiBBcnJheUJ1ZmZlcikgPT4gaGFuZGxlcihkYXRhKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgdG9TdHJlYW1lckhhbmRsZXJzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fd2ViUnRjQ29udHJvbGxlci5zdHJlYW1NZXNzYWdlQ29udHJvbGxlci50b1N0cmVhbWVySGFuZGxlcnM7XG4gICAgfVxuXG4gICAgcHVibGljIGlzUmVjb25uZWN0aW5nKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fd2ViUnRjQ29udHJvbGxlci5pc1JlY29ubmVjdGluZztcbiAgICB9XG59XG4iLCIvLyBDb3B5cmlnaHQgRXBpYyBHYW1lcywgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuXG5pbXBvcnQgeyBVbnF1YW50aXplZERlbm9ybWFsaXplZFVuc2lnbmVkQ29vcmQgfSBmcm9tICcuLi9VdGlsL0Nvb3JkaW5hdGVDb252ZXJ0ZXInO1xuaW1wb3J0IHsgTWVzc2FnZU9uU2NyZWVuS2V5Ym9hcmQgfSBmcm9tICcuLi9XZWJTb2NrZXRzL01lc3NhZ2VSZWNlaXZlJztcblxuLyoqXG4gKiBDbGFzcyBmb3IgaGFuZGxpbmcgb24gc2NyZWVuIGtleWJvYXJkIHVzYWdlXG4gKi9cbmV4cG9ydCBjbGFzcyBPblNjcmVlbktleWJvYXJkIHtcbiAgICAvLyBJZiB0aGUgdXNlciBmb2N1c2VzIG9uIGEgVUUgaW5wdXQgd2lkZ2V0IHRoZW4gd2Ugc2hvdyB0aGVtIGEgYnV0dG9uIHRvIG9wZW5cbiAgICAvLyB0aGUgb24tc2NyZWVuIGtleWJvYXJkLiBKYXZhU2NyaXB0IHNlY3VyaXR5IG1lYW5zIHdlIGNhbiBvbmx5IHNob3cgdGhlXG4gICAgLy8gb24tc2NyZWVuIGtleWJvYXJkIGluIHJlc3BvbnNlIHRvIGEgdXNlciBpbnRlcmFjdGlvbi5cbiAgICBlZGl0VGV4dEJ1dHRvbjogSFRNTEJ1dHRvbkVsZW1lbnQ7XG5cbiAgICAvLyBBIGhpZGRlbiBpbnB1dCB0ZXh0IGJveCB3aGljaCBpcyB1c2VkIG9ubHkgZm9yIGZvY3VzaW5nIGFuZCBvcGVuaW5nIHRoZVxuICAgIC8vIG9uLXNjcmVlbiBrZXlib2FyZC5cbiAgICBoaWRkZW5JbnB1dDogSFRNTElucHV0RWxlbWVudDtcblxuICAgIC8qKlxuICAgICAqXG4gICAgICogQHBhcmFtIHZpZGVvRWxlbWVudFBhcmVudCBUaGUgZGl2IGVsZW1lbnQgdGhlIHZpZGVvIHBsYXllciBpcyBpbmplY3RlZCBpbnRvXG4gICAgICovXG4gICAgY29uc3RydWN0b3IodmlkZW9FbGVtZW50UGFyZW50OiBIVE1MRWxlbWVudCkge1xuICAgICAgICB0aGlzLmVkaXRUZXh0QnV0dG9uID0gbnVsbDtcbiAgICAgICAgdGhpcy5oaWRkZW5JbnB1dCA9IG51bGw7XG5cbiAgICAgICAgaWYgKCdvbnRvdWNoc3RhcnQnIGluIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCkge1xuICAgICAgICAgICAgdGhpcy5jcmVhdGVPblNjcmVlbktleWJvYXJkSGVscGVycyh2aWRlb0VsZW1lbnRQYXJlbnQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQW4gb3ZlcnJpZGUgZm9yIHVucXVhbnRpemVBbmREZW5vcm1hbGl6ZVVuc2lnbmVkXG4gICAgICogQHBhcmFtIHggdGhlIHggYXhpcyBwb2ludFxuICAgICAqIEBwYXJhbSB5IHRoZSB5IGF4aXMgcG9pbnRcbiAgICAgKiBAcmV0dXJucyB1bnF1YW50aXplQW5kRGVub3JtYWxpemVVbnNpZ25lZCBvYmplY3RcbiAgICAgKi9cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzXG4gICAgdW5xdWFudGl6ZUFuZERlbm9ybWFsaXplVW5zaWduZWQoXG4gICAgICAgIHg6IG51bWJlcixcbiAgICAgICAgeTogbnVtYmVyXG4gICAgKTogVW5xdWFudGl6ZWREZW5vcm1hbGl6ZWRVbnNpZ25lZENvb3JkIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBvbiBzY3JlZW4ga2V5Ym9hcmQgaGVscGVyc1xuICAgICAqIEBwYXJhbSB2aWRlb0VsZW1lbnRQYXJlbnQgVGhlIGRpdiBlbGVtZW50IHRoZSB2aWRlbyBwbGF5ZXIgaSBpbmplY3RlZCBpbnRvXG4gICAgICovXG4gICAgY3JlYXRlT25TY3JlZW5LZXlib2FyZEhlbHBlcnModmlkZW9FbGVtZW50UGFyZW50OiBIVE1MRWxlbWVudCkge1xuICAgICAgICBpZiAoIXRoaXMuaGlkZGVuSW5wdXQpIHtcbiAgICAgICAgICAgIHRoaXMuaGlkZGVuSW5wdXQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpbnB1dCcpO1xuICAgICAgICAgICAgdGhpcy5oaWRkZW5JbnB1dC5pZCA9ICdoaWRkZW5JbnB1dCc7XG4gICAgICAgICAgICB0aGlzLmhpZGRlbklucHV0Lm1heExlbmd0aCA9IDA7XG4gICAgICAgICAgICB2aWRlb0VsZW1lbnRQYXJlbnQuYXBwZW5kQ2hpbGQodGhpcy5oaWRkZW5JbnB1dCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRoaXMuZWRpdFRleHRCdXR0b24pIHtcbiAgICAgICAgICAgIHRoaXMuZWRpdFRleHRCdXR0b24gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdidXR0b24nKTtcbiAgICAgICAgICAgIHRoaXMuZWRpdFRleHRCdXR0b24uaWQgPSAnZWRpdFRleHRCdXR0b24nO1xuICAgICAgICAgICAgdGhpcy5lZGl0VGV4dEJ1dHRvbi5pbm5lckhUTUwgPSAnZWRpdCB0ZXh0JztcbiAgICAgICAgICAgIHZpZGVvRWxlbWVudFBhcmVudC5hcHBlbmRDaGlsZCh0aGlzLmVkaXRUZXh0QnV0dG9uKTtcblxuICAgICAgICAgICAgLy8gSGlkZSB0aGUgJ2VkaXQgdGV4dCcgYnV0dG9uLlxuICAgICAgICAgICAgdGhpcy5lZGl0VGV4dEJ1dHRvbi5jbGFzc0xpc3QuYWRkKCdoaWRkZW5TdGF0ZScpO1xuXG4gICAgICAgICAgICB0aGlzLmVkaXRUZXh0QnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoZW5kJywgKGV2ZW50OiBFdmVudCkgPT4ge1xuICAgICAgICAgICAgICAgIC8vIFNob3cgdGhlIG9uLXNjcmVlbiBrZXlib2FyZC5cbiAgICAgICAgICAgICAgICB0aGlzLmhpZGRlbklucHV0LmZvY3VzKCk7XG4gICAgICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2hvd3MgdGhlIG9uIHNjcmVlbiBrZXlib2FyZFxuICAgICAqIEBwYXJhbSBjb21tYW5kIHRoZSBjb21tYW5kIHJlY2VpdmVkIHZpYSB0aGUgZGF0YSBjaGFubmVsIGNvbnRhaW5pbmcga2V5Ym9hcmQgcG9zaXRpb25zXG4gICAgICovXG4gICAgc2hvd09uU2NyZWVuS2V5Ym9hcmQoY29tbWFuZDogTWVzc2FnZU9uU2NyZWVuS2V5Ym9hcmQpIHtcbiAgICAgICAgaWYgKGNvbW1hbmQuc2hvd09uU2NyZWVuS2V5Ym9hcmQpIHtcbiAgICAgICAgICAgIC8vIFNob3cgdGhlICdlZGl0IHRleHQnIGJ1dHRvbi5cbiAgICAgICAgICAgIHRoaXMuZWRpdFRleHRCdXR0b24uY2xhc3NMaXN0LnJlbW92ZSgnaGlkZGVuU3RhdGUnKTtcbiAgICAgICAgICAgIC8vIFBsYWNlIHRoZSAnZWRpdCB0ZXh0JyBidXR0b24gbmVhciB0aGUgVUUgaW5wdXQgd2lkZ2V0LlxuICAgICAgICAgICAgY29uc3QgcG9zID0gdGhpcy51bnF1YW50aXplQW5kRGVub3JtYWxpemVVbnNpZ25lZChcbiAgICAgICAgICAgICAgICBjb21tYW5kLngsXG4gICAgICAgICAgICAgICAgY29tbWFuZC55XG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgdGhpcy5lZGl0VGV4dEJ1dHRvbi5zdHlsZS50b3AgPSBwb3MueS50b1N0cmluZygpICsgJ3B4JztcbiAgICAgICAgICAgIHRoaXMuZWRpdFRleHRCdXR0b24uc3R5bGUubGVmdCA9IChwb3MueCAtIDQwKS50b1N0cmluZygpICsgJ3B4JztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIEhpZGUgdGhlICdlZGl0IHRleHQnIGJ1dHRvbi5cbiAgICAgICAgICAgIHRoaXMuZWRpdFRleHRCdXR0b24uY2xhc3NMaXN0LmFkZCgnaGlkZGVuU3RhdGUnKTtcbiAgICAgICAgICAgIC8vIEhpZGUgdGhlIG9uLXNjcmVlbiBrZXlib2FyZC5cbiAgICAgICAgICAgIHRoaXMuaGlkZGVuSW5wdXQuYmx1cigpO1xuICAgICAgICB9XG4gICAgfVxufVxuIiwiLy8gQ29weXJpZ2h0IEVwaWMgR2FtZXMsIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cblxuaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSAnLi4vTG9nZ2VyL0xvZ2dlcic7XG5cbmV4cG9ydCBjbGFzcyBSZXNwb25zZUNvbnRyb2xsZXIge1xuICAgIHJlc3BvbnNlRXZlbnRMaXN0ZW5lcnM6IE1hcDxzdHJpbmcsIChyZXNwb25zZTogc3RyaW5nKSA9PiB2b2lkPiA9IG5ldyBNYXAoKTtcblxuICAgIC8qKlxuICAgICAqIEFkZCBhIHJlc3BvbnNlIGV2ZW50IGxpc3RlbmVyIHRvIHRoZSByZXNwb25zZSBtYXBcbiAgICAgKiBAcGFyYW0gbmFtZSAtIFRoZSBuYW1lIG9mIHRoZSByZXNwb25zZVxuICAgICAqIEBwYXJhbSBsaXN0ZW5lciAtIFRoZSBtZXRob2QgdG8gYmUgYWN0aXZhdGVkIHdoZW4gdGhlIHJlc3BvbnNlIGlzIHNlbGVjdGVkXG4gICAgICovXG4gICAgYWRkUmVzcG9uc2VFdmVudExpc3RlbmVyKFxuICAgICAgICBuYW1lOiBzdHJpbmcsXG4gICAgICAgIGxpc3RlbmVyOiAocmVzcG9uc2U6IHN0cmluZykgPT4gdm9pZFxuICAgICkge1xuICAgICAgICB0aGlzLnJlc3BvbnNlRXZlbnRMaXN0ZW5lcnMuc2V0KG5hbWUsIGxpc3RlbmVyKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgYSByZXNwb25zZSBldmVudCBsaXN0ZW5lciB0byB0aGUgcmVzcG9uc2UgbWFwXG4gICAgICogQHBhcmFtIG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgcmVzcG9uc2VcbiAgICAgKi9cbiAgICByZW1vdmVSZXNwb25zZUV2ZW50TGlzdGVuZXIobmFtZTogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMucmVzcG9uc2VFdmVudExpc3RlbmVycy5kZWxldGUobmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlIGEgcmVzcG9uc2Ugd2hlbiByZWNlaXZpbmcgb25lIGZvcm0gdGhlIHN0cmVhbWVyXG4gICAgICogQHBhcmFtIG1lc3NhZ2UgLSBEYXRhIHJlY2VpdmVkIGZyb20gdGhlIGRhdGEgY2hhbm5lbCB3aXRoIHRoZSBjb21tYW5kIGluIHF1ZXN0aW9uXG4gICAgICovXG4gICAgb25SZXNwb25zZShtZXNzYWdlOiBBcnJheUJ1ZmZlcikge1xuICAgICAgICBMb2dnZXIuTG9nKFxuICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICdEYXRhQ2hhbm5lbFJlY2VpdmVNZXNzYWdlVHlwZS5SZXNwb25zZScsXG4gICAgICAgICAgICA2XG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IHJlc3BvbnNlcyA9IG5ldyBUZXh0RGVjb2RlcigndXRmLTE2JykuZGVjb2RlKG1lc3NhZ2Uuc2xpY2UoMSkpO1xuXG4gICAgICAgIExvZ2dlci5Mb2coTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSwgcmVzcG9uc2VzLCA2KTtcbiAgICAgICAgdGhpcy5yZXNwb25zZUV2ZW50TGlzdGVuZXJzLmZvckVhY2goXG4gICAgICAgICAgICAobGlzdGVuZXI6IChyZXNwb25zZTogc3RyaW5nKSA9PiB2b2lkKSA9PiB7XG4gICAgICAgICAgICAgICAgbGlzdGVuZXIocmVzcG9uc2VzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICB9XG59XG4iLCIvLyBDb3B5cmlnaHQgRXBpYyBHYW1lcywgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuXG5pbXBvcnQgeyBEYXRhQ2hhbm5lbFNlbmRlciB9IGZyb20gJy4uL0RhdGFDaGFubmVsL0RhdGFDaGFubmVsU2VuZGVyJztcbmltcG9ydCB7IExvZ2dlciB9IGZyb20gJy4uL0xvZ2dlci9Mb2dnZXInO1xuaW1wb3J0IHsgU3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIgfSBmcm9tICcuL1N0cmVhbU1lc3NhZ2VDb250cm9sbGVyJztcblxuZXhwb3J0IGNsYXNzIFNlbmRNZXNzYWdlQ29udHJvbGxlciB7XG4gICAgdG9TdHJlYW1lck1lc3NhZ2VzTWFwUHJvdmlkZXI6IFN0cmVhbU1lc3NhZ2VDb250cm9sbGVyO1xuICAgIGRhdGFDaGFubmVsU2VuZGVyOiBEYXRhQ2hhbm5lbFNlbmRlcjtcblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBkYXRhQ2hhbm5lbFNlbmRlciAtIERhdGEgY2hhbm5lbCBpbnN0YW5jZVxuICAgICAqIEBwYXJhbSB0b1N0cmVhbWVyTWVzc2FnZXNNYXBQcm92aWRlciAtIFN0cmVhbSBNZXNzYWdlcyBpbnN0YW5jZVxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICBkYXRhQ2hhbm5lbFNlbmRlcjogRGF0YUNoYW5uZWxTZW5kZXIsXG4gICAgICAgIHRvU3RyZWFtZXJNZXNzYWdlc01hcFByb3ZpZGVyOiBTdHJlYW1NZXNzYWdlQ29udHJvbGxlclxuICAgICkge1xuICAgICAgICB0aGlzLmRhdGFDaGFubmVsU2VuZGVyID0gZGF0YUNoYW5uZWxTZW5kZXI7XG4gICAgICAgIHRoaXMudG9TdHJlYW1lck1lc3NhZ2VzTWFwUHJvdmlkZXIgPSB0b1N0cmVhbWVyTWVzc2FnZXNNYXBQcm92aWRlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZW5kIGEgbWVzc2FnZSB0byB0aGUgc3RyZWFtZXIgdGhyb3VnaCB0aGUgZGF0YSBjaGFubmVsXG4gICAgICogQHBhcmFtIG1lc3NhZ2VUeXBlIC0gdGhlIHR5cGUgb2YgbWVzc2FnZSB3ZSBhcmUgc2VuZGluZ1xuICAgICAqIEBwYXJhbSBtZXNzYWdlRGF0YSAtIHRoZSBtZXNzYWdlIGRhdGEgd2UgYXJlIHNlbmRpbmcgb3ZlciB0aGUgZGF0YSBjaGFubmVsXG4gICAgICogQHJldHVybnMgLSBuaWxcbiAgICAgKi9cbiAgICBzZW5kTWVzc2FnZVRvU3RyZWFtZXIobWVzc2FnZVR5cGU6IHN0cmluZywgbWVzc2FnZURhdGE/OiBBcnJheTxudW1iZXIgfCBzdHJpbmc+KSB7XG4gICAgICAgIGlmIChtZXNzYWdlRGF0YSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBtZXNzYWdlRGF0YSA9IFtdO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdG9TdHJlYW1lck1lc3NhZ2VzID1cbiAgICAgICAgICAgIHRoaXMudG9TdHJlYW1lck1lc3NhZ2VzTWFwUHJvdmlkZXIudG9TdHJlYW1lck1lc3NhZ2VzO1xuICAgICAgICBjb25zdCBtZXNzYWdlRm9ybWF0ID0gdG9TdHJlYW1lck1lc3NhZ2VzLmdldChtZXNzYWdlVHlwZSk7XG4gICAgICAgIGlmIChtZXNzYWdlRm9ybWF0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIExvZ2dlci5FcnJvcihcbiAgICAgICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgICAgIGBBdHRlbXB0ZWQgdG8gc2VuZCBhIG1lc3NhZ2UgdG8gdGhlIHN0cmVhbWVyIHdpdGggbWVzc2FnZSB0eXBlOiAke21lc3NhZ2VUeXBlfSwgYnV0IHRoZSBmcm9udGVuZCBoYXNuJ3QgYmVlbiBjb25maWd1cmVkIHRvIHNlbmQgc3VjaCBhIG1lc3NhZ2UuIENoZWNrIHlvdSd2ZSBhZGRlZCB0aGUgbWVzc2FnZSB0eXBlIGluIHlvdXIgY3BwYFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmKG1lc3NhZ2VGb3JtYXQuc3RydWN0dXJlICYmIG1lc3NhZ2VEYXRhICYmIG1lc3NhZ2VGb3JtYXQuc3RydWN0dXJlLmxlbmd0aCAhPT0gbWVzc2FnZURhdGEubGVuZ3RoKSB7XG4gICAgICAgICAgICBMb2dnZXIuRXJyb3IoXG4gICAgICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICAgICBgUHJvdmlkZWQgbWVzc2FnZSBkYXRhIGRvZXNuJ3QgbWF0Y2ggZXhwZWN0ZWQgbGF5b3V0LiBFeHBlY3RlZCBbICR7bWVzc2FnZUZvcm1hdC5zdHJ1Y3R1cmUubWFwKChlbGVtZW50OiBzdHJpbmcpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChlbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlICd1aW50OCc6XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlICd1aW50MTYnOlxuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnaW50MTYnOlxuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnZmxvYXQnOlxuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnZG91YmxlJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ251bWJlcic7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlICdzdHJpbmcnOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnc3RyaW5nJztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pLnRvU3RyaW5nKCkgfSBdIGJ1dCByZWNlaXZlZCBbICR7bWVzc2FnZURhdGEubWFwKChlbGVtZW50OiBudW1iZXIgfCBzdHJpbmcpID0+IHR5cGVvZiBlbGVtZW50KS50b1N0cmluZygpfSBdYFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBieXRlTGVuZ3RoID0gMDtcbiAgICAgICAgY29uc3QgdGV4dEVuY29kZXIgPSBuZXcgVGV4dEVuY29kZXIoKTtcbiAgICAgICAgLy8gT25lIGxvb3AgdG8gY2FsY3VsYXRlIHRoZSBsZW5ndGggaW4gYnl0ZXMgb2YgYWxsIG9mIHRoZSBwcm92aWRlZCBkYXRhXG4gICAgICAgIG1lc3NhZ2VEYXRhLmZvckVhY2goKGVsZW1lbnQ6IG51bWJlciB8IHN0cmluZywgaWR4OiBudW1iZXIpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHR5cGUgPSBtZXNzYWdlRm9ybWF0LnN0cnVjdHVyZVtpZHhdO1xuICAgICAgICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAndWludDgnOlxuICAgICAgICAgICAgICAgICAgICBieXRlTGVuZ3RoICs9IDE7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgY2FzZSAndWludDE2JzpcbiAgICAgICAgICAgICAgICAgICAgYnl0ZUxlbmd0aCArPSAyO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgIGNhc2UgJ2ludDE2JzpcbiAgICAgICAgICAgICAgICAgICAgYnl0ZUxlbmd0aCArPSAyO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgIGNhc2UgJ2Zsb2F0JzpcbiAgICAgICAgICAgICAgICAgICAgYnl0ZUxlbmd0aCArPSA0O1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgIGNhc2UgJ2RvdWJsZSc6XG4gICAgICAgICAgICAgICAgICAgIGJ5dGVMZW5ndGggKz0gODtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICBjYXNlICdzdHJpbmcnOlxuICAgICAgICAgICAgICAgICAgICAvLyAyIGJ5dGVzIGZvciBzdHJpbmcgbGVuZ3RoXG4gICAgICAgICAgICAgICAgICAgIGJ5dGVMZW5ndGggKz0gMjtcbiAgICAgICAgICAgICAgICAgICAgLy8gMiBieXRlcyBwZXIgY2hhcmFjdGVyc1xuICAgICAgICAgICAgICAgICAgICBieXRlTGVuZ3RoICs9IDIgKiB0ZXh0RW5jb2Rlci5lbmNvZGUoZWxlbWVudCBhcyBzdHJpbmcpLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IGRhdGEgPSBuZXcgRGF0YVZpZXcobmV3IEFycmF5QnVmZmVyKGJ5dGVMZW5ndGggKyAxKSk7XG4gICAgICAgIGRhdGEuc2V0VWludDgoMCwgbWVzc2FnZUZvcm1hdC5pZCk7XG4gICAgICAgIGxldCBieXRlT2Zmc2V0ID0gMTtcblxuICAgICAgICBtZXNzYWdlRGF0YS5mb3JFYWNoKChlbGVtZW50OiBudW1iZXIgfCBzdHJpbmcsIGlkeDogbnVtYmVyKSA9PiB7XG4gICAgICAgICAgICBjb25zdCB0eXBlID0gbWVzc2FnZUZvcm1hdC5zdHJ1Y3R1cmVbaWR4XTtcbiAgICAgICAgICAgIHN3aXRjaCAodHlwZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ3VpbnQ4JzpcbiAgICAgICAgICAgICAgICAgICAgZGF0YS5zZXRVaW50OChieXRlT2Zmc2V0LCBlbGVtZW50IGFzIG51bWJlcik7XG4gICAgICAgICAgICAgICAgICAgIGJ5dGVPZmZzZXQgKz0gMTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICBjYXNlICd1aW50MTYnOlxuICAgICAgICAgICAgICAgICAgICBkYXRhLnNldFVpbnQxNihieXRlT2Zmc2V0LCBlbGVtZW50IGFzIG51bWJlciwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIGJ5dGVPZmZzZXQgKz0gMjtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICBjYXNlICdpbnQxNic6XG4gICAgICAgICAgICAgICAgICAgIGRhdGEuc2V0SW50MTYoYnl0ZU9mZnNldCwgZWxlbWVudCBhcyBudW1iZXIsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICBieXRlT2Zmc2V0ICs9IDI7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgY2FzZSAnZmxvYXQnOlxuICAgICAgICAgICAgICAgICAgICBkYXRhLnNldEZsb2F0MzIoYnl0ZU9mZnNldCwgZWxlbWVudCBhcyBudW1iZXIsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICBieXRlT2Zmc2V0ICs9IDQ7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgY2FzZSAnZG91YmxlJzpcbiAgICAgICAgICAgICAgICAgICAgZGF0YS5zZXRGbG9hdDY0KGJ5dGVPZmZzZXQsIGVsZW1lbnQgYXMgbnVtYmVyLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgYnl0ZU9mZnNldCArPSA4O1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgIGNhc2UgJ3N0cmluZyc6XG4gICAgICAgICAgICAgICAgICAgIGRhdGEuc2V0VWludDE2KGJ5dGVPZmZzZXQsIChlbGVtZW50IGFzIHN0cmluZykubGVuZ3RoLCB0cnVlKTtcbiAgICAgICAgICAgICAgICAgICAgYnl0ZU9mZnNldCArPSAyO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IChlbGVtZW50IGFzIHN0cmluZykubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGEuc2V0VWludDE2KGJ5dGVPZmZzZXQsIChlbGVtZW50IGFzIHN0cmluZykuY2hhckNvZGVBdChpKSwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBieXRlT2Zmc2V0ICs9IDI7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICghdGhpcy5kYXRhQ2hhbm5lbFNlbmRlci5jYW5TZW5kKCkpIHtcbiAgICAgICAgICAgIExvZ2dlci5JbmZvKFxuICAgICAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAgICAgYERhdGEgY2hhbm5lbCBjYW5ub3Qgc2VuZCB5ZXQsIHNraXBwaW5nIHNlbmRpbmcgbWVzc2FnZTogJHttZXNzYWdlVHlwZX0gLSAke25ldyBVaW50OEFycmF5KFxuICAgICAgICAgICAgICAgICAgICBkYXRhLmJ1ZmZlclxuICAgICAgICAgICAgICAgICl9YFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZGF0YUNoYW5uZWxTZW5kZXIuc2VuZERhdGEoZGF0YS5idWZmZXIpO1xuICAgIH1cbn1cbiIsIi8vIENvcHlyaWdodCBFcGljIEdhbWVzLCBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG5cbmltcG9ydCB7IExvZ2dlciB9IGZyb20gJy4uL0xvZ2dlci9Mb2dnZXInO1xuXG5leHBvcnQgY2xhc3MgVG9TdHJlYW1lck1lc3NhZ2Uge1xuICAgIGlkOiBudW1iZXI7XG4gICAgc3RydWN0dXJlPzogQXJyYXk8c3RyaW5nPjtcbn1cblxuZXhwb3J0IGNsYXNzIFN0cmVhbU1lc3NhZ2VDb250cm9sbGVyIHtcbiAgICB0b1N0cmVhbWVySGFuZGxlcnM6IE1hcDxcbiAgICAgICAgc3RyaW5nLFxuICAgICAgICAobWVzc2FnZURhdGE/OiBBcnJheTxudW1iZXIgfCBzdHJpbmc+IHwgdW5kZWZpbmVkKSA9PiB2b2lkXG4gICAgPjtcbiAgICBmcm9tU3RyZWFtZXJIYW5kbGVyczogTWFwPFxuICAgICAgICBzdHJpbmcsXG4gICAgICAgIChtZXNzYWdlVHlwZTogc3RyaW5nLCBtZXNzYWdlRGF0YT86IEFycmF5QnVmZmVyIHwgdW5kZWZpbmVkKSA9PiB2b2lkXG4gICAgPjtcbiAgICAvLyAgICAgICAgICAgICAgICAgICAgICAgIFR5cGUgICAgICBGb3JtYXRcbiAgICB0b1N0cmVhbWVyTWVzc2FnZXM6IE1hcDxzdHJpbmcsIFRvU3RyZWFtZXJNZXNzYWdlPjtcbiAgICAvLyAgICAgICAgICAgICAgICAgICAgICAgICBJRCAgICAgIFR5cGVcbiAgICBmcm9tU3RyZWFtZXJNZXNzYWdlczogTWFwPG51bWJlciwgc3RyaW5nPjtcblxuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICB0aGlzLnRvU3RyZWFtZXJIYW5kbGVycyA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy5mcm9tU3RyZWFtZXJIYW5kbGVycyA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXMgPSBuZXcgTWFwKCk7XG4gICAgICAgIHRoaXMuZnJvbVN0cmVhbWVyTWVzc2FnZXMgPSBuZXcgTWFwKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUG9wdWxhdGUgdGhlIERlZmF1bHQgbWVzc2FnZSBwcm90b2NvbFxuICAgICAqL1xuICAgIHBvcHVsYXRlRGVmYXVsdFByb3RvY29sKCkge1xuICAgICAgICAvKlxuICAgICAgICAgKiBDb250cm9sIE1lc3NhZ2VzLiBSYW5nZSA9IDAuLjQ5LlxuICAgICAgICAgKi9cbiAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXMuc2V0KCdJRnJhbWVSZXF1ZXN0Jywge1xuICAgICAgICAgICAgaWQ6IDAsXG4gICAgICAgICAgICBzdHJ1Y3R1cmU6IFtdXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnRvU3RyZWFtZXJNZXNzYWdlcy5zZXQoJ1JlcXVlc3RRdWFsaXR5Q29udHJvbCcsIHtcbiAgICAgICAgICAgIGlkOiAxLFxuICAgICAgICAgICAgc3RydWN0dXJlOiBbXVxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXMuc2V0KCdGcHNSZXF1ZXN0Jywge1xuICAgICAgICAgICAgaWQ6IDIsXG4gICAgICAgICAgICBzdHJ1Y3R1cmU6IFtdXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnRvU3RyZWFtZXJNZXNzYWdlcy5zZXQoJ0F2ZXJhZ2VCaXRyYXRlUmVxdWVzdCcsIHtcbiAgICAgICAgICAgIGlkOiAzLFxuICAgICAgICAgICAgc3RydWN0dXJlOiBbXVxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXMuc2V0KCdTdGFydFN0cmVhbWluZycsIHtcbiAgICAgICAgICAgIGlkOiA0LFxuICAgICAgICAgICAgc3RydWN0dXJlOiBbXVxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXMuc2V0KCdTdG9wU3RyZWFtaW5nJywge1xuICAgICAgICAgICAgaWQ6IDUsXG4gICAgICAgICAgICBzdHJ1Y3R1cmU6IFtdXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnRvU3RyZWFtZXJNZXNzYWdlcy5zZXQoJ0xhdGVuY3lUZXN0Jywge1xuICAgICAgICAgICAgaWQ6IDYsXG4gICAgICAgICAgICBzdHJ1Y3R1cmU6IFsnc3RyaW5nJ11cbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMudG9TdHJlYW1lck1lc3NhZ2VzLnNldCgnUmVxdWVzdEluaXRpYWxTZXR0aW5ncycsIHtcbiAgICAgICAgICAgIGlkOiA3LFxuICAgICAgICAgICAgc3RydWN0dXJlOiBbXVxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXMuc2V0KCdUZXN0RWNobycsIHtcbiAgICAgICAgICAgIGlkOiA4LFxuICAgICAgICAgICAgc3RydWN0dXJlOiBbXVxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXMuc2V0KCdEYXRhQ2hhbm5lbExhdGVuY3lUZXN0Jywge1xuICAgICAgICAgICAgaWQ6IDksXG4gICAgICAgICAgICBzdHJ1Y3R1cmU6IFtdXG4gICAgICAgIH0pO1xuICAgICAgICAvKlxuICAgICAgICAgKiBJbnB1dCBNZXNzYWdlcy4gUmFuZ2UgPSA1MC4uODkuXG4gICAgICAgICAqL1xuICAgICAgICAvLyBHZW5lcmljIElucHV0IE1lc3NhZ2VzLiBSYW5nZSA9IDUwLi41OS5cbiAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXMuc2V0KCdVSUludGVyYWN0aW9uJywge1xuICAgICAgICAgICAgaWQ6IDUwLFxuICAgICAgICAgICAgc3RydWN0dXJlOiBbJ3N0cmluZyddXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnRvU3RyZWFtZXJNZXNzYWdlcy5zZXQoJ0NvbW1hbmQnLCB7XG4gICAgICAgICAgICBpZDogNTEsXG4gICAgICAgICAgICBzdHJ1Y3R1cmU6IFsnc3RyaW5nJ11cbiAgICAgICAgfSk7XG4gICAgICAgIC8vIEtleWJvYXJkIElucHV0IE1lc3NhZ2UuIFJhbmdlID0gNjAuLjY5LlxuICAgICAgICB0aGlzLnRvU3RyZWFtZXJNZXNzYWdlcy5zZXQoJ0tleURvd24nLCB7XG4gICAgICAgICAgICBpZDogNjAsXG4gICAgICAgICAgICAvLyAgICAgICAgICAgIGtleUNvZGUgIGlzUmVwZWF0XG4gICAgICAgICAgICBzdHJ1Y3R1cmU6IFsndWludDgnLCAndWludDgnXVxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXMuc2V0KCdLZXlVcCcsIHtcbiAgICAgICAgICAgIGlkOiA2MSxcbiAgICAgICAgICAgIC8vICAgICAgICAgICAga2V5Q29kZVxuICAgICAgICAgICAgc3RydWN0dXJlOiBbJ3VpbnQ4J11cbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMudG9TdHJlYW1lck1lc3NhZ2VzLnNldCgnS2V5UHJlc3MnLCB7XG4gICAgICAgICAgICBpZDogNjIsXG4gICAgICAgICAgICAvLyAgICAgICAgICAgIGNoYXJjb2RlXG4gICAgICAgICAgICBzdHJ1Y3R1cmU6IFsndWludDE2J11cbiAgICAgICAgfSk7XG4gICAgICAgIC8vIE1vdXNlIElucHV0IE1lc3NhZ2VzLiBSYW5nZSA9IDcwLi43OS5cbiAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXMuc2V0KCdNb3VzZUVudGVyJywge1xuICAgICAgICAgICAgaWQ6IDcwLFxuICAgICAgICAgICAgc3RydWN0dXJlOiBbXVxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXMuc2V0KCdNb3VzZUxlYXZlJywge1xuICAgICAgICAgICAgaWQ6IDcxLFxuICAgICAgICAgICAgc3RydWN0dXJlOiBbXVxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXMuc2V0KCdNb3VzZURvd24nLCB7XG4gICAgICAgICAgICBpZDogNzIsXG4gICAgICAgICAgICAvLyAgICAgICAgICAgICAgYnV0dG9uICAgICB4ICAgICAgICAgeVxuICAgICAgICAgICAgc3RydWN0dXJlOiBbJ3VpbnQ4JywgJ3VpbnQxNicsICd1aW50MTYnXVxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXMuc2V0KCdNb3VzZVVwJywge1xuICAgICAgICAgICAgaWQ6IDczLFxuICAgICAgICAgICAgLy8gICAgICAgICAgICAgIGJ1dHRvbiAgICAgeCAgICAgICAgIHlcbiAgICAgICAgICAgIHN0cnVjdHVyZTogWyd1aW50OCcsICd1aW50MTYnLCAndWludDE2J11cbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMudG9TdHJlYW1lck1lc3NhZ2VzLnNldCgnTW91c2VNb3ZlJywge1xuICAgICAgICAgICAgaWQ6IDc0LFxuICAgICAgICAgICAgLy8gICAgICAgICAgICAgIHggICAgICAgICAgIHkgICAgICBkZWx0YVggICAgZGVsdGFZXG4gICAgICAgICAgICBzdHJ1Y3R1cmU6IFsndWludDE2JywgJ3VpbnQxNicsICdpbnQxNicsICdpbnQxNiddXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnRvU3RyZWFtZXJNZXNzYWdlcy5zZXQoJ01vdXNlV2hlZWwnLCB7XG4gICAgICAgICAgICBpZDogNzUsXG4gICAgICAgICAgICAvLyAgICAgICAgICAgICAgZGVsdGEgICAgICAgeCAgICAgICAgeVxuICAgICAgICAgICAgc3RydWN0dXJlOiBbJ2ludDE2JywgJ3VpbnQxNicsICd1aW50MTYnXVxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXMuc2V0KCdNb3VzZURvdWJsZScsIHtcbiAgICAgICAgICAgIGlkOiA3NixcbiAgICAgICAgICAgIC8vICAgICAgICAgICAgICBidXR0b24gICAgIHggICAgICAgICB5XG4gICAgICAgICAgICBzdHJ1Y3R1cmU6IFsndWludDgnLCAndWludDE2JywgJ3VpbnQxNiddXG4gICAgICAgIH0pO1xuICAgICAgICAvLyBUb3VjaCBJbnB1dCBNZXNzYWdlcy4gUmFuZ2UgPSA4MC4uODkuXG4gICAgICAgIHRoaXMudG9TdHJlYW1lck1lc3NhZ2VzLnNldCgnVG91Y2hTdGFydCcsIHtcbiAgICAgICAgICAgIGlkOiA4MCxcbiAgICAgICAgICAgIC8vICAgICAgICAgIG51bXRvdWNoZXMoMSkgICB4ICAgICAgIHkgICAgICAgIGlkeCAgICAgZm9yY2UgICAgIHZhbGlkXG4gICAgICAgICAgICBzdHJ1Y3R1cmU6IFsndWludDgnLCAndWludDE2JywgJ3VpbnQxNicsICd1aW50OCcsICd1aW50OCcsICd1aW50OCddXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnRvU3RyZWFtZXJNZXNzYWdlcy5zZXQoJ1RvdWNoRW5kJywge1xuICAgICAgICAgICAgaWQ6IDgxLFxuICAgICAgICAgICAgLy8gICAgICAgICAgbnVtdG91Y2hlcygxKSAgIHggICAgICAgeSAgICAgICAgaWR4ICAgICBmb3JjZSAgICAgdmFsaWRcbiAgICAgICAgICAgIHN0cnVjdHVyZTogWyd1aW50OCcsICd1aW50MTYnLCAndWludDE2JywgJ3VpbnQ4JywgJ3VpbnQ4JywgJ3VpbnQ4J11cbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMudG9TdHJlYW1lck1lc3NhZ2VzLnNldCgnVG91Y2hNb3ZlJywge1xuICAgICAgICAgICAgaWQ6IDgyLFxuICAgICAgICAgICAgLy8gICAgICAgICAgbnVtdG91Y2hlcygxKSAgIHggICAgICAgeSAgICAgICBpZHggICAgICBmb3JjZSAgICAgdmFsaWRcbiAgICAgICAgICAgIHN0cnVjdHVyZTogWyd1aW50OCcsICd1aW50MTYnLCAndWludDE2JywgJ3VpbnQ4JywgJ3VpbnQ4JywgJ3VpbnQ4J11cbiAgICAgICAgfSk7XG4gICAgICAgIC8vIEdhbWVwYWQgSW5wdXQgTWVzc2FnZXMuIFJhbmdlID0gOTAuLjk5XG4gICAgICAgIHRoaXMudG9TdHJlYW1lck1lc3NhZ2VzLnNldCgnR2FtZXBhZENvbm5lY3RlZCcsIHtcbiAgICAgICAgICAgIGlkOiA5MyxcbiAgICAgICAgICAgIHN0cnVjdHVyZTogW11cbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMudG9TdHJlYW1lck1lc3NhZ2VzLnNldCgnR2FtZXBhZEJ1dHRvblByZXNzZWQnLCB7XG4gICAgICAgICAgICBpZDogOTAsXG4gICAgICAgICAgICAvLyAgICAgICAgIGN0cmxlcklkICAgYnV0dG9uICBpc1JlcGVhdFxuICAgICAgICAgICAgc3RydWN0dXJlOiBbJ3VpbnQ4JywgJ3VpbnQ4JywgJ3VpbnQ4J11cbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMudG9TdHJlYW1lck1lc3NhZ2VzLnNldCgnR2FtZXBhZEJ1dHRvblJlbGVhc2VkJywge1xuICAgICAgICAgICAgaWQ6IDkxLFxuICAgICAgICAgICAgLy8gICAgICAgICBjdHJsZXJJZCAgIGJ1dHRvbiAgaXNSZXBlYXQoMClcbiAgICAgICAgICAgIHN0cnVjdHVyZTogWyd1aW50OCcsICd1aW50OCcsICd1aW50OCddXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnRvU3RyZWFtZXJNZXNzYWdlcy5zZXQoJ0dhbWVwYWRBbmFsb2cnLCB7XG4gICAgICAgICAgICBpZDogOTIsXG4gICAgICAgICAgICAvLyAgICAgICAgIGN0cmxlcklkICAgYnV0dG9uICBhbmFsb2dWYWx1ZVxuICAgICAgICAgICAgc3RydWN0dXJlOiBbJ3VpbnQ4JywgJ3VpbnQ4JywgJ2RvdWJsZSddXG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLnRvU3RyZWFtZXJNZXNzYWdlcy5zZXQoJ0dhbWVwYWREaXNjb25uZWN0ZWQnLCB7XG4gICAgICAgICAgICBpZDogOTQsXG4gICAgICAgICAgICAvLyAgICAgICAgICBjdHJsZXJJZFxuICAgICAgICAgICAgc3RydWN0dXJlOiBbJ3VpbnQ4J11cbiAgICAgICAgfSk7XG5cbiAgICAgICAgdGhpcy5mcm9tU3RyZWFtZXJNZXNzYWdlcy5zZXQoMCwgJ1F1YWxpdHlDb250cm9sT3duZXJzaGlwJyk7XG4gICAgICAgIHRoaXMuZnJvbVN0cmVhbWVyTWVzc2FnZXMuc2V0KDEsICdSZXNwb25zZScpO1xuICAgICAgICB0aGlzLmZyb21TdHJlYW1lck1lc3NhZ2VzLnNldCgyLCAnQ29tbWFuZCcpO1xuICAgICAgICB0aGlzLmZyb21TdHJlYW1lck1lc3NhZ2VzLnNldCgzLCAnRnJlZXplRnJhbWUnKTtcbiAgICAgICAgdGhpcy5mcm9tU3RyZWFtZXJNZXNzYWdlcy5zZXQoNCwgJ1VuZnJlZXplRnJhbWUnKTtcbiAgICAgICAgdGhpcy5mcm9tU3RyZWFtZXJNZXNzYWdlcy5zZXQoNSwgJ1ZpZGVvRW5jb2RlckF2Z1FQJyk7XG4gICAgICAgIHRoaXMuZnJvbVN0cmVhbWVyTWVzc2FnZXMuc2V0KDYsICdMYXRlbmN5VGVzdCcpO1xuICAgICAgICB0aGlzLmZyb21TdHJlYW1lck1lc3NhZ2VzLnNldCg3LCAnSW5pdGlhbFNldHRpbmdzJyk7XG4gICAgICAgIHRoaXMuZnJvbVN0cmVhbWVyTWVzc2FnZXMuc2V0KDgsICdGaWxlRXh0ZW5zaW9uJyk7XG4gICAgICAgIHRoaXMuZnJvbVN0cmVhbWVyTWVzc2FnZXMuc2V0KDksICdGaWxlTWltZVR5cGUnKTtcbiAgICAgICAgdGhpcy5mcm9tU3RyZWFtZXJNZXNzYWdlcy5zZXQoMTAsICdGaWxlQ29udGVudHMnKTtcbiAgICAgICAgdGhpcy5mcm9tU3RyZWFtZXJNZXNzYWdlcy5zZXQoMTEsICdUZXN0RWNobycpO1xuICAgICAgICB0aGlzLmZyb21TdHJlYW1lck1lc3NhZ2VzLnNldCgxMiwgJ0lucHV0Q29udHJvbE93bmVyc2hpcCcpO1xuICAgICAgICB0aGlzLmZyb21TdHJlYW1lck1lc3NhZ2VzLnNldCgxMywgJ0dhbWVwYWRSZXNwb25zZScpO1xuICAgICAgICB0aGlzLmZyb21TdHJlYW1lck1lc3NhZ2VzLnNldCgxNCwgJ0RhdGFDaGFubmVsTGF0ZW5jeVRlc3QnKTtcbiAgICAgICAgdGhpcy5mcm9tU3RyZWFtZXJNZXNzYWdlcy5zZXQoMjU1LCAnUHJvdG9jb2wnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZWdpc3RlciBhIG1lc3NhZ2UgaGFuZGxlclxuICAgICAqIEBwYXJhbSBtZXNzYWdlRGlyZWN0aW9uIC0gdGhlIGRpcmVjdGlvbiBvZiB0aGUgbWVzc2FnZTsgdG9TdHJlYW1lciBvciBmcm9tU3RyZWFtZXJcbiAgICAgKiBAcGFyYW0gbWVzc2FnZVR5cGUgLSB0aGUgdHlwZSBvZiB0aGUgbWVzc2FnZVxuICAgICAqIEBwYXJhbSBtZXNzYWdlSGFuZGxlciAtIHRoZSBmdW5jdGlvbiBvciBtZXRob2QgdG8gYmUgZXhlY3V0ZWQgd2hlbiB0aGlzIGhhbmRsZXIgaXMgY2FsbGVkXG4gICAgICovXG4gICAgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlcihcbiAgICAgICAgbWVzc2FnZURpcmVjdGlvbjogTWVzc2FnZURpcmVjdGlvbixcbiAgICAgICAgbWVzc2FnZVR5cGU6IHN0cmluZyxcbiAgICAgICAgbWVzc2FnZUhhbmRsZXI6IChtZXNzYWdlRGF0YT86IHVua25vd24gfCB1bmRlZmluZWQpID0+IHZvaWRcbiAgICApIHtcbiAgICAgICAgc3dpdGNoIChtZXNzYWdlRGlyZWN0aW9uKSB7XG4gICAgICAgICAgICBjYXNlIE1lc3NhZ2VEaXJlY3Rpb24uVG9TdHJlYW1lcjpcbiAgICAgICAgICAgICAgICB0aGlzLnRvU3RyZWFtZXJIYW5kbGVycy5zZXQobWVzc2FnZVR5cGUsIG1lc3NhZ2VIYW5kbGVyKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgTWVzc2FnZURpcmVjdGlvbi5Gcm9tU3RyZWFtZXI6XG4gICAgICAgICAgICAgICAgdGhpcy5mcm9tU3RyZWFtZXJIYW5kbGVycy5zZXQobWVzc2FnZVR5cGUsIG1lc3NhZ2VIYW5kbGVyKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgTG9nZ2VyLkxvZyhcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICAgICAgICAgYFVua25vd24gbWVzc2FnZSBkaXJlY3Rpb24gJHttZXNzYWdlRGlyZWN0aW9ufWBcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgfVxufVxuXG4vKipcbiAqIFRoZSBlbnVtIGZvciBtZXNzYWdlIGRpcmVjdGlvbnNcbiAqL1xuZXhwb3J0IGVudW0gTWVzc2FnZURpcmVjdGlvbiB7XG4gICAgVG9TdHJlYW1lciA9IDAsXG4gICAgRnJvbVN0cmVhbWVyID0gMVxufVxuIiwiLy8gQ29weXJpZ2h0IEVwaWMgR2FtZXMsIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cblxuaW1wb3J0IHsgU2VuZE1lc3NhZ2VDb250cm9sbGVyIH0gZnJvbSAnLi9TZW5kTWVzc2FnZUNvbnRyb2xsZXInO1xuXG5leHBvcnQgY2xhc3MgVG9TdHJlYW1lck1lc3NhZ2VzQ29udHJvbGxlciB7XG4gICAgc2VuZE1lc3NhZ2VDb250cm9sbGVyOiBTZW5kTWVzc2FnZUNvbnRyb2xsZXI7XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gc2VuZE1lc3NhZ2VDb250cm9sbGVyIC0gU3RyZWFtIG1lc3NhZ2UgY29udHJvbGxlciBpbnN0YW5jZVxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHNlbmRNZXNzYWdlQ29udHJvbGxlcjogU2VuZE1lc3NhZ2VDb250cm9sbGVyKSB7XG4gICAgICAgIHRoaXMuc2VuZE1lc3NhZ2VDb250cm9sbGVyID0gc2VuZE1lc3NhZ2VDb250cm9sbGVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlbmQgUmVxdWVzdCB0byBUYWtlIFF1YWxpdHkgQ29udHJvbCB0byB0aGUgVUUgSW5zdGFuY2VcbiAgICAgKi9cbiAgICBTZW5kUmVxdWVzdFF1YWxpdHlDb250cm9sKCkge1xuICAgICAgICB0aGlzLnNlbmRNZXNzYWdlQ29udHJvbGxlci5zZW5kTWVzc2FnZVRvU3RyZWFtZXIoXG4gICAgICAgICAgICAnUmVxdWVzdFF1YWxpdHlDb250cm9sJ1xuICAgICAgICApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlbmQgTWF4IEZQUyBSZXF1ZXN0IHRvIHRoZSBVRSBJbnN0YW5jZVxuICAgICAqL1xuICAgIFNlbmRNYXhGcHNSZXF1ZXN0KCkge1xuICAgICAgICB0aGlzLnNlbmRNZXNzYWdlQ29udHJvbGxlci5zZW5kTWVzc2FnZVRvU3RyZWFtZXIoJ0Zwc1JlcXVlc3QnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZW5kIEF2ZXJhZ2UgQml0cmF0ZSBSZXF1ZXN0IHRvIHRoZSBVRSBJbnN0YW5jZVxuICAgICAqL1xuICAgIFNlbmRBdmVyYWdlQml0cmF0ZVJlcXVlc3QoKSB7XG4gICAgICAgIHRoaXMuc2VuZE1lc3NhZ2VDb250cm9sbGVyLnNlbmRNZXNzYWdlVG9TdHJlYW1lcihcbiAgICAgICAgICAgICdBdmVyYWdlQml0cmF0ZVJlcXVlc3QnXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VuZCBhIFN0YXJ0IFN0cmVhbWluZyBNZXNzYWdlIHRvIHRoZSBVRSBJbnN0YW5jZVxuICAgICAqL1xuICAgIFNlbmRTdGFydFN0cmVhbWluZygpIHtcbiAgICAgICAgdGhpcy5zZW5kTWVzc2FnZUNvbnRyb2xsZXIuc2VuZE1lc3NhZ2VUb1N0cmVhbWVyKCdTdGFydFN0cmVhbWluZycpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlbmQgYSBTdG9wIFN0cmVhbWluZyBNZXNzYWdlIHRvIHRoZSBVRSBJbnN0YW5jZVxuICAgICAqL1xuICAgIFNlbmRTdG9wU3RyZWFtaW5nKCkge1xuICAgICAgICB0aGlzLnNlbmRNZXNzYWdlQ29udHJvbGxlci5zZW5kTWVzc2FnZVRvU3RyZWFtZXIoJ1N0b3BTdHJlYW1pbmcnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZW5kIGEgUmVxdWVzdCBJbml0aWFsIFNldHRpbmdzIHRvIHRoZSBVRSBJbnN0YW5jZVxuICAgICAqL1xuICAgIFNlbmRSZXF1ZXN0SW5pdGlhbFNldHRpbmdzKCkge1xuICAgICAgICB0aGlzLnNlbmRNZXNzYWdlQ29udHJvbGxlci5zZW5kTWVzc2FnZVRvU3RyZWFtZXIoXG4gICAgICAgICAgICAnUmVxdWVzdEluaXRpYWxTZXR0aW5ncydcbiAgICAgICAgKTtcbiAgICB9XG59XG4iLCIvLyBDb3B5cmlnaHQgRXBpYyBHYW1lcywgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuXG5pbXBvcnQgeyBMb2dnZXIgfSBmcm9tICcuLi9Mb2dnZXIvTG9nZ2VyJztcbmltcG9ydCB7IFZpZGVvUGxheWVyIH0gZnJvbSAnLi4vVmlkZW9QbGF5ZXIvVmlkZW9QbGF5ZXInO1xuXG4vKipcbiAqIENvbnZlcnRzIGNvb3JkaW5hdGVzIGZyb20gZWxlbWVudCByZWxhdGl2ZSBjb29yZGluYXRlcyB0byB2YWx1ZXMgbm9ybWFsaXplZCB3aXRoaW4gdGhlIHZhbHVlIHJhbmdlIG9mIGEgc2hvcnQgKGFuZCBiYWNrIGFnYWluKVxuICovXG5leHBvcnQgY2xhc3MgQ29vcmRpbmF0ZUNvbnZlcnRlciB7XG4gICAgdmlkZW9FbGVtZW50UHJvdmlkZXI6IFZpZGVvUGxheWVyO1xuICAgIHZpZGVvRWxlbWVudFBhcmVudDogSFRNTEVsZW1lbnQ7XG4gICAgdmlkZW9FbGVtZW50OiBIVE1MVmlkZW9FbGVtZW50O1xuICAgIHJhdGlvOiBudW1iZXI7XG5cbiAgICBub3JtYWxpemVBbmRRdWFudGl6ZVVuc2lnbmVkRnVuYzogKFxuICAgICAgICB4OiBudW1iZXIsXG4gICAgICAgIHk6IG51bWJlclxuICAgICkgPT4gTm9ybWFsaXplZFF1YW50aXplZFVuc2lnbmVkQ29vcmQ7XG4gICAgbm9ybWFsaXplQW5kUXVhbnRpemVTaWduZWRGdW5jOiAoXG4gICAgICAgIHg6IG51bWJlcixcbiAgICAgICAgeTogbnVtYmVyXG4gICAgKSA9PiBOb3JtYWxpemVkUXVhbnRpemVkU2lnbmVkQ29vcmQ7XG4gICAgZGVub3JtYWxpemVBbmRVbnF1YW50aXplVW5zaWduZWRGdW5jOiAoXG4gICAgICAgIHg6IG51bWJlcixcbiAgICAgICAgeTogbnVtYmVyXG4gICAgKSA9PiBVbnF1YW50aXplZERlbm9ybWFsaXplZFVuc2lnbmVkQ29vcmQ7XG5cbiAgICAvKipcbiAgICAgKiBAcGFyYW0gdmlkZW9FbGVtZW50UHJvdmlkZXIgLSB0aGUgZGl2IGVsZW1lbnQgdGhhdCB0aGUgdmlkZW8gcGxheWVyIHdpbGwgYmUgaW5qZWN0ZWQgaW50b1xuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHZpZGVvRWxlbWVudFByb3ZpZGVyOiBWaWRlb1BsYXllcikge1xuICAgICAgICB0aGlzLnZpZGVvRWxlbWVudFByb3ZpZGVyID0gdmlkZW9FbGVtZW50UHJvdmlkZXI7XG4gICAgICAgIHRoaXMubm9ybWFsaXplQW5kUXVhbnRpemVVbnNpZ25lZEZ1bmMgPSAoKSA9PiB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgICAgJ05vcm1hbGl6ZSBhbmQgcXVhbnRpemUgdW5zaWduZWQsIG1ldGhvZCBub3QgaW1wbGVtZW50ZWQuJ1xuICAgICAgICAgICAgKTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5ub3JtYWxpemVBbmRRdWFudGl6ZVNpZ25lZEZ1bmMgPSAoKSA9PiB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgICAgJ05vcm1hbGl6ZSBhbmQgdW5xdWFudGl6ZSBzaWduZWQsIG1ldGhvZCBub3QgaW1wbGVtZW50ZWQuJ1xuICAgICAgICAgICAgKTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5kZW5vcm1hbGl6ZUFuZFVucXVhbnRpemVVbnNpZ25lZEZ1bmMgPSAoKSA9PiB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgICAgJ0Rlbm9ybWFsaXplIGFuZCB1bnF1YW50aXplIHVuc2lnbmVkLCBtZXRob2Qgbm90IGltcGxlbWVudGVkLidcbiAgICAgICAgICAgICk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIHN1cmZhY2UgbWV0aG9kIGZvciBzZXR0ZXJOb3JtYWxpemVBbmRRdWFudGl6ZVVuc2lnbmVkXG4gICAgICogQHBhcmFtIHggLSB4IGF4aXMgcG9pbnRcbiAgICAgKiBAcGFyYW0geSAtIHkgYXhpcyBwb2ludFxuICAgICAqL1xuICAgIG5vcm1hbGl6ZUFuZFF1YW50aXplVW5zaWduZWQoXG4gICAgICAgIHg6IG51bWJlcixcbiAgICAgICAgeTogbnVtYmVyXG4gICAgKTogTm9ybWFsaXplZFF1YW50aXplZFVuc2lnbmVkQ29vcmQge1xuICAgICAgICByZXR1cm4gdGhpcy5ub3JtYWxpemVBbmRRdWFudGl6ZVVuc2lnbmVkRnVuYyh4LCB5KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgc3VyZmFjZSBtZXRob2QgZm9yIHNldHRlclVucXVhbnRpemVBbmREZW5vcm1hbGl6ZVVuc2lnbmVkXG4gICAgICogQHBhcmFtIHggLSB4IGF4aXMgcG9pbnRcbiAgICAgKiBAcGFyYW0geSAtIHkgYXhpcyBwb2ludFxuICAgICAqL1xuICAgIHVucXVhbnRpemVBbmREZW5vcm1hbGl6ZVVuc2lnbmVkKFxuICAgICAgICB4OiBudW1iZXIsXG4gICAgICAgIHk6IG51bWJlclxuICAgICk6IFVucXVhbnRpemVkRGVub3JtYWxpemVkVW5zaWduZWRDb29yZCB7XG4gICAgICAgIHJldHVybiB0aGlzLmRlbm9ybWFsaXplQW5kVW5xdWFudGl6ZVVuc2lnbmVkRnVuYyh4LCB5KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGUgc3VyZmFjZSBtZXRob2QgZm9yIHNldHRlck5vcm1hbGl6ZUFuZFF1YW50aXplU2lnbmVkXG4gICAgICogQHBhcmFtIHggLSB4IGF4aXMgcG9pbnRcbiAgICAgKiBAcGFyYW0geSAtIHkgYXhpcyBwb2ludFxuICAgICAqL1xuICAgIG5vcm1hbGl6ZUFuZFF1YW50aXplU2lnbmVkKFxuICAgICAgICB4OiBudW1iZXIsXG4gICAgICAgIHk6IG51bWJlclxuICAgICk6IE5vcm1hbGl6ZWRRdWFudGl6ZWRTaWduZWRDb29yZCB7XG4gICAgICAgIHJldHVybiB0aGlzLm5vcm1hbGl6ZUFuZFF1YW50aXplU2lnbmVkRnVuYyh4LCB5KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBzZXQgdXAgdGhlIE5vcm1hbGl6ZSBBbmQgUXVhbnRpemUgbWV0aG9kcyBiYXNlZCBvbiB0aGUgYXNwZWN0IHJhdGlvIGFuZCB0aGUgdmlkZW8gcGxheWVyIHJhdGlvXG4gICAgICovXG4gICAgc2V0dXBOb3JtYWxpemVBbmRRdWFudGl6ZSgpIHtcbiAgICAgICAgdGhpcy52aWRlb0VsZW1lbnRQYXJlbnQgPVxuICAgICAgICAgICAgdGhpcy52aWRlb0VsZW1lbnRQcm92aWRlci5nZXRWaWRlb1BhcmVudEVsZW1lbnQoKTtcbiAgICAgICAgdGhpcy52aWRlb0VsZW1lbnQgPSB0aGlzLnZpZGVvRWxlbWVudFByb3ZpZGVyLmdldFZpZGVvRWxlbWVudCgpO1xuXG4gICAgICAgIGlmICh0aGlzLnZpZGVvRWxlbWVudFBhcmVudCAmJiB0aGlzLnZpZGVvRWxlbWVudCkge1xuICAgICAgICAgICAgY29uc3QgcGxheWVyQXNwZWN0UmF0aW8gPVxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9FbGVtZW50UGFyZW50LmNsaWVudEhlaWdodCAvXG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb0VsZW1lbnRQYXJlbnQuY2xpZW50V2lkdGg7XG4gICAgICAgICAgICBjb25zdCB2aWRlb0FzcGVjdFJhdGlvID1cbiAgICAgICAgICAgICAgICB0aGlzLnZpZGVvRWxlbWVudC52aWRlb0hlaWdodCAvIHRoaXMudmlkZW9FbGVtZW50LnZpZGVvV2lkdGg7XG4gICAgICAgICAgICBpZiAocGxheWVyQXNwZWN0UmF0aW8gPiB2aWRlb0FzcGVjdFJhdGlvKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLkxvZyhcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICAgICAgICAgJ1NldHVwIE5vcm1hbGl6ZSBhbmQgUXVhbnRpemUgZm9yIHBsYXllckFzcGVjdFJhdGlvID4gdmlkZW9Bc3BlY3RSYXRpbycsXG4gICAgICAgICAgICAgICAgICAgIDZcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIHRoaXMucmF0aW8gPSBwbGF5ZXJBc3BlY3RSYXRpbyAvIHZpZGVvQXNwZWN0UmF0aW87XG4gICAgICAgICAgICAgICAgdGhpcy5ub3JtYWxpemVBbmRRdWFudGl6ZVVuc2lnbmVkRnVuYyA9IChcbiAgICAgICAgICAgICAgICAgICAgeDogbnVtYmVyLFxuICAgICAgICAgICAgICAgICAgICB5OiBudW1iZXJcbiAgICAgICAgICAgICAgICApID0+IHRoaXMubm9ybWFsaXplQW5kUXVhbnRpemVVbnNpZ25lZFBsYXllckJpZ2dlcih4LCB5KTtcbiAgICAgICAgICAgICAgICB0aGlzLm5vcm1hbGl6ZUFuZFF1YW50aXplU2lnbmVkRnVuYyA9ICh4OiBudW1iZXIsIHk6IG51bWJlcikgPT5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5ub3JtYWxpemVBbmRRdWFudGl6ZVNpZ25lZFBsYXllckJpZ2dlcih4LCB5KTtcbiAgICAgICAgICAgICAgICB0aGlzLmRlbm9ybWFsaXplQW5kVW5xdWFudGl6ZVVuc2lnbmVkRnVuYyA9IChcbiAgICAgICAgICAgICAgICAgICAgeDogbnVtYmVyLFxuICAgICAgICAgICAgICAgICAgICB5OiBudW1iZXJcbiAgICAgICAgICAgICAgICApID0+IHRoaXMuZGVub3JtYWxpemVBbmRVbnF1YW50aXplVW5zaWduZWRQbGF5ZXJCaWdnZXIoeCwgeSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIExvZ2dlci5Mb2coXG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAgICAgICAgICdTZXR1cCBOb3JtYWxpemUgYW5kIFF1YW50aXplIGZvciBwbGF5ZXJBc3BlY3RSYXRpbyA8PSB2aWRlb0FzcGVjdFJhdGlvJyxcbiAgICAgICAgICAgICAgICAgICAgNlxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgdGhpcy5yYXRpbyA9IHZpZGVvQXNwZWN0UmF0aW8gLyBwbGF5ZXJBc3BlY3RSYXRpbztcbiAgICAgICAgICAgICAgICB0aGlzLm5vcm1hbGl6ZUFuZFF1YW50aXplVW5zaWduZWRGdW5jID0gKFxuICAgICAgICAgICAgICAgICAgICB4OiBudW1iZXIsXG4gICAgICAgICAgICAgICAgICAgIHk6IG51bWJlclxuICAgICAgICAgICAgICAgICkgPT4gdGhpcy5ub3JtYWxpemVBbmRRdWFudGl6ZVVuc2lnbmVkUGxheWVyU21hbGxlcih4LCB5KTtcbiAgICAgICAgICAgICAgICB0aGlzLm5vcm1hbGl6ZUFuZFF1YW50aXplU2lnbmVkRnVuYyA9ICh4OiBudW1iZXIsIHk6IG51bWJlcikgPT5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5ub3JtYWxpemVBbmRRdWFudGl6ZVNpZ25lZFBsYXllclNtYWxsZXIoeCwgeSk7XG4gICAgICAgICAgICAgICAgdGhpcy5kZW5vcm1hbGl6ZUFuZFVucXVhbnRpemVVbnNpZ25lZEZ1bmMgPSAoXG4gICAgICAgICAgICAgICAgICAgIHg6IG51bWJlcixcbiAgICAgICAgICAgICAgICAgICAgeTogbnVtYmVyXG4gICAgICAgICAgICAgICAgKSA9PiB0aGlzLmRlbm9ybWFsaXplQW5kVW5xdWFudGl6ZVVuc2lnbmVkUGxheWVyU21hbGxlcih4LCB5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIG5vcm1hbGl6ZUFuZFF1YW50aXplVW5zaWduZWQgZm9yIHBsYXllckFzcGVjdFJhdGlvID4gdmlkZW9Bc3BlY3RSYXRpb1xuICAgICAqIEBwYXJhbSB4IC0geCBheGlzIHBvaW50XG4gICAgICogQHBhcmFtIHkgLSB5IGF4aXMgcG9pbnRcbiAgICAgKi9cbiAgICBub3JtYWxpemVBbmRRdWFudGl6ZVVuc2lnbmVkUGxheWVyQmlnZ2VyKFxuICAgICAgICB4OiBudW1iZXIsXG4gICAgICAgIHk6IG51bWJlclxuICAgICk6IE5vcm1hbGl6ZWRRdWFudGl6ZWRVbnNpZ25lZENvb3JkIHtcbiAgICAgICAgY29uc3Qgbm9ybWFsaXplZFggPSB4IC8gdGhpcy52aWRlb0VsZW1lbnRQYXJlbnQuY2xpZW50V2lkdGg7XG4gICAgICAgIGNvbnN0IG5vcm1hbGl6ZWRZID1cbiAgICAgICAgICAgIHRoaXMucmF0aW8gKiAoeSAvIHRoaXMudmlkZW9FbGVtZW50UGFyZW50LmNsaWVudEhlaWdodCAtIDAuNSkgKyAwLjU7XG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIG5vcm1hbGl6ZWRYIDwgMC4wIHx8XG4gICAgICAgICAgICBub3JtYWxpemVkWCA+IDEuMCB8fFxuICAgICAgICAgICAgbm9ybWFsaXplZFkgPCAwLjAgfHxcbiAgICAgICAgICAgIG5vcm1hbGl6ZWRZID4gMS4wXG4gICAgICAgICkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBOb3JtYWxpemVkUXVhbnRpemVkVW5zaWduZWRDb29yZChmYWxzZSwgNjU1MzUsIDY1NTM1KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgTm9ybWFsaXplZFF1YW50aXplZFVuc2lnbmVkQ29vcmQoXG4gICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgICAgICAgICBub3JtYWxpemVkWCAqIDY1NTM2LFxuICAgICAgICAgICAgICAgIG5vcm1hbGl6ZWRZICogNjU1MzZcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiB1bnF1YW50aXplQW5kRGVub3JtYWxpemVVbnNpZ25lZCBmb3IgcGxheWVyQXNwZWN0UmF0aW8gPiB2aWRlb0FzcGVjdFJhdGlvXG4gICAgICogQHBhcmFtIHggLSB4IGF4aXMgcG9pbnRcbiAgICAgKiBAcGFyYW0geSAtIHkgYXhpcyBwb2ludFxuICAgICAqL1xuICAgIGRlbm9ybWFsaXplQW5kVW5xdWFudGl6ZVVuc2lnbmVkUGxheWVyQmlnZ2VyKHg6IG51bWJlciwgeTogbnVtYmVyKSB7XG4gICAgICAgIGNvbnN0IG5vcm1hbGl6ZWRYID0geCAvIDY1NTM2O1xuICAgICAgICBjb25zdCBub3JtYWxpemVkWSA9ICh5IC8gNjU1MzYgLSAwLjUpIC8gdGhpcy5yYXRpbyArIDAuNTtcbiAgICAgICAgcmV0dXJuIG5ldyBVbnF1YW50aXplZERlbm9ybWFsaXplZFVuc2lnbmVkQ29vcmQoXG4gICAgICAgICAgICBub3JtYWxpemVkWCAqIHRoaXMudmlkZW9FbGVtZW50UGFyZW50LmNsaWVudFdpZHRoLFxuICAgICAgICAgICAgbm9ybWFsaXplZFkgKiB0aGlzLnZpZGVvRWxlbWVudFBhcmVudC5jbGllbnRIZWlnaHRcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBub3JtYWxpemVBbmRRdWFudGl6ZVNpZ25lZCBmb3IgcGxheWVyQXNwZWN0UmF0aW8gPiB2aWRlb0FzcGVjdFJhdGlvXG4gICAgICogQHBhcmFtIHggLSB4IGF4aXMgcG9pbnRcbiAgICAgKiBAcGFyYW0geSAtIHkgYXhpcyBwb2ludFxuICAgICAqL1xuICAgIG5vcm1hbGl6ZUFuZFF1YW50aXplU2lnbmVkUGxheWVyQmlnZ2VyKHg6IG51bWJlciwgeTogbnVtYmVyKSB7XG4gICAgICAgIGNvbnN0IG5vcm1hbGl6ZWRYID0geCAvICgwLjUgKiB0aGlzLnZpZGVvRWxlbWVudFBhcmVudC5jbGllbnRXaWR0aCk7XG4gICAgICAgIGNvbnN0IG5vcm1hbGl6ZWRZID1cbiAgICAgICAgICAgICh0aGlzLnJhdGlvICogeSkgLyAoMC41ICogdGhpcy52aWRlb0VsZW1lbnRQYXJlbnQuY2xpZW50SGVpZ2h0KTtcbiAgICAgICAgcmV0dXJuIG5ldyBOb3JtYWxpemVkUXVhbnRpemVkU2lnbmVkQ29vcmQoXG4gICAgICAgICAgICBub3JtYWxpemVkWCAqIDMyNzY3LFxuICAgICAgICAgICAgbm9ybWFsaXplZFkgKiAzMjc2N1xuICAgICAgICApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIG5vcm1hbGl6ZUFuZFF1YW50aXplVW5zaWduZWQgZm9yIHBsYXllckFzcGVjdFJhdGlvIDw9IHZpZGVvQXNwZWN0UmF0aW9cbiAgICAgKiBAcGFyYW0geCAtIHggYXhpcyBwb2ludFxuICAgICAqIEBwYXJhbSB5IC0geSBheGlzIHBvaW50XG4gICAgICovXG4gICAgbm9ybWFsaXplQW5kUXVhbnRpemVVbnNpZ25lZFBsYXllclNtYWxsZXIoeDogbnVtYmVyLCB5OiBudW1iZXIpIHtcbiAgICAgICAgY29uc3Qgbm9ybWFsaXplZFggPVxuICAgICAgICAgICAgdGhpcy5yYXRpbyAqICh4IC8gdGhpcy52aWRlb0VsZW1lbnRQYXJlbnQuY2xpZW50V2lkdGggLSAwLjUpICsgMC41O1xuICAgICAgICBjb25zdCBub3JtYWxpemVkWSA9IHkgLyB0aGlzLnZpZGVvRWxlbWVudFBhcmVudC5jbGllbnRIZWlnaHQ7XG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIG5vcm1hbGl6ZWRYIDwgMC4wIHx8XG4gICAgICAgICAgICBub3JtYWxpemVkWCA+IDEuMCB8fFxuICAgICAgICAgICAgbm9ybWFsaXplZFkgPCAwLjAgfHxcbiAgICAgICAgICAgIG5vcm1hbGl6ZWRZID4gMS4wXG4gICAgICAgICkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBOb3JtYWxpemVkUXVhbnRpemVkVW5zaWduZWRDb29yZChmYWxzZSwgNjU1MzUsIDY1NTM1KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgTm9ybWFsaXplZFF1YW50aXplZFVuc2lnbmVkQ29vcmQoXG4gICAgICAgICAgICAgICAgdHJ1ZSxcbiAgICAgICAgICAgICAgICBub3JtYWxpemVkWCAqIDY1NTM2LFxuICAgICAgICAgICAgICAgIG5vcm1hbGl6ZWRZICogNjU1MzZcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiB1bnF1YW50aXplQW5kRGVub3JtYWxpemVVbnNpZ25lZCBmb3IgcGxheWVyQXNwZWN0UmF0aW8gPD0gdmlkZW9Bc3BlY3RSYXRpb1xuICAgICAqIEBwYXJhbSB4IC0geCBheGlzIHBvaW50XG4gICAgICogQHBhcmFtIHkgLSB5IGF4aXMgcG9pbnRcbiAgICAgKi9cbiAgICBkZW5vcm1hbGl6ZUFuZFVucXVhbnRpemVVbnNpZ25lZFBsYXllclNtYWxsZXIoeDogbnVtYmVyLCB5OiBudW1iZXIpIHtcbiAgICAgICAgY29uc3Qgbm9ybWFsaXplZFggPSAoeCAvIDY1NTM2IC0gMC41KSAvIHRoaXMucmF0aW8gKyAwLjU7XG4gICAgICAgIGNvbnN0IG5vcm1hbGl6ZWRZID0geSAvIDY1NTM2O1xuICAgICAgICByZXR1cm4gbmV3IFVucXVhbnRpemVkRGVub3JtYWxpemVkVW5zaWduZWRDb29yZChcbiAgICAgICAgICAgIG5vcm1hbGl6ZWRYICogdGhpcy52aWRlb0VsZW1lbnRQYXJlbnQuY2xpZW50V2lkdGgsXG4gICAgICAgICAgICBub3JtYWxpemVkWSAqIHRoaXMudmlkZW9FbGVtZW50UGFyZW50LmNsaWVudEhlaWdodFxuICAgICAgICApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIG5vcm1hbGl6ZUFuZFF1YW50aXplU2lnbmVkIGZvciBwbGF5ZXJBc3BlY3RSYXRpbyA8PSB2aWRlb0FzcGVjdFJhdGlvXG4gICAgICogQHBhcmFtIHggLSB4IGF4aXMgcG9pbnRcbiAgICAgKiBAcGFyYW0geSAtIHkgYXhpcyBwb2ludFxuICAgICAqL1xuICAgIG5vcm1hbGl6ZUFuZFF1YW50aXplU2lnbmVkUGxheWVyU21hbGxlcih4OiBudW1iZXIsIHk6IG51bWJlcikge1xuICAgICAgICBjb25zdCBub3JtYWxpemVkWCA9XG4gICAgICAgICAgICAodGhpcy5yYXRpbyAqIHgpIC8gKDAuNSAqIHRoaXMudmlkZW9FbGVtZW50UGFyZW50LmNsaWVudFdpZHRoKTtcbiAgICAgICAgY29uc3Qgbm9ybWFsaXplZFkgPSB5IC8gKDAuNSAqIHRoaXMudmlkZW9FbGVtZW50UGFyZW50LmNsaWVudEhlaWdodCk7XG4gICAgICAgIHJldHVybiBuZXcgTm9ybWFsaXplZFF1YW50aXplZFNpZ25lZENvb3JkKFxuICAgICAgICAgICAgbm9ybWFsaXplZFggKiAzMjc2NyxcbiAgICAgICAgICAgIG5vcm1hbGl6ZWRZICogMzI3NjdcbiAgICAgICAgKTtcbiAgICB9XG59XG5cbi8qKlxuICogQSBjbGFzcyBmb3IgTm9ybWFsaXplQW5kUXVhbnRpemVVbnNpZ25lZCBvYmplY3RzXG4gKi9cbmV4cG9ydCBjbGFzcyBOb3JtYWxpemVkUXVhbnRpemVkVW5zaWduZWRDb29yZCB7XG4gICAgaW5SYW5nZTogYm9vbGVhbjtcbiAgICB4OiBudW1iZXI7XG4gICAgeTogbnVtYmVyO1xuXG4gICAgY29uc3RydWN0b3IoaW5SYW5nZTogYm9vbGVhbiwgeDogbnVtYmVyLCB5OiBudW1iZXIpIHtcbiAgICAgICAgdGhpcy5pblJhbmdlID0gaW5SYW5nZTtcbiAgICAgICAgdGhpcy54ID0geDtcbiAgICAgICAgdGhpcy55ID0geTtcbiAgICB9XG59XG5cbi8qKlxuICogQSBjbGFzcyBmb3IgVW5xdWFudGl6ZWRBbmREZW5vcm1hbGl6ZVVuc2lnbmVkIG9iamVjdHNcbiAqL1xuZXhwb3J0IGNsYXNzIFVucXVhbnRpemVkRGVub3JtYWxpemVkVW5zaWduZWRDb29yZCB7XG4gICAgeDogbnVtYmVyO1xuICAgIHk6IG51bWJlcjtcblxuICAgIGNvbnN0cnVjdG9yKHg6IG51bWJlciwgeTogbnVtYmVyKSB7XG4gICAgICAgIHRoaXMueCA9IHg7XG4gICAgICAgIHRoaXMueSA9IHk7XG4gICAgfVxufVxuXG4vKipcbiAqIEEgY2xhc3MgZm9yIE5vcm1hbGl6ZWRRdWFudGl6ZWRTaWduZWRDb29yZCBvYmplY3RzXG4gKi9cbmV4cG9ydCBjbGFzcyBOb3JtYWxpemVkUXVhbnRpemVkU2lnbmVkQ29vcmQge1xuICAgIHg6IG51bWJlcjtcbiAgICB5OiBudW1iZXI7XG5cbiAgICBjb25zdHJ1Y3Rvcih4OiBudW1iZXIsIHk6IG51bWJlcikge1xuICAgICAgICB0aGlzLnggPSB4O1xuICAgICAgICB0aGlzLnkgPSB5O1xuICAgIH1cbn1cbiIsImltcG9ydCB7XG4gICAgRmxhZ3NJZHMsXG4gICAgTnVtZXJpY1BhcmFtZXRlcnNJZHMsXG4gICAgT3B0aW9uUGFyYW1ldGVyc0lkcyxcbiAgICBUZXh0UGFyYW1ldGVyc0lkc1xufSBmcm9tICcuLi9Db25maWcvQ29uZmlnJztcbmltcG9ydCB7IExhdGVuY3lUZXN0UmVzdWx0cyB9IGZyb20gJy4uL0RhdGFDaGFubmVsL0xhdGVuY3lUZXN0UmVzdWx0cyc7XG5pbXBvcnQgeyBBZ2dyZWdhdGVkU3RhdHMgfSBmcm9tICcuLi9QZWVyQ29ubmVjdGlvbkNvbnRyb2xsZXIvQWdncmVnYXRlZFN0YXRzJztcbmltcG9ydCB7IEluaXRpYWxTZXR0aW5ncyB9IGZyb20gJy4uL3BpeGVsc3RyZWFtaW5nZnJvbnRlbmQnO1xuaW1wb3J0IHsgTWVzc2FnZVN0cmVhbWVyTGlzdCB9IGZyb20gJy4uL1dlYlNvY2tldHMvTWVzc2FnZVJlY2VpdmUnO1xuaW1wb3J0IHsgU2V0dGluZ0ZsYWcgfSBmcm9tICcuLi9Db25maWcvU2V0dGluZ0ZsYWcnO1xuaW1wb3J0IHsgU2V0dGluZ051bWJlciB9IGZyb20gJy4uL0NvbmZpZy9TZXR0aW5nTnVtYmVyJztcbmltcG9ydCB7IFNldHRpbmdUZXh0IH0gZnJvbSAnLi4vQ29uZmlnL1NldHRpbmdUZXh0JztcbmltcG9ydCB7IFNldHRpbmdPcHRpb24gfSBmcm9tICcuLi9Db25maWcvU2V0dGluZ09wdGlvbic7XG5pbXBvcnQge1xuICAgIERhdGFDaGFubmVsTGF0ZW5jeVRlc3RSZXNwb25zZSxcbiAgICBEYXRhQ2hhbm5lbExhdGVuY3lUZXN0UmVzdWx0XG59IGZyb20gXCIuLi9EYXRhQ2hhbm5lbC9EYXRhQ2hhbm5lbExhdGVuY3lUZXN0UmVzdWx0c1wiO1xuXG4vKipcbiAqIEFuIGV2ZW50IHRoYXQgaXMgZW1pdHRlZCB3aGVuIEFGSyBkaXNjb25uZWN0IGlzIGFib3V0IHRvIGhhcHBlbi5cbiAqIENhbiBiZSBjYW5jZWxsZWQgYnkgY2FsbGluZyB0aGUgY2FsbGJhY2sgZnVuY3Rpb24gcHJvdmlkZWQgYXMgcGFydCBvZiB0aGUgZXZlbnQuXG4gKi9cbmV4cG9ydCBjbGFzcyBBZmtXYXJuaW5nQWN0aXZhdGVFdmVudCBleHRlbmRzIEV2ZW50IHtcbiAgICByZWFkb25seSB0eXBlOiAnYWZrV2FybmluZ0FjdGl2YXRlJztcbiAgICByZWFkb25seSBkYXRhOiB7XG4gICAgICAgIC8qKiBIb3cgbWFueSBzZWNvbmRzIHVudGlsIHRoZSBzZXNzaW9uIGlzIGRpc2Nvbm5lY3RlZCAqL1xuICAgICAgICBjb3VudERvd246IG51bWJlcjtcbiAgICAgICAgLyoqIENhbGxiYWNrIGZ1bmN0aW9uIHRoYXQgbmVlZHMgdG8gYmUgY2FsbGVkIGlmIHlvdSB3aXNoIHRvIGNhbmNlbCB0aGUgQUZLIGRpc2Nvbm5lY3QgdGltZW91dC4gKi9cbiAgICAgICAgZGlzbWlzc0FmazogKCkgPT4gdm9pZDtcbiAgICB9O1xuICAgIGNvbnN0cnVjdG9yKGRhdGE6IEFma1dhcm5pbmdBY3RpdmF0ZUV2ZW50WydkYXRhJ10pIHtcbiAgICAgICAgc3VwZXIoJ2Fma1dhcm5pbmdBY3RpdmF0ZScpO1xuICAgICAgICB0aGlzLmRhdGEgPSBkYXRhO1xuICAgIH1cbn1cblxuLyoqXG4gKiBBbiBldmVudCB0aGF0IGlzIGVtaXR0ZWQgd2hlbiB0aGUgQUZLIGRpc2Nvbm5lY3QgY291bnRkb3duIGlzIHVwZGF0ZWQuXG4gKi9cbmV4cG9ydCBjbGFzcyBBZmtXYXJuaW5nVXBkYXRlRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG4gICAgcmVhZG9ubHkgdHlwZTogJ2Fma1dhcm5pbmdVcGRhdGUnO1xuICAgIHJlYWRvbmx5IGRhdGE6IHtcbiAgICAgICAgLyoqIEhvdyBtYW55IHNlY29uZHMgdW50aWwgdGhlIHNlc3Npb24gaXMgZGlzY29ubmVjdGVkICovXG4gICAgICAgIGNvdW50RG93bjogbnVtYmVyXG4gICAgfTtcbiAgICBjb25zdHJ1Y3RvcihkYXRhOiBBZmtXYXJuaW5nVXBkYXRlRXZlbnRbJ2RhdGEnXSkge1xuICAgICAgICBzdXBlcignYWZrV2FybmluZ1VwZGF0ZScpO1xuICAgICAgICB0aGlzLmRhdGEgPSBkYXRhO1xuICAgIH1cbn1cblxuLyoqXG4gKiBBbiBldmVudCB0aGF0IGlzIGVtaXR0ZWQgd2hlbiBBRksgd2FybmluZyBpcyBkZWFjdGl2YXRlZC5cbiAqL1xuZXhwb3J0IGNsYXNzIEFma1dhcm5pbmdEZWFjdGl2YXRlRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG4gICAgcmVhZG9ubHkgdHlwZTogJ2Fma1dhcm5pbmdEZWFjdGl2YXRlJztcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoJ2Fma1dhcm5pbmdEZWFjdGl2YXRlJyk7XG4gICAgfVxufVxuXG4vKipcbiAqIEFuIGV2ZW50IHRoYXQgaXMgZW1pdHRlZCB3aGVuIEFGSyBjb3VudGRvd24gcmVhY2hlcyAwIGFuZCB0aGUgdXNlciBpcyBkaXNjb25uZWN0ZWQuXG4gKi9cbmV4cG9ydCBjbGFzcyBBZmtUaW1lZE91dEV2ZW50IGV4dGVuZHMgRXZlbnQge1xuICAgIHJlYWRvbmx5IHR5cGU6ICdhZmtUaW1lZE91dCc7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKCdhZmtUaW1lZE91dCcpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBBbiBldmVudCB0aGF0IGlzIGVtaXR0ZWQgd2hlbiB3ZSByZWNlaXZlIG5ldyB2aWRlbyBxdWFsaXR5IHZhbHVlLlxuICovXG5leHBvcnQgY2xhc3MgVmlkZW9FbmNvZGVyQXZnUVBFdmVudCBleHRlbmRzIEV2ZW50IHtcbiAgICByZWFkb25seSB0eXBlOiAndmlkZW9FbmNvZGVyQXZnUVAnO1xuICAgIHJlYWRvbmx5IGRhdGE6IHtcbiAgICAgICAgLyoqIEF2ZXJhZ2UgdmlkZW8gcXVhbGl0eSB2YWx1ZSAqL1xuICAgICAgICBhdmdRUDogbnVtYmVyXG4gICAgfTtcbiAgICBjb25zdHJ1Y3RvcihkYXRhOiBWaWRlb0VuY29kZXJBdmdRUEV2ZW50WydkYXRhJ10pIHtcbiAgICAgICAgc3VwZXIoJ3ZpZGVvRW5jb2RlckF2Z1FQJyk7XG4gICAgICAgIHRoaXMuZGF0YSA9IGRhdGE7XG4gICAgfVxufVxuXG4vKipcbiAqIEFuIGV2ZW50IHRoYXQgaXMgZW1pdHRlZCBhZnRlciBhIFdlYlJ0YyBjb25uZWN0aW9uIGhhcyBiZWVuIG5lZ290aWF0ZWQuIFxuICovXG5leHBvcnQgY2xhc3MgV2ViUnRjU2RwRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG4gICAgcmVhZG9ubHkgdHlwZTogJ3dlYlJ0Y1NkcCc7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKCd3ZWJSdGNTZHAnKTtcbiAgICB9XG59XG5cbi8qKlxuICogQW4gZXZlbnQgdGhhdCBpcyBlbWl0dGVkIHdoZW4gYXV0byBjb25uZWN0aW5nLlxuICovXG5leHBvcnQgY2xhc3MgV2ViUnRjQXV0b0Nvbm5lY3RFdmVudCBleHRlbmRzIEV2ZW50IHtcbiAgICByZWFkb25seSB0eXBlOiAnd2ViUnRjQXV0b0Nvbm5lY3QnO1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICBzdXBlcignd2ViUnRjQXV0b0Nvbm5lY3QnKTtcbiAgICB9XG59XG5cbi8qKlxuICogQW4gZXZlbnQgdGhhdCBpcyBlbWl0dGVkIHdoZW4gc2VuZGluZyBhIFdlYlJ0YyBvZmZlci5cbiAqL1xuZXhwb3J0IGNsYXNzIFdlYlJ0Y0Nvbm5lY3RpbmdFdmVudCBleHRlbmRzIEV2ZW50IHtcbiAgICByZWFkb25seSB0eXBlOiAnd2ViUnRjQ29ubmVjdGluZyc7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKCd3ZWJSdGNDb25uZWN0aW5nJyk7XG4gICAgfVxufVxuXG4vKipcbiAqIEFuIGV2ZW50IHRoYXQgaXMgZW1pdHRlZCB3aGVuIFdlYlJ0YyBjb25uZWN0aW9uIGhhcyBiZWVuIGVzdGFibGlzaGVkLlxuICovXG5leHBvcnQgY2xhc3MgV2ViUnRjQ29ubmVjdGVkRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG4gICAgcmVhZG9ubHkgdHlwZTogJ3dlYlJ0Y0Nvbm5lY3RlZCc7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKCd3ZWJSdGNDb25uZWN0ZWQnKTtcbiAgICB9XG59XG5cbi8qKlxuICogQW4gZXZlbnQgdGhhdCBpcyBlbWl0dGVkIGlmIFdlYlJ0YyBjb25uZWN0aW9uIGhhcyBmYWlsZWQuXG4gKi9cbmV4cG9ydCBjbGFzcyBXZWJSdGNGYWlsZWRFdmVudCBleHRlbmRzIEV2ZW50IHtcbiAgICByZWFkb25seSB0eXBlOiAnd2ViUnRjRmFpbGVkJztcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoJ3dlYlJ0Y0ZhaWxlZCcpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBBbiBldmVudCB0aGF0IGlzIGVtaXR0ZWQgaWYgV2ViUnRjIGNvbm5lY3Rpb24gaXMgZGlzY29ubmVjdGVkLlxuICovXG5leHBvcnQgY2xhc3MgV2ViUnRjRGlzY29ubmVjdGVkRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG4gICAgcmVhZG9ubHkgdHlwZTogJ3dlYlJ0Y0Rpc2Nvbm5lY3RlZCc7XG4gICAgcmVhZG9ubHkgZGF0YToge1xuICAgICAgICAvKiogTWVzc2FnZSBkZXNjcmliaW5nIHRoZSBkaXNjb25uZWN0IHJlYXNvbiAqL1xuICAgICAgICBldmVudFN0cmluZzogc3RyaW5nO1xuICAgICAgICAvKiogdHJ1ZSBpZiB0aGUgdXNlciBpcyBhYmxlIHRvIHJlY29ubmVjdCwgZmFsc2UgaWYgZGlzY29ubmVjdGVkIGJlY2F1c2Ugb2YgdW5yZWNvdmVyYWJsZSByZWFzb25zIGxpa2Ugbm90IGFibGUgdG8gY29ubmVjdCB0byB0aGUgc2lnbmFsaW5nIHNlcnZlciAqL1xuICAgICAgICBhbGxvd0NsaWNrVG9SZWNvbm5lY3Q6IGJvb2xlYW47XG4gICAgfTtcbiAgICBjb25zdHJ1Y3RvcihkYXRhOiBXZWJSdGNEaXNjb25uZWN0ZWRFdmVudFsnZGF0YSddKSB7XG4gICAgICAgIHN1cGVyKCd3ZWJSdGNEaXNjb25uZWN0ZWQnKTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICB9XG59XG5cbi8qKlxuICogQW4gZXZlbnQgdGhhdCBpcyBlbWl0dGVkIHdoZW4gUlRDRGF0YUNoYW5uZWwgaXMgb3BlbmVkLlxuICovXG5leHBvcnQgY2xhc3MgRGF0YUNoYW5uZWxPcGVuRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG4gICAgcmVhZG9ubHkgdHlwZTogJ2RhdGFDaGFubmVsT3Blbic7XG4gICAgcmVhZG9ubHkgZGF0YToge1xuICAgICAgICAvKiogRGF0YSBjaGFubmVsIGxhYmVsLiBPbmUgb2YgJ2RhdGFjaGFubmVsJywgJ3NlbmQtZGF0YWNoYW5uZWwnLCAncmVjdi1kYXRhY2hhbm5lbCcgKi9cbiAgICAgICAgbGFiZWw6IHN0cmluZztcbiAgICAgICAgLyoqIFJUQ0RhdGFDaGFubmVsIG9uT3BlbiBldmVudCAqL1xuICAgICAgICBldmVudDogRXZlbnRcbiAgICB9O1xuICAgIGNvbnN0cnVjdG9yKGRhdGE6IERhdGFDaGFubmVsT3BlbkV2ZW50WydkYXRhJ10pIHtcbiAgICAgICAgc3VwZXIoJ2RhdGFDaGFubmVsT3BlbicpO1xuICAgICAgICB0aGlzLmRhdGEgPSBkYXRhO1xuICAgIH1cbn1cblxuLyoqXG4gKiBBbiBldmVudCB0aGF0IGlzIGVtaXR0ZWQgd2hlbiBSVENEYXRhQ2hhbm5lbCBpcyBjbG9zZWQuXG4gKi9cbmV4cG9ydCBjbGFzcyBEYXRhQ2hhbm5lbENsb3NlRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG4gICAgcmVhZG9ubHkgdHlwZTogJ2RhdGFDaGFubmVsQ2xvc2UnO1xuICAgIHJlYWRvbmx5IGRhdGE6IHtcbiAgICAgICAgLyoqIERhdGEgY2hhbm5lbCBsYWJlbC4gT25lIG9mICdkYXRhY2hhbm5lbCcsICdzZW5kLWRhdGFjaGFubmVsJywgJ3JlY3YtZGF0YWNoYW5uZWwnICovXG4gICAgICAgIGxhYmVsOiBzdHJpbmc7XG4gICAgICAgIC8qKiBSVENEYXRhQ2hhbm5lbCBvbkNsb3NlIGV2ZW50ICovXG4gICAgICAgIGV2ZW50OiBFdmVudFxuICAgIH07XG4gICAgY29uc3RydWN0b3IoZGF0YTogRGF0YUNoYW5uZWxDbG9zZUV2ZW50WydkYXRhJ10pIHtcbiAgICAgICAgc3VwZXIoJ2RhdGFDaGFubmVsQ2xvc2UnKTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICB9XG59XG5cbi8qKlxuICogQW4gZXZlbnQgdGhhdCBpcyBlbWl0dGVkIG9uIFJUQ0RhdGFDaGFubmVsIGVycm9ycy5cbiAqL1xuZXhwb3J0IGNsYXNzIERhdGFDaGFubmVsRXJyb3JFdmVudCBleHRlbmRzIEV2ZW50IHtcbiAgICByZWFkb25seSB0eXBlOiAnZGF0YUNoYW5uZWxFcnJvcic7XG4gICAgcmVhZG9ubHkgZGF0YToge1xuICAgICAgICAvKiogRGF0YSBjaGFubmVsIGxhYmVsLiBPbmUgb2YgJ2RhdGFjaGFubmVsJywgJ3NlbmQtZGF0YWNoYW5uZWwnLCAncmVjdi1kYXRhY2hhbm5lbCcgKi9cbiAgICAgICAgbGFiZWw6IHN0cmluZztcbiAgICAgICAgLyoqIFJUQ0RhdGFDaGFubmVsIG9uRXJyb3IgZXZlbnQgKi9cbiAgICAgICAgZXZlbnQ6IEV2ZW50XG4gICAgfTtcbiAgICBjb25zdHJ1Y3RvcihkYXRhOiBEYXRhQ2hhbm5lbEVycm9yRXZlbnRbJ2RhdGEnXSkge1xuICAgICAgICBzdXBlcignZGF0YUNoYW5uZWxFcnJvcicpO1xuICAgICAgICB0aGlzLmRhdGEgPSBkYXRhO1xuICAgIH1cbn1cblxuLyoqXG4gKiBBbiBldmVudCB0aGF0IGlzIGVtaXR0ZWQgd2hlbiB0aGUgdmlkZW8gc3RyZWFtIGhhcyBiZWVuIGluaXRpYWxpemVkLlxuICovXG5leHBvcnQgY2xhc3MgVmlkZW9Jbml0aWFsaXplZEV2ZW50IGV4dGVuZHMgRXZlbnQge1xuICAgIHJlYWRvbmx5IHR5cGU6ICd2aWRlb0luaXRpYWxpemVkJztcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoJ3ZpZGVvSW5pdGlhbGl6ZWQnKTtcbiAgICB9XG59XG5cbi8qKlxuICogQW4gZXZlbnQgdGhhdCBpcyBlbWl0dGVkIHdoZW4gdmlkZW8gc3RyZWFtIGxvYWRpbmcgc3RhcnRzLlxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtTG9hZGluZ0V2ZW50IGV4dGVuZHMgRXZlbnQge1xuICAgIHJlYWRvbmx5IHR5cGU6ICdzdHJlYW1Mb2FkaW5nJztcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoJ3N0cmVhbUxvYWRpbmcnKTtcbiAgICB9XG59XG5cbi8qKlxuICogQW4gZXZlbnQgdGhhdCBpcyBlbWl0dGVkIHdoZW4gdmlkZW8gc3RyZWFtIGxvYWRpbmcgaGFzIGZpbmlzaGVkLlxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtUHJlQ29ubmVjdEV2ZW50IGV4dGVuZHMgRXZlbnQge1xuICAgIHJlYWRvbmx5IHR5cGU6ICdzdHJlYW1Db25uZWN0JztcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoJ3N0cmVhbUNvbm5lY3QnKTtcbiAgICB9XG59XG5cbi8qKlxuICogQW4gZXZlbnQgdGhhdCBpcyBlbWl0dGVkIHdoZW4gdmlkZW8gc3RyZWFtIGhhcyBzdG9wcGVkLlxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtUHJlRGlzY29ubmVjdEV2ZW50IGV4dGVuZHMgRXZlbnQge1xuICAgIHJlYWRvbmx5IHR5cGU6ICdzdHJlYW1EaXNjb25uZWN0JztcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoJ3N0cmVhbURpc2Nvbm5lY3QnKTtcbiAgICB9XG59XG5cbi8qKlxuICogQW4gZXZlbnQgdGhhdCBpcyBlbWl0dGVkIHdoZW4gdmlkZW8gc3RyZWFtIGlzIHJlY29ubmVjdGluZy5cbiAqL1xuZXhwb3J0IGNsYXNzIFN0cmVhbVJlY29ubmVjdEV2ZW50IGV4dGVuZHMgRXZlbnQge1xuICAgIHJlYWRvbmx5IHR5cGU6ICdzdHJlYW1SZWNvbm5lY3QnO1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICBzdXBlcignc3RyZWFtUmVjb25uZWN0Jyk7XG4gICAgfVxufVxuXG4vKipcbiAqIEFuIGV2ZW50IHRoYXQgaXMgZW1pdHRlZCBpZiB0aGVyZSBhcmUgZXJyb3JzIGxvYWRpbmcgdGhlIHZpZGVvIHN0cmVhbS5cbiAqL1xuZXhwb3J0IGNsYXNzIFBsYXlTdHJlYW1FcnJvckV2ZW50IGV4dGVuZHMgRXZlbnQge1xuICAgIHJlYWRvbmx5IHR5cGU6ICdwbGF5U3RyZWFtRXJyb3InO1xuICAgIHJlYWRvbmx5IGRhdGE6IHtcbiAgICAgICAgLyoqIEVycm9yIG1lc3NhZ2UgKi9cbiAgICAgICAgbWVzc2FnZTogc3RyaW5nXG4gICAgfTtcbiAgICBjb25zdHJ1Y3RvcihkYXRhOiBQbGF5U3RyZWFtRXJyb3JFdmVudFsnZGF0YSddKSB7XG4gICAgICAgIHN1cGVyKCdwbGF5U3RyZWFtRXJyb3InKTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICB9XG59XG5cbi8qKlxuICogQW4gZXZlbnQgdGhhdCBpcyBlbWl0dGVkIGJlZm9yZSB0cnlpbmcgdG8gc3RhcnQgdmlkZW8gcGxheWJhY2suXG4gKi9cbmV4cG9ydCBjbGFzcyBQbGF5U3RyZWFtRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG4gICAgcmVhZG9ubHkgdHlwZTogJ3BsYXlTdHJlYW0nO1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICBzdXBlcigncGxheVN0cmVhbScpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBBbiBldmVudCB0aGF0IGlzIGVtaXR0ZWQgaWYgdGhlIGJyb3dzZXIgcmVqZWN0cyB2aWRlbyBwbGF5YmFjay4gQ2FuIGhhcHBlbiBmb3IgZXhhbXBsZSBpZlxuICogdmlkZW8gYXV0by1wbGF5IHdpdGhvdXQgdXNlciBpbnRlcmFjdGlvbiBpcyByZWZ1c2VkIGJ5IHRoZSBicm93c2VyLlxuICovXG5leHBvcnQgY2xhc3MgUGxheVN0cmVhbVJlamVjdGVkRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG4gICAgcmVhZG9ubHkgdHlwZTogJ3BsYXlTdHJlYW1SZWplY3RlZCc7XG4gICAgcmVhZG9ubHkgZGF0YToge1xuICAgICAgICAvKiogUmVqZWN0aW9uIHJlYXNvbiAqL1xuICAgICAgICByZWFzb246IHVua25vd25cbiAgICB9O1xuICAgIGNvbnN0cnVjdG9yKGRhdGE6IFBsYXlTdHJlYW1SZWplY3RlZEV2ZW50WydkYXRhJ10pIHtcbiAgICAgICAgc3VwZXIoJ3BsYXlTdHJlYW1SZWplY3RlZCcpO1xuICAgICAgICB0aGlzLmRhdGEgPSBkYXRhO1xuICAgIH1cbn1cblxuLyoqXG4gKiBBbiBldmVudCB0aGF0IGlzIGVtaXR0ZWQgd2hlbiByZWNlaXZpbmcgYSBmdWxsIEZyZWV6ZUZyYW1lIGltYWdlIGZyb20gVUUuXG4gKi9cbmV4cG9ydCBjbGFzcyBMb2FkRnJlZXplRnJhbWVFdmVudCBleHRlbmRzIEV2ZW50IHtcbiAgICByZWFkb25seSB0eXBlOiAnbG9hZEZyZWV6ZUZyYW1lJztcbiAgICByZWFkb25seSBkYXRhOiB7XG4gICAgICAgIC8qKiB0cnVlIGlmIHNob3VsZCBzaG93IGNsaWNrLXRvLXBsYXkgb3ZlcmxheSwgbm90IHRoZSBmcmVlemUgZnJhbWUgY29udGVudHMgKi9cbiAgICAgICAgc2hvdWxkU2hvd1BsYXlPdmVybGF5OiBib29sZWFuO1xuICAgICAgICAvKiogdHJ1ZSBpZiB0aGUgcmVjZWl2ZWQgaW1hZ2UgaXMgdmFsaWQgKi9cbiAgICAgICAgaXNWYWxpZDogYm9vbGVhbjtcbiAgICAgICAgLyoqIEltYWdlIGRhdGEuIENhbiBiZSBlLmcuIGRpc3BsYXllZCBieSBlbmNvZGluZyBhcyBhIGRhdGEgdXJsLiAqL1xuICAgICAgICBqcGVnRGF0YT86IFVpbnQ4QXJyYXk7XG4gICAgfTtcbiAgICBjb25zdHJ1Y3RvcihkYXRhOiBMb2FkRnJlZXplRnJhbWVFdmVudFsnZGF0YSddKSB7XG4gICAgICAgIHN1cGVyKCdsb2FkRnJlZXplRnJhbWUnKTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICB9XG59XG5cbi8qKlxuICogQW4gZXZlbnQgdGhhdCBpcyBlbWl0dGVkIHdoZW4gcmVjZWl2aW5nIFVuZnJlZXplRnJhbWUgbWVzc2FnZSBmcm9tIFVFIGFuZCB2aWRlbyBwbGF5YmFjayBpcyBhYm91dCB0byBiZSByZXN1bWVkLlxuICovXG5leHBvcnQgY2xhc3MgSGlkZUZyZWV6ZUZyYW1lRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG4gICAgcmVhZG9ubHkgdHlwZTogJ2hpZGVGcmVlemVGcmFtZSc7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKCdoaWRlRnJlZXplRnJhbWUnKTtcbiAgICB9XG59XG5cbi8qKlxuICogQW4gZXZlbnQgdGhhdCBpcyBlbWl0dGVkIHdoZW4gcmVjZWl2aW5nIFdlYlJUQyBzdGF0aXN0aWNzLlxuICovXG5leHBvcnQgY2xhc3MgU3RhdHNSZWNlaXZlZEV2ZW50IGV4dGVuZHMgRXZlbnQge1xuICAgIHJlYWRvbmx5IHR5cGU6ICdzdGF0c1JlY2VpdmVkJztcbiAgICByZWFkb25seSBkYXRhOiB7XG4gICAgICAgIC8qKiBTdGF0aXN0aWNzIG9iamVjdCAqL1xuICAgICAgICBhZ2dyZWdhdGVkU3RhdHM6IEFnZ3JlZ2F0ZWRTdGF0c1xuICAgIH07XG4gICAgY29uc3RydWN0b3IoZGF0YTogU3RhdHNSZWNlaXZlZEV2ZW50WydkYXRhJ10pIHtcbiAgICAgICAgc3VwZXIoJ3N0YXRzUmVjZWl2ZWQnKTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICB9XG59XG5cbi8qKlxuICogQW4gZXZlbnQgdGhhdCBpcyBlbWl0dGVkIHdoZW4gc3RyZWFtZXIgbGlzdCBjaGFuZ2VzLlxuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtZXJMaXN0TWVzc2FnZUV2ZW50IGV4dGVuZHMgRXZlbnQge1xuICAgIHJlYWRvbmx5IHR5cGU6ICdzdHJlYW1lckxpc3RNZXNzYWdlJztcbiAgICByZWFkb25seSBkYXRhOiB7XG4gICAgICAgIC8qKiBTdHJlYW1lciBsaXN0IG1lc3NhZ2UgY29udGFpbmluZyBhbiBhcnJheSBvZiBzdHJlYW1lciBpZHMgKi9cbiAgICAgICAgbWVzc2FnZVN0cmVhbWVyTGlzdDogTWVzc2FnZVN0cmVhbWVyTGlzdDtcbiAgICAgICAgLyoqIEF1dG8tc2VsZWN0ZWQgc3RyZWFtZXIgZnJvbSB0aGUgbGlzdCwgb3IgbnVsbCBpZiB1bmFibGUgdG8gYXV0by1zZWxlY3QgYW5kIHVzZXIgc2hvdWxkIGJlIHByb21wdGVkIHRvIHNlbGVjdCAqL1xuICAgICAgICBhdXRvU2VsZWN0ZWRTdHJlYW1lcklkOiBzdHJpbmc7XG4gICAgICAgIC8qKiBXYW50ZWQgc3RyZWFtZXIgaWQgZnJvbSB2YXJpb3VzIGNvbmZpZ3VyYXRpb25zLiAqL1xuICAgICAgICB3YW50ZWRTdHJlYW1lcklkOiBzdHJpbmc7XG4gICAgfTtcbiAgICBjb25zdHJ1Y3RvcihkYXRhOiBTdHJlYW1lckxpc3RNZXNzYWdlRXZlbnRbJ2RhdGEnXSkge1xuICAgICAgICBzdXBlcignc3RyZWFtZXJMaXN0TWVzc2FnZScpO1xuICAgICAgICB0aGlzLmRhdGEgPSBkYXRhO1xuICAgIH1cbn1cblxuLyoqXG4gKiBBbiBldmVudCB0aGF0IGlzIGVtaXR0ZWQgd2hlbiByZWNlaXZpbmcgbGF0ZW5jeSB0ZXN0IHJlc3VsdHMuXG4gKi9cbmV4cG9ydCBjbGFzcyBMYXRlbmN5VGVzdFJlc3VsdEV2ZW50IGV4dGVuZHMgRXZlbnQge1xuICAgIHJlYWRvbmx5IHR5cGU6ICdsYXRlbmN5VGVzdFJlc3VsdCc7XG4gICAgcmVhZG9ubHkgZGF0YToge1xuICAgICAgICAvKiogTGF0ZW5jeSB0ZXN0IHJlc3VsdCBvYmplY3QgKi9cbiAgICAgICAgbGF0ZW5jeVRpbWluZ3M6IExhdGVuY3lUZXN0UmVzdWx0c1xuICAgIH07XG4gICAgY29uc3RydWN0b3IoZGF0YTogTGF0ZW5jeVRlc3RSZXN1bHRFdmVudFsnZGF0YSddKSB7XG4gICAgICAgIHN1cGVyKCdsYXRlbmN5VGVzdFJlc3VsdCcpO1xuICAgICAgICB0aGlzLmRhdGEgPSBkYXRhO1xuICAgIH1cbn1cblxuLyoqXG4gKiBBbiBldmVudCB0aGF0IGlzIGVtaXR0ZWQgd2hlbiByZWNlaXZpbmcgZGF0YSBjaGFubmVsIGxhdGVuY3kgdGVzdCByZXNwb25zZSBmcm9tIHNlcnZlci5cbiAqIFRoaXMgZXZlbnQgaXMgaGFuZGxlZCBieSBEYXRhQ2hhbm5lbExhdGVuY3lUZXN0Q29udHJvbGxlclxuICovXG5leHBvcnQgY2xhc3MgRGF0YUNoYW5uZWxMYXRlbmN5VGVzdFJlc3BvbnNlRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG4gICAgcmVhZG9ubHkgdHlwZTogJ2RhdGFDaGFubmVsTGF0ZW5jeVRlc3RSZXNwb25zZSc7XG4gICAgcmVhZG9ubHkgZGF0YToge1xuICAgICAgICAvKiogTGF0ZW5jeSB0ZXN0IHJlc3VsdCBvYmplY3QgKi9cbiAgICAgICAgcmVzcG9uc2U6IERhdGFDaGFubmVsTGF0ZW5jeVRlc3RSZXNwb25zZVxuICAgIH07XG4gICAgY29uc3RydWN0b3IoZGF0YTogRGF0YUNoYW5uZWxMYXRlbmN5VGVzdFJlc3BvbnNlRXZlbnRbJ2RhdGEnXSkge1xuICAgICAgICBzdXBlcignZGF0YUNoYW5uZWxMYXRlbmN5VGVzdFJlc3BvbnNlJyk7XG4gICAgICAgIHRoaXMuZGF0YSA9IGRhdGE7XG4gICAgfVxufVxuXG4vKipcbiAqIEFuIGV2ZW50IHRoYXQgaXMgZW1pdHRlZCB3aGVuIGRhdGEgY2hhbm5lbCBsYXRlbmN5IHRlc3QgcmVzdWx0cyBhcmUgcmVhZHkuXG4gKi9cbmV4cG9ydCBjbGFzcyBEYXRhQ2hhbm5lbExhdGVuY3lUZXN0UmVzdWx0RXZlbnQgZXh0ZW5kcyBFdmVudCB7XG4gICAgcmVhZG9ubHkgdHlwZTogJ2RhdGFDaGFubmVsTGF0ZW5jeVRlc3RSZXN1bHQnO1xuICAgIHJlYWRvbmx5IGRhdGE6IHtcbiAgICAgICAgLyoqIExhdGVuY3kgdGVzdCByZXN1bHQgb2JqZWN0ICovXG4gICAgICAgIHJlc3VsdDogRGF0YUNoYW5uZWxMYXRlbmN5VGVzdFJlc3VsdFxuICAgIH07XG4gICAgY29uc3RydWN0b3IoZGF0YTogRGF0YUNoYW5uZWxMYXRlbmN5VGVzdFJlc3VsdEV2ZW50WydkYXRhJ10pIHtcbiAgICAgICAgc3VwZXIoJ2RhdGFDaGFubmVsTGF0ZW5jeVRlc3RSZXN1bHQnKTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICB9XG59XG5cbi8qKlxuICogQW4gZXZlbnQgdGhhdCBpcyBlbWl0dGVkIHdoZW4gcmVjZWl2aW5nIGluaXRpYWwgc2V0dGluZ3MgZnJvbSBVRS5cbiAqL1xuZXhwb3J0IGNsYXNzIEluaXRpYWxTZXR0aW5nc0V2ZW50IGV4dGVuZHMgRXZlbnQge1xuICAgIHJlYWRvbmx5IHR5cGU6ICdpbml0aWFsU2V0dGluZ3MnO1xuICAgIHJlYWRvbmx5IGRhdGE6IHtcbiAgICAgICAgLyoqIEluaXRpYWwgc2V0dGluZ3MgZnJvbSBVRSAqL1xuICAgICAgICBzZXR0aW5nczogSW5pdGlhbFNldHRpbmdzXG4gICAgfTtcbiAgICBjb25zdHJ1Y3RvcihkYXRhOiBJbml0aWFsU2V0dGluZ3NFdmVudFsnZGF0YSddKSB7XG4gICAgICAgIHN1cGVyKCdpbml0aWFsU2V0dGluZ3MnKTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICB9XG59XG5cbmV4cG9ydCB0eXBlIFNldHRpbmdzRGF0YSA9XG4gICAgfCB7XG4gICAgICAgICAgLyoqIEZsYWcgaWQgKi9cbiAgICAgICAgICBpZDogRmxhZ3NJZHM7XG4gICAgICAgICAgdHlwZTogJ2ZsYWcnO1xuICAgICAgICAgIC8qKiBGbGFnIHZhbHVlICovXG4gICAgICAgICAgdmFsdWU6IGJvb2xlYW47XG4gICAgICAgICAgLyoqIFNldHRpbmdGbGFnIG9iamVjdCAqL1xuICAgICAgICAgIHRhcmdldDogU2V0dGluZ0ZsYWc7XG4gICAgICB9XG4gICAgfCB7XG4gICAgICAgICAgLyoqIE51bWVyaWMgc2V0dGluZyBpZCAqL1xuICAgICAgICAgIGlkOiBOdW1lcmljUGFyYW1ldGVyc0lkcztcbiAgICAgICAgICB0eXBlOiAnbnVtYmVyJztcbiAgICAgICAgICAvKiogTnVtZXJpYyBzZXR0aW5nIHZhbHVlICovXG4gICAgICAgICAgdmFsdWU6IG51bWJlcjtcbiAgICAgICAgICAvKiogU2V0dGluZ051bWJlciBvYmplY3QgKi9cbiAgICAgICAgICB0YXJnZXQ6IFNldHRpbmdOdW1iZXI7XG4gICAgICB9XG4gICAgfCB7XG4gICAgICAgICAgLyoqIFRleHQgc2V0dGluZyBpZCAqL1xuICAgICAgICAgIGlkOiBUZXh0UGFyYW1ldGVyc0lkcztcbiAgICAgICAgICB0eXBlOiAndGV4dCc7XG4gICAgICAgICAgLyoqIFRleHQgc2V0dGluZyB2YWx1ZSAqL1xuICAgICAgICAgIHZhbHVlOiBzdHJpbmc7XG4gICAgICAgICAgLyoqIFNldHRpbmdUZXh0IG9iamVjdCAqL1xuICAgICAgICAgIHRhcmdldDogU2V0dGluZ1RleHQ7XG4gICAgICB9XG4gICAgfCB7XG4gICAgICAgICAgLyoqIE9wdGlvbiBzZXR0aW5nIGlkICovXG4gICAgICAgICAgaWQ6IE9wdGlvblBhcmFtZXRlcnNJZHM7XG4gICAgICAgICAgdHlwZTogJ29wdGlvbic7XG4gICAgICAgICAgLyoqIE9wdGlvbiBzZXR0aW5nIHNlbGVjdGVkIHZhbHVlICovXG4gICAgICAgICAgdmFsdWU6IHN0cmluZztcbiAgICAgICAgICAvKiogU2V0dGluZ09wdGlvbiBvYmplY3QgKi9cbiAgICAgICAgICB0YXJnZXQ6IFNldHRpbmdPcHRpb247XG4gICAgICB9O1xuXG4vKipcbiAqIEFuIGV2ZW50IHRoYXQgaXMgZW1pdHRlZCB3aGVuIFBpeGVsU3RyZWFtaW5nIHNldHRpbmdzIGNoYW5nZS5cbiAqL1xuZXhwb3J0IGNsYXNzIFNldHRpbmdzQ2hhbmdlZEV2ZW50IGV4dGVuZHMgRXZlbnQge1xuICAgIHJlYWRvbmx5IHR5cGU6ICdzZXR0aW5nc0NoYW5nZWQnO1xuICAgIHJlYWRvbmx5IGRhdGE6IFNldHRpbmdzRGF0YTtcbiAgICBjb25zdHJ1Y3RvcihkYXRhOiBTZXR0aW5nc0NoYW5nZWRFdmVudFsnZGF0YSddKSB7XG4gICAgICAgIHN1cGVyKCdzZXR0aW5nc0NoYW5nZWQnKTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICB9XG59XG5cbi8qKlxuICogRXZlbnQgZW1pdHRlZCB3aGVuIGFuIFhSIFNlc3Npb24gc3RhcnRzXG4gKi9cbmV4cG9ydCBjbGFzcyBYclNlc3Npb25TdGFydGVkRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG4gICAgcmVhZG9ubHkgdHlwZTogJ3hyU2Vzc2lvblN0YXJ0ZWQnO1xuICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICBzdXBlcigneHJTZXNzaW9uU3RhcnRlZCcpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBFdmVudCBlbWl0dGVkIHdoZW4gYW4gWFIgU2Vzc2lvbiBlbmRzXG4gKi9cbmV4cG9ydCBjbGFzcyBYclNlc3Npb25FbmRlZEV2ZW50IGV4dGVuZHMgRXZlbnQge1xuICAgIHJlYWRvbmx5IHR5cGU6ICd4clNlc3Npb25FbmRlZCc7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKCd4clNlc3Npb25FbmRlZCcpO1xuICAgIH1cbn1cblxuZXhwb3J0IHR5cGUgWHJGcmFtZURhdGEgPSB7XG4gICAgLyoqIFRoZSBmcmFtZSB0aW1lc3RhbXAgICovXG4gICAgdGltZTogRE9NSGlnaFJlc1RpbWVTdGFtcDtcbiAgICAvKiogVGhlIFhSRnJhbWUgKi9cbiAgICBmcmFtZTogWFJGcmFtZTtcbn07XG5cbi8qKlxuICogRXZlbnQgZW1pdHRlZCB3aGVuIGFuIFhSIEZyYW1lIGlzIGNvbXBsZXRlXG4gKi9cbmV4cG9ydCBjbGFzcyBYckZyYW1lRXZlbnQgZXh0ZW5kcyBFdmVudCB7XG4gICAgcmVhZG9ubHkgdHlwZTogJ3hyRnJhbWUnO1xuICAgIHJlYWRvbmx5IGRhdGE6IFhyRnJhbWVEYXRhXG4gICAgY29uc3RydWN0b3IoZGF0YTogWHJGcmFtZUV2ZW50WydkYXRhJ10pIHtcbiAgICAgICAgc3VwZXIoJ3hyRnJhbWUnKTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICB9XG59XG5cbi8qKlxuICogQW4gZXZlbnQgdGhhdCBpcyBlbWl0dGVkIHdoZW4gcmVjZWl2aW5nIGEgcGxheWVyIGNvdW50IGZyb20gdGhlIHNpZ25hbGxpbmcgc2VydmVyXG4gKi9cbmV4cG9ydCBjbGFzcyBQbGF5ZXJDb3VudEV2ZW50IGV4dGVuZHMgRXZlbnQge1xuICAgIHJlYWRvbmx5IHR5cGU6ICdwbGF5ZXJDb3VudCc7XG4gICAgcmVhZG9ubHkgZGF0YToge1xuICAgICAgICAvKiogY291bnQgb2JqZWN0ICovXG4gICAgICAgIGNvdW50OiBudW1iZXJcbiAgICB9O1xuICAgIGNvbnN0cnVjdG9yKGRhdGE6IFBsYXllckNvdW50RXZlbnRbJ2RhdGEnXSkge1xuICAgICAgICBzdXBlcigncGxheWVyQ291bnQnKTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YTtcbiAgICB9XG59XG5cbmV4cG9ydCB0eXBlIFBpeGVsU3RyZWFtaW5nRXZlbnQgPVxuICAgIHwgQWZrV2FybmluZ0FjdGl2YXRlRXZlbnRcbiAgICB8IEFma1dhcm5pbmdVcGRhdGVFdmVudFxuICAgIHwgQWZrV2FybmluZ0RlYWN0aXZhdGVFdmVudFxuICAgIHwgQWZrVGltZWRPdXRFdmVudFxuICAgIHwgVmlkZW9FbmNvZGVyQXZnUVBFdmVudFxuICAgIHwgV2ViUnRjU2RwRXZlbnRcbiAgICB8IFdlYlJ0Y0F1dG9Db25uZWN0RXZlbnRcbiAgICB8IFdlYlJ0Y0Nvbm5lY3RpbmdFdmVudFxuICAgIHwgV2ViUnRjQ29ubmVjdGVkRXZlbnRcbiAgICB8IFdlYlJ0Y0ZhaWxlZEV2ZW50XG4gICAgfCBXZWJSdGNEaXNjb25uZWN0ZWRFdmVudFxuICAgIHwgRGF0YUNoYW5uZWxPcGVuRXZlbnRcbiAgICB8IERhdGFDaGFubmVsQ2xvc2VFdmVudFxuICAgIHwgRGF0YUNoYW5uZWxFcnJvckV2ZW50XG4gICAgfCBWaWRlb0luaXRpYWxpemVkRXZlbnRcbiAgICB8IFN0cmVhbUxvYWRpbmdFdmVudFxuICAgIHwgU3RyZWFtUHJlQ29ubmVjdEV2ZW50XG4gICAgfCBTdHJlYW1SZWNvbm5lY3RFdmVudFxuICAgIHwgU3RyZWFtUHJlRGlzY29ubmVjdEV2ZW50XG4gICAgfCBQbGF5U3RyZWFtRXJyb3JFdmVudFxuICAgIHwgUGxheVN0cmVhbUV2ZW50XG4gICAgfCBQbGF5U3RyZWFtUmVqZWN0ZWRFdmVudFxuICAgIHwgTG9hZEZyZWV6ZUZyYW1lRXZlbnRcbiAgICB8IEhpZGVGcmVlemVGcmFtZUV2ZW50XG4gICAgfCBTdGF0c1JlY2VpdmVkRXZlbnRcbiAgICB8IFN0cmVhbWVyTGlzdE1lc3NhZ2VFdmVudFxuICAgIHwgTGF0ZW5jeVRlc3RSZXN1bHRFdmVudFxuICAgIHwgRGF0YUNoYW5uZWxMYXRlbmN5VGVzdFJlc3BvbnNlRXZlbnRcbiAgICB8IERhdGFDaGFubmVsTGF0ZW5jeVRlc3RSZXN1bHRFdmVudFxuICAgIHwgSW5pdGlhbFNldHRpbmdzRXZlbnRcbiAgICB8IFNldHRpbmdzQ2hhbmdlZEV2ZW50XG4gICAgfCBYclNlc3Npb25TdGFydGVkRXZlbnRcbiAgICB8IFhyU2Vzc2lvbkVuZGVkRXZlbnRcbiAgICB8IFhyRnJhbWVFdmVudFxuICAgIHwgUGxheWVyQ291bnRFdmVudDtcblxuZXhwb3J0IGNsYXNzIEV2ZW50RW1pdHRlciBleHRlbmRzIEV2ZW50VGFyZ2V0IHtcbiAgICAvKipcbiAgICAgKiBEaXNwYXRjaCBhIG5ldyBldmVudC5cbiAgICAgKiBAcGFyYW0gZSBldmVudFxuICAgICAqIEByZXR1cm5zXG4gICAgICovXG4gICAgcHVibGljIGRpc3BhdGNoRXZlbnQoZTogUGl4ZWxTdHJlYW1pbmdFdmVudCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gc3VwZXIuZGlzcGF0Y2hFdmVudChlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZWdpc3RlciBhbiBldmVudCBoYW5kbGVyLlxuICAgICAqIEBwYXJhbSB0eXBlIGV2ZW50IG5hbWVcbiAgICAgKiBAcGFyYW0gbGlzdGVuZXIgZXZlbnQgaGFuZGxlciBmdW5jdGlvblxuICAgICAqL1xuICAgIHB1YmxpYyBhZGRFdmVudExpc3RlbmVyPFxuICAgICAgICBUIGV4dGVuZHMgUGl4ZWxTdHJlYW1pbmdFdmVudFsndHlwZSddLFxuICAgICAgICBFIGV4dGVuZHMgUGl4ZWxTdHJlYW1pbmdFdmVudCAmIHsgdHlwZTogVCB9XG4gICAgPih0eXBlOiBULCBsaXN0ZW5lcjogKGU6IEV2ZW50ICYgRSkgPT4gdm9pZCkge1xuICAgICAgICBzdXBlci5hZGRFdmVudExpc3RlbmVyKHR5cGUsIGxpc3RlbmVyKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgYW4gZXZlbnQgaGFuZGxlci5cbiAgICAgKiBAcGFyYW0gdHlwZSBldmVudCBuYW1lXG4gICAgICogQHBhcmFtIGxpc3RlbmVyIGV2ZW50IGhhbmRsZXIgZnVuY3Rpb25cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVtb3ZlRXZlbnRMaXN0ZW5lcjxcbiAgICAgICAgVCBleHRlbmRzIFBpeGVsU3RyZWFtaW5nRXZlbnRbJ3R5cGUnXSxcbiAgICAgICAgRSBleHRlbmRzIFBpeGVsU3RyZWFtaW5nRXZlbnQgJiB7IHR5cGU6IFQgfVxuICAgID4odHlwZTogVCwgbGlzdGVuZXI6IChlOiBFdmVudCAmIEUpID0+IHZvaWQpIHtcbiAgICAgICAgc3VwZXIucmVtb3ZlRXZlbnRMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcik7XG4gICAgfVxufVxuIiwiLy8gQ29weXJpZ2h0IEVwaWMgR2FtZXMsIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cblxuZXhwb3J0IHR5cGUgVW5yZWdpc3RlckZ1bmN0aW9uID0gKCkgPT4gdm9pZDtcblxuZXhwb3J0IGNsYXNzIEV2ZW50TGlzdGVuZXJUcmFja2VyIHtcbiAgICBwcml2YXRlIHVucmVnaXN0ZXJDYWxsYmFja3M6IFVucmVnaXN0ZXJGdW5jdGlvbltdO1xuXG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMudW5yZWdpc3RlckNhbGxiYWNrcyA9IFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZCBhIG5ldyBjYWxsYmFjayB0aGF0IGlzIGV4ZWN1dGVkIHdoZW4gdW5yZWdpc3RlckFsbCBpcyBjYWxsZWQuXG4gICAgICogQHBhcmFtIGNhbGxiYWNrIFxuICAgICAqL1xuICAgIGFkZFVucmVnaXN0ZXJDYWxsYmFjayhjYWxsYmFjazogVW5yZWdpc3RlckZ1bmN0aW9uKSB7XG4gICAgICAgIHRoaXMudW5yZWdpc3RlckNhbGxiYWNrcy5wdXNoKGNhbGxiYWNrKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFeGVjdXRlIGFsbCBjYWxsYmFja3MgYW5kIGNsZWFyIHRoZSBsaXN0LlxuICAgICAqL1xuICAgIHVucmVnaXN0ZXJBbGwoKSB7XG4gICAgICAgIGZvciAoY29uc3QgY2FsbGJhY2sgb2YgdGhpcy51bnJlZ2lzdGVyQ2FsbGJhY2tzKSB7XG4gICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMudW5yZWdpc3RlckNhbGxiYWNrcyA9IFtdO1xuICAgIH1cbn1cbiIsIi8vIENvcHlyaWdodCBFcGljIEdhbWVzLCBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG5cbmltcG9ydCB7IExvZ2dlciB9IGZyb20gJy4uL0xvZ2dlci9Mb2dnZXInO1xuXG4vKipcbiAqIFV0aWxpdHkgZnVuY3Rpb24gZm9yIHBvcHVsYXRlIGZpbGUgaW5mb3JtYXRpb24gZnJvbSBieXRlIGJ1ZmZlcnMuXG4gKi9cbmV4cG9ydCBjbGFzcyBGaWxlVXRpbCB7XG4gICAgLyoqXG4gICAgICogUHJvY2Vzc2VzIGEgZmlsZXMgZXh0ZW5zaW9uIHdoZW4gcmVjZWl2ZWQgb3ZlciBkYXRhIGNoYW5uZWxcbiAgICAgKiBAcGFyYW0gdmlldyAtIHRoZSBmaWxlIGV4dGVuc2lvbiBkYXRhXG4gICAgICovXG4gICAgc3RhdGljIHNldEV4dGVuc2lvbkZyb21CeXRlcyh2aWV3OiBVaW50OEFycmF5LCBmaWxlOiBGaWxlVGVtcGxhdGUpIHtcbiAgICAgICAgLy8gUmVzZXQgZmlsZSBpZiB3ZSBnb3QgYSBmaWxlIG1lc3NhZ2UgYW5kIHdlIGFyZSBub3QgXCJyZWNlaXZpbmdcIiBpdCB5ZXRcbiAgICAgICAgaWYgKCFmaWxlLnJlY2VpdmluZykge1xuICAgICAgICAgICAgZmlsZS5taW1ldHlwZSA9ICcnO1xuICAgICAgICAgICAgZmlsZS5leHRlbnNpb24gPSAnJztcbiAgICAgICAgICAgIGZpbGUucmVjZWl2aW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIGZpbGUudmFsaWQgPSBmYWxzZTtcbiAgICAgICAgICAgIGZpbGUuc2l6ZSA9IDA7XG4gICAgICAgICAgICBmaWxlLmRhdGEgPSBbXTtcbiAgICAgICAgICAgIGZpbGUudGltZXN0YW1wU3RhcnQgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcbiAgICAgICAgICAgIExvZ2dlci5Mb2coXG4gICAgICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICAgICAnUmVjZWl2ZWQgZmlyc3QgY2h1bmsgb2YgZmlsZScsXG4gICAgICAgICAgICAgICAgNlxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGV4dGVuc2lvbkFzU3RyaW5nID0gbmV3IFRleHREZWNvZGVyKCd1dGYtMTYnKS5kZWNvZGUoXG4gICAgICAgICAgICB2aWV3LnNsaWNlKDEpXG4gICAgICAgICk7XG4gICAgICAgIExvZ2dlci5Mb2coTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSwgZXh0ZW5zaW9uQXNTdHJpbmcsIDYpO1xuICAgICAgICBmaWxlLmV4dGVuc2lvbiA9IGV4dGVuc2lvbkFzU3RyaW5nO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFByb2Nlc3NlcyBhIGZpbGVzIG1pbWUgdHlwZSB3aGVuIHJlY2VpdmVkIG92ZXIgZGF0YSBjaGFubmVsXG4gICAgICogQHBhcmFtIHZpZXcgLSB0aGUgZmlsZSBtaW1lIHR5cGUgZGF0YVxuICAgICAqL1xuICAgIHN0YXRpYyBzZXRNaW1lVHlwZUZyb21CeXRlcyh2aWV3OiBVaW50OEFycmF5LCBmaWxlOiBGaWxlVGVtcGxhdGUpIHtcbiAgICAgICAgLy8gUmVzZXQgZmlsZSBpZiB3ZSBnb3QgYSBmaWxlIG1lc3NhZ2UgYW5kIHdlIGFyZSBub3QgXCJyZWNlaXZpbmdcIiBpdCB5ZXRcbiAgICAgICAgaWYgKCFmaWxlLnJlY2VpdmluZykge1xuICAgICAgICAgICAgZmlsZS5taW1ldHlwZSA9ICcnO1xuICAgICAgICAgICAgZmlsZS5leHRlbnNpb24gPSAnJztcbiAgICAgICAgICAgIGZpbGUucmVjZWl2aW5nID0gdHJ1ZTtcbiAgICAgICAgICAgIGZpbGUudmFsaWQgPSBmYWxzZTtcbiAgICAgICAgICAgIGZpbGUuc2l6ZSA9IDA7XG4gICAgICAgICAgICBmaWxlLmRhdGEgPSBbXTtcbiAgICAgICAgICAgIGZpbGUudGltZXN0YW1wU3RhcnQgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcbiAgICAgICAgICAgIExvZ2dlci5Mb2coXG4gICAgICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICAgICAnUmVjZWl2ZWQgZmlyc3QgY2h1bmsgb2YgZmlsZScsXG4gICAgICAgICAgICAgICAgNlxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IG1pbWVBc1N0cmluZyA9IG5ldyBUZXh0RGVjb2RlcigndXRmLTE2JykuZGVjb2RlKHZpZXcuc2xpY2UoMSkpO1xuICAgICAgICBMb2dnZXIuTG9nKExvZ2dlci5HZXRTdGFja1RyYWNlKCksIG1pbWVBc1N0cmluZywgNik7XG4gICAgICAgIGZpbGUubWltZXR5cGUgPSBtaW1lQXNTdHJpbmc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUHJvY2Vzc2VzIGEgZmlsZXMgY29udGVudHMgd2hlbiByZWNlaXZlZCBvdmVyIGRhdGEgY2hhbm5lbFxuICAgICAqIEBwYXJhbSB2aWV3IC0gdGhlIGZpbGUgY29udGVudHMgZGF0YVxuICAgICAqL1xuICAgIHN0YXRpYyBzZXRDb250ZW50c0Zyb21CeXRlcyh2aWV3OiBVaW50OEFycmF5LCBmaWxlOiBGaWxlVGVtcGxhdGUpIHtcbiAgICAgICAgLy8gSWYgd2UgaGF2ZW4ndCByZWNlaXZlZCB0aGUgaW5pdGlhbCBzZXR1cCBpbnN0cnVjdGlvbnMsIHJldHVyblxuICAgICAgICBpZiAoIWZpbGUucmVjZWl2aW5nKSByZXR1cm47XG5cbiAgICAgICAgLy8gRXh0cmFjdCB0aGUgdG90YWwgc2l6ZSBvZiB0aGUgZmlsZSAoYWNyb3NzIGFsbCBjaHVua3MpXG4gICAgICAgIGZpbGUuc2l6ZSA9IE1hdGguY2VpbChcbiAgICAgICAgICAgIG5ldyBEYXRhVmlldyh2aWV3LnNsaWNlKDEsIDUpLmJ1ZmZlcikuZ2V0SW50MzIoMCwgdHJ1ZSkgL1xuICAgICAgICAgICAgICAgIDE2Mzc5IC8qIFRoZSBtYXhpbXVtIG51bWJlciBvZiBwYXlsb2FkIGJpdHMgcGVyIG1lc3NhZ2UqL1xuICAgICAgICApO1xuXG4gICAgICAgIC8vIEdldCB0aGUgZmlsZSBwYXJ0IG9mIHRoZSBwYXlsb2FkXG4gICAgICAgIGNvbnN0IGZpbGVCeXRlcyA9IHZpZXcuc2xpY2UoMSArIDQpO1xuXG4gICAgICAgIC8vIEFwcGVuZCB0byBleGlzdGluZyBkYXRhIHRoYXQgaG9sZHMgdGhlIGZpbGVcbiAgICAgICAgZmlsZS5kYXRhLnB1c2goZmlsZUJ5dGVzKTtcblxuICAgICAgICAvLyBVbmNvbW1lbnQgZm9yIGRlYnVnXG4gICAgICAgIExvZ2dlci5Mb2coXG4gICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgYFJlY2VpdmVkIGZpbGUgY2h1bms6ICR7ZmlsZS5kYXRhLmxlbmd0aH0vJHtmaWxlLnNpemV9YCxcbiAgICAgICAgICAgIDZcbiAgICAgICAgKTtcblxuICAgICAgICBpZiAoZmlsZS5kYXRhLmxlbmd0aCA9PT0gZmlsZS5zaXplKSB7XG4gICAgICAgICAgICBmaWxlLnJlY2VpdmluZyA9IGZhbHNlO1xuICAgICAgICAgICAgZmlsZS52YWxpZCA9IHRydWU7XG4gICAgICAgICAgICBMb2dnZXIuTG9nKExvZ2dlci5HZXRTdGFja1RyYWNlKCksICdSZWNlaXZlZCBjb21wbGV0ZSBmaWxlJywgNik7XG4gICAgICAgICAgICBjb25zdCB0cmFuc2ZlckR1cmF0aW9uID0gbmV3IERhdGUoKS5nZXRUaW1lKCkgLSBmaWxlLnRpbWVzdGFtcFN0YXJ0O1xuICAgICAgICAgICAgY29uc3QgdHJhbnNmZXJCaXRyYXRlID0gTWF0aC5yb3VuZChcbiAgICAgICAgICAgICAgICAoZmlsZS5zaXplICogMTYgKiAxMDI0KSAvIHRyYW5zZmVyRHVyYXRpb25cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBMb2dnZXIuTG9nKFxuICAgICAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAgICAgYEF2ZXJhZ2UgdHJhbnNmZXIgYml0cmF0ZTogJHt0cmFuc2ZlckJpdHJhdGV9a2IvcyBvdmVyICR7XG4gICAgICAgICAgICAgICAgICAgIHRyYW5zZmVyRHVyYXRpb24gLyAxMDAwXG4gICAgICAgICAgICAgICAgfSBzZWNvbmRzYCxcbiAgICAgICAgICAgICAgICA2XG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAvLyBGaWxlIHJlY29uc3RydWN0aW9uXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEV4YW1wbGUgY29kZSB0byByZWNvbnN0cnVjdCB0aGUgZmlsZVxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIFRoaXMgY29kZSByZWNvbnN0cnVjdHMgdGhlIHJlY2VpdmVkIGRhdGEgaW50byB0aGUgb3JpZ2luYWwgZmlsZSBiYXNlZCBvbiB0aGUgbWltZSB0eXBlIGFuZCBleHRlbnNpb24gcHJvdmlkZWQgYW5kIHRoZW4gZG93bmxvYWRzIHRoZSByZWNvbnN0cnVjdGVkIGZpbGVcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgY29uc3QgcmVjZWl2ZWQgPSBuZXcgQmxvYihmaWxlLmRhdGEsIHsgdHlwZTogZmlsZS5taW1ldHlwZSB9KTtcbiAgICAgICAgICAgIGNvbnN0IGEgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdhJyk7XG4gICAgICAgICAgICBhLnNldEF0dHJpYnV0ZSgnaHJlZicsIFVSTC5jcmVhdGVPYmplY3RVUkwocmVjZWl2ZWQpKTtcbiAgICAgICAgICAgIGEuc2V0QXR0cmlidXRlKCdkb3dubG9hZCcsIGB0cmFuc2Zlci4ke2ZpbGUuZXh0ZW5zaW9ufWApO1xuICAgICAgICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmQoYSk7XG4gICAgICAgICAgICAvLyBpZiB5b3UgYXJlIHNvIGluY2xpbmVkIHRvIG1ha2UgaXQgYXV0by1kb3dubG9hZCwgZG8gc29tZXRoaW5nIGxpa2U6IGEuY2xpY2soKTtcbiAgICAgICAgICAgIGEucmVtb3ZlKCk7XG4gICAgICAgIH0gZWxzZSBpZiAoZmlsZS5kYXRhLmxlbmd0aCA+IGZpbGUuc2l6ZSkge1xuICAgICAgICAgICAgZmlsZS5yZWNlaXZpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgIExvZ2dlci5FcnJvcihcbiAgICAgICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgICAgIGBSZWNlaXZlZCBiaWdnZXIgZmlsZSB0aGFuIGFkdmVydGlzZWQ6ICR7ZmlsZS5kYXRhLmxlbmd0aH0vJHtmaWxlLnNpemV9YFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuLyoqXG4gKiBBIGNsYXNzIHRoYXQgcmVwcmVzZW50cyBhIHRlbXBsYXRlIGZvciBhIGRvd25sb2FkZWQgZmlsZVxuICovXG5leHBvcnQgY2xhc3MgRmlsZVRlbXBsYXRlIHtcbiAgICBtaW1ldHlwZSA9ICcnO1xuICAgIGV4dGVuc2lvbiA9ICcnO1xuICAgIHJlY2VpdmluZyA9IGZhbHNlO1xuICAgIHNpemUgPSAwO1xuICAgIGRhdGE6IEFycmF5PFVpbnQ4QXJyYXk+ID0gW107XG4gICAgdmFsaWQgPSBmYWxzZTtcbiAgICB0aW1lc3RhbXBTdGFydDogbnVtYmVyO1xufVxuIiwiZXhwb3J0IGNsYXNzIFJUQ1V0aWxzIHtcbiAgICBzdGF0aWMgaXNWaWRlb1RyYW5zY2lldmVyKHRyYW5zY2VpdmVyIDogUlRDUnRwVHJhbnNjZWl2ZXIgfCB1bmRlZmluZWQpIDogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLmNhblRyYW5zY2VpdmVyUmVjZWl2ZVZpZGVvKHRyYW5zY2VpdmVyKSB8fCB0aGlzLmNhblRyYW5zY2VpdmVyU2VuZFZpZGVvKHRyYW5zY2VpdmVyKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY2FuVHJhbnNjZWl2ZXJSZWNlaXZlVmlkZW8odHJhbnNjZWl2ZXIgOiBSVENSdHBUcmFuc2NlaXZlciB8IHVuZGVmaW5lZCkgOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICEhdHJhbnNjZWl2ZXIgJiZcbiAgICAgICAgICAgICh0cmFuc2NlaXZlci5kaXJlY3Rpb24gPT09ICdzZW5kcmVjdicgfHwgdHJhbnNjZWl2ZXIuZGlyZWN0aW9uID09PSAncmVjdm9ubHknKSAmJlxuICAgICAgICAgICAgdHJhbnNjZWl2ZXIucmVjZWl2ZXIgJiZcbiAgICAgICAgICAgIHRyYW5zY2VpdmVyLnJlY2VpdmVyLnRyYWNrICYmXG4gICAgICAgICAgICB0cmFuc2NlaXZlci5yZWNlaXZlci50cmFjay5raW5kID09PSAndmlkZW8nOyAgICBcbiAgICB9XG5cbiAgICBzdGF0aWMgY2FuVHJhbnNjZWl2ZXJTZW5kVmlkZW8odHJhbnNjZWl2ZXIgOiBSVENSdHBUcmFuc2NlaXZlciB8IHVuZGVmaW5lZCkgOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICEhdHJhbnNjZWl2ZXIgJiZcbiAgICAgICAgICAgICh0cmFuc2NlaXZlci5kaXJlY3Rpb24gPT09ICdzZW5kcmVjdicgfHwgdHJhbnNjZWl2ZXIuZGlyZWN0aW9uID09PSAnc2VuZG9ubHknKSAmJlxuICAgICAgICAgICAgdHJhbnNjZWl2ZXIuc2VuZGVyICYmXG4gICAgICAgICAgICB0cmFuc2NlaXZlci5zZW5kZXIudHJhY2sgJiZcbiAgICAgICAgICAgIHRyYW5zY2VpdmVyLnNlbmRlci50cmFjay5raW5kID09PSAndmlkZW8nOyAgICBcbiAgICB9XG5cbiAgICBzdGF0aWMgaXNBdWRpb1RyYW5zY2lldmVyKHRyYW5zY2VpdmVyIDogUlRDUnRwVHJhbnNjZWl2ZXIgfCB1bmRlZmluZWQpIDogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLmNhblRyYW5zY2VpdmVyUmVjZWl2ZUF1ZGlvKHRyYW5zY2VpdmVyKSB8fCB0aGlzLmNhblRyYW5zY2VpdmVyU2VuZEF1ZGlvKHRyYW5zY2VpdmVyKTtcbiAgICB9XG5cbiAgICBzdGF0aWMgY2FuVHJhbnNjZWl2ZXJSZWNlaXZlQXVkaW8odHJhbnNjZWl2ZXIgOiBSVENSdHBUcmFuc2NlaXZlciB8IHVuZGVmaW5lZCkgOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICEhdHJhbnNjZWl2ZXIgJiZcbiAgICAgICAgICAgICh0cmFuc2NlaXZlci5kaXJlY3Rpb24gPT09ICdzZW5kcmVjdicgfHwgdHJhbnNjZWl2ZXIuZGlyZWN0aW9uID09PSAncmVjdm9ubHknKSAmJlxuICAgICAgICAgICAgdHJhbnNjZWl2ZXIucmVjZWl2ZXIgJiZcbiAgICAgICAgICAgIHRyYW5zY2VpdmVyLnJlY2VpdmVyLnRyYWNrICYmXG4gICAgICAgICAgICB0cmFuc2NlaXZlci5yZWNlaXZlci50cmFjay5raW5kID09PSAnYXVkaW8nOyAgICBcbiAgICB9XG5cbiAgICBzdGF0aWMgY2FuVHJhbnNjZWl2ZXJTZW5kQXVkaW8odHJhbnNjZWl2ZXIgOiBSVENSdHBUcmFuc2NlaXZlciB8IHVuZGVmaW5lZCkgOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICEhdHJhbnNjZWl2ZXIgJiZcbiAgICAgICAgICAgICh0cmFuc2NlaXZlci5kaXJlY3Rpb24gPT09ICdzZW5kcmVjdicgfHwgdHJhbnNjZWl2ZXIuZGlyZWN0aW9uID09PSAnc2VuZG9ubHknKSAmJlxuICAgICAgICAgICAgdHJhbnNjZWl2ZXIuc2VuZGVyICYmXG4gICAgICAgICAgICB0cmFuc2NlaXZlci5zZW5kZXIudHJhY2sgJiZcbiAgICAgICAgICAgIHRyYW5zY2VpdmVyLnNlbmRlci50cmFjay5raW5kID09PSAnYXVkaW8nO1xuICAgIH1cbn0iLCIvLyBDb3B5cmlnaHQgRXBpYyBHYW1lcywgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuXG5leHBvcnQgY2xhc3MgV2ViR0xVdGlscyB7XG4gICAgc3RhdGljIHZlcnRleFNoYWRlcigpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gYFxuXHRcdGF0dHJpYnV0ZSB2ZWMyIGFfcG9zaXRpb247XG5cdFx0YXR0cmlidXRlIHZlYzIgYV90ZXhDb29yZDtcblxuXHRcdC8vIGlucHV0XG5cdFx0dW5pZm9ybSB2ZWMyIHVfcmVzb2x1dGlvbjtcblx0XHR1bmlmb3JtIHZlYzQgdV9vZmZzZXQ7XG5cblx0XHQvL1xuXHRcdHZhcnlpbmcgdmVjMiB2X3RleENvb3JkO1xuXG5cdFx0dm9pZCBtYWluKCkge1xuXHRcdCAgIC8vIGNvbnZlcnQgdGhlIHJlY3RhbmdsZSBmcm9tIHBpeGVscyB0byAwLjAgdG8gMS4wXG5cdFx0ICAgdmVjMiB6ZXJvVG9PbmUgPSBhX3Bvc2l0aW9uIC8gdV9yZXNvbHV0aW9uO1xuXG5cdFx0ICAgLy8gY29udmVydCBmcm9tIDAtPjEgdG8gMC0+MlxuXHRcdCAgIHZlYzIgemVyb1RvVHdvID0gemVyb1RvT25lICogMi4wO1xuXG5cdFx0ICAgLy8gY29udmVydCBmcm9tIDAtPjIgdG8gLTEtPisxIChjbGlwc3BhY2UpXG5cdFx0ICAgdmVjMiBjbGlwU3BhY2UgPSB6ZXJvVG9Ud28gLSAxLjA7XG5cblx0XHQgICBnbF9Qb3NpdGlvbiA9IHZlYzQoY2xpcFNwYWNlICogdmVjMigxLCAtMSksIDAsIDEpO1xuXHRcdCAgIC8vIHBhc3MgdGhlIHRleENvb3JkIHRvIHRoZSBmcmFnbWVudCBzaGFkZXJcblx0XHQgICAvLyBUaGUgR1BVIHdpbGwgaW50ZXJwb2xhdGUgdGhpcyB2YWx1ZSBiZXR3ZWVuIHBvaW50cy5cblx0XHQgICB2X3RleENvb3JkID0gKGFfdGV4Q29vcmQgKiB1X29mZnNldC54eSkgKyB1X29mZnNldC56dztcblx0XHR9XG5cdFx0YDtcbiAgICB9XG5cbiAgICBzdGF0aWMgZnJhZ21lbnRTaGFkZXIoKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIGBcblx0XHRwcmVjaXNpb24gbWVkaXVtcCBmbG9hdDtcblxuXHRcdC8vIG91ciB0ZXh0dXJlXG5cdFx0dW5pZm9ybSBzYW1wbGVyMkQgdV9pbWFnZTtcblxuXHRcdC8vIHRoZSB0ZXhDb29yZHMgcGFzc2VkIGluIGZyb20gdGhlIHZlcnRleCBzaGFkZXIuXG5cdFx0dmFyeWluZyB2ZWMyIHZfdGV4Q29vcmQ7XG5cblx0XHR2b2lkIG1haW4oKSB7XG5cdFx0ICAgZ2xfRnJhZ0NvbG9yID0gdGV4dHVyZTJEKHVfaW1hZ2UsIHZfdGV4Q29vcmQpO1xuXHRcdH1cblx0XHRgO1xuICAgIH1cbn1cbiIsIi8vIENvcHlyaWdodCBFcGljIEdhbWVzLCBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG5cbmV4cG9ydCBjbGFzcyBXZWJYUlV0aWxzIHtcbiAgICAvKipcbiAgICAgKiBEZWVwIGNvcGllcyBhIGdhbWVwYWQncyB2YWx1ZXMgYnkgZmlyc3QgY29udmVydGluZyBpdCB0byBhIEpTT04gb2JqZWN0IGFuZCB0aGVuIGJhY2sgdG8gYSBnYW1lcGFkXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZ2FtZXBhZCB0aGUgb3JpZ2luYWwgZ2FtZXBhZFxuICAgICAqIEByZXR1cm5zIGEgbmV3IGdhbWVwYWQgb2JqZWN0LCBwb3B1bGF0ZWQgd2l0aCB0aGUgb3JpZ2luYWwgZ2FtZXBhZHMgdmFsdWVzXG4gICAgICovXG4gICAgc3RhdGljIGRlZXBDb3B5R2FtZXBhZChnYW1lcGFkOiBHYW1lcGFkKTogR2FtZXBhZCB7XG4gICAgICAgIHJldHVybiBKU09OLnBhcnNlKFxuICAgICAgICAgICAgSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgICAgIGJ1dHRvbnM6IGdhbWVwYWQuYnV0dG9ucy5tYXAoKGIpID0+XG4gICAgICAgICAgICAgICAgICAgIEpTT04ucGFyc2UoXG4gICAgICAgICAgICAgICAgICAgICAgICBKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlc3NlZDogYi5wcmVzc2VkLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvdWNoZWQ6IGIudG91Y2hlZFxuICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgYXhlczogZ2FtZXBhZC5heGVzXG4gICAgICAgICAgICB9KVxuICAgICAgICApO1xuICAgIH1cbn1cbiIsIi8vIENvcHlyaWdodCBFcGljIEdhbWVzLCBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG5cbmltcG9ydCB7IE1vdXNlQ29udHJvbGxlciB9IGZyb20gJy4uL0lucHV0cy9Nb3VzZUNvbnRyb2xsZXInO1xuaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSAnLi4vTG9nZ2VyL0xvZ2dlcic7XG5pbXBvcnQgeyBWaWRlb1BsYXllciB9IGZyb20gJy4vVmlkZW9QbGF5ZXInO1xuXG4vKipcbiAqIFZpZGVvIFBsYXllciBDb250cm9sbGVyIGhhbmRsZXMgdGhlIGNyZWF0aW9uIG9mIHRoZSB2aWRlbyBIVE1MIGVsZW1lbnQgYW5kIGFsbCBoYW5kbGVyc1xuICovXG5leHBvcnQgY2xhc3MgU3RyZWFtQ29udHJvbGxlciB7XG4gICAgdmlkZW9FbGVtZW50UHJvdmlkZXI6IFZpZGVvUGxheWVyO1xuICAgIGF1ZGlvRWxlbWVudDogSFRNTEF1ZGlvRWxlbWVudDtcbiAgICBtb3VzZUNvbnRyb2xsZXI6IE1vdXNlQ29udHJvbGxlcjtcblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB2aWRlb0VsZW1lbnRQcm92aWRlciBWaWRlbyBQbGF5ZXIgaW5zdGFuY2VcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcih2aWRlb0VsZW1lbnRQcm92aWRlcjogVmlkZW9QbGF5ZXIpIHtcbiAgICAgICAgdGhpcy52aWRlb0VsZW1lbnRQcm92aWRlciA9IHZpZGVvRWxlbWVudFByb3ZpZGVyO1xuICAgICAgICB0aGlzLmF1ZGlvRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ0F1ZGlvJykgYXMgSFRNTEF1ZGlvRWxlbWVudDtcbiAgICAgICAgdGhpcy52aWRlb0VsZW1lbnRQcm92aWRlci5zZXRBdWRpb0VsZW1lbnQodGhpcy5hdWRpb0VsZW1lbnQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXMgd2hlbiB0aGUgUGVlciBjb25uZWN0aW9uIGhhcyBhIHRyYWNrIGV2ZW50XG4gICAgICogQHBhcmFtIHJ0Y1RyYWNrRXZlbnQgLSBSVEMgVHJhY2sgRXZlbnRcbiAgICAgKi9cbiAgICBoYW5kbGVPblRyYWNrKHJ0Y1RyYWNrRXZlbnQ6IFJUQ1RyYWNrRXZlbnQpIHtcbiAgICAgICAgTG9nZ2VyLkxvZyhcbiAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAnaGFuZGxlT25UcmFjayAnICsgSlNPTi5zdHJpbmdpZnkocnRjVHJhY2tFdmVudC5zdHJlYW1zKSxcbiAgICAgICAgICAgIDZcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgdmlkZW9FbGVtZW50ID0gdGhpcy52aWRlb0VsZW1lbnRQcm92aWRlci5nZXRWaWRlb0VsZW1lbnQoKTtcblxuICAgICAgICBpZiAocnRjVHJhY2tFdmVudC50cmFjaykge1xuICAgICAgICAgICAgTG9nZ2VyLkxvZyhcbiAgICAgICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgICAgICdHb3QgdHJhY2sgLSAnICtcbiAgICAgICAgICAgICAgICAgICAgcnRjVHJhY2tFdmVudC50cmFjay5raW5kICtcbiAgICAgICAgICAgICAgICAgICAgJyBpZD0nICtcbiAgICAgICAgICAgICAgICAgICAgcnRjVHJhY2tFdmVudC50cmFjay5pZCArXG4gICAgICAgICAgICAgICAgICAgICcgcmVhZHlTdGF0ZT0nICtcbiAgICAgICAgICAgICAgICAgICAgcnRjVHJhY2tFdmVudC50cmFjay5yZWFkeVN0YXRlLFxuICAgICAgICAgICAgICAgIDZcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocnRjVHJhY2tFdmVudC50cmFjay5raW5kID09ICdhdWRpbycpIHtcbiAgICAgICAgICAgIHRoaXMuQ3JlYXRlQXVkaW9UcmFjayhydGNUcmFja0V2ZW50LnN0cmVhbXNbMF0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9IGVsc2UgaWYgKFxuICAgICAgICAgICAgcnRjVHJhY2tFdmVudC50cmFjay5raW5kID09ICd2aWRlbycgJiZcbiAgICAgICAgICAgIHZpZGVvRWxlbWVudC5zcmNPYmplY3QgIT09IHJ0Y1RyYWNrRXZlbnQuc3RyZWFtc1swXVxuICAgICAgICApIHtcbiAgICAgICAgICAgIHZpZGVvRWxlbWVudC5zcmNPYmplY3QgPSBydGNUcmFja0V2ZW50LnN0cmVhbXNbMF07XG4gICAgICAgICAgICBMb2dnZXIuTG9nKFxuICAgICAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAgICAgJ1NldCB2aWRlbyBzb3VyY2UgZnJvbSB2aWRlbyB0cmFjayBvbnRyYWNrLidcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIHRoZSBhdWRpbyBkZXZpY2Ugd2hlbiByZWNlaXZpbmcgYW4gUlRDVHJhY2tFdmVudCB3aXRoIHRoZSBraW5kIG9mIFwiYXVkaW9cIlxuICAgICAqIEBwYXJhbSBhdWRpb01lZGlhU3RyZWFtIC0gQXVkaW8gTWVkaWEgc3RyZWFtIHRyYWNrXG4gICAgICovXG4gICAgQ3JlYXRlQXVkaW9UcmFjayhhdWRpb01lZGlhU3RyZWFtOiBNZWRpYVN0cmVhbSkge1xuICAgICAgICBjb25zdCB2aWRlb0VsZW1lbnQgPSB0aGlzLnZpZGVvRWxlbWVudFByb3ZpZGVyLmdldFZpZGVvRWxlbWVudCgpO1xuXG4gICAgICAgIC8vIGRvIG5vdGhpbmcgdGhlIHZpZGVvIGhhcyB0aGUgc2FtZSBtZWRpYSBzdHJlYW0gYXMgdGhlIGF1ZGlvIHRyYWNrIHdlIGhhdmUgaGVyZSAodGhleSBhcmUgbGlua2VkKVxuICAgICAgICBpZiAodmlkZW9FbGVtZW50LnNyY09iamVjdCA9PSBhdWRpb01lZGlhU3RyZWFtKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgLy8gdmlkZW8gZWxlbWVudCBoYXMgc29tZSBvdGhlciBtZWRpYSBzdHJlYW0gdGhhdCBpcyBub3QgYXNzb2NpYXRlZCB3aXRoIHRoaXMgYXVkaW8gdHJhY2tcbiAgICAgICAgZWxzZSBpZiAoXG4gICAgICAgICAgICB2aWRlb0VsZW1lbnQuc3JjT2JqZWN0ICYmXG4gICAgICAgICAgICB2aWRlb0VsZW1lbnQuc3JjT2JqZWN0ICE9PSBhdWRpb01lZGlhU3RyZWFtXG4gICAgICAgICkge1xuICAgICAgICAgICAgLy8gY3JlYXRlIGEgbmV3IGF1ZGlvIGVsZW1lbnRcbiAgICAgICAgICAgIHRoaXMuYXVkaW9FbGVtZW50LnNyY09iamVjdCA9IGF1ZGlvTWVkaWFTdHJlYW07XG4gICAgICAgICAgICBMb2dnZXIuTG9nKFxuICAgICAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAgICAgJ0NyZWF0ZWQgbmV3IGF1ZGlvIGVsZW1lbnQgdG8gcGxheSBzZXBhcmF0ZSBhdWRpbyBzdHJlYW0uJ1xuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgIH1cbn1cbiIsIi8vIENvcHlyaWdodCBFcGljIEdhbWVzLCBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG5cbmltcG9ydCB7IENvbmZpZywgRmxhZ3MgfSBmcm9tICcuLi9Db25maWcvQ29uZmlnJztcbmltcG9ydCB7IExvZ2dlciB9IGZyb20gJy4uL0xvZ2dlci9Mb2dnZXInO1xuXG4vKipcbiAqIEV4dHJhIHR5cGVzIGZvciB0aGUgSFRNTEVsZW1lbnRcbiAqL1xuZGVjbGFyZSBnbG9iYWwge1xuICAgIGludGVyZmFjZSBIVE1MRWxlbWVudCB7XG4gICAgICAgIG1velJlcXVlc3RQb2ludGVyTG9jaz8oKTogdm9pZDtcbiAgICB9XG59XG5cbi8qKlxuICogVGhlIHZpZGVvIHBsYXllciBodG1sIGVsZW1lbnRcbiAqL1xuZXhwb3J0IGNsYXNzIFZpZGVvUGxheWVyIHtcbiAgICBwcml2YXRlIGNvbmZpZzogQ29uZmlnO1xuICAgIHByaXZhdGUgdmlkZW9FbGVtZW50OiBIVE1MVmlkZW9FbGVtZW50O1xuICAgIHByaXZhdGUgYXVkaW9FbGVtZW50PzogSFRNTEF1ZGlvRWxlbWVudDtcbiAgICBwcml2YXRlIG9yaWVudGF0aW9uQ2hhbmdlVGltZW91dDogbnVtYmVyO1xuICAgIHByaXZhdGUgbGFzdFRpbWVSZXNpemVkID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG5cbiAgICBvbk1hdGNoVmlld3BvcnRSZXNvbHV0aW9uQ2FsbGJhY2s6ICh3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlcikgPT4gdm9pZDtcbiAgICBvblJlc2l6ZVBsYXllckNhbGxiYWNrOiAoKSA9PiB2b2lkO1xuICAgIHJlc2l6ZVRpbWVvdXRIYW5kbGU6IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSB2aWRlb0VsZW1lbnRQYXJlbnQgdGhlIGh0bWwgZGl2IHRoZSB0aGUgdmlkZW8gcGxheWVyIHdpbGwgYmUgaW5qZWN0ZWQgaW50b1xuICAgICAqIEBwYXJhbSBjb25maWcgdGhlIGFwcGxpY2F0aW9ucyBjb25maWd1cmF0aW9uLiBXZSdyZSBpbnRlcmVzdGVkIGluIHRoZSBzdGFydFZpZGVvTXV0ZWQgZmxhZ1xuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKHZpZGVvRWxlbWVudFBhcmVudDogSFRNTEVsZW1lbnQsIGNvbmZpZzogQ29uZmlnKSB7XG4gICAgICAgIHRoaXMudmlkZW9FbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgndmlkZW8nKTtcbiAgICAgICAgdGhpcy5jb25maWcgPSBjb25maWc7XG4gICAgICAgIHRoaXMudmlkZW9FbGVtZW50LmlkID0gJ3N0cmVhbWluZ1ZpZGVvJztcbiAgICAgICAgdGhpcy52aWRlb0VsZW1lbnQuZGlzYWJsZVBpY3R1cmVJblBpY3R1cmUgPSB0cnVlO1xuICAgICAgICB0aGlzLnZpZGVvRWxlbWVudC5wbGF5c0lubGluZSA9IHRydWU7XG4gICAgICAgIHRoaXMudmlkZW9FbGVtZW50LnN0eWxlLndpZHRoID0gJzEwMCUnO1xuICAgICAgICB0aGlzLnZpZGVvRWxlbWVudC5zdHlsZS5oZWlnaHQgPSAnMTAwJSc7XG4gICAgICAgIHRoaXMudmlkZW9FbGVtZW50LnN0eWxlLnBvc2l0aW9uID0gJ2Fic29sdXRlJztcbiAgICAgICAgdGhpcy52aWRlb0VsZW1lbnQuc3R5bGUucG9pbnRlckV2ZW50cyA9ICdhbGwnO1xuICAgICAgICB2aWRlb0VsZW1lbnRQYXJlbnQuYXBwZW5kQ2hpbGQodGhpcy52aWRlb0VsZW1lbnQpO1xuXG4gICAgICAgIHRoaXMub25SZXNpemVQbGF5ZXJDYWxsYmFjayA9ICgpID0+IHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgICAgICAgICdSZXNvbHV0aW9uIGNoYW5nZWQsIHJlc3R5bGluZyBwbGF5ZXIsIGRpZCB5b3UgZm9yZ2V0IHRvIG92ZXJyaWRlIHRoaXMgZnVuY3Rpb24/J1xuICAgICAgICAgICAgKTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5vbk1hdGNoVmlld3BvcnRSZXNvbHV0aW9uQ2FsbGJhY2sgPSAoKSA9PiB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICAgICAgICAnUmVzb2x1dGlvbiBjaGFuZ2VkIGFuZCBtYXRjaCB2aWV3cG9ydCByZXNvbHV0aW9uIGlzIHR1cm5lZCBvbiwgZGlkIHlvdSBmb3JnZXQgdG8gb3ZlcnJpZGUgdGhpcyBmdW5jdGlvbj8nXG4gICAgICAgICAgICApO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIHNldCBwbGF5IGZvciB2aWRlbyAoYW5kIGF1ZGlvKVxuICAgICAgICB0aGlzLnZpZGVvRWxlbWVudC5vbmNsaWNrID0gKCkgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuYXVkaW9FbGVtZW50ICE9IHVuZGVmaW5lZCAmJiB0aGlzLmF1ZGlvRWxlbWVudC5wYXVzZWQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmF1ZGlvRWxlbWVudC5wbGF5KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy52aWRlb0VsZW1lbnQucGF1c2VkKSB7XG4gICAgICAgICAgICAgICAgdGhpcy52aWRlb0VsZW1lbnQucGxheSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIHRoaXMudmlkZW9FbGVtZW50Lm9ubG9hZGVkbWV0YWRhdGEgPSAoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLm9uVmlkZW9Jbml0aWFsaXplZCgpO1xuICAgICAgICB9O1xuXG4gICAgICAgIC8vIHNldCByZXNpemUgZXZlbnRzIHRvIHRoZSB3aW5kb3dzIGlmIGl0IGlzIHJlc2l6ZWQgb3IgaXRzIG9yaWVudGF0aW9uIGlzIGNoYW5nZWRcbiAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Jlc2l6ZScsICgpID0+IHRoaXMucmVzaXplUGxheWVyU3R5bGUoKSwgdHJ1ZSk7XG4gICAgICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdvcmllbnRhdGlvbmNoYW5nZScsICgpID0+XG4gICAgICAgICAgICB0aGlzLm9uT3JpZW50YXRpb25DaGFuZ2UoKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIHB1YmxpYyBzZXRBdWRpb0VsZW1lbnQoYXVkaW9FbGVtZW50OiBIVE1MQXVkaW9FbGVtZW50KSA6IHZvaWQge1xuICAgICAgICB0aGlzLmF1ZGlvRWxlbWVudCA9IGF1ZGlvRWxlbWVudDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHVwIHRoZSB2aWRlbyBlbGVtZW50IHdpdGggYW55IGFwcGxpY2F0aW9uIGNvbmZpZyBhbmQgcGxheXMgdGhlIHZpZGVvIGVsZW1lbnQuXG4gICAgICogQHJldHVybnMgQSBwcm9taXNlIGZvciBpZiBwbGF5aW5nIHRoZSB2aWRlbyB3YXMgc3VjY2Vzc2Z1bCBvciBub3QuXG4gICAgICovXG4gICAgcGxheSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgdGhpcy52aWRlb0VsZW1lbnQubXV0ZWQgPSB0aGlzLmNvbmZpZy5pc0ZsYWdFbmFibGVkKFxuICAgICAgICAgICAgRmxhZ3MuU3RhcnRWaWRlb011dGVkXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMudmlkZW9FbGVtZW50LmF1dG9wbGF5ID0gdGhpcy5jb25maWcuaXNGbGFnRW5hYmxlZChcbiAgICAgICAgICAgIEZsYWdzLkF1dG9QbGF5VmlkZW9cbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIHRoaXMudmlkZW9FbGVtZW50LnBsYXkoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyBUcnVlIGlmIHRoZSB2aWRlbyBlbGVtZW50IGlzIHBhdXNlZC5cbiAgICAgKi9cbiAgICBpc1BhdXNlZCgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudmlkZW9FbGVtZW50LnBhdXNlZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJucyAtIHdoZXRoZXIgdGhlIHZpZGVvIGVsZW1lbnQgaXMgcGxheWluZy5cbiAgICAgKi9cbiAgICBpc1ZpZGVvUmVhZHkoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICB0aGlzLnZpZGVvRWxlbWVudC5yZWFkeVN0YXRlICE9PSB1bmRlZmluZWQgJiZcbiAgICAgICAgICAgIHRoaXMudmlkZW9FbGVtZW50LnJlYWR5U3RhdGUgPiAwXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQHJldHVybnMgVHJ1ZSBpZiB0aGUgdmlkZW8gZWxlbWVudCBoYXMgYSB2YWxpZCB2aWRlbyBzb3VyY2UgKHNyY09iamVjdCkuXG4gICAgICovXG4gICAgaGFzVmlkZW9Tb3VyY2UoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICB0aGlzLnZpZGVvRWxlbWVudC5zcmNPYmplY3QgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICAgICAgdGhpcy52aWRlb0VsZW1lbnQuc3JjT2JqZWN0ICE9PSBudWxsXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IHRoZSBjdXJyZW50IGNvbnRleHQgb2YgdGhlIGh0bWwgdmlkZW8gZWxlbWVudFxuICAgICAqIEByZXR1cm5zIC0gdGhlIGN1cnJlbnQgY29udGV4dCBvZiB0aGUgdmlkZW8gZWxlbWVudFxuICAgICAqL1xuICAgIGdldFZpZGVvRWxlbWVudCgpOiBIVE1MVmlkZW9FbGVtZW50IHtcbiAgICAgICAgcmV0dXJuIHRoaXMudmlkZW9FbGVtZW50O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldCB0aGUgY3VycmVudCBjb250ZXh0IG9mIHRoZSBodG1sIHZpZGVvIGVsZW1lbnRzIHBhcmVudFxuICAgICAqIEByZXR1cm5zIC0gdGhlIGN1cnJlbnQgY29udGV4dCBvZiB0aGUgdmlkZW8gZWxlbWVudHMgcGFyZW50XG4gICAgICovXG4gICAgZ2V0VmlkZW9QYXJlbnRFbGVtZW50KCk6IEhUTUxFbGVtZW50IHtcbiAgICAgICAgcmV0dXJuIHRoaXMudmlkZW9FbGVtZW50LnBhcmVudEVsZW1lbnQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSBWaWRlbyBFbGVtZW50cyBzcmMgb2JqZWN0IHRyYWNrcyB0byBlbmFibGVcbiAgICAgKiBAcGFyYW0gZW5hYmxlZCAtIEVuYWJsZSBUcmFja3Mgb24gdGhlIFNyYyBPYmplY3RcbiAgICAgKi9cbiAgICBzZXRWaWRlb0VuYWJsZWQoZW5hYmxlZDogYm9vbGVhbikge1xuICAgICAgICAvLyB0aGlzIGlzIGEgdGVtcG9yYXJ5IGhhY2sgdW50aWwgdHlwZSBzY3JpcHRzIHZpZGVvIGVsZW1lbnQgaXMgdXBkYXRlZCB0byByZWZsZWN0IHRoZSBuZWVkIGZvciB0cmFja3Mgb24gYSBodG1sIHZpZGVvIGVsZW1lbnRcbiAgICAgICAgY29uc3QgdmlkZW9FbGVtZW50ID0gdGhpcy52aWRlb0VsZW1lbnQ7XG4gICAgICAgICg8TWVkaWFTdHJlYW0+dmlkZW9FbGVtZW50LnNyY09iamVjdClcbiAgICAgICAgICAgIC5nZXRUcmFja3MoKVxuICAgICAgICAgICAgLmZvckVhY2goKHRyYWNrOiBNZWRpYVN0cmVhbVRyYWNrKSA9PiAodHJhY2suZW5hYmxlZCA9IGVuYWJsZWQpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBbiBvdmVycmlkZSBmb3Igd2hlbiB0aGUgdmlkZW8gaGFzIGJlZW4gaW5pdGlhbGl6ZWQgd2l0aCBhIHNyY09iamVjdFxuICAgICAqL1xuICAgIG9uVmlkZW9Jbml0aWFsaXplZCgpIHtcbiAgICAgICAgLy8gRGVmYXVsdCBGdW5jdGlvbmFsaXR5OiBEbyBOb3RoaW5nXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogT24gdGhlIG9yaWVudGF0aW9uIGNoYW5nZSBvZiBhIHdpbmRvdyBjbGVhciB0aGUgdGltZW91dFxuICAgICAqL1xuICAgIG9uT3JpZW50YXRpb25DaGFuZ2UoKSB7XG4gICAgICAgIGNsZWFyVGltZW91dCh0aGlzLm9yaWVudGF0aW9uQ2hhbmdlVGltZW91dCk7XG4gICAgICAgIHRoaXMub3JpZW50YXRpb25DaGFuZ2VUaW1lb3V0ID0gd2luZG93LnNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5yZXNpemVQbGF5ZXJTdHlsZSgpO1xuICAgICAgICB9LCA1MDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlc2l6ZXMgdGhlIHBsYXllciBzdHlsZSBiYXNlZCBvbiB0aGUgd2luZG93IGhlaWdodCBhbmQgd2lkdGhcbiAgICAgKiBAcmV0dXJucyAtIG5pbCBpZiByZXF1aXJlbWVudHMgYXJlIHNhdGlzZmllZFxuICAgICAqL1xuICAgIHJlc2l6ZVBsYXllclN0eWxlKCkge1xuICAgICAgICBjb25zdCB2aWRlb0VsZW1lbnRQYXJlbnQgPSB0aGlzLmdldFZpZGVvUGFyZW50RWxlbWVudCgpO1xuXG4gICAgICAgIGlmICghdmlkZW9FbGVtZW50UGFyZW50KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnVwZGF0ZVZpZGVvU3RyZWFtU2l6ZSgpO1xuXG4gICAgICAgIGlmICh2aWRlb0VsZW1lbnRQYXJlbnQuY2xhc3NMaXN0LmNvbnRhaW5zKCdmaXhlZC1zaXplJykpIHtcbiAgICAgICAgICAgIHRoaXMub25SZXNpemVQbGF5ZXJDYWxsYmFjaygpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gY29udHJvbHMgZm9yIHJlc2l6aW5nIHRoZSBwbGF5ZXJcbiAgICAgICAgdGhpcy5yZXNpemVQbGF5ZXJTdHlsZVRvRmlsbFBhcmVudEVsZW1lbnQoKTtcbiAgICAgICAgdGhpcy5vblJlc2l6ZVBsYXllckNhbGxiYWNrKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVzaXplcyB0aGUgcGxheWVyIGVsZW1lbnQgdG8gZmlsbCB0aGUgcGFyZW50IGVsZW1lbnRcbiAgICAgKi9cbiAgICByZXNpemVQbGF5ZXJTdHlsZVRvRmlsbFBhcmVudEVsZW1lbnQoKSB7XG4gICAgICAgIGNvbnN0IHZpZGVvRWxlbWVudFBhcmVudCA9IHRoaXMuZ2V0VmlkZW9QYXJlbnRFbGVtZW50KCk7XG5cbiAgICAgICAgLy9WaWRlbyBpcyBub3QgaW5pdGlhbGl6ZWQgeWV0IHNvIHNldCB2aWRlb0VsZW1lbnRQYXJlbnQgdG8gc2l6ZSBvZiBwYXJlbnQgZWxlbWVudFxuICAgICAgICBjb25zdCBzdHlsZVdpZHRoID0gJzEwMCUnO1xuICAgICAgICBjb25zdCBzdHlsZUhlaWdodCA9ICcxMDAlJztcbiAgICAgICAgY29uc3Qgc3R5bGVUb3AgPSAwO1xuICAgICAgICBjb25zdCBzdHlsZUxlZnQgPSAwO1xuICAgICAgICB2aWRlb0VsZW1lbnRQYXJlbnQuc2V0QXR0cmlidXRlKFxuICAgICAgICAgICAgJ3N0eWxlJyxcbiAgICAgICAgICAgICd0b3A6ICcgK1xuICAgICAgICAgICAgICAgIHN0eWxlVG9wICtcbiAgICAgICAgICAgICAgICAncHg7IGxlZnQ6ICcgK1xuICAgICAgICAgICAgICAgIHN0eWxlTGVmdCArXG4gICAgICAgICAgICAgICAgJ3B4OyB3aWR0aDogJyArXG4gICAgICAgICAgICAgICAgc3R5bGVXaWR0aCArXG4gICAgICAgICAgICAgICAgJzsgaGVpZ2h0OiAnICtcbiAgICAgICAgICAgICAgICBzdHlsZUhlaWdodCArXG4gICAgICAgICAgICAgICAgJzsgY3Vyc29yOiBkZWZhdWx0OydcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICB1cGRhdGVWaWRlb1N0cmVhbVNpemUoKSB7XG4gICAgICAgIGlmICghdGhpcy5jb25maWcuaXNGbGFnRW5hYmxlZChGbGFncy5NYXRjaFZpZXdwb3J0UmVzb2x1dGlvbikpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IG5vdyA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgICAgICBpZiAobm93IC0gdGhpcy5sYXN0VGltZVJlc2l6ZWQgPiAzMDApIHtcbiAgICAgICAgICAgIGNvbnN0IHZpZGVvRWxlbWVudFBhcmVudCA9IHRoaXMuZ2V0VmlkZW9QYXJlbnRFbGVtZW50KCk7XG4gICAgICAgICAgICBpZiAoIXZpZGVvRWxlbWVudFBhcmVudCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5vbk1hdGNoVmlld3BvcnRSZXNvbHV0aW9uQ2FsbGJhY2soXG4gICAgICAgICAgICAgICAgdmlkZW9FbGVtZW50UGFyZW50LmNsaWVudFdpZHRoLFxuICAgICAgICAgICAgICAgIHZpZGVvRWxlbWVudFBhcmVudC5jbGllbnRIZWlnaHRcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIHRoaXMubGFzdFRpbWVSZXNpemVkID0gbmV3IERhdGUoKS5nZXRUaW1lKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBMb2dnZXIuTG9nKFxuICAgICAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAgICAgJ1Jlc2l6aW5nIHRvbyBvZnRlbiAtIHNraXBwaW5nJyxcbiAgICAgICAgICAgICAgICA2XG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMucmVzaXplVGltZW91dEhhbmRsZSk7XG4gICAgICAgICAgICB0aGlzLnJlc2l6ZVRpbWVvdXRIYW5kbGUgPSB3aW5kb3cuc2V0VGltZW91dChcbiAgICAgICAgICAgICAgICAoKSA9PiB0aGlzLnVwZGF0ZVZpZGVvU3RyZWFtU2l6ZSgpLFxuICAgICAgICAgICAgICAgIDEwMFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgIH1cbn1cbiIsIi8vIENvcHlyaWdodCBFcGljIEdhbWVzLCBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG5cbmltcG9ydCB7IFdlYlNvY2tldENvbnRyb2xsZXIgfSBmcm9tICcuLi9XZWJTb2NrZXRzL1dlYlNvY2tldENvbnRyb2xsZXInO1xuaW1wb3J0IHsgU3RyZWFtQ29udHJvbGxlciB9IGZyb20gJy4uL1ZpZGVvUGxheWVyL1N0cmVhbUNvbnRyb2xsZXInO1xuaW1wb3J0IHtcbiAgICBNZXNzYWdlQW5zd2VyLFxuICAgIE1lc3NhZ2VPZmZlcixcbiAgICBNZXNzYWdlQ29uZmlnLFxuICAgIE1lc3NhZ2VTdHJlYW1lckxpc3Rcbn0gZnJvbSAnLi4vV2ViU29ja2V0cy9NZXNzYWdlUmVjZWl2ZSc7XG5pbXBvcnQgeyBGcmVlemVGcmFtZUNvbnRyb2xsZXIgfSBmcm9tICcuLi9GcmVlemVGcmFtZS9GcmVlemVGcmFtZUNvbnRyb2xsZXInO1xuaW1wb3J0IHsgQUZLQ29udHJvbGxlciB9IGZyb20gJy4uL0FGSy9BRktDb250cm9sbGVyJztcbmltcG9ydCB7IERhdGFDaGFubmVsQ29udHJvbGxlciB9IGZyb20gJy4uL0RhdGFDaGFubmVsL0RhdGFDaGFubmVsQ29udHJvbGxlcic7XG5pbXBvcnQgeyBQZWVyQ29ubmVjdGlvbkNvbnRyb2xsZXIgfSBmcm9tICcuLi9QZWVyQ29ubmVjdGlvbkNvbnRyb2xsZXIvUGVlckNvbm5lY3Rpb25Db250cm9sbGVyJztcbmltcG9ydCB7IEtleWJvYXJkQ29udHJvbGxlciB9IGZyb20gJy4uL0lucHV0cy9LZXlib2FyZENvbnRyb2xsZXInO1xuaW1wb3J0IHsgQWdncmVnYXRlZFN0YXRzIH0gZnJvbSAnLi4vUGVlckNvbm5lY3Rpb25Db250cm9sbGVyL0FnZ3JlZ2F0ZWRTdGF0cyc7XG5pbXBvcnQge1xuICAgIENvbmZpZyxcbiAgICBGbGFncyxcbiAgICBDb250cm9sU2NoZW1lVHlwZSxcbiAgICBUZXh0UGFyYW1ldGVycyxcbiAgICBPcHRpb25QYXJhbWV0ZXJzLFxuICAgIE51bWVyaWNQYXJhbWV0ZXJzXG59IGZyb20gJy4uL0NvbmZpZy9Db25maWcnO1xuaW1wb3J0IHtcbiAgICBFbmNvZGVyU2V0dGluZ3MsXG4gICAgSW5pdGlhbFNldHRpbmdzLFxuICAgIFdlYlJUQ1NldHRpbmdzXG59IGZyb20gJy4uL0RhdGFDaGFubmVsL0luaXRpYWxTZXR0aW5ncyc7XG5pbXBvcnQgeyBMYXRlbmN5VGVzdFJlc3VsdHMgfSBmcm9tICcuLi9EYXRhQ2hhbm5lbC9MYXRlbmN5VGVzdFJlc3VsdHMnO1xuaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSAnLi4vTG9nZ2VyL0xvZ2dlcic7XG5pbXBvcnQgeyBGaWxlVGVtcGxhdGUsIEZpbGVVdGlsIH0gZnJvbSAnLi4vVXRpbC9GaWxlVXRpbCc7XG5pbXBvcnQgeyBJbnB1dENsYXNzZXNGYWN0b3J5IH0gZnJvbSAnLi4vSW5wdXRzL0lucHV0Q2xhc3Nlc0ZhY3RvcnknO1xuaW1wb3J0IHsgVmlkZW9QbGF5ZXIgfSBmcm9tICcuLi9WaWRlb1BsYXllci9WaWRlb1BsYXllcic7XG5pbXBvcnQge1xuICAgIFN0cmVhbU1lc3NhZ2VDb250cm9sbGVyLFxuICAgIE1lc3NhZ2VEaXJlY3Rpb25cbn0gZnJvbSAnLi4vVWVJbnN0YW5jZU1lc3NhZ2UvU3RyZWFtTWVzc2FnZUNvbnRyb2xsZXInO1xuaW1wb3J0IHsgUmVzcG9uc2VDb250cm9sbGVyIH0gZnJvbSAnLi4vVWVJbnN0YW5jZU1lc3NhZ2UvUmVzcG9uc2VDb250cm9sbGVyJztcbmltcG9ydCAqIGFzIE1lc3NhZ2VSZWNlaXZlIGZyb20gJy4uL1dlYlNvY2tldHMvTWVzc2FnZVJlY2VpdmUnO1xuaW1wb3J0IHsgTWVzc2FnZU9uU2NyZWVuS2V5Ym9hcmQgfSBmcm9tICcuLi9XZWJTb2NrZXRzL01lc3NhZ2VSZWNlaXZlJztcbmltcG9ydCB7IFNlbmRNZXNzYWdlQ29udHJvbGxlciB9IGZyb20gJy4uL1VlSW5zdGFuY2VNZXNzYWdlL1NlbmRNZXNzYWdlQ29udHJvbGxlcic7XG5pbXBvcnQgeyBUb1N0cmVhbWVyTWVzc2FnZXNDb250cm9sbGVyIH0gZnJvbSAnLi4vVWVJbnN0YW5jZU1lc3NhZ2UvVG9TdHJlYW1lck1lc3NhZ2VzQ29udHJvbGxlcic7XG5pbXBvcnQgeyBNb3VzZUNvbnRyb2xsZXIgfSBmcm9tICcuLi9JbnB1dHMvTW91c2VDb250cm9sbGVyJztcbmltcG9ydCB7IEdhbWVQYWRDb250cm9sbGVyIH0gZnJvbSAnLi4vSW5wdXRzL0dhbWVwYWRDb250cm9sbGVyJztcbmltcG9ydCB7IERhdGFDaGFubmVsU2VuZGVyIH0gZnJvbSAnLi4vRGF0YUNoYW5uZWwvRGF0YUNoYW5uZWxTZW5kZXInO1xuaW1wb3J0IHtcbiAgICBDb29yZGluYXRlQ29udmVydGVyLFxuICAgIFVucXVhbnRpemVkRGVub3JtYWxpemVkVW5zaWduZWRDb29yZFxufSBmcm9tICcuLi9VdGlsL0Nvb3JkaW5hdGVDb252ZXJ0ZXInO1xuaW1wb3J0IHsgUGl4ZWxTdHJlYW1pbmcgfSBmcm9tICcuLi9QaXhlbFN0cmVhbWluZy9QaXhlbFN0cmVhbWluZyc7XG5pbXBvcnQgeyBJVG91Y2hDb250cm9sbGVyIH0gZnJvbSAnLi4vSW5wdXRzL0lUb3VjaENvbnRyb2xsZXInO1xuaW1wb3J0IHtcbiAgICBEYXRhQ2hhbm5lbENsb3NlRXZlbnQsXG4gICAgRGF0YUNoYW5uZWxFcnJvckV2ZW50LFxuICAgIERhdGFDaGFubmVsT3BlbkV2ZW50LFxuICAgIEhpZGVGcmVlemVGcmFtZUV2ZW50LFxuICAgIExvYWRGcmVlemVGcmFtZUV2ZW50LFxuICAgIFBsYXlTdHJlYW1FcnJvckV2ZW50LFxuICAgIFBsYXlTdHJlYW1FdmVudCxcbiAgICBQbGF5U3RyZWFtUmVqZWN0ZWRFdmVudCxcbiAgICBTdHJlYW1lckxpc3RNZXNzYWdlRXZlbnRcbn0gZnJvbSAnLi4vVXRpbC9FdmVudEVtaXR0ZXInO1xuaW1wb3J0IHtcbiAgICBEYXRhQ2hhbm5lbExhdGVuY3lUZXN0UmVxdWVzdCxcbiAgICBEYXRhQ2hhbm5lbExhdGVuY3lUZXN0UmVzcG9uc2Vcbn0gZnJvbSBcIi4uL0RhdGFDaGFubmVsL0RhdGFDaGFubmVsTGF0ZW5jeVRlc3RSZXN1bHRzXCI7XG4vKipcbiAqIEVudHJ5IHBvaW50IGZvciB0aGUgV2ViUlRDIFBsYXllclxuICovXG5leHBvcnQgY2xhc3MgV2ViUnRjUGxheWVyQ29udHJvbGxlciB7XG4gICAgY29uZmlnOiBDb25maWc7XG4gICAgcmVzcG9uc2VDb250cm9sbGVyOiBSZXNwb25zZUNvbnRyb2xsZXI7XG4gICAgc2RwQ29uc3RyYWludHM6IFJUQ09mZmVyT3B0aW9ucztcbiAgICB3ZWJTb2NrZXRDb250cm9sbGVyOiBXZWJTb2NrZXRDb250cm9sbGVyO1xuICAgIC8vIFRoZSBwcmltYXJ5IGRhdGEgY2hhbm5lbC4gVGhpcyBpcyBiaWRpcmVjdGlvbmFsIHdoZW4gcDJwIGFuZCBzZW5kIG9ubHkgd2hlbiB1c2luZyBhbiBTRlVcbiAgICBzZW5kcmVjdkRhdGFDaGFubmVsQ29udHJvbGxlcjogRGF0YUNoYW5uZWxDb250cm9sbGVyO1xuICAgIC8vIEEgcmVjdiBvbmx5IGRhdGEgY2hhbm5lbCByZXF1aXJlZCB3aGVuIHVzaW5nIGFuIFNGVVxuICAgIHJlY3ZEYXRhQ2hhbm5lbENvbnRyb2xsZXI6IERhdGFDaGFubmVsQ29udHJvbGxlcjtcbiAgICBkYXRhQ2hhbm5lbFNlbmRlcjogRGF0YUNoYW5uZWxTZW5kZXI7XG4gICAgZGF0YWNoYW5uZWxPcHRpb25zOiBSVENEYXRhQ2hhbm5lbEluaXQ7XG4gICAgdmlkZW9QbGF5ZXI6IFZpZGVvUGxheWVyO1xuICAgIHN0cmVhbUNvbnRyb2xsZXI6IFN0cmVhbUNvbnRyb2xsZXI7XG4gICAgcGVlckNvbm5lY3Rpb25Db250cm9sbGVyOiBQZWVyQ29ubmVjdGlvbkNvbnRyb2xsZXI7XG4gICAgaW5wdXRDbGFzc2VzRmFjdG9yeTogSW5wdXRDbGFzc2VzRmFjdG9yeTtcbiAgICBmcmVlemVGcmFtZUNvbnRyb2xsZXI6IEZyZWV6ZUZyYW1lQ29udHJvbGxlcjtcbiAgICBzaG91bGRTaG93UGxheU92ZXJsYXkgPSB0cnVlO1xuICAgIGFma0NvbnRyb2xsZXI6IEFGS0NvbnRyb2xsZXI7XG4gICAgdmlkZW9FbGVtZW50UGFyZW50Q2xpZW50UmVjdDogRE9NUmVjdDtcbiAgICBsYXRlbmN5U3RhcnRUaW1lOiBudW1iZXI7XG4gICAgcGl4ZWxTdHJlYW1pbmc6IFBpeGVsU3RyZWFtaW5nO1xuICAgIHN0cmVhbU1lc3NhZ2VDb250cm9sbGVyOiBTdHJlYW1NZXNzYWdlQ29udHJvbGxlcjtcbiAgICBzZW5kTWVzc2FnZUNvbnRyb2xsZXI6IFNlbmRNZXNzYWdlQ29udHJvbGxlcjtcbiAgICB0b1N0cmVhbWVyTWVzc2FnZXNDb250cm9sbGVyOiBUb1N0cmVhbWVyTWVzc2FnZXNDb250cm9sbGVyO1xuICAgIGtleWJvYXJkQ29udHJvbGxlcjogS2V5Ym9hcmRDb250cm9sbGVyO1xuICAgIG1vdXNlQ29udHJvbGxlcjogTW91c2VDb250cm9sbGVyO1xuICAgIHRvdWNoQ29udHJvbGxlcjogSVRvdWNoQ29udHJvbGxlcjtcbiAgICBnYW1lUGFkQ29udHJvbGxlcjogR2FtZVBhZENvbnRyb2xsZXI7XG4gICAgY29vcmRpbmF0ZUNvbnZlcnRlcjogQ29vcmRpbmF0ZUNvbnZlcnRlcjtcbiAgICBpc1VzaW5nU0ZVOiBib29sZWFuO1xuICAgIGlzUXVhbGl0eUNvbnRyb2xsZXI6IGJvb2xlYW47XG4gICAgc3RhdHNUaW1lckhhbmRsZTogbnVtYmVyO1xuICAgIGZpbGU6IEZpbGVUZW1wbGF0ZTtcbiAgICBwcmVmZXJyZWRDb2RlYzogc3RyaW5nO1xuICAgIHBlZXJDb25maWc6IFJUQ0NvbmZpZ3VyYXRpb247XG4gICAgdmlkZW9BdmdRcDogbnVtYmVyO1xuICAgIGxvY2FsbHlDbG9zZWQ6IGJvb2xlYW47XG4gICAgc2hvdWxkUmVjb25uZWN0OiBib29sZWFuO1xuICAgIGlzUmVjb25uZWN0aW5nOiBib29sZWFuO1xuICAgIHJlY29ubmVjdEF0dGVtcHQ6IG51bWJlcjtcbiAgICBkaXNjb25uZWN0TWVzc2FnZTogc3RyaW5nO1xuICAgIHN1YnNjcmliZWRTdHJlYW06IHN0cmluZztcbiAgICBzaWduYWxsaW5nVXJsQnVpbGRlcjogKCkgPT4gc3RyaW5nO1xuICAgIGF1dG9Kb2luVGltZXI6IFJldHVyblR5cGU8dHlwZW9mIHNldFRpbWVvdXQ+ID0gdW5kZWZpbmVkO1xuXG4gICAgLyoqXG4gICAgICpcbiAgICAgKiBAcGFyYW0gY29uZmlnIC0gdGhlIGZyb250ZW5kIGNvbmZpZyBvYmplY3RcbiAgICAgKiBAcGFyYW0gcGl4ZWxTdHJlYW1pbmcgLSB0aGUgUGl4ZWxTdHJlYW1pbmcgb2JqZWN0XG4gICAgICovXG4gICAgY29uc3RydWN0b3IoY29uZmlnOiBDb25maWcsIHBpeGVsU3RyZWFtaW5nOiBQaXhlbFN0cmVhbWluZykge1xuICAgICAgICB0aGlzLmNvbmZpZyA9IGNvbmZpZztcbiAgICAgICAgdGhpcy5waXhlbFN0cmVhbWluZyA9IHBpeGVsU3RyZWFtaW5nO1xuICAgICAgICB0aGlzLnJlc3BvbnNlQ29udHJvbGxlciA9IG5ldyBSZXNwb25zZUNvbnRyb2xsZXIoKTtcbiAgICAgICAgdGhpcy5maWxlID0gbmV3IEZpbGVUZW1wbGF0ZSgpO1xuXG4gICAgICAgIHRoaXMuc2RwQ29uc3RyYWludHMgPSB7XG4gICAgICAgICAgICBvZmZlclRvUmVjZWl2ZUF1ZGlvOiB0cnVlLFxuICAgICAgICAgICAgb2ZmZXJUb1JlY2VpdmVWaWRlbzogdHJ1ZVxuICAgICAgICB9O1xuXG4gICAgICAgIC8vIHNldCB1cCB0aGUgYWZrIGxvZ2ljIGNsYXNzIGFuZCBjb25uZWN0IHVwIGl0cyBtZXRob2QgZm9yIGNsb3NpbmcgdGhlIHNpZ25hbGluZyBzZXJ2ZXJcbiAgICAgICAgdGhpcy5hZmtDb250cm9sbGVyID0gbmV3IEFGS0NvbnRyb2xsZXIoXG4gICAgICAgICAgICB0aGlzLmNvbmZpZyxcbiAgICAgICAgICAgIHRoaXMucGl4ZWxTdHJlYW1pbmcsXG4gICAgICAgICAgICB0aGlzLm9uQWZrVHJpZ2dlcmVkLmJpbmQodGhpcylcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5hZmtDb250cm9sbGVyLm9uQUZLVGltZWRPdXRDYWxsYmFjayA9ICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuY2xvc2VTaWduYWxpbmdTZXJ2ZXIoJ1lvdSBoYXZlIGJlZW4gZGlzY29ubmVjdGVkIGR1ZSB0byBpbmFjdGl2aXR5Jyk7XG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5mcmVlemVGcmFtZUNvbnRyb2xsZXIgPSBuZXcgRnJlZXplRnJhbWVDb250cm9sbGVyKFxuICAgICAgICAgICAgdGhpcy5waXhlbFN0cmVhbWluZy52aWRlb0VsZW1lbnRQYXJlbnRcbiAgICAgICAgKTtcblxuICAgICAgICB0aGlzLnZpZGVvUGxheWVyID0gbmV3IFZpZGVvUGxheWVyKFxuICAgICAgICAgICAgdGhpcy5waXhlbFN0cmVhbWluZy52aWRlb0VsZW1lbnRQYXJlbnQsXG4gICAgICAgICAgICB0aGlzLmNvbmZpZ1xuICAgICAgICApO1xuICAgICAgICB0aGlzLnZpZGVvUGxheWVyLm9uVmlkZW9Jbml0aWFsaXplZCA9ICgpID0+XG4gICAgICAgICAgICB0aGlzLmhhbmRsZVZpZGVvSW5pdGlhbGl6ZWQoKTtcblxuICAgICAgICAvLyBXaGVuIGluIG1hdGNoIHZpZXdwb3J0IHJlc29sdXRpb24gbW9kZSwgd2hlbiB0aGUgYnJvd3NlciB2aWV3cG9ydCBpcyByZXNpemVkIHdlIHNlbmQgYSByZXNpemUgY29tbWFuZCBiYWNrIHRvIFVFLlxuICAgICAgICB0aGlzLnZpZGVvUGxheWVyLm9uTWF0Y2hWaWV3cG9ydFJlc29sdXRpb25DYWxsYmFjayA9IChcbiAgICAgICAgICAgIHdpZHRoOiBudW1iZXIsXG4gICAgICAgICAgICBoZWlnaHQ6IG51bWJlclxuICAgICAgICApID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGRlc2NyaXB0b3IgPSB7XG4gICAgICAgICAgICAgICAgJ1Jlc29sdXRpb24uV2lkdGgnOiB3aWR0aCxcbiAgICAgICAgICAgICAgICAnUmVzb2x1dGlvbi5IZWlnaHQnOiBoZWlnaHRcbiAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgIHRoaXMuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIudG9TdHJlYW1lckhhbmRsZXJzLmdldChcbiAgICAgICAgICAgICAgICAnQ29tbWFuZCdcbiAgICAgICAgICAgICkoW0pTT04uc3RyaW5naWZ5KGRlc2NyaXB0b3IpXSk7XG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gRXZlcnkgdGltZSB2aWRlbyBwbGF5ZXIgaXMgcmVzaXplZCBpbiBicm93c2VyIHdlIG5lZWQgdG8gcmVpbml0aWFsaXplIHRoZSBtb3VzZSBjb29yZGluYXRlIGNvbnZlcnNpb24gYW5kIGZyZWV6ZSBmcmFtZSBzaXppbmcgbG9naWMuXG4gICAgICAgIHRoaXMudmlkZW9QbGF5ZXIub25SZXNpemVQbGF5ZXJDYWxsYmFjayA9ICgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuc2V0VXBNb3VzZUFuZEZyZWV6ZUZyYW1lKCk7XG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5zdHJlYW1Db250cm9sbGVyID0gbmV3IFN0cmVhbUNvbnRyb2xsZXIodGhpcy52aWRlb1BsYXllcik7XG5cbiAgICAgICAgdGhpcy5jb29yZGluYXRlQ29udmVydGVyID0gbmV3IENvb3JkaW5hdGVDb252ZXJ0ZXIodGhpcy52aWRlb1BsYXllcik7XG5cbiAgICAgICAgdGhpcy5zZW5kcmVjdkRhdGFDaGFubmVsQ29udHJvbGxlciA9IG5ldyBEYXRhQ2hhbm5lbENvbnRyb2xsZXIoKTtcbiAgICAgICAgdGhpcy5yZWN2RGF0YUNoYW5uZWxDb250cm9sbGVyID0gbmV3IERhdGFDaGFubmVsQ29udHJvbGxlcigpO1xuICAgICAgICB0aGlzLnJlZ2lzdGVyRGF0YUNoYW5uZWxFdmVudEVtaXR0ZXJzKFxuICAgICAgICAgICAgdGhpcy5zZW5kcmVjdkRhdGFDaGFubmVsQ29udHJvbGxlclxuICAgICAgICApO1xuICAgICAgICB0aGlzLnJlZ2lzdGVyRGF0YUNoYW5uZWxFdmVudEVtaXR0ZXJzKHRoaXMucmVjdkRhdGFDaGFubmVsQ29udHJvbGxlcik7XG4gICAgICAgIHRoaXMuZGF0YUNoYW5uZWxTZW5kZXIgPSBuZXcgRGF0YUNoYW5uZWxTZW5kZXIoXG4gICAgICAgICAgICB0aGlzLnNlbmRyZWN2RGF0YUNoYW5uZWxDb250cm9sbGVyXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuZGF0YUNoYW5uZWxTZW5kZXIucmVzZXRBZmtXYXJuaW5nVGltZXJPbkRhdGFTZW5kID0gKCkgPT5cbiAgICAgICAgICAgIHRoaXMuYWZrQ29udHJvbGxlci5yZXNldEFma1dhcm5pbmdUaW1lcigpO1xuXG4gICAgICAgIHRoaXMuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIgPSBuZXcgU3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIoKTtcblxuICAgICAgICAvLyBzZXQgdXAgd2Vic29ja2V0IG1ldGhvZHNcbiAgICAgICAgdGhpcy53ZWJTb2NrZXRDb250cm9sbGVyID0gbmV3IFdlYlNvY2tldENvbnRyb2xsZXIoKTtcbiAgICAgICAgdGhpcy53ZWJTb2NrZXRDb250cm9sbGVyLm9uQ29uZmlnID0gKFxuICAgICAgICAgICAgbWVzc2FnZUNvbmZpZzogTWVzc2FnZVJlY2VpdmUuTWVzc2FnZUNvbmZpZ1xuICAgICAgICApID0+IHRoaXMuaGFuZGxlT25Db25maWdNZXNzYWdlKG1lc3NhZ2VDb25maWcpO1xuICAgICAgICB0aGlzLndlYlNvY2tldENvbnRyb2xsZXIub25TdHJlYW1lckxpc3QgPSAoXG4gICAgICAgICAgICBtZXNzYWdlTGlzdDogTWVzc2FnZVJlY2VpdmUuTWVzc2FnZVN0cmVhbWVyTGlzdFxuICAgICAgICApID0+IHRoaXMuaGFuZGxlU3RyZWFtZXJMaXN0TWVzc2FnZShtZXNzYWdlTGlzdCk7XG4gICAgICAgIHRoaXMud2ViU29ja2V0Q29udHJvbGxlci5vblBsYXllckNvdW50ID0gKHBsYXllckNvdW50OiBNZXNzYWdlUmVjZWl2ZS5NZXNzYWdlUGxheWVyQ291bnQpID0+IHsgXG4gICAgICAgICAgICB0aGlzLnBpeGVsU3RyZWFtaW5nLl9vblBsYXllckNvdW50KHBsYXllckNvdW50LmNvdW50KTsgXG4gICAgICAgIH07XG4gICAgICAgIHRoaXMud2ViU29ja2V0Q29udHJvbGxlci5vbk9wZW4uYWRkRXZlbnRMaXN0ZW5lcignb3BlbicsICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IEJyb3dzZXJTZW5kc09mZmVyID0gdGhpcy5jb25maWcuaXNGbGFnRW5hYmxlZChcbiAgICAgICAgICAgICAgICBGbGFncy5Ccm93c2VyU2VuZE9mZmVyXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgaWYoIUJyb3dzZXJTZW5kc09mZmVyKVxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHRoaXMud2ViU29ja2V0Q29udHJvbGxlci5yZXF1ZXN0U3RyZWFtZXJMaXN0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICB0aGlzLndlYlNvY2tldENvbnRyb2xsZXIub25DbG9zZS5hZGRFdmVudExpc3RlbmVyKCdjbG9zZScsIChldmVudCA6IEN1c3RvbUV2ZW50KSA9PiB7XG4gICAgICAgICAgICAvLyB3aGVuIHdlIHJlZnJlc2ggdGhlIHBhZ2UgZHVyaW5nIGEgc3RyZWFtIHdlIGdldCB0aGUgZ29pbmcgYXdheSBjb2RlLlxuICAgICAgICAgICAgLy8gaW4gdGhhdCBjYXNlIHdlIGRvbid0IHdhbnQgdG8gcmVjb25uZWN0IHNpbmNlIHdlJ3JlIG5hdmlnYXRpbmcgYXdheS5cbiAgICAgICAgICAgIC8vIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9DbG9zZUV2ZW50L2NvZGVcbiAgICAgICAgICAgIC8vIGxpc3RzIGFsbCB0aGUgY29kZXMuIFxuICAgICAgICAgICAgY29uc3QgQ09ERV9HT0lOR19BV0FZID0gMTAwMTtcblxuICAgICAgICAgICAgY29uc3Qgd2lsbFRyeVJlY29ubmVjdCA9IHRoaXMuc2hvdWxkUmVjb25uZWN0XG4gICAgICAgICAgICAgICAmJiBldmVudC5kZXRhaWwuY29kZSAhPSBDT0RFX0dPSU5HX0FXQVlcbiAgICAgICAgICAgICAgICYmIHRoaXMuY29uZmlnLmdldE51bWVyaWNTZXR0aW5nVmFsdWUoTnVtZXJpY1BhcmFtZXRlcnMuTWF4UmVjb25uZWN0QXR0ZW1wdHMpID4gMFxuXG4gICAgICAgICAgICBjb25zdCBkaXNjb25uZWN0TWVzc2FnZSA9IHRoaXMuZGlzY29ubmVjdE1lc3NhZ2UgPyB0aGlzLmRpc2Nvbm5lY3RNZXNzYWdlIDogZXZlbnQuZGV0YWlsLnJlYXNvbjtcbiAgICAgICAgICAgIHRoaXMucGl4ZWxTdHJlYW1pbmcuX29uRGlzY29ubmVjdChkaXNjb25uZWN0TWVzc2FnZSwgIXdpbGxUcnlSZWNvbm5lY3QgJiYgIXRoaXMuaXNSZWNvbm5lY3RpbmcpO1xuXG4gICAgICAgICAgICB0aGlzLmFma0NvbnRyb2xsZXIuc3RvcEFma1dhcm5pbmdUaW1lcigpO1xuXG4gICAgICAgICAgICAvLyBzdG9wIHNlbmRpbmcgc3RhdHMgb24gaW50ZXJ2YWwgaWYgd2UgaGF2ZSBjbG9zZWQgb3VyIGNvbm5lY3Rpb25cbiAgICAgICAgICAgIGlmICh0aGlzLnN0YXRzVGltZXJIYW5kbGUgJiYgdGhpcy5zdGF0c1RpbWVySGFuZGxlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICB3aW5kb3cuY2xlYXJJbnRlcnZhbCh0aGlzLnN0YXRzVGltZXJIYW5kbGUpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyByZXNldCB0aGUgc3RyZWFtIHF1YWxpdHkgaWNvbi5cbiAgICAgICAgICAgIHRoaXMuc2V0VmlkZW9FbmNvZGVyQXZnUVAoMCk7XG5cbiAgICAgICAgICAgIC8vIHVucmVnaXN0ZXIgYWxsIGlucHV0IGRldmljZSBldmVudCBoYW5kbGVycyBvbiBkaXNjb25uZWN0XG4gICAgICAgICAgICB0aGlzLnNldFRvdWNoSW5wdXRFbmFibGVkKGZhbHNlKTtcbiAgICAgICAgICAgIHRoaXMuc2V0TW91c2VJbnB1dEVuYWJsZWQoZmFsc2UpO1xuICAgICAgICAgICAgdGhpcy5zZXRLZXlib2FyZElucHV0RW5hYmxlZChmYWxzZSk7XG4gICAgICAgICAgICB0aGlzLnNldEdhbWVQYWRJbnB1dEVuYWJsZWQoZmFsc2UpO1xuXG4gICAgICAgICAgICBpZiAod2lsbFRyeVJlY29ubmVjdCkge1xuICAgICAgICAgICAgICAgIC8vIG5lZWQgYSBzbWFsbCBkZWxheSBoZXJlIHRvIHByZXZlbnQgcmVjb25uZWN0IHNwYW1taW5nXG4gICAgICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaXNSZWNvbm5lY3RpbmcgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlY29ubmVjdEF0dGVtcHQrKztcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50cnlSZWNvbm5lY3QoZXZlbnQuZGV0YWlsLnJlYXNvbik7XG4gICAgICAgICAgICAgICAgfSwgMjAwMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIHNldCB1cCB0aGUgZmluYWwgd2ViUnRjIHBsYXllciBjb250cm9sbGVyIG1ldGhvZHMgZnJvbSB3aXRoaW4gb3VyIGFwcGxpY2F0aW9uIHNvIGEgY29ubmVjdGlvbiBjYW4gYmUgYWN0aXZhdGVkXG4gICAgICAgIHRoaXMuc2VuZE1lc3NhZ2VDb250cm9sbGVyID0gbmV3IFNlbmRNZXNzYWdlQ29udHJvbGxlcihcbiAgICAgICAgICAgIHRoaXMuZGF0YUNoYW5uZWxTZW5kZXIsXG4gICAgICAgICAgICB0aGlzLnN0cmVhbU1lc3NhZ2VDb250cm9sbGVyXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMudG9TdHJlYW1lck1lc3NhZ2VzQ29udHJvbGxlciA9IG5ldyBUb1N0cmVhbWVyTWVzc2FnZXNDb250cm9sbGVyKFxuICAgICAgICAgICAgdGhpcy5zZW5kTWVzc2FnZUNvbnRyb2xsZXJcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5yZWdpc3Rlck1lc3NhZ2VIYW5kbGVycygpO1xuICAgICAgICB0aGlzLnN0cmVhbU1lc3NhZ2VDb250cm9sbGVyLnBvcHVsYXRlRGVmYXVsdFByb3RvY29sKCk7XG5cbiAgICAgICAgdGhpcy5pbnB1dENsYXNzZXNGYWN0b3J5ID0gbmV3IElucHV0Q2xhc3Nlc0ZhY3RvcnkoXG4gICAgICAgICAgICB0aGlzLnN0cmVhbU1lc3NhZ2VDb250cm9sbGVyLFxuICAgICAgICAgICAgdGhpcy52aWRlb1BsYXllcixcbiAgICAgICAgICAgIHRoaXMuY29vcmRpbmF0ZUNvbnZlcnRlclxuICAgICAgICApO1xuXG4gICAgICAgIHRoaXMuaXNVc2luZ1NGVSA9IGZhbHNlO1xuICAgICAgICB0aGlzLmlzUXVhbGl0eUNvbnRyb2xsZXIgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5wcmVmZXJyZWRDb2RlYyA9ICcnO1xuICAgICAgICB0aGlzLnNob3VsZFJlY29ubmVjdCA9IHRydWU7XG4gICAgICAgIHRoaXMuaXNSZWNvbm5lY3RpbmcgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5yZWNvbm5lY3RBdHRlbXB0ID0gMDtcblxuICAgICAgICB0aGlzLmNvbmZpZy5fYWRkT25PcHRpb25TZXR0aW5nQ2hhbmdlZExpc3RlbmVyKFxuICAgICAgICAgICAgT3B0aW9uUGFyYW1ldGVycy5TdHJlYW1lcklkLFxuICAgICAgICAgICAgKHN0cmVhbWVyaWQpID0+IHtcbiAgICAgICAgICAgICAgICBpZihzdHJlYW1lcmlkID09PSBcIlwiKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBjbG9zZSB0aGUgY3VycmVudCBwZWVyIGNvbm5lY3Rpb24gYW5kIGNyZWF0ZSBhIG5ldyBvbmVcbiAgICAgICAgICAgICAgICB0aGlzLnBlZXJDb25uZWN0aW9uQ29udHJvbGxlci5wZWVyQ29ubmVjdGlvbi5jbG9zZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMucGVlckNvbm5lY3Rpb25Db250cm9sbGVyLmNyZWF0ZVBlZXJDb25uZWN0aW9uKFxuICAgICAgICAgICAgICAgICAgICB0aGlzLnBlZXJDb25maWcsXG4gICAgICAgICAgICAgICAgICAgIHRoaXMucHJlZmVycmVkQ29kZWNcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIHRoaXMuc3Vic2NyaWJlZFN0cmVhbSA9IHN0cmVhbWVyaWQ7XG4gICAgICAgICAgICAgICAgdGhpcy53ZWJTb2NrZXRDb250cm9sbGVyLnNlbmRTdWJzY3JpYmUoc3RyZWFtZXJpZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICk7XG5cbiAgICAgICAgdGhpcy5zZXRWaWRlb0VuY29kZXJBdmdRUCgtMSk7XG5cbiAgICAgICAgdGhpcy5zaWduYWxsaW5nVXJsQnVpbGRlciA9ICAoKSA9PiB7XG4gICAgICAgICAgICBsZXQgc2lnbmFsbGluZ1NlcnZlclVybCA9IHRoaXMuY29uZmlnLmdldFRleHRTZXR0aW5nVmFsdWUoXG4gICAgICAgICAgICAgICAgVGV4dFBhcmFtZXRlcnMuU2lnbmFsbGluZ1NlcnZlclVybFxuICAgICAgICAgICAgKTtcbiAgICBcbiAgICAgICAgICAgIC8vIElmIHdlIGFyZSBjb25uZWN0aW5nIHRvIHRoZSBTRlUgYWRkIGEgc3BlY2lhbCB1cmwgcGFyYW1ldGVyIHRvIHRoZSB1cmxcbiAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZy5pc0ZsYWdFbmFibGVkKEZsYWdzLkJyb3dzZXJTZW5kT2ZmZXIpKSB7XG4gICAgICAgICAgICAgICAgc2lnbmFsbGluZ1NlcnZlclVybCArPSAnPycgKyBGbGFncy5Ccm93c2VyU2VuZE9mZmVyICsgJz10cnVlJztcbiAgICAgICAgICAgIH1cbiAgICBcbiAgICAgICAgICAgIC8vIFRoaXMgY29kZSBpcyBubyBsb25nZXIgbmVlZGVkLCBidXQgaXMgYSBnb29kIGV4YW1wbGUgZm9yIGhvdyBzdWJzZXF1ZW50IGNvbmZpZyBmbGFncyBjYW4gYmUgYXBwZW5kZWRcbiAgICAgICAgICAgIC8vIGlmICh0aGlzLmNvbmZpZy5pc0ZsYWdFbmFibGVkKEZsYWdzLkJyb3dzZXJTZW5kT2ZmZXIpKSB7XG4gICAgICAgICAgICAvLyAgICAgc2lnbmFsbGluZ1NlcnZlclVybCArPSAoc2lnbmFsbGluZ1NlcnZlclVybC5pbmNsdWRlcygnPycpID8gJyYnIDogJz8nKSArIEZsYWdzLkJyb3dzZXJTZW5kT2ZmZXIgKyAnPXRydWUnO1xuICAgICAgICAgICAgLy8gfVxuICAgIFxuICAgICAgICAgICAgcmV0dXJuIHNpZ25hbGxpbmdTZXJ2ZXJVcmw7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNYWtlIGEgcmVxdWVzdCB0byBVbnF1YW50aXplZEFuZERlbm9ybWFsaXplVW5zaWduZWQgY29vcmRpbmF0ZXNcbiAgICAgKiBAcGFyYW0geCB4IGF4aXMgY29vcmRpbmF0ZVxuICAgICAqIEBwYXJhbSB5IHkgYXhpcyBjb29yZGluYXRlXG4gICAgICovXG4gICAgcmVxdWVzdFVucXVhbnRpemVkQW5kRGVub3JtYWxpemVVbnNpZ25lZChcbiAgICAgICAgeDogbnVtYmVyLFxuICAgICAgICB5OiBudW1iZXJcbiAgICApOiBVbnF1YW50aXplZERlbm9ybWFsaXplZFVuc2lnbmVkQ29vcmQge1xuICAgICAgICByZXR1cm4gdGhpcy5jb29yZGluYXRlQ29udmVydGVyLnVucXVhbnRpemVBbmREZW5vcm1hbGl6ZVVuc2lnbmVkKHgsIHkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXMgd2hlbiBhIG1lc3NhZ2UgaXMgcmVjZWl2ZWRcbiAgICAgKiBAcGFyYW0gZXZlbnQgLSBNZXNzYWdlIEV2ZW50XG4gICAgICovXG4gICAgaGFuZGxlT25NZXNzYWdlKGV2ZW50OiBNZXNzYWdlRXZlbnQpIHtcbiAgICAgICAgY29uc3QgbWVzc2FnZSA9IG5ldyBVaW50OEFycmF5KGV2ZW50LmRhdGEpO1xuICAgICAgICBMb2dnZXIuTG9nKExvZ2dlci5HZXRTdGFja1RyYWNlKCksICdNZXNzYWdlIGluY29taW5nOicgKyBtZXNzYWdlLCA2KTtcblxuICAgICAgICAvL3RyeSB7XG4gICAgICAgIGNvbnN0IG1lc3NhZ2VUeXBlID1cbiAgICAgICAgICAgIHRoaXMuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIuZnJvbVN0cmVhbWVyTWVzc2FnZXMuZ2V0KFxuICAgICAgICAgICAgICAgIG1lc3NhZ2VbMF1cbiAgICAgICAgICAgICk7XG4gICAgICAgIHRoaXMuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIuZnJvbVN0cmVhbWVySGFuZGxlcnMuZ2V0KG1lc3NhZ2VUeXBlKShcbiAgICAgICAgICAgIGV2ZW50LmRhdGFcbiAgICAgICAgKTtcbiAgICAgICAgLy99IGNhdGNoIChlKSB7XG4gICAgICAgIC8vTG9nZ2VyLkVycm9yKExvZ2dlci5HZXRTdGFja1RyYWNlKCksIGBDdXN0b20gZGF0YSBjaGFubmVsIG1lc3NhZ2Ugd2l0aCBtZXNzYWdlIHR5cGUgdGhhdCBpcyB1bmtub3duIHRvIHRoZSBQaXhlbCBTdHJlYW1pbmcgcHJvdG9jb2wuIERvZXMgeW91ciBQaXhlbFN0cmVhbWluZ1Byb3RvY29sIG5lZWQgdXBkYXRpbmc/IFRoZSBtZXNzYWdlIHR5cGUgd2FzOiAke21lc3NhZ2VbMF19YCk7XG4gICAgICAgIC8vfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlZ2lzdGVyIG1lc3NhZ2UgYWxsIGhhbmRsZXJzXG4gICAgICovXG4gICAgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlcnMoKSB7XG4gICAgICAgIC8vIEZyb20gU3RyZWFtZXJcbiAgICAgICAgLy8gTWVzc2FnZSBldmVudHMgZnJvbSB0aGUgc3RyZWFtZXIgaGF2ZSBhIGRhdGEgdHlwZSBvZiBBcnJheUJ1ZmZlciBhcyB3ZSBmb3JjZSB0aGlzIHR5cGUgaW4gdGhlIERhdGFjaGFubmVsQ29udHJvbGxlclxuICAgICAgICB0aGlzLnN0cmVhbU1lc3NhZ2VDb250cm9sbGVyLnJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIoXG4gICAgICAgICAgICBNZXNzYWdlRGlyZWN0aW9uLkZyb21TdHJlYW1lcixcbiAgICAgICAgICAgICdRdWFsaXR5Q29udHJvbE93bmVyc2hpcCcsXG4gICAgICAgICAgICAoZGF0YTogQXJyYXlCdWZmZXIpID0+IHRoaXMub25RdWFsaXR5Q29udHJvbE93bmVyc2hpcChkYXRhKVxuICAgICAgICApO1xuICAgICAgICB0aGlzLnN0cmVhbU1lc3NhZ2VDb250cm9sbGVyLnJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIoXG4gICAgICAgICAgICBNZXNzYWdlRGlyZWN0aW9uLkZyb21TdHJlYW1lcixcbiAgICAgICAgICAgICdSZXNwb25zZScsXG4gICAgICAgICAgICAoZGF0YTogQXJyYXlCdWZmZXIpID0+IHRoaXMucmVzcG9uc2VDb250cm9sbGVyLm9uUmVzcG9uc2UoZGF0YSlcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5zdHJlYW1NZXNzYWdlQ29udHJvbGxlci5yZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKFxuICAgICAgICAgICAgTWVzc2FnZURpcmVjdGlvbi5Gcm9tU3RyZWFtZXIsXG4gICAgICAgICAgICAnQ29tbWFuZCcsXG4gICAgICAgICAgICAoZGF0YTogQXJyYXlCdWZmZXIpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLm9uQ29tbWFuZChkYXRhKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5zdHJlYW1NZXNzYWdlQ29udHJvbGxlci5yZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKFxuICAgICAgICAgICAgTWVzc2FnZURpcmVjdGlvbi5Gcm9tU3RyZWFtZXIsXG4gICAgICAgICAgICAnRnJlZXplRnJhbWUnLFxuICAgICAgICAgICAgKGRhdGE6IEFycmF5QnVmZmVyKSA9PiB0aGlzLm9uRnJlZXplRnJhbWVNZXNzYWdlKGRhdGEpXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIucmVnaXN0ZXJNZXNzYWdlSGFuZGxlcihcbiAgICAgICAgICAgIE1lc3NhZ2VEaXJlY3Rpb24uRnJvbVN0cmVhbWVyLFxuICAgICAgICAgICAgJ1VuZnJlZXplRnJhbWUnLFxuICAgICAgICAgICAgKCkgPT4gdGhpcy5pbnZhbGlkYXRlRnJlZXplRnJhbWVBbmRFbmFibGVWaWRlbygpXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIucmVnaXN0ZXJNZXNzYWdlSGFuZGxlcihcbiAgICAgICAgICAgIE1lc3NhZ2VEaXJlY3Rpb24uRnJvbVN0cmVhbWVyLFxuICAgICAgICAgICAgJ1ZpZGVvRW5jb2RlckF2Z1FQJyxcbiAgICAgICAgICAgIChkYXRhOiBBcnJheUJ1ZmZlcikgPT4gdGhpcy5oYW5kbGVWaWRlb0VuY29kZXJBdmdRUChkYXRhKVxuICAgICAgICApO1xuICAgICAgICB0aGlzLnN0cmVhbU1lc3NhZ2VDb250cm9sbGVyLnJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIoXG4gICAgICAgICAgICBNZXNzYWdlRGlyZWN0aW9uLkZyb21TdHJlYW1lcixcbiAgICAgICAgICAgICdMYXRlbmN5VGVzdCcsXG4gICAgICAgICAgICAoZGF0YTogQXJyYXlCdWZmZXIpID0+IHRoaXMuaGFuZGxlTGF0ZW5jeVRlc3RSZXN1bHQoZGF0YSlcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5zdHJlYW1NZXNzYWdlQ29udHJvbGxlci5yZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKFxuICAgICAgICAgICAgTWVzc2FnZURpcmVjdGlvbi5Gcm9tU3RyZWFtZXIsXG4gICAgICAgICAgICAnRGF0YUNoYW5uZWxMYXRlbmN5VGVzdCcsXG4gICAgICAgICAgICAoZGF0YTogQXJyYXlCdWZmZXIpID0+IHRoaXMuaGFuZGxlRGF0YUNoYW5uZWxMYXRlbmN5VGVzdFJlc3BvbnNlKGRhdGEpXG4gICAgICAgIClcbiAgICAgICAgdGhpcy5zdHJlYW1NZXNzYWdlQ29udHJvbGxlci5yZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKFxuICAgICAgICAgICAgTWVzc2FnZURpcmVjdGlvbi5Gcm9tU3RyZWFtZXIsXG4gICAgICAgICAgICAnSW5pdGlhbFNldHRpbmdzJyxcbiAgICAgICAgICAgIChkYXRhOiBBcnJheUJ1ZmZlcikgPT4gdGhpcy5oYW5kbGVJbml0aWFsU2V0dGluZ3MoZGF0YSlcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5zdHJlYW1NZXNzYWdlQ29udHJvbGxlci5yZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKFxuICAgICAgICAgICAgTWVzc2FnZURpcmVjdGlvbi5Gcm9tU3RyZWFtZXIsXG4gICAgICAgICAgICAnRmlsZUV4dGVuc2lvbicsXG4gICAgICAgICAgICAoZGF0YTogQXJyYXlCdWZmZXIpID0+IHRoaXMub25GaWxlRXh0ZW5zaW9uKGRhdGEpXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIucmVnaXN0ZXJNZXNzYWdlSGFuZGxlcihcbiAgICAgICAgICAgIE1lc3NhZ2VEaXJlY3Rpb24uRnJvbVN0cmVhbWVyLFxuICAgICAgICAgICAgJ0ZpbGVNaW1lVHlwZScsXG4gICAgICAgICAgICAoZGF0YTogQXJyYXlCdWZmZXIpID0+IHRoaXMub25GaWxlTWltZVR5cGUoZGF0YSlcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5zdHJlYW1NZXNzYWdlQ29udHJvbGxlci5yZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKFxuICAgICAgICAgICAgTWVzc2FnZURpcmVjdGlvbi5Gcm9tU3RyZWFtZXIsXG4gICAgICAgICAgICAnRmlsZUNvbnRlbnRzJyxcbiAgICAgICAgICAgIChkYXRhOiBBcnJheUJ1ZmZlcikgPT4gdGhpcy5vbkZpbGVDb250ZW50cyhkYXRhKVxuICAgICAgICApO1xuICAgICAgICB0aGlzLnN0cmVhbU1lc3NhZ2VDb250cm9sbGVyLnJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIoXG4gICAgICAgICAgICBNZXNzYWdlRGlyZWN0aW9uLkZyb21TdHJlYW1lcixcbiAgICAgICAgICAgICdUZXN0RWNobycsXG4gICAgICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgICAgICAgLyogRG8gbm90aGluZyAqL1xuICAgICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgICB0aGlzLnN0cmVhbU1lc3NhZ2VDb250cm9sbGVyLnJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIoXG4gICAgICAgICAgICBNZXNzYWdlRGlyZWN0aW9uLkZyb21TdHJlYW1lcixcbiAgICAgICAgICAgICdJbnB1dENvbnRyb2xPd25lcnNoaXAnLFxuICAgICAgICAgICAgKGRhdGE6IEFycmF5QnVmZmVyKSA9PiB0aGlzLm9uSW5wdXRDb250cm9sT3duZXJzaGlwKGRhdGEpXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIucmVnaXN0ZXJNZXNzYWdlSGFuZGxlcihcbiAgICAgICAgICAgIE1lc3NhZ2VEaXJlY3Rpb24uRnJvbVN0cmVhbWVyLFxuICAgICAgICAgICAgJ0dhbWVwYWRSZXNwb25zZScsXG4gICAgICAgICAgICAoZGF0YTogQXJyYXlCdWZmZXIpID0+IHRoaXMub25HYW1lcGFkUmVzcG9uc2UoZGF0YSlcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5zdHJlYW1NZXNzYWdlQ29udHJvbGxlci5yZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKFxuICAgICAgICAgICAgTWVzc2FnZURpcmVjdGlvbi5Gcm9tU3RyZWFtZXIsXG4gICAgICAgICAgICAnUHJvdG9jb2wnLFxuICAgICAgICAgICAgKGRhdGE6IEFycmF5QnVmZmVyKSA9PiB0aGlzLm9uUHJvdG9jb2xNZXNzYWdlKGRhdGEpXG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gVG8gU3RyZWFtZXJcbiAgICAgICAgdGhpcy5zdHJlYW1NZXNzYWdlQ29udHJvbGxlci5yZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKFxuICAgICAgICAgICAgTWVzc2FnZURpcmVjdGlvbi5Ub1N0cmVhbWVyLFxuICAgICAgICAgICAgJ0lGcmFtZVJlcXVlc3QnLFxuICAgICAgICAgICAgKCkgPT5cbiAgICAgICAgICAgICAgICB0aGlzLnNlbmRNZXNzYWdlQ29udHJvbGxlci5zZW5kTWVzc2FnZVRvU3RyZWFtZXIoXG4gICAgICAgICAgICAgICAgICAgICdJRnJhbWVSZXF1ZXN0J1xuICAgICAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5zdHJlYW1NZXNzYWdlQ29udHJvbGxlci5yZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKFxuICAgICAgICAgICAgTWVzc2FnZURpcmVjdGlvbi5Ub1N0cmVhbWVyLFxuICAgICAgICAgICAgJ1JlcXVlc3RRdWFsaXR5Q29udHJvbCcsXG4gICAgICAgICAgICAoKSA9PlxuICAgICAgICAgICAgICAgIHRoaXMuc2VuZE1lc3NhZ2VDb250cm9sbGVyLnNlbmRNZXNzYWdlVG9TdHJlYW1lcihcbiAgICAgICAgICAgICAgICAgICAgJ1JlcXVlc3RRdWFsaXR5Q29udHJvbCdcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIucmVnaXN0ZXJNZXNzYWdlSGFuZGxlcihcbiAgICAgICAgICAgIE1lc3NhZ2VEaXJlY3Rpb24uVG9TdHJlYW1lcixcbiAgICAgICAgICAgICdGcHNSZXF1ZXN0JyxcbiAgICAgICAgICAgICgpID0+IHRoaXMuc2VuZE1lc3NhZ2VDb250cm9sbGVyLnNlbmRNZXNzYWdlVG9TdHJlYW1lcignRnBzUmVxdWVzdCcpXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIucmVnaXN0ZXJNZXNzYWdlSGFuZGxlcihcbiAgICAgICAgICAgIE1lc3NhZ2VEaXJlY3Rpb24uVG9TdHJlYW1lcixcbiAgICAgICAgICAgICdBdmVyYWdlQml0cmF0ZVJlcXVlc3QnLFxuICAgICAgICAgICAgKCkgPT5cbiAgICAgICAgICAgICAgICB0aGlzLnNlbmRNZXNzYWdlQ29udHJvbGxlci5zZW5kTWVzc2FnZVRvU3RyZWFtZXIoXG4gICAgICAgICAgICAgICAgICAgICdBdmVyYWdlQml0cmF0ZVJlcXVlc3QnXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgICAgICB0aGlzLnN0cmVhbU1lc3NhZ2VDb250cm9sbGVyLnJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIoXG4gICAgICAgICAgICBNZXNzYWdlRGlyZWN0aW9uLlRvU3RyZWFtZXIsXG4gICAgICAgICAgICAnU3RhcnRTdHJlYW1pbmcnLFxuICAgICAgICAgICAgKCkgPT5cbiAgICAgICAgICAgICAgICB0aGlzLnNlbmRNZXNzYWdlQ29udHJvbGxlci5zZW5kTWVzc2FnZVRvU3RyZWFtZXIoXG4gICAgICAgICAgICAgICAgICAgICdTdGFydFN0cmVhbWluZydcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIucmVnaXN0ZXJNZXNzYWdlSGFuZGxlcihcbiAgICAgICAgICAgIE1lc3NhZ2VEaXJlY3Rpb24uVG9TdHJlYW1lcixcbiAgICAgICAgICAgICdTdG9wU3RyZWFtaW5nJyxcbiAgICAgICAgICAgICgpID0+XG4gICAgICAgICAgICAgICAgdGhpcy5zZW5kTWVzc2FnZUNvbnRyb2xsZXIuc2VuZE1lc3NhZ2VUb1N0cmVhbWVyKFxuICAgICAgICAgICAgICAgICAgICAnU3RvcFN0cmVhbWluZydcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIucmVnaXN0ZXJNZXNzYWdlSGFuZGxlcihcbiAgICAgICAgICAgIE1lc3NhZ2VEaXJlY3Rpb24uVG9TdHJlYW1lcixcbiAgICAgICAgICAgICdMYXRlbmN5VGVzdCcsXG4gICAgICAgICAgICAoZGF0YTogQXJyYXk8bnVtYmVyIHwgc3RyaW5nPikgPT5cbiAgICAgICAgICAgICAgICB0aGlzLnNlbmRNZXNzYWdlQ29udHJvbGxlci5zZW5kTWVzc2FnZVRvU3RyZWFtZXIoXG4gICAgICAgICAgICAgICAgICAgICdMYXRlbmN5VGVzdCcsIGRhdGFcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIucmVnaXN0ZXJNZXNzYWdlSGFuZGxlcihcbiAgICAgICAgICAgIE1lc3NhZ2VEaXJlY3Rpb24uVG9TdHJlYW1lcixcbiAgICAgICAgICAgICdSZXF1ZXN0SW5pdGlhbFNldHRpbmdzJyxcbiAgICAgICAgICAgICgpID0+XG4gICAgICAgICAgICAgICAgdGhpcy5zZW5kTWVzc2FnZUNvbnRyb2xsZXIuc2VuZE1lc3NhZ2VUb1N0cmVhbWVyKFxuICAgICAgICAgICAgICAgICAgICAnUmVxdWVzdEluaXRpYWxTZXR0aW5ncydcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIucmVnaXN0ZXJNZXNzYWdlSGFuZGxlcihcbiAgICAgICAgICAgIE1lc3NhZ2VEaXJlY3Rpb24uVG9TdHJlYW1lcixcbiAgICAgICAgICAgICdUZXN0RWNobycsXG4gICAgICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgICAgICAgLyogRG8gbm90aGluZyAqL1xuICAgICAgICAgICAgfVxuICAgICAgICApO1xuICAgICAgICB0aGlzLnN0cmVhbU1lc3NhZ2VDb250cm9sbGVyLnJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIoXG4gICAgICAgICAgICBNZXNzYWdlRGlyZWN0aW9uLlRvU3RyZWFtZXIsXG4gICAgICAgICAgICAnVUlJbnRlcmFjdGlvbicsXG4gICAgICAgICAgICAoZGF0YTogQXJyYXk8bnVtYmVyIHwgc3RyaW5nPikgPT5cbiAgICAgICAgICAgICAgICB0aGlzLnNlbmRNZXNzYWdlQ29udHJvbGxlci5zZW5kTWVzc2FnZVRvU3RyZWFtZXIoXG4gICAgICAgICAgICAgICAgICAgICdVSUludGVyYWN0aW9uJywgZGF0YVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5zdHJlYW1NZXNzYWdlQ29udHJvbGxlci5yZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKFxuICAgICAgICAgICAgTWVzc2FnZURpcmVjdGlvbi5Ub1N0cmVhbWVyLFxuICAgICAgICAgICAgJ0NvbW1hbmQnLFxuICAgICAgICAgICAgKGRhdGE6IEFycmF5PG51bWJlciB8IHN0cmluZz4pID0+IFxuICAgICAgICAgICAgICAgIHRoaXMuc2VuZE1lc3NhZ2VDb250cm9sbGVyLnNlbmRNZXNzYWdlVG9TdHJlYW1lcihcbiAgICAgICAgICAgICAgICAgICAgJ0NvbW1hbmQnLCBkYXRhXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgICAgICB0aGlzLnN0cmVhbU1lc3NhZ2VDb250cm9sbGVyLnJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIoXG4gICAgICAgICAgICBNZXNzYWdlRGlyZWN0aW9uLlRvU3RyZWFtZXIsXG4gICAgICAgICAgICAnVGV4dGJveEVudHJ5JyxcbiAgICAgICAgICAgIChkYXRhOiBBcnJheTxudW1iZXIgfCBzdHJpbmc+KSA9PiBcbiAgICAgICAgICAgICAgICB0aGlzLnNlbmRNZXNzYWdlQ29udHJvbGxlci5zZW5kTWVzc2FnZVRvU3RyZWFtZXIoXG4gICAgICAgICAgICAgICAgICAgICdUZXh0Ym94RW50cnknLCBkYXRhXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgICAgICB0aGlzLnN0cmVhbU1lc3NhZ2VDb250cm9sbGVyLnJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIoXG4gICAgICAgICAgICBNZXNzYWdlRGlyZWN0aW9uLlRvU3RyZWFtZXIsXG4gICAgICAgICAgICAnS2V5RG93bicsXG4gICAgICAgICAgICAoZGF0YTogQXJyYXk8bnVtYmVyIHwgc3RyaW5nPikgPT5cbiAgICAgICAgICAgICAgICB0aGlzLnNlbmRNZXNzYWdlQ29udHJvbGxlci5zZW5kTWVzc2FnZVRvU3RyZWFtZXIoXG4gICAgICAgICAgICAgICAgICAgICdLZXlEb3duJyxcbiAgICAgICAgICAgICAgICAgICAgZGF0YVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5zdHJlYW1NZXNzYWdlQ29udHJvbGxlci5yZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKFxuICAgICAgICAgICAgTWVzc2FnZURpcmVjdGlvbi5Ub1N0cmVhbWVyLFxuICAgICAgICAgICAgJ0tleVVwJyxcbiAgICAgICAgICAgIChkYXRhOiBBcnJheTxudW1iZXIgfCBzdHJpbmc+KSA9PlxuICAgICAgICAgICAgICAgIHRoaXMuc2VuZE1lc3NhZ2VDb250cm9sbGVyLnNlbmRNZXNzYWdlVG9TdHJlYW1lcignS2V5VXAnLCBkYXRhKVxuICAgICAgICApO1xuICAgICAgICB0aGlzLnN0cmVhbU1lc3NhZ2VDb250cm9sbGVyLnJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIoXG4gICAgICAgICAgICBNZXNzYWdlRGlyZWN0aW9uLlRvU3RyZWFtZXIsXG4gICAgICAgICAgICAnS2V5UHJlc3MnLFxuICAgICAgICAgICAgKGRhdGE6IEFycmF5PG51bWJlciB8IHN0cmluZz4pID0+XG4gICAgICAgICAgICAgICAgdGhpcy5zZW5kTWVzc2FnZUNvbnRyb2xsZXIuc2VuZE1lc3NhZ2VUb1N0cmVhbWVyKFxuICAgICAgICAgICAgICAgICAgICAnS2V5UHJlc3MnLFxuICAgICAgICAgICAgICAgICAgICBkYXRhXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgICAgICB0aGlzLnN0cmVhbU1lc3NhZ2VDb250cm9sbGVyLnJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIoXG4gICAgICAgICAgICBNZXNzYWdlRGlyZWN0aW9uLlRvU3RyZWFtZXIsXG4gICAgICAgICAgICAnTW91c2VFbnRlcicsXG4gICAgICAgICAgICAoZGF0YTogQXJyYXk8bnVtYmVyIHwgc3RyaW5nPikgPT5cbiAgICAgICAgICAgICAgICB0aGlzLnNlbmRNZXNzYWdlQ29udHJvbGxlci5zZW5kTWVzc2FnZVRvU3RyZWFtZXIoXG4gICAgICAgICAgICAgICAgICAgICdNb3VzZUVudGVyJyxcbiAgICAgICAgICAgICAgICAgICAgZGF0YVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5zdHJlYW1NZXNzYWdlQ29udHJvbGxlci5yZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKFxuICAgICAgICAgICAgTWVzc2FnZURpcmVjdGlvbi5Ub1N0cmVhbWVyLFxuICAgICAgICAgICAgJ01vdXNlTGVhdmUnLFxuICAgICAgICAgICAgKGRhdGE6IEFycmF5PG51bWJlciB8IHN0cmluZz4pID0+XG4gICAgICAgICAgICAgICAgdGhpcy5zZW5kTWVzc2FnZUNvbnRyb2xsZXIuc2VuZE1lc3NhZ2VUb1N0cmVhbWVyKFxuICAgICAgICAgICAgICAgICAgICAnTW91c2VMZWF2ZScsXG4gICAgICAgICAgICAgICAgICAgIGRhdGFcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIucmVnaXN0ZXJNZXNzYWdlSGFuZGxlcihcbiAgICAgICAgICAgIE1lc3NhZ2VEaXJlY3Rpb24uVG9TdHJlYW1lcixcbiAgICAgICAgICAgICdNb3VzZURvd24nLFxuICAgICAgICAgICAgKGRhdGE6IEFycmF5PG51bWJlciB8IHN0cmluZz4pID0+XG4gICAgICAgICAgICAgICAgdGhpcy5zZW5kTWVzc2FnZUNvbnRyb2xsZXIuc2VuZE1lc3NhZ2VUb1N0cmVhbWVyKFxuICAgICAgICAgICAgICAgICAgICAnTW91c2VEb3duJyxcbiAgICAgICAgICAgICAgICAgICAgZGF0YVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5zdHJlYW1NZXNzYWdlQ29udHJvbGxlci5yZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKFxuICAgICAgICAgICAgTWVzc2FnZURpcmVjdGlvbi5Ub1N0cmVhbWVyLFxuICAgICAgICAgICAgJ01vdXNlVXAnLFxuICAgICAgICAgICAgKGRhdGE6IEFycmF5PG51bWJlciB8IHN0cmluZz4pID0+XG4gICAgICAgICAgICAgICAgdGhpcy5zZW5kTWVzc2FnZUNvbnRyb2xsZXIuc2VuZE1lc3NhZ2VUb1N0cmVhbWVyKFxuICAgICAgICAgICAgICAgICAgICAnTW91c2VVcCcsXG4gICAgICAgICAgICAgICAgICAgIGRhdGFcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIucmVnaXN0ZXJNZXNzYWdlSGFuZGxlcihcbiAgICAgICAgICAgIE1lc3NhZ2VEaXJlY3Rpb24uVG9TdHJlYW1lcixcbiAgICAgICAgICAgICdNb3VzZU1vdmUnLFxuICAgICAgICAgICAgKGRhdGE6IEFycmF5PG51bWJlciB8IHN0cmluZz4pID0+XG4gICAgICAgICAgICAgICAgdGhpcy5zZW5kTWVzc2FnZUNvbnRyb2xsZXIuc2VuZE1lc3NhZ2VUb1N0cmVhbWVyKFxuICAgICAgICAgICAgICAgICAgICAnTW91c2VNb3ZlJyxcbiAgICAgICAgICAgICAgICAgICAgZGF0YVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5zdHJlYW1NZXNzYWdlQ29udHJvbGxlci5yZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKFxuICAgICAgICAgICAgTWVzc2FnZURpcmVjdGlvbi5Ub1N0cmVhbWVyLFxuICAgICAgICAgICAgJ01vdXNlV2hlZWwnLFxuICAgICAgICAgICAgKGRhdGE6IEFycmF5PG51bWJlciB8IHN0cmluZz4pID0+XG4gICAgICAgICAgICAgICAgdGhpcy5zZW5kTWVzc2FnZUNvbnRyb2xsZXIuc2VuZE1lc3NhZ2VUb1N0cmVhbWVyKFxuICAgICAgICAgICAgICAgICAgICAnTW91c2VXaGVlbCcsXG4gICAgICAgICAgICAgICAgICAgIGRhdGFcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIucmVnaXN0ZXJNZXNzYWdlSGFuZGxlcihcbiAgICAgICAgICAgIE1lc3NhZ2VEaXJlY3Rpb24uVG9TdHJlYW1lcixcbiAgICAgICAgICAgICdNb3VzZURvdWJsZScsXG4gICAgICAgICAgICAoZGF0YTogQXJyYXk8bnVtYmVyIHwgc3RyaW5nPikgPT5cbiAgICAgICAgICAgICAgICB0aGlzLnNlbmRNZXNzYWdlQ29udHJvbGxlci5zZW5kTWVzc2FnZVRvU3RyZWFtZXIoXG4gICAgICAgICAgICAgICAgICAgICdNb3VzZURvdWJsZScsXG4gICAgICAgICAgICAgICAgICAgIGRhdGFcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIucmVnaXN0ZXJNZXNzYWdlSGFuZGxlcihcbiAgICAgICAgICAgIE1lc3NhZ2VEaXJlY3Rpb24uVG9TdHJlYW1lcixcbiAgICAgICAgICAgICdUb3VjaFN0YXJ0JyxcbiAgICAgICAgICAgIChkYXRhOiBBcnJheTxudW1iZXIgfCBzdHJpbmc+KSA9PlxuICAgICAgICAgICAgICAgIHRoaXMuc2VuZE1lc3NhZ2VDb250cm9sbGVyLnNlbmRNZXNzYWdlVG9TdHJlYW1lcihcbiAgICAgICAgICAgICAgICAgICAgJ1RvdWNoU3RhcnQnLFxuICAgICAgICAgICAgICAgICAgICBkYXRhXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgICAgICB0aGlzLnN0cmVhbU1lc3NhZ2VDb250cm9sbGVyLnJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIoXG4gICAgICAgICAgICBNZXNzYWdlRGlyZWN0aW9uLlRvU3RyZWFtZXIsXG4gICAgICAgICAgICAnVG91Y2hFbmQnLFxuICAgICAgICAgICAgKGRhdGE6IEFycmF5PG51bWJlciB8IHN0cmluZz4pID0+XG4gICAgICAgICAgICAgICAgdGhpcy5zZW5kTWVzc2FnZUNvbnRyb2xsZXIuc2VuZE1lc3NhZ2VUb1N0cmVhbWVyKFxuICAgICAgICAgICAgICAgICAgICAnVG91Y2hFbmQnLFxuICAgICAgICAgICAgICAgICAgICBkYXRhXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgICAgICB0aGlzLnN0cmVhbU1lc3NhZ2VDb250cm9sbGVyLnJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIoXG4gICAgICAgICAgICBNZXNzYWdlRGlyZWN0aW9uLlRvU3RyZWFtZXIsXG4gICAgICAgICAgICAnVG91Y2hNb3ZlJyxcbiAgICAgICAgICAgIChkYXRhOiBBcnJheTxudW1iZXIgfCBzdHJpbmc+KSA9PlxuICAgICAgICAgICAgICAgIHRoaXMuc2VuZE1lc3NhZ2VDb250cm9sbGVyLnNlbmRNZXNzYWdlVG9TdHJlYW1lcihcbiAgICAgICAgICAgICAgICAgICAgJ1RvdWNoTW92ZScsXG4gICAgICAgICAgICAgICAgICAgIGRhdGFcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIucmVnaXN0ZXJNZXNzYWdlSGFuZGxlcihcbiAgICAgICAgICAgIE1lc3NhZ2VEaXJlY3Rpb24uVG9TdHJlYW1lcixcbiAgICAgICAgICAgICdHYW1lcGFkQ29ubmVjdGVkJyxcbiAgICAgICAgICAgICgpID0+XG4gICAgICAgICAgICAgICAgdGhpcy5zZW5kTWVzc2FnZUNvbnRyb2xsZXIuc2VuZE1lc3NhZ2VUb1N0cmVhbWVyKFxuICAgICAgICAgICAgICAgICAgICAnR2FtZXBhZENvbm5lY3RlZCdcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIucmVnaXN0ZXJNZXNzYWdlSGFuZGxlcihcbiAgICAgICAgICAgIE1lc3NhZ2VEaXJlY3Rpb24uVG9TdHJlYW1lcixcbiAgICAgICAgICAgICdHYW1lcGFkQnV0dG9uUHJlc3NlZCcsXG4gICAgICAgICAgICAoZGF0YTogQXJyYXk8bnVtYmVyIHwgc3RyaW5nPikgPT5cbiAgICAgICAgICAgICAgICB0aGlzLnNlbmRNZXNzYWdlQ29udHJvbGxlci5zZW5kTWVzc2FnZVRvU3RyZWFtZXIoXG4gICAgICAgICAgICAgICAgICAgICdHYW1lcGFkQnV0dG9uUHJlc3NlZCcsXG4gICAgICAgICAgICAgICAgICAgIGRhdGFcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIucmVnaXN0ZXJNZXNzYWdlSGFuZGxlcihcbiAgICAgICAgICAgIE1lc3NhZ2VEaXJlY3Rpb24uVG9TdHJlYW1lcixcbiAgICAgICAgICAgICdHYW1lcGFkQnV0dG9uUmVsZWFzZWQnLFxuICAgICAgICAgICAgKGRhdGE6IEFycmF5PG51bWJlciB8IHN0cmluZz4pID0+XG4gICAgICAgICAgICAgICAgdGhpcy5zZW5kTWVzc2FnZUNvbnRyb2xsZXIuc2VuZE1lc3NhZ2VUb1N0cmVhbWVyKFxuICAgICAgICAgICAgICAgICAgICAnR2FtZXBhZEJ1dHRvblJlbGVhc2VkJyxcbiAgICAgICAgICAgICAgICAgICAgZGF0YVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5zdHJlYW1NZXNzYWdlQ29udHJvbGxlci5yZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKFxuICAgICAgICAgICAgTWVzc2FnZURpcmVjdGlvbi5Ub1N0cmVhbWVyLFxuICAgICAgICAgICAgJ0dhbWVwYWRBbmFsb2cnLFxuICAgICAgICAgICAgKGRhdGE6IEFycmF5PG51bWJlciB8IHN0cmluZz4pID0+XG4gICAgICAgICAgICAgICAgdGhpcy5zZW5kTWVzc2FnZUNvbnRyb2xsZXIuc2VuZE1lc3NhZ2VUb1N0cmVhbWVyKFxuICAgICAgICAgICAgICAgICAgICAnR2FtZXBhZEFuYWxvZycsXG4gICAgICAgICAgICAgICAgICAgIGRhdGFcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIucmVnaXN0ZXJNZXNzYWdlSGFuZGxlcihcbiAgICAgICAgICAgIE1lc3NhZ2VEaXJlY3Rpb24uVG9TdHJlYW1lcixcbiAgICAgICAgICAgICdHYW1lcGFkRGlzY29ubmVjdGVkJyxcbiAgICAgICAgICAgIChkYXRhOiBBcnJheTxudW1iZXIgfCBzdHJpbmc+KSA9PlxuICAgICAgICAgICAgICAgIHRoaXMuc2VuZE1lc3NhZ2VDb250cm9sbGVyLnNlbmRNZXNzYWdlVG9TdHJlYW1lcihcbiAgICAgICAgICAgICAgICAgICAgJ0dhbWVwYWREaXNjb25uZWN0ZWQnLFxuICAgICAgICAgICAgICAgICAgICBkYXRhXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgICAgICB0aGlzLnN0cmVhbU1lc3NhZ2VDb250cm9sbGVyLnJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIoXG4gICAgICAgICAgICBNZXNzYWdlRGlyZWN0aW9uLlRvU3RyZWFtZXIsXG4gICAgICAgICAgICAnWFJITURUcmFuc2Zvcm0nLFxuICAgICAgICAgICAgKGRhdGE6IEFycmF5PG51bWJlciB8IHN0cmluZz4pID0+XG4gICAgICAgICAgICAgICAgdGhpcy5zZW5kTWVzc2FnZUNvbnRyb2xsZXIuc2VuZE1lc3NhZ2VUb1N0cmVhbWVyKFxuICAgICAgICAgICAgICAgICAgICAnWFJITURUcmFuc2Zvcm0nLFxuICAgICAgICAgICAgICAgICAgICBkYXRhXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgICAgICB0aGlzLnN0cmVhbU1lc3NhZ2VDb250cm9sbGVyLnJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIoXG4gICAgICAgICAgICBNZXNzYWdlRGlyZWN0aW9uLlRvU3RyZWFtZXIsXG4gICAgICAgICAgICAnWFJDb250cm9sbGVyVHJhbnNmb3JtJyxcbiAgICAgICAgICAgIChkYXRhOiBBcnJheTxudW1iZXIgfCBzdHJpbmc+KSA9PlxuICAgICAgICAgICAgICAgIHRoaXMuc2VuZE1lc3NhZ2VDb250cm9sbGVyLnNlbmRNZXNzYWdlVG9TdHJlYW1lcihcbiAgICAgICAgICAgICAgICAgICAgJ1hSQ29udHJvbGxlclRyYW5zZm9ybScsXG4gICAgICAgICAgICAgICAgICAgIGRhdGFcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIucmVnaXN0ZXJNZXNzYWdlSGFuZGxlcihcbiAgICAgICAgICAgIE1lc3NhZ2VEaXJlY3Rpb24uVG9TdHJlYW1lcixcbiAgICAgICAgICAgICdYUlN5c3RlbScsXG4gICAgICAgICAgICAoZGF0YTogQXJyYXk8bnVtYmVyIHwgc3RyaW5nPikgPT5cbiAgICAgICAgICAgICAgICB0aGlzLnNlbmRNZXNzYWdlQ29udHJvbGxlci5zZW5kTWVzc2FnZVRvU3RyZWFtZXIoXG4gICAgICAgICAgICAgICAgICAgICdYUlN5c3RlbScsXG4gICAgICAgICAgICAgICAgICAgIGRhdGFcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIucmVnaXN0ZXJNZXNzYWdlSGFuZGxlcihcbiAgICAgICAgICAgIE1lc3NhZ2VEaXJlY3Rpb24uVG9TdHJlYW1lcixcbiAgICAgICAgICAgICdYUkJ1dHRvblRvdWNoZWQnLFxuICAgICAgICAgICAgKGRhdGE6IEFycmF5PG51bWJlciB8IHN0cmluZz4pID0+XG4gICAgICAgICAgICAgICAgdGhpcy5zZW5kTWVzc2FnZUNvbnRyb2xsZXIuc2VuZE1lc3NhZ2VUb1N0cmVhbWVyKFxuICAgICAgICAgICAgICAgICAgICAnWFJCdXR0b25Ub3VjaGVkJyxcbiAgICAgICAgICAgICAgICAgICAgZGF0YVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5zdHJlYW1NZXNzYWdlQ29udHJvbGxlci5yZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKFxuICAgICAgICAgICAgTWVzc2FnZURpcmVjdGlvbi5Ub1N0cmVhbWVyLFxuICAgICAgICAgICAgJ1hSQnV0dG9uUHJlc3NlZCcsXG4gICAgICAgICAgICAoZGF0YTogQXJyYXk8bnVtYmVyIHwgc3RyaW5nPikgPT5cbiAgICAgICAgICAgICAgICB0aGlzLnNlbmRNZXNzYWdlQ29udHJvbGxlci5zZW5kTWVzc2FnZVRvU3RyZWFtZXIoXG4gICAgICAgICAgICAgICAgICAgICdYUkJ1dHRvblByZXNzZWQnLFxuICAgICAgICAgICAgICAgICAgICBkYXRhXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgICAgICB0aGlzLnN0cmVhbU1lc3NhZ2VDb250cm9sbGVyLnJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIoXG4gICAgICAgICAgICBNZXNzYWdlRGlyZWN0aW9uLlRvU3RyZWFtZXIsXG4gICAgICAgICAgICAnWFJCdXR0b25SZWxlYXNlZCcsXG4gICAgICAgICAgICAoZGF0YTogQXJyYXk8bnVtYmVyIHwgc3RyaW5nPikgPT5cbiAgICAgICAgICAgICAgICB0aGlzLnNlbmRNZXNzYWdlQ29udHJvbGxlci5zZW5kTWVzc2FnZVRvU3RyZWFtZXIoXG4gICAgICAgICAgICAgICAgICAgICdYUkJ1dHRvblJlbGVhc2VkJyxcbiAgICAgICAgICAgICAgICAgICAgZGF0YVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5zdHJlYW1NZXNzYWdlQ29udHJvbGxlci5yZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKFxuICAgICAgICAgICAgTWVzc2FnZURpcmVjdGlvbi5Ub1N0cmVhbWVyLFxuICAgICAgICAgICAgJ1hSQW5hbG9nJyxcbiAgICAgICAgICAgIChkYXRhOiBBcnJheTxudW1iZXIgfCBzdHJpbmc+KSA9PlxuICAgICAgICAgICAgICAgIHRoaXMuc2VuZE1lc3NhZ2VDb250cm9sbGVyLnNlbmRNZXNzYWdlVG9TdHJlYW1lcihcbiAgICAgICAgICAgICAgICAgICAgJ1hSQW5hbG9nJyxcbiAgICAgICAgICAgICAgICAgICAgZGF0YVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBY3RpdmF0ZSB0aGUgbG9naWMgYXNzb2NpYXRlZCB3aXRoIGEgY29tbWFuZCBmcm9tIFVFXG4gICAgICogQHBhcmFtIG1lc3NhZ2VcbiAgICAgKi9cbiAgICBvbkNvbW1hbmQobWVzc2FnZTogQXJyYXlCdWZmZXIpIHtcbiAgICAgICAgTG9nZ2VyLkxvZyhcbiAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAnRGF0YUNoYW5uZWxSZWNlaXZlTWVzc2FnZVR5cGUuQ29tbWFuZCcsXG4gICAgICAgICAgICA2XG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IGNvbW1hbmRBc1N0cmluZyA9IG5ldyBUZXh0RGVjb2RlcigndXRmLTE2JykuZGVjb2RlKFxuICAgICAgICAgICAgbWVzc2FnZS5zbGljZSgxKVxuICAgICAgICApO1xuXG4gICAgICAgIExvZ2dlci5Mb2coXG4gICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgJ0RhdGEgQ2hhbm5lbCBDb21tYW5kOiAnICsgY29tbWFuZEFzU3RyaW5nLFxuICAgICAgICAgICAgNlxuICAgICAgICApO1xuICAgICAgICBjb25zdCBjb21tYW5kOiBNZXNzYWdlT25TY3JlZW5LZXlib2FyZCA9IEpTT04ucGFyc2UoY29tbWFuZEFzU3RyaW5nKTtcbiAgICAgICAgaWYgKGNvbW1hbmQuY29tbWFuZCA9PT0gJ29uU2NyZWVuS2V5Ym9hcmQnKSB7XG4gICAgICAgICAgICB0aGlzLnBpeGVsU3RyZWFtaW5nLl9hY3RpdmF0ZU9uU2NyZWVuS2V5Ym9hcmQoY29tbWFuZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVzIGEgcHJvdG9jb2wgbWVzc2FnZSByZWNlaXZlZCBmcm9tIHRoZSBzdHJlYW1lclxuICAgICAqIEBwYXJhbSBtZXNzYWdlIHRoZSBtZXNzYWdlIGRhdGEgZnJvbSB0aGUgc3RyZWFtZXJcbiAgICAgKi9cbiAgICBvblByb3RvY29sTWVzc2FnZShtZXNzYWdlOiBBcnJheUJ1ZmZlcikge1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgY29uc3QgcHJvdG9jb2xTdHJpbmcgPSBuZXcgVGV4dERlY29kZXIoJ3V0Zi0xNicpLmRlY29kZShcbiAgICAgICAgICAgICAgICBtZXNzYWdlLnNsaWNlKDEpXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgY29uc3QgcHJvdG9jb2xKU09OID0gSlNPTi5wYXJzZShwcm90b2NvbFN0cmluZyk7XG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChwcm90b2NvbEpTT04sICdEaXJlY3Rpb24nKVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLkVycm9yKFxuICAgICAgICAgICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgICAgICAgICAnTWFsZm9ybWVkIHByb3RvY29sIHJlY2VpdmVkLiBFbnN1cmUgdGhlIHByb3RvY29sIG1lc3NhZ2UgY29udGFpbnMgYSBkaXJlY3Rpb24nXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGRpcmVjdGlvbiA9IHByb3RvY29sSlNPTi5EaXJlY3Rpb247XG4gICAgICAgICAgICBkZWxldGUgcHJvdG9jb2xKU09OLkRpcmVjdGlvbjtcbiAgICAgICAgICAgIExvZ2dlci5Mb2coXG4gICAgICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICAgICBgUmVjZWl2ZWQgbmV3ICR7XG4gICAgICAgICAgICAgICAgICAgIGRpcmVjdGlvbiA9PSBNZXNzYWdlRGlyZWN0aW9uLkZyb21TdHJlYW1lclxuICAgICAgICAgICAgICAgICAgICAgICAgPyAnRnJvbVN0cmVhbWVyJ1xuICAgICAgICAgICAgICAgICAgICAgICAgOiAnVG9TdHJlYW1lcidcbiAgICAgICAgICAgICAgICB9IHByb3RvY29sLiBVcGRhdGluZyBleGlzdGluZyBwcm90b2NvbC4uLmBcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBPYmplY3Qua2V5cyhwcm90b2NvbEpTT04pLmZvckVhY2goKG1lc3NhZ2VUeXBlKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgbWVzc2FnZSA9IHByb3RvY29sSlNPTlttZXNzYWdlVHlwZV07XG4gICAgICAgICAgICAgICAgc3dpdGNoIChkaXJlY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBNZXNzYWdlRGlyZWN0aW9uLlRvU3RyZWFtZXI6XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBDaGVjayB0aGF0IHRoZSBtZXNzYWdlIGNvbnRhaW5zIGFsbCB0aGUgcmVsZXZhbnQgcGFyYW1zXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2lkJ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIExvZ2dlci5FcnJvcihcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYFRvU3RyZWFtZXItPiR7bWVzc2FnZVR5cGV9IHByb3RvY29sIGRlZmluaXRpb24gd2FzIG1hbGZvcm1lZCBhcyBpdCBkaWRuJ3QgY29udGFpbiBhdCBsZWFzdCBhbiBpZFxcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIERlZmluaXRpb24gd2FzOiAke0pTT04uc3RyaW5naWZ5KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKX1gXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyByZXR1cm4gaW4gYSBmb3JFYWNoIGlzIGVxdWl2YWxlbnQgdG8gYSBjb250aW51ZSBpbiBhIG5vcm1hbCBmb3IgbG9vcFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVUU1LjEgYW5kIFVFNS4yIGRvbid0IHNlbmQgYSBzdHJ1Y3R1cmUgZm9yIHRoZXNlIG1lc3NhZ2UgdHlwZXMsIGJ1dCB0aGV5IGFjdHVhbGx5IGRvIGhhdmUgYSBzdHJ1Y3R1cmUgc28gaWdub3JlIHVwZGF0aW5nIHRoZW1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmKChtZXNzYWdlVHlwZSA9PT0gXCJVSUludGVyYWN0aW9uXCIgfHwgbWVzc2FnZVR5cGUgPT09IFwiQ29tbWFuZFwiIHx8IG1lc3NhZ2VUeXBlID09PSBcIkxhdGVuY3lUZXN0XCIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1NZXNzYWdlQ29udHJvbGxlci50b1N0cmVhbWVySGFuZGxlcnMuZ2V0KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlVHlwZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIHdlJ3ZlIHJlZ2lzdGVyZWQgYSBoYW5kbGVyIGZvciB0aGlzIG1lc3NhZ2UgdHlwZSB3ZSBjYW4gYWRkIGl0IHRvIG91ciBzdXBwb3J0ZWQgbWVzc2FnZXMuIGllIHJlZ2lzdGVyTWVzc2FnZUhhbmRsZXIoLi4uKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIudG9TdHJlYW1lck1lc3NhZ2VzLnNldChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVzc2FnZVR5cGUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2VcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBMb2dnZXIuRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBUaGVyZSB3YXMgbm8gcmVnaXN0ZXJlZCBoYW5kbGVyIGZvciBcIiR7bWVzc2FnZVR5cGV9XCIgLSB0cnkgYWRkaW5nIG9uZSB1c2luZyByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKE1lc3NhZ2VEaXJlY3Rpb24uVG9TdHJlYW1lciwgXCIke21lc3NhZ2VUeXBlfVwiLCBteUhhbmRsZXIpYFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBNZXNzYWdlRGlyZWN0aW9uLkZyb21TdHJlYW1lcjpcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIENoZWNrIHRoYXQgdGhlIG1lc3NhZ2UgY29udGFpbnMgYWxsIHRoZSByZWxldmFudCBwYXJhbXNcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAhT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG1lc3NhZ2UsICdpZCcpXG4gICAgICAgICAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBMb2dnZXIuRXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBGcm9tU3RyZWFtZXItPiR7bWVzc2FnZVR5cGV9IHByb3RvY29sIGRlZmluaXRpb24gd2FzIG1hbGZvcm1lZCBhcyBpdCBkaWRuJ3QgY29udGFpbiBhdCBsZWFzdCBhbiBpZFxcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIERlZmluaXRpb24gd2FzOiAke0pTT04uc3RyaW5naWZ5KG1lc3NhZ2UsIG51bGwsIDIpfWBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHJldHVybiBpbiBhIGZvckVhY2ggaXMgZXF1aXZhbGVudCB0byBhIGNvbnRpbnVlIGluIGEgbm9ybWFsIGZvciBsb29wXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIuZnJvbVN0cmVhbWVySGFuZGxlcnMuZ2V0KFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlVHlwZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIHdlJ3ZlIHJlZ2lzdGVyZWQgYSBoYW5kbGVyIGZvciB0aGlzIG1lc3NhZ2UgdHlwZS4gaWUgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlciguLi4pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1NZXNzYWdlQ29udHJvbGxlci5mcm9tU3RyZWFtZXJNZXNzYWdlcy5zZXQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UuaWQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2VUeXBlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLkVycm9yKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgVGhlcmUgd2FzIG5vIHJlZ2lzdGVyZWQgaGFuZGxlciBmb3IgXCIke21lc3NhZ2V9XCIgLSB0cnkgYWRkaW5nIG9uZSB1c2luZyByZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKE1lc3NhZ2VEaXJlY3Rpb24uRnJvbVN0cmVhbWVyLCBcIiR7bWVzc2FnZVR5cGV9XCIsIG15SGFuZGxlcilgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLkVycm9yKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYFVua25vd24gZGlyZWN0aW9uOiAke2RpcmVjdGlvbn1gXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAvLyBPbmNlIHRoZSBwcm90b2NvbCBoYXMgYmVlbiByZWNlaXZlZCwgd2UgY2FuIHNlbmQgb3VyIGNvbnRyb2wgbWVzc2FnZXNcbiAgICAgICAgICAgIHRoaXMudG9TdHJlYW1lck1lc3NhZ2VzQ29udHJvbGxlci5TZW5kUmVxdWVzdEluaXRpYWxTZXR0aW5ncygpO1xuICAgICAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXNDb250cm9sbGVyLlNlbmRSZXF1ZXN0UXVhbGl0eUNvbnRyb2woKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgTG9nZ2VyLkxvZyhMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLCBlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXMgYW4gaW5wdXQgY29udHJvbCBtZXNzYWdlIHdoZW4gaXQgaXMgcmVjZWl2ZWQgZnJvbSB0aGUgc3RyZWFtZXJcbiAgICAgKiBAcGFyYW0gbWVzc2FnZSBUaGUgaW5wdXQgY29udHJvbCBtZXNzYWdlXG4gICAgICovXG4gICAgb25JbnB1dENvbnRyb2xPd25lcnNoaXAobWVzc2FnZTogQXJyYXlCdWZmZXIpIHtcbiAgICAgICAgY29uc3QgdmlldyA9IG5ldyBVaW50OEFycmF5KG1lc3NhZ2UpO1xuICAgICAgICBMb2dnZXIuTG9nKFxuICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICdEYXRhQ2hhbm5lbFJlY2VpdmVNZXNzYWdlVHlwZS5JbnB1dENvbnRyb2xPd25lcnNoaXAnLFxuICAgICAgICAgICAgNlxuICAgICAgICApO1xuICAgICAgICBjb25zdCBpbnB1dENvbnRyb2xPd25lcnNoaXAgPSBuZXcgQm9vbGVhbih2aWV3WzFdKS52YWx1ZU9mKCk7XG4gICAgICAgIExvZ2dlci5Mb2coXG4gICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgYFJlY2VpdmVkIGlucHV0IGNvbnRyb2xsZXIgbWVzc2FnZSAtIHdpbGwgeW91ciBpbnB1dCBjb250cm9sIHRoZSBzdHJlYW06ICR7aW5wdXRDb250cm9sT3duZXJzaGlwfWBcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5waXhlbFN0cmVhbWluZy5fb25JbnB1dENvbnRyb2xPd25lcnNoaXAoaW5wdXRDb250cm9sT3duZXJzaGlwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBcbiAgICAgKiBAcGFyYW0gbWVzc2FnZSBcbiAgICAgKi9cbiAgICBvbkdhbWVwYWRSZXNwb25zZShtZXNzYWdlOiBBcnJheUJ1ZmZlcikge1xuICAgICAgICBjb25zdCByZXNwb25zZVN0cmluZyA9IG5ldyBUZXh0RGVjb2RlcigndXRmLTE2JykuZGVjb2RlKG1lc3NhZ2Uuc2xpY2UoMSkpO1xuICAgICAgICBjb25zdCByZXNwb25zZUpTT04gPSBKU09OLnBhcnNlKHJlc3BvbnNlU3RyaW5nKTtcbiAgICAgICAgdGhpcy5nYW1lUGFkQ29udHJvbGxlci5vbkdhbWVwYWRSZXNwb25zZVJlY2VpdmVkKHJlc3BvbnNlSlNPTi5jb250cm9sbGVySWQpO1xuICAgIH1cblxuICAgIG9uQWZrVHJpZ2dlcmVkKCk6IHZvaWQge1xuICAgICAgICB0aGlzLmFma0NvbnRyb2xsZXIub25BZmtDbGljaygpO1xuXG4gICAgICAgIC8vIGlmIHRoZSBzdHJlYW0gaXMgcGF1c2VkIHBsYXkgaXQsIGlmIHdlIGNhblxuICAgICAgICBpZiAodGhpcy52aWRlb1BsYXllci5pc1BhdXNlZCgpICYmIHRoaXMudmlkZW9QbGF5ZXIuaGFzVmlkZW9Tb3VyY2UoKSkge1xuICAgICAgICAgICAgdGhpcy5wbGF5U3RyZWFtKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgd2hldGhlciB3ZSBzaG91bGQgdGltZW91dCB3aGVuIGFmay5cbiAgICAgKiBAcGFyYW0gYWZrRW5hYmxlZCBJZiB0cnVlIHdlIHRpbWVvdXQgd2hlbiBpZGxlIGZvciBzb21lIGdpdmVuIGFtb3VudCBvZiB0aW1lLlxuICAgICAqL1xuICAgIHNldEFma0VuYWJsZWQoYWZrRW5hYmxlZDogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICBpZiAoYWZrRW5hYmxlZCkge1xuICAgICAgICAgICAgdGhpcy5vbkFma1RyaWdnZXJlZCgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5hZmtDb250cm9sbGVyLnN0b3BBZmtXYXJuaW5nVGltZXIoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEF0dGVtcHQgYSByZWNvbm5lY3Rpb24gdG8gdGhlIHNpZ25hbGxpbmcgc2VydmVyXG4gICAgICovXG4gICAgdHJ5UmVjb25uZWN0KG1lc3NhZ2U6IHN0cmluZykge1xuICAgICAgICAvLyBpZiB0aGVyZSBpcyBubyB3ZWJTb2NrZXRDb250cm9sbGVyIHJldHVybiBpbW1lZGlhdGVseSBvciB0aGlzIHdpbGwgbm90IHdvcmtcbiAgICAgICAgaWYgKCF0aGlzLndlYlNvY2tldENvbnRyb2xsZXIpIHtcbiAgICAgICAgICAgIExvZ2dlci5Mb2coXG4gICAgICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICAgICAnVGhlIFdlYiBTb2NrZXQgQ29udHJvbGxlciBkb2VzIG5vdCBleGlzdCBzbyB0aGlzIHdpbGwgbm90IHdvcmsgcmlnaHQgbm93LidcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBpZiB0aGUgY29ubmVjdGlvbiBpcyBvcGVuLCBmaXJzdCBjbG9zZSBpdC4gd2FpdCBzb21lIHRpbWUgYW5kIHRyeSBhZ2Fpbi5cbiAgICAgICAgdGhpcy5pc1JlY29ubmVjdGluZyA9IHRydWU7XG4gICAgICAgIGlmICh0aGlzLndlYlNvY2tldENvbnRyb2xsZXIud2ViU29ja2V0ICYmIHRoaXMud2ViU29ja2V0Q29udHJvbGxlci53ZWJTb2NrZXQucmVhZHlTdGF0ZSAhPSBXZWJTb2NrZXQuQ0xPU0VEKSB7XG4gICAgICAgICAgICB0aGlzLmNsb3NlU2lnbmFsaW5nU2VydmVyKGAke21lc3NhZ2V9IFJlc3RhcnRpbmcgc3RyZWFtLi4uYCk7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnRyeVJlY29ubmVjdChtZXNzYWdlKTtcbiAgICAgICAgICAgIH0sIDMwMDApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5waXhlbFN0cmVhbWluZy5fb25XZWJSdGNBdXRvQ29ubmVjdCgpO1xuICAgICAgICAgICAgdGhpcy5jb25uZWN0VG9TaWduYWxsaW5nU2VydmVyKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBMb2FkcyBhIGZyZWV6ZSBmcmFtZSBpZiBpdCBpcyByZXF1aXJlZCBvdGhlcndpc2Ugc2hvd3MgdGhlIHBsYXkgb3ZlcmxheVxuICAgICAqL1xuICAgIGxvYWRGcmVlemVGcmFtZU9yU2hvd1BsYXlPdmVybGF5KCkge1xuICAgICAgICB0aGlzLnBpeGVsU3RyZWFtaW5nLmRpc3BhdGNoRXZlbnQoXG4gICAgICAgICAgICBuZXcgTG9hZEZyZWV6ZUZyYW1lRXZlbnQoe1xuICAgICAgICAgICAgICAgIHNob3VsZFNob3dQbGF5T3ZlcmxheTogdGhpcy5zaG91bGRTaG93UGxheU92ZXJsYXksXG4gICAgICAgICAgICAgICAgaXNWYWxpZDogdGhpcy5mcmVlemVGcmFtZUNvbnRyb2xsZXIudmFsaWQsXG4gICAgICAgICAgICAgICAganBlZ0RhdGE6IHRoaXMuZnJlZXplRnJhbWVDb250cm9sbGVyLmpwZWdcbiAgICAgICAgICAgIH0pXG4gICAgICAgICk7XG4gICAgICAgIGlmICh0aGlzLnNob3VsZFNob3dQbGF5T3ZlcmxheSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgTG9nZ2VyLkxvZyhMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLCAnc2hvd2luZyBwbGF5IG92ZXJsYXknKTtcbiAgICAgICAgICAgIHRoaXMucmVzaXplUGxheWVyU3R5bGUoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIExvZ2dlci5Mb2coTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSwgJ3Nob3dpbmcgZnJlZXplIGZyYW1lJyk7XG4gICAgICAgICAgICB0aGlzLmZyZWV6ZUZyYW1lQ29udHJvbGxlci5zaG93RnJlZXplRnJhbWUoKTtcbiAgICAgICAgfVxuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMudmlkZW9QbGF5ZXIuc2V0VmlkZW9FbmFibGVkKGZhbHNlKTtcbiAgICAgICAgfSwgdGhpcy5mcmVlemVGcmFtZUNvbnRyb2xsZXIuZnJlZXplRnJhbWVEZWxheSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUHJvY2VzcyB0aGUgZnJlZXplIGZyYW1lIGFuZCBsb2FkIGl0XG4gICAgICogQHBhcmFtIG1lc3NhZ2UgVGhlIGZyZWV6ZSBmcmFtZSBkYXRhIGluIGJ5dGVzXG4gICAgICovXG4gICAgb25GcmVlemVGcmFtZU1lc3NhZ2UobWVzc2FnZTogQXJyYXlCdWZmZXIpIHtcbiAgICAgICAgTG9nZ2VyLkxvZyhcbiAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAnRGF0YUNoYW5uZWxSZWNlaXZlTWVzc2FnZVR5cGUuRnJlZXplRnJhbWUnLFxuICAgICAgICAgICAgNlxuICAgICAgICApO1xuICAgICAgICBjb25zdCB2aWV3ID0gbmV3IFVpbnQ4QXJyYXkobWVzc2FnZSk7XG4gICAgICAgIHRoaXMuZnJlZXplRnJhbWVDb250cm9sbGVyLnByb2Nlc3NGcmVlemVGcmFtZU1lc3NhZ2UodmlldywgKCkgPT5cbiAgICAgICAgICAgIHRoaXMubG9hZEZyZWV6ZUZyYW1lT3JTaG93UGxheU92ZXJsYXkoKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEVuYWJsZSB0aGUgdmlkZW8gYWZ0ZXIgaGlkaW5nIGEgZnJlZXplIGZyYW1lXG4gICAgICovXG4gICAgaW52YWxpZGF0ZUZyZWV6ZUZyYW1lQW5kRW5hYmxlVmlkZW8oKSB7XG4gICAgICAgIExvZ2dlci5Mb2coXG4gICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgJ0RhdGFDaGFubmVsUmVjZWl2ZU1lc3NhZ2VUeXBlLkZyZWV6ZUZyYW1lJyxcbiAgICAgICAgICAgIDZcbiAgICAgICAgKTtcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnBpeGVsU3RyZWFtaW5nLmRpc3BhdGNoRXZlbnQoXG4gICAgICAgICAgICAgICAgbmV3IEhpZGVGcmVlemVGcmFtZUV2ZW50KClcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICB0aGlzLmZyZWV6ZUZyYW1lQ29udHJvbGxlci5oaWRlRnJlZXplRnJhbWUoKTtcbiAgICAgICAgfSwgdGhpcy5mcmVlemVGcmFtZUNvbnRyb2xsZXIuZnJlZXplRnJhbWVEZWxheSk7XG4gICAgICAgIGlmICh0aGlzLnZpZGVvUGxheWVyLmdldFZpZGVvRWxlbWVudCgpKSB7XG4gICAgICAgICAgICB0aGlzLnZpZGVvUGxheWVyLnNldFZpZGVvRW5hYmxlZCh0cnVlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFByZXAgZGF0YWNoYW5uZWwgZGF0YSBmb3IgcHJvY2Vzc2luZyBmaWxlIGV4dGVuc2lvblxuICAgICAqIEBwYXJhbSBkYXRhIHRoZSBmaWxlIGV4dGVuc2lvbiBkYXRhXG4gICAgICovXG4gICAgb25GaWxlRXh0ZW5zaW9uKGRhdGE6IEFycmF5QnVmZmVyKSB7XG4gICAgICAgIGNvbnN0IHZpZXcgPSBuZXcgVWludDhBcnJheShkYXRhKTtcbiAgICAgICAgRmlsZVV0aWwuc2V0RXh0ZW5zaW9uRnJvbUJ5dGVzKHZpZXcsIHRoaXMuZmlsZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUHJlcCBkYXRhY2hhbm5lbCBkYXRhIGZvciBwcm9jZXNzaW5nIHRoZSBmaWxlIG1pbWUgdHlwZVxuICAgICAqIEBwYXJhbSBkYXRhIHRoZSBmaWxlIG1pbWUgdHlwZSBkYXRhXG4gICAgICovXG4gICAgb25GaWxlTWltZVR5cGUoZGF0YTogQXJyYXlCdWZmZXIpIHtcbiAgICAgICAgY29uc3QgdmlldyA9IG5ldyBVaW50OEFycmF5KGRhdGEpO1xuICAgICAgICBGaWxlVXRpbC5zZXRNaW1lVHlwZUZyb21CeXRlcyh2aWV3LCB0aGlzLmZpbGUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFByZXAgZGF0YWNoYW5uZWwgZGF0YSBmb3IgcHJvY2Vzc2luZyB0aGUgZmlsZSBjb250ZW50c1xuICAgICAqIEBwYXJhbSBkYXRhIHRoZSBmaWxlIGNvbnRlbnRzIGRhdGFcbiAgICAgKi9cbiAgICBvbkZpbGVDb250ZW50cyhkYXRhOiBBcnJheUJ1ZmZlcikge1xuICAgICAgICBjb25zdCB2aWV3ID0gbmV3IFVpbnQ4QXJyYXkoZGF0YSk7XG4gICAgICAgIEZpbGVVdGlsLnNldENvbnRlbnRzRnJvbUJ5dGVzKHZpZXcsIHRoaXMuZmlsZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGxheXMgdGhlIHN0cmVhbSBhdWRpbyBhbmQgdmlkZW8gc291cmNlIGFuZCBzZXRzIHVwIG90aGVyIHBpZWNlcyB3aGlsZSB0aGUgc3RyZWFtIHN0YXJ0c1xuICAgICAqL1xuICAgIHBsYXlTdHJlYW0oKSB7XG4gICAgICAgIGlmICghdGhpcy52aWRlb1BsYXllci5nZXRWaWRlb0VsZW1lbnQoKSkge1xuICAgICAgICAgICAgY29uc3QgbWVzc2FnZSA9XG4gICAgICAgICAgICAgICAgJ0NvdWxkIG5vdCBwbGF5IHZpZGVvIHN0cmVhbSBiZWNhdXNlIHRoZSB2aWRlbyBwbGF5ZXIgd2FzIG5vdCBpbml0aWFsaXplZCBjb3JyZWN0bHkuJztcbiAgICAgICAgICAgIHRoaXMucGl4ZWxTdHJlYW1pbmcuZGlzcGF0Y2hFdmVudChcbiAgICAgICAgICAgICAgICBuZXcgUGxheVN0cmVhbUVycm9yRXZlbnQoeyBtZXNzYWdlIH0pXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgTG9nZ2VyLkVycm9yKExvZ2dlci5HZXRTdGFja1RyYWNlKCksIG1lc3NhZ2UpO1xuXG4gICAgICAgICAgICAvLyBjbG9zZSB0aGUgY29ubmVjdGlvblxuICAgICAgICAgICAgdGhpcy5jbG9zZVNpZ25hbGluZ1NlcnZlcignU3RyZWFtIG5vdCBpbml0aWFsaXplZCBjb3JyZWN0bHknKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGhpcy52aWRlb1BsYXllci5oYXNWaWRlb1NvdXJjZSgpKSB7XG4gICAgICAgICAgICBMb2dnZXIuV2FybmluZyhcbiAgICAgICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgICAgICdDYW5ub3QgcGxheSBzdHJlYW0sIHRoZSB2aWRlbyBlbGVtZW50IGhhcyBubyBzcmNPYmplY3QgdG8gcGxheS4nXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5zZXRUb3VjaElucHV0RW5hYmxlZCh0aGlzLmNvbmZpZy5pc0ZsYWdFbmFibGVkKEZsYWdzLlRvdWNoSW5wdXQpKTtcbiAgICAgICAgdGhpcy5waXhlbFN0cmVhbWluZy5kaXNwYXRjaEV2ZW50KG5ldyBQbGF5U3RyZWFtRXZlbnQoKSk7XG5cbiAgICAgICAgaWYgKHRoaXMuc3RyZWFtQ29udHJvbGxlci5hdWRpb0VsZW1lbnQuc3JjT2JqZWN0KSB7XG4gICAgICAgICAgICBjb25zdCBzdGFydE11dGVkID0gdGhpcy5jb25maWcuaXNGbGFnRW5hYmxlZChGbGFncy5TdGFydFZpZGVvTXV0ZWQpXG4gICAgICAgICAgICB0aGlzLnN0cmVhbUNvbnRyb2xsZXIuYXVkaW9FbGVtZW50Lm11dGVkID0gc3RhcnRNdXRlZDtcblxuICAgICAgICAgICAgaWYgKHN0YXJ0TXV0ZWQpIHtcbiAgICAgICAgICAgICAgdGhpcy5wbGF5VmlkZW8oKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdHJlYW1Db250cm9sbGVyLmF1ZGlvRWxlbWVudFxuICAgICAgICAgICAgICAgICAgICAucGxheSgpXG4gICAgICAgICAgICAgICAgICAgIC50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGxheVZpZGVvKCk7XG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgIC5jYXRjaCgob25SZWplY3RlZFJlYXNvbikgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLkxvZyhMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLCBvblJlamVjdGVkUmVhc29uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIExvZ2dlci5Mb2coXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQnJvd3NlciBkb2VzIG5vdCBzdXBwb3J0IGF1dG9wbGF5aW5nIHZpZGVvIHdpdGhvdXQgaW50ZXJhY3Rpb24gLSB0byByZXNvbHZlIHRoaXMgd2UgYXJlIGdvaW5nIHRvIHNob3cgdGhlIHBsYXkgYnV0dG9uIG92ZXJsYXkuJ1xuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGl4ZWxTdHJlYW1pbmcuZGlzcGF0Y2hFdmVudChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXcgUGxheVN0cmVhbVJlamVjdGVkRXZlbnQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWFzb246IG9uUmVqZWN0ZWRSZWFzb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnBsYXlWaWRlbygpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5zaG91bGRTaG93UGxheU92ZXJsYXkgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5mcmVlemVGcmFtZUNvbnRyb2xsZXIuc2hvd0ZyZWV6ZUZyYW1lKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGxheXMgdGhlIHZpZGVvIHN0cmVhbVxuICAgICAqL1xuICAgIHByaXZhdGUgcGxheVZpZGVvKCkge1xuICAgICAgICAvLyBoYW5kbGUgcGxheSgpIHdpdGggcHJvbWlzZSBhcyBpdCBpcyBhbiBhc3luY2hyb25vdXMgY2FsbFxuICAgICAgICB0aGlzLnZpZGVvUGxheWVyLnBsYXkoKS5jYXRjaCgob25SZWplY3RlZFJlYXNvbjogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5zdHJlYW1Db250cm9sbGVyLmF1ZGlvRWxlbWVudC5zcmNPYmplY3QpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbUNvbnRyb2xsZXIuYXVkaW9FbGVtZW50LnBhdXNlKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBMb2dnZXIuTG9nKExvZ2dlci5HZXRTdGFja1RyYWNlKCksIG9uUmVqZWN0ZWRSZWFzb24pO1xuICAgICAgICAgICAgTG9nZ2VyLkxvZyhcbiAgICAgICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgICAgICdCcm93c2VyIGRvZXMgbm90IHN1cHBvcnQgYXV0b3BsYXlpbmcgdmlkZW8gd2l0aG91dCBpbnRlcmFjdGlvbiAtIHRvIHJlc29sdmUgdGhpcyB3ZSBhcmUgZ29pbmcgdG8gc2hvdyB0aGUgcGxheSBidXR0b24gb3ZlcmxheS4nXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgdGhpcy5waXhlbFN0cmVhbWluZy5kaXNwYXRjaEV2ZW50KFxuICAgICAgICAgICAgICAgIG5ldyBQbGF5U3RyZWFtUmVqZWN0ZWRFdmVudCh7IHJlYXNvbjogb25SZWplY3RlZFJlYXNvbiB9KVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRW5hYmxlIHRoZSB2aWRlbyB0byBwbGF5IGF1dG9tYXRpY2FsbHkgaWYgZW5hYmxlQXV0b3BsYXkgaXMgdHJ1ZVxuICAgICAqL1xuICAgIGF1dG9QbGF5VmlkZW9PclNldFVwUGxheU92ZXJsYXkoKSB7XG4gICAgICAgIGlmICh0aGlzLmNvbmZpZy5pc0ZsYWdFbmFibGVkKEZsYWdzLkF1dG9QbGF5VmlkZW8pKSB7XG4gICAgICAgICAgICAvLyBhdHRlbXB0IHRvIHBsYXkgdGhlIHZpZGVvXG4gICAgICAgICAgICB0aGlzLnBsYXlTdHJlYW0oKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlc2l6ZVBsYXllclN0eWxlKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29ubmVjdCB0byB0aGUgU2lnbmFsaW5nIHNlcnZlclxuICAgICAqL1xuICAgIGNvbm5lY3RUb1NpZ25hbGxpbmdTZXJ2ZXIoKSB7XG4gICAgICAgIHRoaXMubG9jYWxseUNsb3NlZCA9IGZhbHNlO1xuICAgICAgICB0aGlzLnNob3VsZFJlY29ubmVjdCA9IHRydWU7XG4gICAgICAgIHRoaXMuZGlzY29ubmVjdE1lc3NhZ2UgPSBudWxsO1xuICAgICAgICBjb25zdCBzaWduYWxsaW5nVXJsID0gdGhpcy5zaWduYWxsaW5nVXJsQnVpbGRlcigpO1xuICAgICAgICB0aGlzLndlYlNvY2tldENvbnRyb2xsZXIuY29ubmVjdChzaWduYWxsaW5nVXJsKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIHdpbGwgc3RhcnQgdGhlIGhhbmRzaGFrZSB0byB0aGUgc2lnbmFsbGluZyBzZXJ2ZXJcbiAgICAgKiBAcGFyYW0gcGVlckNvbmZpZyAgLSBSVEMgQ29uZmlndXJhdGlvbiBPcHRpb25zIGZyb20gdGhlIFNpZ25hbGluZyBzZXJ2ZXJcbiAgICAgKiBAcmVtYXJrIFJUQyBQZWVyIENvbm5lY3Rpb24gb24gSWNlIENhbmRpZGF0ZSBldmVudCBoYXZlIGl0IGhhbmRsZWQgYnkgaGFuZGxlIFNlbmQgSWNlIENhbmRpZGF0ZVxuICAgICAqL1xuICAgIHN0YXJ0U2Vzc2lvbihwZWVyQ29uZmlnOiBSVENDb25maWd1cmF0aW9uKSB7XG4gICAgICAgIHRoaXMucGVlckNvbmZpZyA9IHBlZXJDb25maWc7XG4gICAgICAgIC8vIGNoZWNrIGZvciBmb3JjaW5nIHR1cm5cbiAgICAgICAgaWYgKHRoaXMuY29uZmlnLmlzRmxhZ0VuYWJsZWQoRmxhZ3MuRm9yY2VUVVJOKSkge1xuICAgICAgICAgICAgLy8gY2hlY2sgZm9yIGEgdHVybiBzZXJ2ZXJcbiAgICAgICAgICAgIGNvbnN0IGhhc1R1cm5TZXJ2ZXIgPSB0aGlzLmNoZWNrVHVyblNlcnZlckF2YWlsYWJpbGl0eShwZWVyQ29uZmlnKTtcblxuICAgICAgICAgICAgLy8gY2xvc2UgYW5kIGVycm9yIGlmIHR1cm4gaXMgZm9yY2VkIGFuZCB0aGVyZSBpcyBubyB0dXJuIHNlcnZlclxuICAgICAgICAgICAgaWYgKCFoYXNUdXJuU2VydmVyKSB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLkluZm8oXG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAgICAgICAgICdObyB0dXJuIHNlcnZlciB3YXMgZm91bmQgaW4gdGhlIFBlZXIgQ29ubmVjdGlvbiBPcHRpb25zLiBUVVJOIGNhbm5vdCBiZSBmb3JjZWQsIGNsb3NpbmcgY29ubmVjdGlvbi4gUGxlYXNlIHVzZSBTVFVOIGluc3RlYWQnXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB0aGlzLmNsb3NlU2lnbmFsaW5nU2VydmVyKCdUVVJOIGNhbm5vdCBiZSBmb3JjZWQsIGNsb3NpbmcgY29ubmVjdGlvbi4gUGxlYXNlIHVzZSBTVFVOIGluc3RlYWQuJyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gc2V0IHVwIHRoZSBwZWVyIGNvbm5lY3Rpb24gY29udHJvbGxlclxuICAgICAgICB0aGlzLnBlZXJDb25uZWN0aW9uQ29udHJvbGxlciA9IG5ldyBQZWVyQ29ubmVjdGlvbkNvbnRyb2xsZXIoXG4gICAgICAgICAgICB0aGlzLnBlZXJDb25maWcsXG4gICAgICAgICAgICB0aGlzLmNvbmZpZyxcbiAgICAgICAgICAgIHRoaXMucHJlZmVycmVkQ29kZWNcbiAgICAgICAgKTtcblxuICAgICAgICAvLyBzZXQgdXAgcGVlciBjb25uZWN0aW9uIGNvbnRyb2xsZXIgdmlkZW8gc3RhdHNcbiAgICAgICAgdGhpcy5wZWVyQ29ubmVjdGlvbkNvbnRyb2xsZXIub25WaWRlb1N0YXRzID0gKGV2ZW50OiBBZ2dyZWdhdGVkU3RhdHMpID0+XG4gICAgICAgICAgICB0aGlzLmhhbmRsZVZpZGVvU3RhdHMoZXZlbnQpO1xuXG4gICAgICAgIC8qIFdoZW4gdGhlIFBlZXIgQ29ubmVjdGlvbiB3YW50cyB0byBzZW5kIGFuIG9mZmVyIGhhdmUgaXQgaGFuZGxlZCAqL1xuICAgICAgICB0aGlzLnBlZXJDb25uZWN0aW9uQ29udHJvbGxlci5vblNlbmRXZWJSVENPZmZlciA9IChcbiAgICAgICAgICAgIG9mZmVyOiBSVENTZXNzaW9uRGVzY3JpcHRpb25Jbml0XG4gICAgICAgICkgPT4gdGhpcy5oYW5kbGVTZW5kV2ViUlRDT2ZmZXIob2ZmZXIpO1xuXG4gICAgICAgIC8qIFdoZW4gdGhlIFBlZXIgQ29ubmVjdGlvbiB3YW50cyB0byBzZW5kIGFuIGFuc3dlciBoYXZlIGl0IGhhbmRsZWQgKi9cbiAgICAgICAgdGhpcy5wZWVyQ29ubmVjdGlvbkNvbnRyb2xsZXIub25TZW5kV2ViUlRDQW5zd2VyID0gKFxuICAgICAgICAgICAgb2ZmZXI6IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbkluaXRcbiAgICAgICAgKSA9PiB0aGlzLmhhbmRsZVNlbmRXZWJSVENBbnN3ZXIob2ZmZXIpO1xuXG4gICAgICAgIC8qIFdoZW4gdGhlIFBlZXIgQ29ubmVjdGlvbiBpY2UgY2FuZGlkYXRlIGlzIGFkZGVkIGhhdmUgaXQgaGFuZGxlZCAqL1xuICAgICAgICB0aGlzLnBlZXJDb25uZWN0aW9uQ29udHJvbGxlci5vblBlZXJJY2VDYW5kaWRhdGUgPSAoXG4gICAgICAgICAgICBwZWVyQ29ubmVjdGlvbkljZUV2ZW50OiBSVENQZWVyQ29ubmVjdGlvbkljZUV2ZW50XG4gICAgICAgICkgPT4gdGhpcy5oYW5kbGVTZW5kSWNlQ2FuZGlkYXRlKHBlZXJDb25uZWN0aW9uSWNlRXZlbnQpO1xuXG4gICAgICAgIC8qIFdoZW4gdGhlIFBlZXIgQ29ubmVjdGlvbiBoYXMgYSBkYXRhIGNoYW5uZWwgY3JlYXRlZCBmb3IgaXQgYnkgdGhlIGJyb3dzZXIsIGhhbmRsZSBpdCAqL1xuICAgICAgICB0aGlzLnBlZXJDb25uZWN0aW9uQ29udHJvbGxlci5vbkRhdGFDaGFubmVsID0gKFxuICAgICAgICAgICAgZGF0YWNoYW5uZWxFdmVudDogUlRDRGF0YUNoYW5uZWxFdmVudFxuICAgICAgICApID0+IHRoaXMuaGFuZGxlRGF0YUNoYW5uZWwoZGF0YWNoYW5uZWxFdmVudCk7XG5cbiAgICAgICAgLy8gc2V0IHVwIHdlYlJ0YyB0ZXh0IG92ZXJsYXlzXG4gICAgICAgIHRoaXMucGVlckNvbm5lY3Rpb25Db250cm9sbGVyLnNob3dUZXh0T3ZlcmxheUNvbm5lY3RpbmcgPSAoKSA9PlxuICAgICAgICAgICAgdGhpcy5waXhlbFN0cmVhbWluZy5fb25XZWJSdGNDb25uZWN0aW5nKCk7XG4gICAgICAgIHRoaXMucGVlckNvbm5lY3Rpb25Db250cm9sbGVyLnNob3dUZXh0T3ZlcmxheVNldHVwRmFpbHVyZSA9ICgpID0+XG4gICAgICAgICAgICB0aGlzLnBpeGVsU3RyZWFtaW5nLl9vbldlYlJ0Y0ZhaWxlZCgpO1xuICAgICAgICBsZXQgd2ViUnRjQ29ubmVjdGVkU2VudCA9IGZhbHNlO1xuICAgICAgICB0aGlzLnBlZXJDb25uZWN0aW9uQ29udHJvbGxlci5vbkljZUNvbm5lY3Rpb25TdGF0ZUNoYW5nZSA9ICgpID0+IHtcbiAgICAgICAgICAgIC8vIEJyb3dzZXJzIGVtaXQgXCJjb25uZWN0ZWRcIiB3aGVuIGdldHRpbmcgZmlyc3QgY29ubmVjdGlvbiBhbmQgXCJjb21wbGV0ZWRcIiB3aGVuIGZpbmlzaGluZ1xuICAgICAgICAgICAgLy8gY2FuZGlkYXRlIGNoZWNraW5nLiBIb3dldmVyLCBzb21ldGltZXMgYnJvd3NlcnMgY2FuIHNraXAgXCJjb25uZWN0ZWRcIiBhbmQgb25seSBlbWl0IFwiY29tcGxldGVkXCIuXG4gICAgICAgICAgICAvLyBUaGVyZWZvcmUgbmVlZCB0byBjaGVjayBib3RoIGNhc2VzIGFuZCBlbWl0IG9uV2ViUnRjQ29ubmVjdGVkIG9ubHkgb25jZSBvbiB0aGUgZmlyc3QgaGl0LlxuICAgICAgICAgICAgaWYgKCF3ZWJSdGNDb25uZWN0ZWRTZW50ICYmIFxuICAgICAgICAgICAgICAgIFtcImNvbm5lY3RlZFwiLCBcImNvbXBsZXRlZFwiXS5pbmNsdWRlcyh0aGlzLnBlZXJDb25uZWN0aW9uQ29udHJvbGxlci5wZWVyQ29ubmVjdGlvbi5pY2VDb25uZWN0aW9uU3RhdGUpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5waXhlbFN0cmVhbWluZy5fb25XZWJSdGNDb25uZWN0ZWQoKTtcbiAgICAgICAgICAgICAgICB3ZWJSdGNDb25uZWN0ZWRTZW50ID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICAvKiBSVEMgUGVlciBDb25uZWN0aW9uIG9uIFRyYWNrIGV2ZW50IC0+IGhhbmRsZSBvbiB0cmFjayAqL1xuICAgICAgICB0aGlzLnBlZXJDb25uZWN0aW9uQ29udHJvbGxlci5vblRyYWNrID0gKHRyYWNrRXZlbnQ6IFJUQ1RyYWNrRXZlbnQpID0+XG4gICAgICAgICAgICB0aGlzLnN0cmVhbUNvbnRyb2xsZXIuaGFuZGxlT25UcmFjayh0cmFja0V2ZW50KTtcblxuICAgICAgICAvKiBTdGFydCB0aGUgSGFuZCBzaGFrZSBwcm9jZXNzIGJ5IGNyZWF0aW5nIGFuIE9mZmVyICovXG4gICAgICAgIGNvbnN0IEJyb3dzZXJTZW5kc09mZmVyID0gdGhpcy5jb25maWcuaXNGbGFnRW5hYmxlZChcbiAgICAgICAgICAgIEZsYWdzLkJyb3dzZXJTZW5kT2ZmZXJcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKEJyb3dzZXJTZW5kc09mZmVyKSB7XG4gICAgICAgICAgICAvLyBJZiBicm93c2VyIGlzIHNlbmRpbmcgdGhlIG9mZmVyLCBjcmVhdGUgYW4gb2ZmZXIgYW5kIHNlbmQgaXQgdG8gdGhlIHN0cmVhbWVyXG4gICAgICAgICAgICB0aGlzLnNlbmRyZWN2RGF0YUNoYW5uZWxDb250cm9sbGVyLmNyZWF0ZURhdGFDaGFubmVsKFxuICAgICAgICAgICAgICAgIHRoaXMucGVlckNvbm5lY3Rpb25Db250cm9sbGVyLnBlZXJDb25uZWN0aW9uLFxuICAgICAgICAgICAgICAgICdjaXJydXMnLFxuICAgICAgICAgICAgICAgIHRoaXMuZGF0YWNoYW5uZWxPcHRpb25zXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgdGhpcy5zZW5kcmVjdkRhdGFDaGFubmVsQ29udHJvbGxlci5oYW5kbGVPbk1lc3NhZ2UgPSAoXG4gICAgICAgICAgICAgICAgZXY6IE1lc3NhZ2VFdmVudDxBcnJheUJ1ZmZlcj5cbiAgICAgICAgICAgICkgPT4gdGhpcy5oYW5kbGVPbk1lc3NhZ2UoZXYpO1xuICAgICAgICAgICAgdGhpcy5wZWVyQ29ubmVjdGlvbkNvbnRyb2xsZXIuY3JlYXRlT2ZmZXIoXG4gICAgICAgICAgICAgICAgdGhpcy5zZHBDb25zdHJhaW50cyxcbiAgICAgICAgICAgICAgICB0aGlzLmNvbmZpZ1xuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrcyB0aGUgcGVlciBjb25uZWN0aW9uIG9wdGlvbnMgZm9yIGEgdHVybiBzZXJ2ZXIgYW5kIHJldHVybnMgdHJ1ZSBvciBmYWxzZVxuICAgICAqL1xuICAgIGNoZWNrVHVyblNlcnZlckF2YWlsYWJpbGl0eShvcHRpb25zOiBSVENDb25maWd1cmF0aW9uKSB7XG4gICAgICAgIC8vIGlmIGljZVNlcnZlcnMgaXMgZW1wdHkgcmV0dXJuIGZhbHNlIHRoaXMgc2hvdWxkIG5vdCBiZSB0aGUgZ2VuZXJhbCB1c2UgY2FzZSBidXQgaXMgaGVyZSBpbmNhc2VcbiAgICAgICAgaWYgKCFvcHRpb25zLmljZVNlcnZlcnMpIHtcbiAgICAgICAgICAgIExvZ2dlci5JbmZvKExvZ2dlci5HZXRTdGFja1RyYWNlKCksICdBIHR1cm4gc2V2ZXIgd2FzIG5vdCBmb3VuZCcpO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gbG9vcCB0aHJvdWdoIHRoZSBpY2Ugc2VydmVycyB0byBjaGVjayBmb3IgYSB0dXJuIHVybFxuICAgICAgICBmb3IgKGNvbnN0IGljZVNlcnZlciBvZiBvcHRpb25zLmljZVNlcnZlcnMpIHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgdXJsIG9mIGljZVNlcnZlci51cmxzKSB7XG4gICAgICAgICAgICAgICAgaWYgKHVybC5pbmNsdWRlcygndHVybicpKSB7XG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5Mb2coXG4gICAgICAgICAgICAgICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgYEEgdHVybiBzZXZlciB3YXMgZm91bmQgYXQgJHt1cmx9YFxuICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBMb2dnZXIuSW5mbyhMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLCAnQSB0dXJuIHNldmVyIHdhcyBub3QgZm91bmQnKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXMgd2hlbiBhIENvbmZpZyBNZXNzYWdlIGlzIHJlY2VpdmVkIGNvbnRhaW5zIHRoZSBQZWVyIENvbm5lY3Rpb24gT3B0aW9ucyByZXF1aXJlZCAoU1RVTiBhbmQgVFVSTiBTZXJ2ZXIgSW5mbylcbiAgICAgKiBAcGFyYW0gbWVzc2FnZUNvbmZpZyAtIENvbmZpZyBNZXNzYWdlIHJlY2VpdmVkIGZyb20gdGhlIHNpZ25hbGluZyBzZXJ2ZXJcbiAgICAgKi9cbiAgICBoYW5kbGVPbkNvbmZpZ01lc3NhZ2UobWVzc2FnZUNvbmZpZzogTWVzc2FnZUNvbmZpZykge1xuICAgICAgICB0aGlzLnJlc2l6ZVBsYXllclN0eWxlKCk7XG5cbiAgICAgICAgLy8gVGVsbCB0aGUgV2ViUnRjQ29udHJvbGxlciB0byBzdGFydCBhIHNlc3Npb24gd2l0aCB0aGUgcGVlciBvcHRpb25zIHNlbnQgZnJvbSB0aGUgc2lnbmFsaW5nIHNlcnZlclxuICAgICAgICB0aGlzLnN0YXJ0U2Vzc2lvbihtZXNzYWdlQ29uZmlnLnBlZXJDb25uZWN0aW9uT3B0aW9ucyk7XG5cbiAgICAgICAgLy8gV2hlbiB0aGUgc2lnbmFsaW5nIHNlcnZlciBzZW5kcyBhIFdlYlJUQyBBbnN3ZXIgb3ZlciB0aGUgd2Vic29ja2V0IGNvbm5lY3Rpb24gaGF2ZSB0aGUgV2ViUnRjQ29udHJvbGxlciBoYW5kbGUgdGhlIG1lc3NhZ2VcbiAgICAgICAgdGhpcy53ZWJTb2NrZXRDb250cm9sbGVyLm9uV2ViUnRjQW5zd2VyID0gKFxuICAgICAgICAgICAgbWVzc2FnZUFuc3dlcjogTWVzc2FnZVJlY2VpdmUuTWVzc2FnZUFuc3dlclxuICAgICAgICApID0+IHRoaXMuaGFuZGxlV2ViUnRjQW5zd2VyKG1lc3NhZ2VBbnN3ZXIpO1xuICAgICAgICB0aGlzLndlYlNvY2tldENvbnRyb2xsZXIub25XZWJSdGNPZmZlciA9IChcbiAgICAgICAgICAgIG1lc3NhZ2VPZmZlcjogTWVzc2FnZVJlY2VpdmUuTWVzc2FnZU9mZmVyXG4gICAgICAgICkgPT4gdGhpcy5oYW5kbGVXZWJSdGNPZmZlcihtZXNzYWdlT2ZmZXIpO1xuICAgICAgICB0aGlzLndlYlNvY2tldENvbnRyb2xsZXIub25XZWJSdGNQZWVyRGF0YUNoYW5uZWxzID0gKFxuICAgICAgICAgICAgbWVzc2FnZURhdGFDaGFubmVsczogTWVzc2FnZVJlY2VpdmUuTWVzc2FnZVBlZXJEYXRhQ2hhbm5lbHNcbiAgICAgICAgKSA9PiB0aGlzLmhhbmRsZVdlYlJ0Y1NGVVBlZXJEYXRhY2hhbm5lbHMobWVzc2FnZURhdGFDaGFubmVscyk7XG5cbiAgICAgICAgLy8gV2hlbiB0aGUgc2lnbmFsaW5nIHNlcnZlciBzZW5kcyBhIEljZUNhbmRpZGF0ZSBvdmVyIHRoZSB3ZWJzb2NrZXQgY29ubmVjdGlvbiBoYXZlIHRoZSBXZWJSdGNDb250cm9sbGVyIGhhbmRsZSB0aGUgbWVzc2FnZVxuICAgICAgICB0aGlzLndlYlNvY2tldENvbnRyb2xsZXIub25JY2VDYW5kaWRhdGUgPSAoXG4gICAgICAgICAgICBpY2VDYW5kaWRhdGU6IFJUQ0ljZUNhbmRpZGF0ZUluaXRcbiAgICAgICAgKSA9PiB0aGlzLmhhbmRsZUljZUNhbmRpZGF0ZShpY2VDYW5kaWRhdGUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXMgd2hlbiB0aGUgc2lnbmFsbGluZyBzZXJ2ZXIgZ2l2ZXMgdXMgdGhlIGxpc3Qgb2Ygc3RyZWFtZXIgaWRzLlxuICAgICAqL1xuICAgIGhhbmRsZVN0cmVhbWVyTGlzdE1lc3NhZ2UobWVzc2FnZVN0cmVhbWVyTGlzdDogTWVzc2FnZVN0cmVhbWVyTGlzdCkge1xuICAgICAgICBMb2dnZXIuTG9nKFxuICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgIGBHb3Qgc3RyZWFtZXIgbGlzdCAke21lc3NhZ2VTdHJlYW1lckxpc3QuaWRzfWAsXG4gICAgICAgICAgICA2XG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gYWRkIHRoZSBzdHJlYW1lcnMgdG8gdGhlIFVJXG4gICAgICAgIGNvbnN0IHNldHRpbmdPcHRpb25zID0gWy4uLm1lc3NhZ2VTdHJlYW1lckxpc3QuaWRzXTsgLy8gY29weSB0aGUgb3JpZ2luYWwgbWVzc2FnZVN0cmVhbWVyTGlzdC5pZHNcbiAgICAgICAgc2V0dGluZ09wdGlvbnMudW5zaGlmdCgnJyk7IC8vIGFkZCBhbiBlbXB0eSBvcHRpb24gYXQgdGhlIHRvcFxuICAgICAgICB0aGlzLmNvbmZpZy5zZXRPcHRpb25TZXR0aW5nT3B0aW9ucyhcbiAgICAgICAgICAgIE9wdGlvblBhcmFtZXRlcnMuU3RyZWFtZXJJZCxcbiAgICAgICAgICAgIHNldHRpbmdPcHRpb25zXG4gICAgICAgICk7XG5cbiAgICAgICAgbGV0IHdhbnRlZFN0cmVhbWVySWQ6IHN0cmluZyA9IG51bGw7XG4gICAgICAgIGxldCBhdXRvU2VsZWN0ZWRTdHJlYW1lcklkOiBzdHJpbmcgID0gbnVsbDtcbiAgICAgICAgY29uc3Qgd2FpdEZvclN0cmVhbWVyID0gdGhpcy5jb25maWcuaXNGbGFnRW5hYmxlZChGbGFncy5XYWl0Rm9yU3RyZWFtZXIpO1xuICAgICAgICBjb25zdCByZWNvbm5lY3RMaW1pdCA9IHRoaXMuY29uZmlnLmdldE51bWVyaWNTZXR0aW5nVmFsdWUoTnVtZXJpY1BhcmFtZXRlcnMuTWF4UmVjb25uZWN0QXR0ZW1wdHMpO1xuICAgICAgICBjb25zdCByZWNvbm5lY3REZWxheSA9IHRoaXMuY29uZmlnLmdldE51bWVyaWNTZXR0aW5nVmFsdWUoTnVtZXJpY1BhcmFtZXRlcnMuU3RyZWFtZXJBdXRvSm9pbkludGVydmFsKTtcblxuICAgICAgICAvLyBmaXJzdCB3ZSBmaWd1cmUgb3V0IGEgd2FudGVkIHN0cmVhbWVyIGlkIHRocm91Z2ggdmFyaW91cyBtZWFuc1xuICAgICAgICBjb25zdCB1cmxQYXJhbXMgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKHdpbmRvdy5sb2NhdGlvbi5zZWFyY2gpO1xuICAgICAgICBpZiAodXJsUGFyYW1zLmhhcyhPcHRpb25QYXJhbWV0ZXJzLlN0cmVhbWVySWQpKSB7XG4gICAgICAgICAgICAvLyBpZiB3ZSd2ZSBzZXQgdGhlIHN0cmVhbWVyIGlkIG9uIHRoZSB1cmwgd2Ugb25seSB3YW50IHRoYXQgc3RyZWFtZXIgaWRcbiAgICAgICAgICAgIHdhbnRlZFN0cmVhbWVySWQgPSB1cmxQYXJhbXMuZ2V0KE9wdGlvblBhcmFtZXRlcnMuU3RyZWFtZXJJZCk7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5zdWJzY3JpYmVkU3RyZWFtKSB7XG4gICAgICAgICAgICAvLyB3ZSB3ZXJlIHByZXZpb3VzbHkgc3Vic2NyaWJlZCB0byBhIHN0cmVhbWVyLCB3ZSB3YW50IHRoYXRcbiAgICAgICAgICAgIHdhbnRlZFN0cmVhbWVySWQgPSB0aGlzLnN1YnNjcmliZWRTdHJlYW07XG4gICAgICAgIH1cblxuICAgICAgICAvLyBub3cgbGV0cyBzZWUgaWYgd2UgY2FuIHBpY2sgaXQuXG4gICAgICAgIGlmICh3YW50ZWRTdHJlYW1lcklkICYmIG1lc3NhZ2VTdHJlYW1lckxpc3QuaWRzLmluY2x1ZGVzKHdhbnRlZFN0cmVhbWVySWQpKSB7XG4gICAgICAgICAgICAvLyBpZiB0aGUgd2FudGVkIHN0cmVhbSBpcyBpbiB0aGUgbGlzdC4gd2UgcGljayB0aGF0XG4gICAgICAgICAgICBhdXRvU2VsZWN0ZWRTdHJlYW1lcklkID0gd2FudGVkU3RyZWFtZXJJZDtcbiAgICAgICAgfSBlbHNlIGlmICgoIXdhbnRlZFN0cmVhbWVySWQgfHwgIXdhaXRGb3JTdHJlYW1lcikgJiYgbWVzc2FnZVN0cmVhbWVyTGlzdC5pZHMubGVuZ3RoID09IDEpIHtcbiAgICAgICAgICAgIC8vIG90aGVyd2lzZSwgaWYgd2UncmUgbm90IHdhaXRpbmcgZm9yIHRoZSB3YW50ZWQgc3RyZWFtZXIgYW5kIHRoZXJlJ3Mgb25seSBvbmUgc3RyZWFtZXIsIGNvbm5lY3QgdG8gaXRcbiAgICAgICAgICAgIGF1dG9TZWxlY3RlZFN0cmVhbWVySWQgPSBtZXNzYWdlU3RyZWFtZXJMaXN0Lmlkc1swXTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGlmIHdlIGZvdW5kIGEgc3RyZWFtZXIgaWQgdG8gYXV0byBzZWxlY3QsIHNlbGVjdCBpdFxuICAgICAgICBpZiAoYXV0b1NlbGVjdGVkU3RyZWFtZXJJZCkge1xuICAgICAgICAgICAgdGhpcy5pc1JlY29ubmVjdGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5yZWNvbm5lY3RBdHRlbXB0ID0gMDtcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLnNldE9wdGlvblNldHRpbmdWYWx1ZShcbiAgICAgICAgICAgICAgICBPcHRpb25QYXJhbWV0ZXJzLlN0cmVhbWVySWQsXG4gICAgICAgICAgICAgICAgYXV0b1NlbGVjdGVkU3RyZWFtZXJJZFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIG5vIGF1dG8gc2VsZWN0ZWQgc3RyZWFtZXIuXG4gICAgICAgICAgICAvLyBpZiB3ZSdyZSB3YWl0aW5nIGZvciBhIHN0cmVhbWVyIHRoZW4gdHJ5IHJlY29ubmVjdGluZ1xuICAgICAgICAgICAgaWYgKHdhaXRGb3JTdHJlYW1lcikge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnJlY29ubmVjdEF0dGVtcHQgPCByZWNvbm5lY3RMaW1pdCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBzdGlsbCByZWNvbm5lY3RzIGF2YWlsYWJsZVxuICAgICAgICAgICAgICAgICAgICB0aGlzLmlzUmVjb25uZWN0aW5nID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZWNvbm5lY3RBdHRlbXB0Kys7XG4gICAgICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy53ZWJTb2NrZXRDb250cm9sbGVyLnJlcXVlc3RTdHJlYW1lckxpc3QoKTtcbiAgICAgICAgICAgICAgICAgICAgfSwgcmVjb25uZWN0RGVsYXkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFdlJ3ZlIGV4aGF1c3RlZCBvdXIgcmVjb25uZWN0IGF0dGVtcHRzLCByZXR1cm4gdG8gbWFpbiBzY3JlZW5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZWNvbm5lY3RBdHRlbXB0ID0gMDtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pc1JlY29ubmVjdGluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNob3VsZFJlY29ubmVjdCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGRpc3BhdGNoIHRoaXMgZXZlbnQgZmluYWxseVxuICAgICAgICB0aGlzLnBpeGVsU3RyZWFtaW5nLmRpc3BhdGNoRXZlbnQoXG4gICAgICAgICAgICBuZXcgU3RyZWFtZXJMaXN0TWVzc2FnZUV2ZW50KHtcbiAgICAgICAgICAgICAgICBtZXNzYWdlU3RyZWFtZXJMaXN0LFxuICAgICAgICAgICAgICAgIGF1dG9TZWxlY3RlZFN0cmVhbWVySWQsXG4gICAgICAgICAgICAgICAgd2FudGVkU3RyZWFtZXJJZFxuICAgICAgICAgICAgfSlcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGUgdGhlIFJUQyBBbnN3ZXIgZnJvbSB0aGUgc2lnbmFsaW5nIHNlcnZlclxuICAgICAqIEBwYXJhbSBBbnN3ZXIgLSBBbnN3ZXIgU0RQIGZyb20gdGhlIHBlZXIuXG4gICAgICovXG4gICAgaGFuZGxlV2ViUnRjQW5zd2VyKEFuc3dlcjogTWVzc2FnZUFuc3dlcikge1xuICAgICAgICBMb2dnZXIuTG9nKExvZ2dlci5HZXRTdGFja1RyYWNlKCksIGBHb3QgYW5zd2VyIHNkcCAke0Fuc3dlci5zZHB9YCwgNik7XG5cbiAgICAgICAgY29uc3Qgc2RwQW5zd2VyOiBSVENTZXNzaW9uRGVzY3JpcHRpb25Jbml0ID0ge1xuICAgICAgICAgICAgc2RwOiBBbnN3ZXIuc2RwLFxuICAgICAgICAgICAgdHlwZTogJ2Fuc3dlcidcbiAgICAgICAgfTtcblxuICAgICAgICB0aGlzLnBlZXJDb25uZWN0aW9uQ29udHJvbGxlci5yZWNlaXZlQW5zd2VyKHNkcEFuc3dlcik7XG4gICAgICAgIHRoaXMuaGFuZGxlUG9zdFdlYnJ0Y05lZ290aWF0aW9uKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlIHRoZSBSVEMgb2ZmZXIgZnJvbSBhIFdlYlJUQyBwZWVyIChyZWNlaXZlZCB0aHJvdWdoIHRoZSBzaWduYWxsaW5nIHNlcnZlcikuXG4gICAgICogQHBhcmFtIE9mZmVyIC0gT2ZmZXIgU0RQIGZyb20gdGhlIHBlZXIuXG4gICAgICovXG4gICAgaGFuZGxlV2ViUnRjT2ZmZXIoT2ZmZXI6IE1lc3NhZ2VPZmZlcikge1xuICAgICAgICBMb2dnZXIuTG9nKExvZ2dlci5HZXRTdGFja1RyYWNlKCksIGBHb3Qgb2ZmZXIgc2RwICR7T2ZmZXIuc2RwfWAsIDYpO1xuXG4gICAgICAgIHRoaXMuaXNVc2luZ1NGVSA9IE9mZmVyLnNmdSA/IE9mZmVyLnNmdSA6IGZhbHNlO1xuICAgICAgICBpZiAodGhpcy5pc1VzaW5nU0ZVKSB7XG4gICAgICAgICAgICAvLyBEaXNhYmxlIG5lZ290aWF0aW5nIHdpdGggdGhlIHNmdSBhcyB0aGUgc2Z1IG9ubHkgc3VwcG9ydHMgb25lIGNvZGVjIGF0IGEgdGltZVxuICAgICAgICAgICAgdGhpcy5wZWVyQ29ubmVjdGlvbkNvbnRyb2xsZXIucHJlZmVycmVkQ29kZWMgPSAnJztcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHNkcE9mZmVyOiBSVENTZXNzaW9uRGVzY3JpcHRpb25Jbml0ID0ge1xuICAgICAgICAgICAgc2RwOiBPZmZlci5zZHAsXG4gICAgICAgICAgICB0eXBlOiAnb2ZmZXInXG4gICAgICAgIH07XG5cbiAgICAgICAgdGhpcy5wZWVyQ29ubmVjdGlvbkNvbnRyb2xsZXIucmVjZWl2ZU9mZmVyKHNkcE9mZmVyLCB0aGlzLmNvbmZpZyk7XG4gICAgICAgIHRoaXMuaGFuZGxlUG9zdFdlYnJ0Y05lZ290aWF0aW9uKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlIHdoZW4gdGhlIFNGVSBwcm92aWRlcyB0aGUgcGVlciB3aXRoIGl0cyBkYXRhIGNoYW5uZWxzXG4gICAgICogQHBhcmFtIERhdGFDaGFubmVscyAtIFRoZSBtZXNzYWdlIGZyb20gdGhlIFNGVSBjb250YWluaW5nIHRoZSBkYXRhIGNoYW5uZWxzIGlkc1xuICAgICAqL1xuICAgIGhhbmRsZVdlYlJ0Y1NGVVBlZXJEYXRhY2hhbm5lbHMoXG4gICAgICAgIERhdGFDaGFubmVsczogTWVzc2FnZVJlY2VpdmUuTWVzc2FnZVBlZXJEYXRhQ2hhbm5lbHNcbiAgICApIHtcbiAgICAgICAgY29uc3QgU2VuZE9wdGlvbnM6IFJUQ0RhdGFDaGFubmVsSW5pdCA9IHtcbiAgICAgICAgICAgIG9yZGVyZWQ6IHRydWUsXG4gICAgICAgICAgICBuZWdvdGlhdGVkOiB0cnVlLFxuICAgICAgICAgICAgaWQ6IERhdGFDaGFubmVscy5zZW5kU3RyZWFtSWRcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCB1bmlkaXJlY3Rpb25hbCA9XG4gICAgICAgICAgICBEYXRhQ2hhbm5lbHMuc2VuZFN0cmVhbUlkICE9IERhdGFDaGFubmVscy5yZWN2U3RyZWFtSWQ7XG5cbiAgICAgICAgdGhpcy5zZW5kcmVjdkRhdGFDaGFubmVsQ29udHJvbGxlci5jcmVhdGVEYXRhQ2hhbm5lbChcbiAgICAgICAgICAgIHRoaXMucGVlckNvbm5lY3Rpb25Db250cm9sbGVyLnBlZXJDb25uZWN0aW9uLFxuICAgICAgICAgICAgdW5pZGlyZWN0aW9uYWwgPyAnc2VuZC1kYXRhY2hhbm5lbCcgOiAnZGF0YWNoYW5uZWwnLFxuICAgICAgICAgICAgU2VuZE9wdGlvbnNcbiAgICAgICAgKTtcblxuICAgICAgICBpZiAodW5pZGlyZWN0aW9uYWwpIHtcbiAgICAgICAgICAgIGNvbnN0IFJlY3ZPcHRpb25zOiBSVENEYXRhQ2hhbm5lbEluaXQgPSB7XG4gICAgICAgICAgICAgICAgb3JkZXJlZDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBuZWdvdGlhdGVkOiB0cnVlLFxuICAgICAgICAgICAgICAgIGlkOiBEYXRhQ2hhbm5lbHMucmVjdlN0cmVhbUlkXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLnJlY3ZEYXRhQ2hhbm5lbENvbnRyb2xsZXIuY3JlYXRlRGF0YUNoYW5uZWwoXG4gICAgICAgICAgICAgICAgdGhpcy5wZWVyQ29ubmVjdGlvbkNvbnRyb2xsZXIucGVlckNvbm5lY3Rpb24sXG4gICAgICAgICAgICAgICAgJ3JlY3YtZGF0YWNoYW5uZWwnLFxuICAgICAgICAgICAgICAgIFJlY3ZPcHRpb25zXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgdGhpcy5yZWN2RGF0YUNoYW5uZWxDb250cm9sbGVyLmhhbmRsZU9uT3BlbiA9ICgpID0+XG4gICAgICAgICAgICAgICAgdGhpcy53ZWJTb2NrZXRDb250cm9sbGVyLnNlbmRTRlVSZWN2RGF0YUNoYW5uZWxSZWFkeSgpO1xuICAgICAgICAgICAgLy8gSWYgd2UncmUgdW5pLWRpcmVjdGlvbmFsLCBvbmx5IHRoZSByZWN2IGRhdGEgY2hhbm5lbCBzaG91bGQgaGFuZGxlIGluY29taW5nIG1lc3NhZ2VzXG4gICAgICAgICAgICB0aGlzLnJlY3ZEYXRhQ2hhbm5lbENvbnRyb2xsZXIuaGFuZGxlT25NZXNzYWdlID0gKFxuICAgICAgICAgICAgICAgIGV2OiBNZXNzYWdlRXZlbnRcbiAgICAgICAgICAgICkgPT4gdGhpcy5oYW5kbGVPbk1lc3NhZ2UoZXYpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gZWxzZSBvdXIgcHJpbWFyeSBkYXRhY2hhbm5lbCBpcyBzZW5kL3JlY3Ygc28gaXQgY2FuIGhhbmRsZSBpbmNvbWluZyBtZXNzYWdlc1xuICAgICAgICAgICAgdGhpcy5zZW5kcmVjdkRhdGFDaGFubmVsQ29udHJvbGxlci5oYW5kbGVPbk1lc3NhZ2UgPSAoXG4gICAgICAgICAgICAgICAgZXY6IE1lc3NhZ2VFdmVudFxuICAgICAgICAgICAgKSA9PiB0aGlzLmhhbmRsZU9uTWVzc2FnZShldik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBoYW5kbGVQb3N0V2VicnRjTmVnb3RpYXRpb24oKSB7XG4gICAgICAgIC8vIHN0YXJ0IHRoZSBhZmsgd2FybmluZyB0aW1lciBhcyBQUyBpcyBub3cgcnVubmluZ1xuICAgICAgICB0aGlzLmFma0NvbnRyb2xsZXIuc3RhcnRBZmtXYXJuaW5nVGltZXIoKTtcbiAgICAgICAgLy8gc2hvdyB0aGUgb3ZlcmxheSB0aGF0IHdlIGhhdmUgbmVnb3RpYXRlZCBhIGNvbm5lY3Rpb25cbiAgICAgICAgdGhpcy5waXhlbFN0cmVhbWluZy5fb25XZWJSdGNTZHAoKTtcblxuICAgICAgICBpZiAodGhpcy5zdGF0c1RpbWVySGFuZGxlICYmIHRoaXMuc3RhdHNUaW1lckhhbmRsZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB3aW5kb3cuY2xlYXJJbnRlcnZhbCh0aGlzLnN0YXRzVGltZXJIYW5kbGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5zdGF0c1RpbWVySGFuZGxlID0gd2luZG93LnNldEludGVydmFsKCgpID0+IHRoaXMuZ2V0U3RhdHMoKSwgMTAwMCk7XG5cbiAgICAgICAgLyogICovXG4gICAgICAgIHRoaXMuc2V0TW91c2VJbnB1dEVuYWJsZWQodGhpcy5jb25maWcuaXNGbGFnRW5hYmxlZChGbGFncy5Nb3VzZUlucHV0KSk7XG4gICAgICAgIHRoaXMuc2V0S2V5Ym9hcmRJbnB1dEVuYWJsZWQodGhpcy5jb25maWcuaXNGbGFnRW5hYmxlZChGbGFncy5LZXlib2FyZElucHV0KSk7XG4gICAgICAgIHRoaXMuc2V0R2FtZVBhZElucHV0RW5hYmxlZCh0aGlzLmNvbmZpZy5pc0ZsYWdFbmFibGVkKEZsYWdzLkdhbWVwYWRJbnB1dCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFdoZW4gYW4gaWNlIENhbmRpZGF0ZSBpcyByZWNlaXZlZCBmcm9tIHRoZSBTaWduYWxpbmcgc2VydmVyIGFkZCBpdCB0byB0aGUgUGVlciBDb25uZWN0aW9uIENsaWVudFxuICAgICAqIEBwYXJhbSBpY2VDYW5kaWRhdGUgLSBJY2UgQ2FuZGlkYXRlIGZyb20gU2VydmVyXG4gICAgICovXG4gICAgaGFuZGxlSWNlQ2FuZGlkYXRlKGljZUNhbmRpZGF0ZTogUlRDSWNlQ2FuZGlkYXRlSW5pdCkge1xuICAgICAgICBMb2dnZXIuTG9nKFxuICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICdXZWIgUlRDIENvbnRyb2xsZXI6IG9uV2ViUnRjSWNlJyxcbiAgICAgICAgICAgIDZcbiAgICAgICAgKTtcblxuICAgICAgICBjb25zdCBjYW5kaWRhdGUgPSBuZXcgUlRDSWNlQ2FuZGlkYXRlKGljZUNhbmRpZGF0ZSk7XG4gICAgICAgIHRoaXMucGVlckNvbm5lY3Rpb25Db250cm9sbGVyLmhhbmRsZU9uSWNlKGNhbmRpZGF0ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VuZCB0aGUgaWNlIENhbmRpZGF0ZSB0byB0aGUgc2lnbmFsaW5nIHNlcnZlciB2aWEgd2Vic29ja2V0XG4gICAgICogQHBhcmFtIGljZUV2ZW50IC0gUlRDIFBlZXIgQ29ubmVjdGlvbkljZUV2ZW50KSB7XG4gICAgICovXG4gICAgaGFuZGxlU2VuZEljZUNhbmRpZGF0ZShpY2VFdmVudDogUlRDUGVlckNvbm5lY3Rpb25JY2VFdmVudCkge1xuICAgICAgICBMb2dnZXIuTG9nKExvZ2dlci5HZXRTdGFja1RyYWNlKCksICdPbkljZUNhbmRpZGF0ZScsIDYpO1xuICAgICAgICBpZiAoaWNlRXZlbnQuY2FuZGlkYXRlICYmIGljZUV2ZW50LmNhbmRpZGF0ZS5jYW5kaWRhdGUpIHtcbiAgICAgICAgICAgIHRoaXMud2ViU29ja2V0Q29udHJvbGxlci5zZW5kSWNlQ2FuZGlkYXRlKGljZUV2ZW50LmNhbmRpZGF0ZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZW5kIHRoZSBpY2UgQ2FuZGlkYXRlIHRvIHRoZSBzaWduYWxpbmcgc2VydmVyIHZpYSB3ZWJzb2NrZXRcbiAgICAgKiBAcGFyYW0gaWNlRXZlbnQgLSBSVEMgUGVlciBDb25uZWN0aW9uSWNlRXZlbnQpIHtcbiAgICAgKi9cbiAgICBoYW5kbGVEYXRhQ2hhbm5lbChkYXRhY2hhbm5lbEV2ZW50OiBSVENEYXRhQ2hhbm5lbEV2ZW50KSB7XG4gICAgICAgIExvZ2dlci5Mb2coXG4gICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgJ0RhdGEgY2hhbm5lbCBjcmVhdGVkIGZvciB1cyBieSBicm93c2VyIGFzIHdlIGFyZSBhIHJlY2VpdmluZyBwZWVyLicsXG4gICAgICAgICAgICA2XG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuc2VuZHJlY3ZEYXRhQ2hhbm5lbENvbnRyb2xsZXIuZGF0YUNoYW5uZWwgPVxuICAgICAgICAgICAgZGF0YWNoYW5uZWxFdmVudC5jaGFubmVsO1xuICAgICAgICAvLyBEYXRhIGNoYW5uZWwgd2FzIGNyZWF0ZWQgZm9yIHVzLCBzbyB3ZSBqdXN0IG5lZWQgdG8gc2V0dXAgaXRzIGNhbGxiYWNrcyBhbmQgYXJyYXkgdHlwZVxuICAgICAgICB0aGlzLnNlbmRyZWN2RGF0YUNoYW5uZWxDb250cm9sbGVyLnNldHVwRGF0YUNoYW5uZWwoKTtcbiAgICAgICAgdGhpcy5zZW5kcmVjdkRhdGFDaGFubmVsQ29udHJvbGxlci5oYW5kbGVPbk1lc3NhZ2UgPSAoXG4gICAgICAgICAgICBldjogTWVzc2FnZUV2ZW50PEFycmF5QnVmZmVyPlxuICAgICAgICApID0+IHRoaXMuaGFuZGxlT25NZXNzYWdlKGV2KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZW5kIHRoZSBSVEMgT2ZmZXIgU2Vzc2lvbiB0byB0aGUgU2lnbmFsaW5nIHNlcnZlciB2aWEgd2Vic29ja2V0XG4gICAgICogQHBhcmFtIG9mZmVyIC0gUlRDIFNlc3Npb24gRGVzY3JpcHRpb25cbiAgICAgKi9cbiAgICBoYW5kbGVTZW5kV2ViUlRDT2ZmZXIob2ZmZXI6IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbkluaXQpIHtcbiAgICAgICAgTG9nZ2VyLkxvZyhcbiAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAnU2VuZGluZyB0aGUgb2ZmZXIgdG8gdGhlIFNlcnZlcicsXG4gICAgICAgICAgICA2XG4gICAgICAgICk7XG4gICAgICAgIHRoaXMud2ViU29ja2V0Q29udHJvbGxlci5zZW5kV2ViUnRjT2ZmZXIob2ZmZXIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlbmQgdGhlIFJUQyBPZmZlciBTZXNzaW9uIHRvIHRoZSBTaWduYWxpbmcgc2VydmVyIHZpYSB3ZWJzb2NrZXRcbiAgICAgKiBAcGFyYW0gYW5zd2VyIC0gUlRDIFNlc3Npb24gRGVzY3JpcHRpb25cbiAgICAgKi9cbiAgICBoYW5kbGVTZW5kV2ViUlRDQW5zd2VyKGFuc3dlcjogUlRDU2Vzc2lvbkRlc2NyaXB0aW9uSW5pdCkge1xuICAgICAgICBMb2dnZXIuTG9nKFxuICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICdTZW5kaW5nIHRoZSBhbnN3ZXIgdG8gdGhlIFNlcnZlcicsXG4gICAgICAgICAgICA2XG4gICAgICAgICk7XG4gICAgICAgIHRoaXMud2ViU29ja2V0Q29udHJvbGxlci5zZW5kV2ViUnRjQW5zd2VyKGFuc3dlcik7XG5cbiAgICAgICAgaWYgKHRoaXMuaXNVc2luZ1NGVSkge1xuICAgICAgICAgICAgdGhpcy53ZWJTb2NrZXRDb250cm9sbGVyLnNlbmRXZWJSdGNEYXRhY2hhbm5lbFJlcXVlc3QoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgZnJlZXplIGZyYW1lIG92ZXJsYXkgdG8gdGhlIHBsYXllciBkaXZcbiAgICAgKi9cbiAgICBzZXRVcE1vdXNlQW5kRnJlZXplRnJhbWUoKSB7XG4gICAgICAgIC8vIENhbGN1bGF0aW5nIGFuZCBub3JtYWxpemluZyBwb3NpdGlvbnMgZGVwZW5kcyBvbiB0aGUgd2lkdGggYW5kIGhlaWdodCBvZiB0aGUgcGxheWVyLlxuICAgICAgICB0aGlzLnZpZGVvRWxlbWVudFBhcmVudENsaWVudFJlY3QgPSB0aGlzLnZpZGVvUGxheWVyXG4gICAgICAgICAgICAuZ2V0VmlkZW9QYXJlbnRFbGVtZW50KClcbiAgICAgICAgICAgIC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgICAgdGhpcy5jb29yZGluYXRlQ29udmVydGVyLnNldHVwTm9ybWFsaXplQW5kUXVhbnRpemUoKTtcbiAgICAgICAgdGhpcy5mcmVlemVGcmFtZUNvbnRyb2xsZXIuZnJlZXplRnJhbWUucmVzaXplKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2xvc2UgdGhlIENvbm5lY3Rpb24gdG8gdGhlIHNpZ25hbGluZyBzZXJ2ZXJcbiAgICAgKi9cbiAgICBjbG9zZVNpZ25hbGluZ1NlcnZlcihtZXNzYWdlOiBzdHJpbmcpIHtcbiAgICAgICAgLy8gV2UgZXhwbGljaXRseSBjYWxsZWQgY2xvc2UsIHRoZXJlZm9yZSB3ZSBkb24ndCB3YW50IHRvIHRyaWdnZXIgYXV0byByZWNvbm5lY3RcbiAgICAgICAgdGhpcy5sb2NhbGx5Q2xvc2VkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5zaG91bGRSZWNvbm5lY3QgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5kaXNjb25uZWN0TWVzc2FnZSA9IG1lc3NhZ2U7XG4gICAgICAgIHRoaXMud2ViU29ja2V0Q29udHJvbGxlcj8uY2xvc2UoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDbG9zZSB0aGUgcGVlciBjb25uZWN0aW9uXG4gICAgICovXG4gICAgY2xvc2VQZWVyQ29ubmVjdGlvbigpIHtcbiAgICAgICAgdGhpcy5wZWVyQ29ubmVjdGlvbkNvbnRyb2xsZXI/LmNsb3NlKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2xvc2UgYWxsIGNvbm5lY3Rpb25zXG4gICAgICovXG4gICAgY2xvc2UoKSB7XG4gICAgICAgIHRoaXMuY2xvc2VTaWduYWxpbmdTZXJ2ZXIoJycpO1xuICAgICAgICB0aGlzLmNsb3NlUGVlckNvbm5lY3Rpb24oKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGaXJlcyBhIFZpZGVvIFN0YXRzIEV2ZW50IGluIHRoZSBSVEMgUGVlciBDb25uZWN0aW9uXG4gICAgICovXG4gICAgZ2V0U3RhdHMoKSB7XG4gICAgICAgIHRoaXMucGVlckNvbm5lY3Rpb25Db250cm9sbGVyLmdlbmVyYXRlU3RhdHMoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZW5kIGEgTGF0ZW5jeSBUZXN0IFJlcXVlc3QgdG8gdGhlIFVFIEluc3RhbmNlXG4gICAgICovXG4gICAgc2VuZExhdGVuY3lUZXN0KCkge1xuICAgICAgICB0aGlzLmxhdGVuY3lTdGFydFRpbWUgPSBEYXRlLm5vdygpO1xuXG4gICAgICAgIHRoaXMuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIudG9TdHJlYW1lckhhbmRsZXJzLmdldChcbiAgICAgICAgICAgICdMYXRlbmN5VGVzdCdcbiAgICAgICAgKShbSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgU3RhcnRUaW1lOiB0aGlzLmxhdGVuY3lTdGFydFRpbWVcbiAgICAgICAgfSldKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZW5kIGEgRGF0YSBDaGFubmVsIExhdGVuY3kgVGVzdCBSZXF1ZXN0IHRvIHRoZSBVRSBJbnN0YW5jZVxuICAgICAqL1xuICAgIHNlbmREYXRhQ2hhbm5lbExhdGVuY3lUZXN0KGRlc2NyaXB0b3I6IERhdGFDaGFubmVsTGF0ZW5jeVRlc3RSZXF1ZXN0KSB7XG4gICAgICAgIHRoaXMuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIudG9TdHJlYW1lckhhbmRsZXJzLmdldChcbiAgICAgICAgICAgICdEYXRhQ2hhbm5lbExhdGVuY3lUZXN0J1xuICAgICAgICApKFtKU09OLnN0cmluZ2lmeShkZXNjcmlwdG9yKV0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlbmQgdGhlIE1pblFQIGVuY29kZXIgc2V0dGluZyB0byB0aGUgVUUgSW5zdGFuY2UuXG4gICAgICogQHBhcmFtIG1pblFQIC0gVGhlIGxvd2VyIGJvdW5kIGZvciBRUCB3aGVuIGVuY29kaW5nXG4gICAgICogdmFsaWQgdmFsdWVzIGFyZSAoMS01MSkgd2hlcmU6XG4gICAgICogMSA9IEJlc3QgcXVhbGl0eSBidXQgaGlnaGVzdCBiaXRyYXRlLlxuICAgICAqIDUxID0gV29yc3QgcXVhbGl0eSBidXQgbG93ZXN0IGJpdHJhdGUuXG4gICAgICogQnkgZGVmYXVsdCB0aGUgbWluUVAgaXMgMSBtZWFuaW5nIHRoZSBlbmNvZGVyIGlzIGZyZWVcbiAgICAgKiB0byBhaW0gZm9yIHRoZSBiZXN0IHF1YWxpdHkgaXQgY2FuIG9uIHRoZSBnaXZlbiBuZXR3b3JrIGxpbmsuXG4gICAgICovXG4gICAgc2VuZEVuY29kZXJNaW5RUChtaW5RUDogbnVtYmVyKSB7XG4gICAgICAgIExvZ2dlci5Mb2coTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSwgYE1pblFQPSR7bWluUVB9XFxuYCwgNik7XG5cbiAgICAgICAgaWYgKG1pblFQICE9IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIudG9TdHJlYW1lckhhbmRsZXJzLmdldChcbiAgICAgICAgICAgICAgICAnQ29tbWFuZCdcbiAgICAgICAgICAgICkoW0pTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgICAgICAnRW5jb2Rlci5NaW5RUCc6IG1pblFQXG4gICAgICAgICAgICB9KV0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VuZCB0aGUgTWF4UVAgZW5jb2RlciBzZXR0aW5nIHRvIHRoZSBVRSBJbnN0YW5jZS5cbiAgICAgKiBAcGFyYW0gbWF4UVAgLSBUaGUgdXBwZXIgYm91bmQgZm9yIFFQIHdoZW4gZW5jb2RpbmdcbiAgICAgKiB2YWxpZCB2YWx1ZXMgYXJlICgxLTUxKSB3aGVyZTpcbiAgICAgKiAxID0gQmVzdCBxdWFsaXR5IGJ1dCBoaWdoZXN0IGJpdHJhdGUuXG4gICAgICogNTEgPSBXb3JzdCBxdWFsaXR5IGJ1dCBsb3dlc3QgYml0cmF0ZS5cbiAgICAgKiBCeSBkZWZhdWx0IHRoZSBtYXhRUCBpcyA1MSBtZWFuaW5nIHRoZSBlbmNvZGVyIGlzIGZyZWVcbiAgICAgKiB0byBkcm9wIHF1YWxpdHkgYXMgbG93IGFzIG5lZWRlZCBvbiB0aGUgZ2l2ZW4gbmV0d29yayBsaW5rLlxuICAgICAqL1xuICAgICBzZW5kRW5jb2Rlck1heFFQKG1heFFQOiBudW1iZXIpIHtcbiAgICAgICAgTG9nZ2VyLkxvZyhMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLCBgTWF4UVA9JHttYXhRUH1cXG5gLCA2KTtcblxuICAgICAgICBpZiAobWF4UVAgIT0gbnVsbCkge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW1NZXNzYWdlQ29udHJvbGxlci50b1N0cmVhbWVySGFuZGxlcnMuZ2V0KFxuICAgICAgICAgICAgICAgICdDb21tYW5kJ1xuICAgICAgICAgICAgKShbSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgICAgICdFbmNvZGVyLk1heFFQJzogbWF4UVBcbiAgICAgICAgICAgIH0pXSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZW5kIHRoZSB7IFdlYlJUQy5NaW5CaXRyYXRlOiBTb21lTnVtYmVyIH19IGNvbW1hbmQgdG8gVUUgdG8gc2V0IFxuICAgICAqIHRoZSBtaW5pbXVtIGJpdHJhdGUgdGhhdCB3ZSBhbGxvdyBXZWJSVEMgdG8gdXNlIFxuICAgICAqIChub3RlIHNldHRpbmcgdGhpcyB0b28gaGlnaCBpbiBwb29yIG5ldHdvcmtzIGNhbiBiZSBwcm9ibGVtYXRpYykuXG4gICAgICogQHBhcmFtIG1pbkJpdHJhdGUgLSBUaGUgbWluaW11bSBiaXRyYXRlIHdlIHdvdWxkIGxpa2UgV2ViUlRDIHRvIG5vdCBmYWxsIGJlbG93LlxuICAgICAqL1xuICAgIHNlbmRXZWJSVENNaW5CaXRyYXRlKG1pbkJpdHJhdGU6IG51bWJlcikge1xuICAgICAgICBMb2dnZXIuTG9nKExvZ2dlci5HZXRTdGFja1RyYWNlKCksIGBXZWJSVEMgTWluIEJpdHJhdGU9JHttaW5CaXRyYXRlfWAsIDYpO1xuICAgICAgICBpZiAobWluQml0cmF0ZSAhPSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLnN0cmVhbU1lc3NhZ2VDb250cm9sbGVyLnRvU3RyZWFtZXJIYW5kbGVycy5nZXQoXG4gICAgICAgICAgICAgICAgJ0NvbW1hbmQnXG4gICAgICAgICAgICApKFtKU09OLnN0cmluZ2lmeSh7XG4gICAgICAgICAgICAgICAgJ1dlYlJUQy5NaW5CaXRyYXRlJzogbWluQml0cmF0ZVxuICAgICAgICAgICAgfSldKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlbmQgdGhlIHsgV2ViUlRDLk1heEJpdHJhdGU6IFNvbWVOdW1iZXIgfX0gY29tbWFuZCB0byBVRSB0byBzZXQgXG4gICAgICogdGhlIG1pbmltdW0gYml0cmF0ZSB0aGF0IHdlIGFsbG93IFdlYlJUQyB0byB1c2UgXG4gICAgICogKG5vdGUgc2V0dGluZyB0aGlzIHRvbyBsb3cgY291bGQgcmVzdWx0IGluIGJsb2NreSB2aWRlbykuXG4gICAgICogQHBhcmFtIG1pbkJpdHJhdGUgLSBUaGUgbWluaW11bSBiaXRyYXRlIHdlIHdvdWxkIGxpa2UgV2ViUlRDIHRvIG5vdCBmYWxsIGJlbG93LlxuICAgICAqL1xuICAgICBzZW5kV2ViUlRDTWF4Qml0cmF0ZShtYXhCaXRyYXRlOiBudW1iZXIpIHtcbiAgICAgICAgTG9nZ2VyLkxvZyhMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLCBgV2ViUlRDIE1heCBCaXRyYXRlPSR7bWF4Qml0cmF0ZX1gLCA2KTtcbiAgICAgICAgaWYgKG1heEJpdHJhdGUgIT0gbnVsbCkge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW1NZXNzYWdlQ29udHJvbGxlci50b1N0cmVhbWVySGFuZGxlcnMuZ2V0KFxuICAgICAgICAgICAgICAgICdDb21tYW5kJ1xuICAgICAgICAgICAgKShbSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgICAgICdXZWJSVEMuTWF4Qml0cmF0ZSc6IG1heEJpdHJhdGVcbiAgICAgICAgICAgIH0pXSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZW5kIHRoZSB7IFdlYlJUQy5GcHM6IFNvbWVOdW1iZXIgfX0gVUUgNS4wK1xuICAgICAqIGFuZCB7IFdlYlJUQy5NYXhGcHMgfSBVRSA0LjI3IGNvbW1hbmQgdG8gc2V0IFxuICAgICAqIHRoZSBtYXhpbXVtIGZwcyB3ZSB3b3VsZCBsaWtlIFdlYlJUQyB0byBzdHJlYW0gYXQuIFxuICAgICAqIEBwYXJhbSBmcHMgLSBUaGUgbWF4aW11bSBzdHJlYW0gZnBzLlxuICAgICAqL1xuICAgICBzZW5kV2ViUlRDRnBzKGZwczogbnVtYmVyKSB7XG4gICAgICAgIExvZ2dlci5Mb2coTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSwgYFdlYlJUQyBGUFM9JHtmcHN9YCwgNik7XG4gICAgICAgIGlmIChmcHMgIT0gbnVsbCkge1xuICAgICAgICAgICAgdGhpcy5zdHJlYW1NZXNzYWdlQ29udHJvbGxlci50b1N0cmVhbWVySGFuZGxlcnMuZ2V0KFxuICAgICAgICAgICAgICAgICdDb21tYW5kJ1xuICAgICAgICAgICAgKShbSlNPTi5zdHJpbmdpZnkoeydXZWJSVEMuRnBzJzogZnBzfSldKTtcblxuICAgICAgICAgICAgLyogVE9ETzogUmVtb3ZlIHdoZW4gVUUgNC4yNyB1bnN1cHBvcnRlZC4gKi9cbiAgICAgICAgICAgIHRoaXMuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIudG9TdHJlYW1lckhhbmRsZXJzLmdldChcbiAgICAgICAgICAgICAgICAnQ29tbWFuZCdcbiAgICAgICAgICAgICkoW0pTT04uc3RyaW5naWZ5KHsnV2ViUlRDLk1heEZwcyc6IGZwc30pXSk7IFxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VuZHMgdGhlIFVJIERlc2NyaXB0b3IgYHN0YXQgZnBzYCB0byB0aGUgVUUgSW5zdGFuY2VcbiAgICAgKi9cbiAgICBzZW5kU2hvd0ZwcygpOiB2b2lkIHtcbiAgICAgICAgTG9nZ2VyLkxvZyhcbiAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAnLS0tLSAgIFNlbmRpbmcgc2hvdyBzdGF0IHRvIFVFICAgLS0tLScsXG4gICAgICAgICAgICA2XG4gICAgICAgICk7XG5cbiAgICAgICAgdGhpcy5zdHJlYW1NZXNzYWdlQ29udHJvbGxlci50b1N0cmVhbWVySGFuZGxlcnMuZ2V0KFxuICAgICAgICAgICAgJ0NvbW1hbmQnXG4gICAgICAgICkoW0pTT04uc3RyaW5naWZ5KHsgJ3N0YXQuZnBzJzogJycgfSldKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZW5kIGFuIElmcmFtZSByZXF1ZXN0IHRvIHRoZSBzdHJlYW1lclxuICAgICAqL1xuICAgIHNlbmRJZnJhbWVSZXF1ZXN0KCk6IHZvaWQge1xuICAgICAgICBMb2dnZXIuTG9nKFxuICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICctLS0tICAgU2VuZGluZyBSZXF1ZXN0IGZvciBhbiBJRnJhbWUgIC0tLS0nLFxuICAgICAgICAgICAgNlxuICAgICAgICApO1xuICAgICAgICB0aGlzLnN0cmVhbU1lc3NhZ2VDb250cm9sbGVyLnRvU3RyZWFtZXJIYW5kbGVycy5nZXQoJ0lGcmFtZVJlcXVlc3QnKSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlbmQgYSBVSUludGVyYWN0aW9uIG1lc3NhZ2VcbiAgICAgKi9cbiAgICBlbWl0VUlJbnRlcmFjdGlvbihkZXNjcmlwdG9yOiBvYmplY3QgfCBzdHJpbmcpIHtcbiAgICAgICAgTG9nZ2VyLkxvZyhcbiAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAnLS0tLSAgIFNlbmRpbmcgY3VzdG9tIFVJSW50ZXJhY3Rpb24gbWVzc2FnZSAgIC0tLS0nLFxuICAgICAgICAgICAgNlxuICAgICAgICApO1xuXG4gICAgICAgIHRoaXMuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIudG9TdHJlYW1lckhhbmRsZXJzLmdldChcbiAgICAgICAgICAgICdVSUludGVyYWN0aW9uJ1xuICAgICAgICApKFtKU09OLnN0cmluZ2lmeShkZXNjcmlwdG9yKV0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlbmQgYSBDb21tYW5kIG1lc3NhZ2VcbiAgICAgKi9cbiAgICBlbWl0Q29tbWFuZChkZXNjcmlwdG9yOiBvYmplY3QpIHtcbiAgICAgICAgTG9nZ2VyLkxvZyhcbiAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAnLS0tLSAgIFNlbmRpbmcgY3VzdG9tIENvbW1hbmQgbWVzc2FnZSAgIC0tLS0nLFxuICAgICAgICAgICAgNlxuICAgICAgICApO1xuICAgICAgICBcbiAgICAgICAgdGhpcy5zdHJlYW1NZXNzYWdlQ29udHJvbGxlci50b1N0cmVhbWVySGFuZGxlcnMuZ2V0KFxuICAgICAgICAgICAgJ0NvbW1hbmQnXG4gICAgICAgICkoW0pTT04uc3RyaW5naWZ5KGRlc2NyaXB0b3IpXSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VuZCBhIGNvbnNvbGUgY29tbWFuZCBtZXNzYWdlXG4gICAgICovXG4gICAgZW1pdENvbnNvbGVDb21tYW5kKGNvbW1hbmQ6IHN0cmluZykge1xuICAgICAgICBMb2dnZXIuTG9nKFxuICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICctLS0tICAgU2VuZGluZyBjdXN0b20gQ29tbWFuZDpDb25zb2xlQ29tbWFuZCBtZXNzYWdlICAgLS0tLScsXG4gICAgICAgICAgICA2XG4gICAgICAgICk7XG5cbiAgICAgICAgdGhpcy5zdHJlYW1NZXNzYWdlQ29udHJvbGxlci50b1N0cmVhbWVySGFuZGxlcnMuZ2V0KFxuICAgICAgICAgICAgJ0NvbW1hbmQnXG4gICAgICAgICkoW0pTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgIENvbnNvbGVDb21tYW5kOiBjb21tYW5kLFxuICAgICAgICB9KV0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlbmRzIGEgcmVxdWVzdCB0byB0aGUgVUUgSW5zdGFuY2UgdG8gaGF2ZSBvd25lcnNoaXAgb2YgUXVhbGl0eVxuICAgICAqL1xuICAgIHNlbmRSZXF1ZXN0UXVhbGl0eUNvbnRyb2xPd25lcnNoaXAoKTogdm9pZCB7XG4gICAgICAgIExvZ2dlci5Mb2coXG4gICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgJy0tLS0gICBTZW5kaW5nIFJlcXVlc3QgdG8gQ29udHJvbCBRdWFsaXR5ICAtLS0tJyxcbiAgICAgICAgICAgIDZcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy50b1N0cmVhbWVyTWVzc2FnZXNDb250cm9sbGVyLlNlbmRSZXF1ZXN0UXVhbGl0eUNvbnRyb2woKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVzIHdoZW4gYSBMYXRlbmN5IFRlc3QgUmVzdWx0IGFyZSByZWNlaXZlZCBmcm9tIHRoZSBVRSBJbnN0YW5jZVxuICAgICAqIEBwYXJhbSBtZXNzYWdlIC0gTGF0ZW5jeSBUZXN0IFRpbWluZ3NcbiAgICAgKi9cbiAgICBoYW5kbGVMYXRlbmN5VGVzdFJlc3VsdChtZXNzYWdlOiBBcnJheUJ1ZmZlcikge1xuICAgICAgICBMb2dnZXIuTG9nKFxuICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICdEYXRhQ2hhbm5lbFJlY2VpdmVNZXNzYWdlVHlwZS5sYXRlbmN5VGVzdCcsXG4gICAgICAgICAgICA2XG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IGxhdGVuY3lBc1N0cmluZyA9IG5ldyBUZXh0RGVjb2RlcigndXRmLTE2JykuZGVjb2RlKFxuICAgICAgICAgICAgbWVzc2FnZS5zbGljZSgxKVxuICAgICAgICApO1xuICAgICAgICBjb25zdCBsYXRlbmN5VGVzdFJlc3VsdHM6IExhdGVuY3lUZXN0UmVzdWx0cyA9IG5ldyBMYXRlbmN5VGVzdFJlc3VsdHMoKTtcbiAgICAgICAgT2JqZWN0LmFzc2lnbihsYXRlbmN5VGVzdFJlc3VsdHMsIEpTT04ucGFyc2UobGF0ZW5jeUFzU3RyaW5nKSk7XG4gICAgICAgIGxhdGVuY3lUZXN0UmVzdWx0cy5wcm9jZXNzRmllbGRzKCk7XG5cbiAgICAgICAgbGF0ZW5jeVRlc3RSZXN1bHRzLnRlc3RTdGFydFRpbWVNcyA9IHRoaXMubGF0ZW5jeVN0YXJ0VGltZTtcbiAgICAgICAgbGF0ZW5jeVRlc3RSZXN1bHRzLmJyb3dzZXJSZWNlaXB0VGltZU1zID0gRGF0ZS5ub3coKTtcblxuICAgICAgICBsYXRlbmN5VGVzdFJlc3VsdHMubGF0ZW5jeUV4Y2x1ZGluZ0RlY29kZSA9IH5+KFxuICAgICAgICAgICAgbGF0ZW5jeVRlc3RSZXN1bHRzLmJyb3dzZXJSZWNlaXB0VGltZU1zIC1cbiAgICAgICAgICAgIGxhdGVuY3lUZXN0UmVzdWx0cy50ZXN0U3RhcnRUaW1lTXNcbiAgICAgICAgKTtcbiAgICAgICAgbGF0ZW5jeVRlc3RSZXN1bHRzLnRlc3REdXJhdGlvbiA9IH5+KFxuICAgICAgICAgICAgbGF0ZW5jeVRlc3RSZXN1bHRzLlRyYW5zbWlzc2lvblRpbWVNcyAtXG4gICAgICAgICAgICBsYXRlbmN5VGVzdFJlc3VsdHMuUmVjZWlwdFRpbWVNc1xuICAgICAgICApO1xuICAgICAgICBsYXRlbmN5VGVzdFJlc3VsdHMubmV0d29ya0xhdGVuY3kgPSB+fihcbiAgICAgICAgICAgIGxhdGVuY3lUZXN0UmVzdWx0cy5sYXRlbmN5RXhjbHVkaW5nRGVjb2RlIC1cbiAgICAgICAgICAgIGxhdGVuY3lUZXN0UmVzdWx0cy50ZXN0RHVyYXRpb25cbiAgICAgICAgKTtcblxuICAgICAgICBpZiAoXG4gICAgICAgICAgICBsYXRlbmN5VGVzdFJlc3VsdHMuZnJhbWVEaXNwbGF5RGVsdGFUaW1lTXMgJiZcbiAgICAgICAgICAgIGxhdGVuY3lUZXN0UmVzdWx0cy5icm93c2VyUmVjZWlwdFRpbWVNc1xuICAgICAgICApIHtcbiAgICAgICAgICAgIGxhdGVuY3lUZXN0UmVzdWx0cy5lbmRUb0VuZExhdGVuY3kgPVxuICAgICAgICAgICAgICAgIH5+KGxhdGVuY3lUZXN0UmVzdWx0cy5mcmFtZURpc3BsYXlEZWx0YVRpbWVNcyArXG4gICAgICAgICAgICAgICAgICAgIGxhdGVuY3lUZXN0UmVzdWx0cy5uZXR3b3JrTGF0ZW5jeSxcbiAgICAgICAgICAgICAgICArbGF0ZW5jeVRlc3RSZXN1bHRzLkNhcHR1cmVUb1NlbmRNcyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5waXhlbFN0cmVhbWluZy5fb25MYXRlbmN5VGVzdFJlc3VsdChsYXRlbmN5VGVzdFJlc3VsdHMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXMgd2hlbiBhIERhdGEgQ2hhbm5lbCBMYXRlbmN5IFRlc3QgUmVzcG9uc2UgaXMgcmVjZWl2ZWQgZnJvbSB0aGUgVUUgSW5zdGFuY2VcbiAgICAgKiBAcGFyYW0gbWVzc2FnZSAtIERhdGEgQ2hhbm5lbCBMYXRlbmN5IFRlc3QgUmVzcG9uc2VcbiAgICAgKi9cbiAgICBoYW5kbGVEYXRhQ2hhbm5lbExhdGVuY3lUZXN0UmVzcG9uc2UobWVzc2FnZTogQXJyYXlCdWZmZXIpIHtcbiAgICAgICAgTG9nZ2VyLkxvZyhcbiAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAnRGF0YUNoYW5uZWxSZWNlaXZlTWVzc2FnZVR5cGUuZGF0YUNoYW5uZWxMYXRlbmN5UmVzcG9uc2UnLFxuICAgICAgICAgICAgNlxuICAgICAgICApO1xuICAgICAgICBjb25zdCByZXNwb25zZUFzU3RyaW5nID0gbmV3IFRleHREZWNvZGVyKCd1dGYtMTYnKS5kZWNvZGUoXG4gICAgICAgICAgICBtZXNzYWdlLnNsaWNlKDEpXG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IGxhdGVuY3lUZXN0UmVzcG9uc2U6IERhdGFDaGFubmVsTGF0ZW5jeVRlc3RSZXNwb25zZSA9IEpTT04ucGFyc2UocmVzcG9uc2VBc1N0cmluZyk7XG4gICAgICAgIHRoaXMucGl4ZWxTdHJlYW1pbmcuX29uRGF0YUNoYW5uZWxMYXRlbmN5VGVzdFJlc3BvbnNlKGxhdGVuY3lUZXN0UmVzcG9uc2UpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXMgd2hlbiB0aGUgRW5jb2RlciBhbmQgV2ViIFJUQyBTZXR0aW5ncyBhcmUgcmVjZWl2ZWQgZnJvbSB0aGUgVUUgSW5zdGFuY2VcbiAgICAgKiBAcGFyYW0gbWVzc2FnZSAtIEluaXRpYWwgRW5jb2RlciBhbmQgV2ViIFJUQyBTZXR0aW5nc1xuICAgICAqL1xuICAgIGhhbmRsZUluaXRpYWxTZXR0aW5ncyhtZXNzYWdlOiBBcnJheUJ1ZmZlcikge1xuICAgICAgICBMb2dnZXIuTG9nKFxuICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICdEYXRhQ2hhbm5lbFJlY2VpdmVNZXNzYWdlVHlwZS5Jbml0aWFsU2V0dGluZ3MnLFxuICAgICAgICAgICAgNlxuICAgICAgICApO1xuICAgICAgICBjb25zdCBwYXlsb2FkQXNTdHJpbmcgPSBuZXcgVGV4dERlY29kZXIoJ3V0Zi0xNicpLmRlY29kZShcbiAgICAgICAgICAgIG1lc3NhZ2Uuc2xpY2UoMSlcbiAgICAgICAgKTtcbiAgICAgICAgY29uc3QgcGFyc2VkSW5pdGlhbFNldHRpbmdzID0gSlNPTi5wYXJzZShwYXlsb2FkQXNTdHJpbmcpO1xuXG4gICAgICAgIGNvbnN0IGluaXRpYWxTZXR0aW5nczogSW5pdGlhbFNldHRpbmdzID0gbmV3IEluaXRpYWxTZXR0aW5ncygpO1xuXG4gICAgICAgIGlmIChwYXJzZWRJbml0aWFsU2V0dGluZ3MuRW5jb2Rlcikge1xuICAgICAgICAgICAgaW5pdGlhbFNldHRpbmdzLkVuY29kZXJTZXR0aW5ncyA9IHBhcnNlZEluaXRpYWxTZXR0aW5ncy5FbmNvZGVyO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBhcnNlZEluaXRpYWxTZXR0aW5ncy5XZWJSVEMpIHtcbiAgICAgICAgICAgIGluaXRpYWxTZXR0aW5ncy5XZWJSVENTZXR0aW5ncyA9IHBhcnNlZEluaXRpYWxTZXR0aW5ncy5XZWJSVEM7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocGFyc2VkSW5pdGlhbFNldHRpbmdzLlBpeGVsU3RyZWFtaW5nKSB7XG4gICAgICAgICAgICBpbml0aWFsU2V0dGluZ3MuUGl4ZWxTdHJlYW1pbmdTZXR0aW5ncyA9XG4gICAgICAgICAgICAgICAgcGFyc2VkSW5pdGlhbFNldHRpbmdzLlBpeGVsU3RyZWFtaW5nO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBhcnNlZEluaXRpYWxTZXR0aW5ncy5Db25maWdPcHRpb25zICYmIHBhcnNlZEluaXRpYWxTZXR0aW5ncy5Db25maWdPcHRpb25zLkRlZmF1bHRUb0hvdmVyICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLnNldEZsYWdFbmFibGVkKFxuICAgICAgICAgICAgICAgIEZsYWdzLkhvdmVyaW5nTW91c2VNb2RlLFxuICAgICAgICAgICAgICAgICEhcGFyc2VkSW5pdGlhbFNldHRpbmdzLkNvbmZpZ09wdGlvbnMuRGVmYXVsdFRvSG92ZXJcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBpbml0aWFsU2V0dGluZ3MudWVDb21wYXRpYmxlKCk7XG4gICAgICAgIExvZ2dlci5Mb2coTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSwgcGF5bG9hZEFzU3RyaW5nLCA2KTtcblxuICAgICAgICB0aGlzLnBpeGVsU3RyZWFtaW5nLl9vbkluaXRpYWxTZXR0aW5ncyhpbml0aWFsU2V0dGluZ3MpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXMgd2hlbiB0aGUgUXVhbnRpemF0aW9uIFBhcmFtZXRlciBhcmUgcmVjZWl2ZWQgZnJvbSB0aGUgVUUgSW5zdGFuY2VcbiAgICAgKiBAcGFyYW0gbWVzc2FnZSAtIEVuY29kZXJzIFF1YW50aXphdGlvbiBQYXJhbWV0ZXJcbiAgICAgKi9cbiAgICBoYW5kbGVWaWRlb0VuY29kZXJBdmdRUChtZXNzYWdlOiBBcnJheUJ1ZmZlcikge1xuICAgICAgICBMb2dnZXIuTG9nKFxuICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICdEYXRhQ2hhbm5lbFJlY2VpdmVNZXNzYWdlVHlwZS5WaWRlb0VuY29kZXJBdmdRUCcsXG4gICAgICAgICAgICA2XG4gICAgICAgICk7XG4gICAgICAgIGNvbnN0IEF2Z1FQID0gTnVtYmVyKFxuICAgICAgICAgICAgbmV3IFRleHREZWNvZGVyKCd1dGYtMTYnKS5kZWNvZGUobWVzc2FnZS5zbGljZSgxKSlcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5zZXRWaWRlb0VuY29kZXJBdmdRUChBdmdRUCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlcyB3aGVuIHRoZSB2aWRlbyBlbGVtZW50IGhhcyBiZWVuIGxvYWRlZCB3aXRoIGEgc3JjT2JqZWN0XG4gICAgICovXG4gICAgaGFuZGxlVmlkZW9Jbml0aWFsaXplZCgpIHtcbiAgICAgICAgdGhpcy5waXhlbFN0cmVhbWluZy5fb25WaWRlb0luaXRpYWxpemVkKCk7XG5cbiAgICAgICAgLy8gZWl0aGVyIGF1dG9wbGF5IHRoZSB2aWRlbyBvciBzZXQgdXAgdGhlIHBsYXkgb3ZlcmxheVxuICAgICAgICB0aGlzLmF1dG9QbGF5VmlkZW9PclNldFVwUGxheU92ZXJsYXkoKTtcbiAgICAgICAgdGhpcy5yZXNpemVQbGF5ZXJTdHlsZSgpO1xuICAgICAgICB0aGlzLnZpZGVvUGxheWVyLnVwZGF0ZVZpZGVvU3RyZWFtU2l6ZSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZsYWcgc2V0IGlmIHRoZSB1c2VyIGhhcyBRdWFsaXR5IE93bmVyc2hpcFxuICAgICAqIEBwYXJhbSBtZXNzYWdlIC0gRG9lcyB0aGUgY3VycmVudCBjbGllbnQgaGF2ZSBRdWFsaXR5IE93bmVyc2hpcFxuICAgICAqL1xuICAgIG9uUXVhbGl0eUNvbnRyb2xPd25lcnNoaXAobWVzc2FnZTogQXJyYXlCdWZmZXIpIHtcbiAgICAgICAgY29uc3QgdmlldyA9IG5ldyBVaW50OEFycmF5KG1lc3NhZ2UpO1xuICAgICAgICBMb2dnZXIuTG9nKFxuICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICdEYXRhQ2hhbm5lbFJlY2VpdmVNZXNzYWdlVHlwZS5RdWFsaXR5Q29udHJvbE93bmVyc2hpcCcsXG4gICAgICAgICAgICA2XG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuaXNRdWFsaXR5Q29udHJvbGxlciA9IG5ldyBCb29sZWFuKHZpZXdbMV0pLnZhbHVlT2YoKTtcbiAgICAgICAgTG9nZ2VyLkxvZyhcbiAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICBgUmVjZWl2ZWQgcXVhbGl0eSBjb250cm9sbGVyIG1lc3NhZ2UsIHdpbGwgY29udHJvbCBxdWFsaXR5OiAke3RoaXMuaXNRdWFsaXR5Q29udHJvbGxlcn1gXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMucGl4ZWxTdHJlYW1pbmcuX29uUXVhbGl0eUNvbnRyb2xPd25lcnNoaXAoXG4gICAgICAgICAgICB0aGlzLmlzUXVhbGl0eUNvbnRyb2xsZXJcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVzIHdoZW4gdGhlIEFnZ3JlZ2F0ZWQgc3RhdHMgYXJlIENvbGxlY3RlZFxuICAgICAqIEBwYXJhbSBzdGF0cyAtIEFnZ3JlZ2F0ZWQgU3RhdHNcbiAgICAgKi9cbiAgICBoYW5kbGVWaWRlb1N0YXRzKHN0YXRzOiBBZ2dyZWdhdGVkU3RhdHMpIHtcbiAgICAgICAgdGhpcy5waXhlbFN0cmVhbWluZy5fb25WaWRlb1N0YXRzKHN0YXRzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUbyBSZXNpemUgdGhlIFZpZGVvIFBsYXllciBlbGVtZW50XG4gICAgICovXG4gICAgcmVzaXplUGxheWVyU3R5bGUoKTogdm9pZCB7XG4gICAgICAgIHRoaXMudmlkZW9QbGF5ZXIucmVzaXplUGxheWVyU3R5bGUoKTtcbiAgICB9XG5cbiAgICBzZXRQcmVmZXJyZWRDb2RlYyhjb2RlYzogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMucHJlZmVycmVkQ29kZWMgPSBjb2RlYztcbiAgICAgICAgaWYgKHRoaXMucGVlckNvbm5lY3Rpb25Db250cm9sbGVyKSB7XG4gICAgICAgICAgICB0aGlzLnBlZXJDb25uZWN0aW9uQ29udHJvbGxlci5wcmVmZXJyZWRDb2RlYyA9IGNvZGVjO1xuICAgICAgICAgICAgdGhpcy5wZWVyQ29ubmVjdGlvbkNvbnRyb2xsZXIudXBkYXRlQ29kZWNTZWxlY3Rpb24gPSBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHNldFZpZGVvRW5jb2RlckF2Z1FQKGF2Z1FQOiBudW1iZXIpIHtcbiAgICAgICAgdGhpcy52aWRlb0F2Z1FwID0gYXZnUVA7XG4gICAgICAgIHRoaXMucGl4ZWxTdHJlYW1pbmcuX29uVmlkZW9FbmNvZGVyQXZnUVAodGhpcy52aWRlb0F2Z1FwKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBlbmFibGVzL2Rpc2FibGVzIGtleWJvYXJkIGV2ZW50IGxpc3RlbmVyc1xuICAgICAqL1xuICAgIHNldEtleWJvYXJkSW5wdXRFbmFibGVkKGlzRW5hYmxlZDogYm9vbGVhbikge1xuICAgICAgICB0aGlzLmtleWJvYXJkQ29udHJvbGxlcj8udW5yZWdpc3RlcktleUJvYXJkRXZlbnRzKCk7XG4gICAgICAgIGlmIChpc0VuYWJsZWQpIHtcbiAgICAgICAgICAgIHRoaXMua2V5Ym9hcmRDb250cm9sbGVyID0gdGhpcy5pbnB1dENsYXNzZXNGYWN0b3J5LnJlZ2lzdGVyS2V5Qm9hcmQoXG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWdcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBlbmFibGVzL2Rpc2FibGVzIG1vdXNlIGV2ZW50IGxpc3RlbmVyc1xuICAgICAqL1xuICAgIHNldE1vdXNlSW5wdXRFbmFibGVkKGlzRW5hYmxlZDogYm9vbGVhbikge1xuICAgICAgICB0aGlzLm1vdXNlQ29udHJvbGxlcj8udW5yZWdpc3Rlck1vdXNlRXZlbnRzKCk7XG4gICAgICAgIGlmIChpc0VuYWJsZWQpIHtcbiAgICAgICAgICAgIGNvbnN0IG1vdXNlTW9kZSA9IHRoaXMuY29uZmlnLmlzRmxhZ0VuYWJsZWQoRmxhZ3MuSG92ZXJpbmdNb3VzZU1vZGUpXG4gICAgICAgICAgICA/IENvbnRyb2xTY2hlbWVUeXBlLkhvdmVyaW5nTW91c2VcbiAgICAgICAgICAgIDogQ29udHJvbFNjaGVtZVR5cGUuTG9ja2VkTW91c2U7XG4gICAgICAgICAgICB0aGlzLm1vdXNlQ29udHJvbGxlciA9XG4gICAgICAgICAgICB0aGlzLmlucHV0Q2xhc3Nlc0ZhY3RvcnkucmVnaXN0ZXJNb3VzZShtb3VzZU1vZGUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogZW5hYmxlcy9kaXNhYmxlcyB0b3VjaCBldmVudCBsaXN0ZW5lcnNcbiAgICAgKi9cbiAgICBzZXRUb3VjaElucHV0RW5hYmxlZChpc0VuYWJsZWQ6IGJvb2xlYW4pIHtcbiAgICAgICAgdGhpcy50b3VjaENvbnRyb2xsZXI/LnVucmVnaXN0ZXJUb3VjaEV2ZW50cygpO1xuICAgICAgICBpZiAoaXNFbmFibGVkKSB7XG4gICAgICAgICAgICB0aGlzLnRvdWNoQ29udHJvbGxlciA9IHRoaXMuaW5wdXRDbGFzc2VzRmFjdG9yeS5yZWdpc3RlclRvdWNoKFxuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLmlzRmxhZ0VuYWJsZWQoRmxhZ3MuRmFrZU1vdXNlV2l0aFRvdWNoZXMpLFxuICAgICAgICAgICAgICAgIHRoaXMudmlkZW9FbGVtZW50UGFyZW50Q2xpZW50UmVjdFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIGVuYWJsZXMvZGlzYWJsZXMgZ2FtZSBwYWQgZXZlbnQgbGlzdGVuZXJzXG4gICAgICovXG4gICAgc2V0R2FtZVBhZElucHV0RW5hYmxlZChpc0VuYWJsZWQ6IGJvb2xlYW4pIHtcbiAgICAgICAgdGhpcy5nYW1lUGFkQ29udHJvbGxlcj8udW5yZWdpc3RlckdhbWVQYWRFdmVudHMoKTtcbiAgICAgICAgaWYgKGlzRW5hYmxlZCkge1xuICAgICAgICAgICAgdGhpcy5nYW1lUGFkQ29udHJvbGxlciA9IHRoaXMuaW5wdXRDbGFzc2VzRmFjdG9yeS5yZWdpc3RlckdhbWVQYWQoKTtcbiAgICAgICAgICAgIHRoaXMuZ2FtZVBhZENvbnRyb2xsZXIub25HYW1lcGFkQ29ubmVjdGVkID0gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIudG9TdHJlYW1lckhhbmRsZXJzLmdldCgnR2FtZXBhZENvbm5lY3RlZCcpKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmdhbWVQYWRDb250cm9sbGVyLm9uR2FtZXBhZERpc2Nvbm5lY3RlZCA9IChjb250cm9sbGVySWR4OiBudW1iZXIpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0cmVhbU1lc3NhZ2VDb250cm9sbGVyLnRvU3RyZWFtZXJIYW5kbGVycy5nZXQoJ0dhbWVwYWREaXNjb25uZWN0ZWQnKShbY29udHJvbGxlcklkeF0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmVnaXN0ZXJEYXRhQ2hhbm5lbEV2ZW50RW1pdHRlcnMoZGF0YUNoYW5uZWw6IERhdGFDaGFubmVsQ29udHJvbGxlcikge1xuICAgICAgICBkYXRhQ2hhbm5lbC5vbk9wZW4gPSAobGFiZWwsIGV2ZW50KSA9PlxuICAgICAgICAgICAgdGhpcy5waXhlbFN0cmVhbWluZy5kaXNwYXRjaEV2ZW50KFxuICAgICAgICAgICAgICAgIG5ldyBEYXRhQ2hhbm5lbE9wZW5FdmVudCh7IGxhYmVsLCBldmVudCB9KVxuICAgICAgICAgICAgKTtcbiAgICAgICAgZGF0YUNoYW5uZWwub25DbG9zZSA9IChsYWJlbCwgZXZlbnQpID0+XG4gICAgICAgICAgICB0aGlzLnBpeGVsU3RyZWFtaW5nLmRpc3BhdGNoRXZlbnQoXG4gICAgICAgICAgICAgICAgbmV3IERhdGFDaGFubmVsQ2xvc2VFdmVudCh7IGxhYmVsLCBldmVudCB9KVxuICAgICAgICAgICAgKTtcbiAgICAgICAgZGF0YUNoYW5uZWwub25FcnJvciA9IChsYWJlbCwgZXZlbnQpID0+XG4gICAgICAgICAgICB0aGlzLnBpeGVsU3RyZWFtaW5nLmRpc3BhdGNoRXZlbnQoXG4gICAgICAgICAgICAgICAgbmV3IERhdGFDaGFubmVsRXJyb3JFdmVudCh7IGxhYmVsLCBldmVudCB9KVxuICAgICAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgcmVnaXN0ZXJNZXNzYWdlSGFuZGxlcihuYW1lOiBzdHJpbmcsIGRpcmVjdGlvbjogTWVzc2FnZURpcmVjdGlvbiwgaGFuZGxlcj86IChkYXRhOiBBcnJheUJ1ZmZlciB8IEFycmF5PG51bWJlciB8IHN0cmluZz4pID0+IHZvaWQpIHtcbiAgICAgICAgaWYoZGlyZWN0aW9uID09PSBNZXNzYWdlRGlyZWN0aW9uLkZyb21TdHJlYW1lciAmJiB0eXBlb2YgaGFuZGxlciA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIExvZ2dlci5XYXJuaW5nKFxuICAgICAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAgICAgYFVuYWJsZSB0byByZWdpc3RlciBoYW5kbGVyIGZvciAke25hbWV9IGFzIG5vIGhhbmRsZXIgd2FzIHBhc3NlZGBcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBcbiAgICAgICAgdGhpcy5zdHJlYW1NZXNzYWdlQ29udHJvbGxlci5yZWdpc3Rlck1lc3NhZ2VIYW5kbGVyKFxuICAgICAgICAgICAgZGlyZWN0aW9uLFxuICAgICAgICAgICAgbmFtZSxcbiAgICAgICAgICAgIChkYXRhOiBBcnJheTxudW1iZXIgfCBzdHJpbmc+KSA9PiAodHlwZW9mIGhhbmRsZXIgPT09ICd1bmRlZmluZWQnICYmIGRpcmVjdGlvbiA9PT0gTWVzc2FnZURpcmVjdGlvbi5Ub1N0cmVhbWVyKSA/IFxuICAgICAgICAgICAgICAgIHRoaXMuc2VuZE1lc3NhZ2VDb250cm9sbGVyLnNlbmRNZXNzYWdlVG9TdHJlYW1lcihcbiAgICAgICAgICAgICAgICAgICAgbmFtZSxcbiAgICAgICAgICAgICAgICAgICAgZGF0YVxuICAgICAgICAgICAgICAgICkgOiAgIFxuICAgICAgICAgICAgICAgIGhhbmRsZXIoZGF0YSlcbiAgICAgICAgKTtcbiAgICB9XG59XG4iLCIvLyBDb3B5cmlnaHQgRXBpYyBHYW1lcywgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuXG4vKipcbiAqIFRoZSBUeXBlcyBvZiBNZXNzYWdlcyB0aGF0IHdpbGwgYmUgcmVjZWl2ZWRcbiAqL1xuZXhwb3J0IGVudW0gTWVzc2FnZVJlY3ZUeXBlcyB7XG4gICAgQ09ORklHID0gJ2NvbmZpZycsXG4gICAgU1RSRUFNRVJfTElTVCA9ICdzdHJlYW1lckxpc3QnLFxuICAgIFBMQVlFUl9DT1VOVCA9ICdwbGF5ZXJDb3VudCcsXG4gICAgT0ZGRVIgPSAnb2ZmZXInLFxuICAgIEFOU1dFUiA9ICdhbnN3ZXInLFxuICAgIElDRV9DQU5ESURBVEUgPSAnaWNlQ2FuZGlkYXRlJyxcbiAgICBQRUVSX0RBVEFfQ0hBTk5FTFMgPSAncGVlckRhdGFDaGFubmVscycsXG4gICAgUElORyA9ICdwaW5nJyxcbiAgICBXQVJOSU5HID0gJ3dhcm5pbmcnXG59XG5cbi8qKlxuICogQ29uY3JldGUgUmVjZWl2ZWQgTWVzc2FnZSB3cmFwcGVyXG4gKi9cbmV4cG9ydCBjbGFzcyBNZXNzYWdlUmVjdiB7XG4gICAgdHlwZTogc3RyaW5nO1xuICAgIGlkOiBzdHJpbmc7XG59XG5cbi8qKlxuICogQXV0aGVudGljYXRpb24gUmVxdWlyZWQgTWVzc2FnZSB3cmFwcGVyXG4gKi9cbmV4cG9ydCBjbGFzcyBNZXNzYWdlQXV0aFJlcXVpcmVkIGV4dGVuZHMgTWVzc2FnZVJlY3Yge31cblxuLyoqXG4gKiBDb25maWcgTWVzc2FnZSBXcmFwcGVyXG4gKi9cbmV4cG9ydCBjbGFzcyBNZXNzYWdlQ29uZmlnIGV4dGVuZHMgTWVzc2FnZVJlY3Yge1xuICAgIHBlZXJDb25uZWN0aW9uT3B0aW9uczogUlRDQ29uZmlndXJhdGlvbjtcbn1cblxuLyoqXG4gKiBTdHJlYW1lciBMaXN0IE1lc3NhZ2UgV3JhcHBlclxuICovXG5leHBvcnQgY2xhc3MgTWVzc2FnZVN0cmVhbWVyTGlzdCBleHRlbmRzIE1lc3NhZ2VSZWN2IHtcbiAgICBpZHM6IHN0cmluZ1tdO1xufVxuXG4vKipcbiAqIFBsYXllciBDb3VudCBNZXNzYWdlIHdyYXBwZXJcbiAqL1xuZXhwb3J0IGNsYXNzIE1lc3NhZ2VQbGF5ZXJDb3VudCBleHRlbmRzIE1lc3NhZ2VSZWN2IHtcbiAgICBjb3VudDogbnVtYmVyO1xufVxuXG4vKipcbiAqIFdlYiBSVEMgb2ZmZXIgQW5zd2VyIE1lc3NhZ2Ugd3JhcHBlclxuICovXG5leHBvcnQgY2xhc3MgTWVzc2FnZUFuc3dlciBleHRlbmRzIE1lc3NhZ2VSZWN2IHtcbiAgICBzZHA6IHN0cmluZztcbn1cblxuLyoqXG4gKiBXZWJSVEMgc2RwIG9mZmVyIE1lc3NhZ2Ugd3JhcHBlci5cbiAqL1xuZXhwb3J0IGNsYXNzIE1lc3NhZ2VPZmZlciBleHRlbmRzIE1lc3NhZ2VSZWN2IHtcbiAgICBzZHA6IHN0cmluZztcbiAgICBzZnU/OiBib29sZWFuO1xuICAgIGRlZmF1bHRUb0hvdmVyPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIEljZSBDYW5kaWRhdGUgTWVzc2FnZSB3cmFwcGVyXG4gKi9cbmV4cG9ydCBjbGFzcyBNZXNzYWdlSWNlQ2FuZGlkYXRlIGV4dGVuZHMgTWVzc2FnZVJlY3Yge1xuICAgIGNhbmRpZGF0ZTogUlRDSWNlQ2FuZGlkYXRlSW5pdDtcbn1cblxuLyoqXG4gKiBQZWVyIERhdGEgQ2hhbm5lbHMgTWVzc2FnZSB3cmFwcGVyXG4gKi9cbmV4cG9ydCBjbGFzcyBNZXNzYWdlUGVlckRhdGFDaGFubmVscyBleHRlbmRzIE1lc3NhZ2VSZWN2IHtcbiAgICByZWN2U3RyZWFtSWQ6IG51bWJlcjtcbiAgICBzZW5kU3RyZWFtSWQ6IG51bWJlcjtcbiAgICB0eXBlOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBjbGFzcyBNZXNzYWdlT25TY3JlZW5LZXlib2FyZCB7XG4gICAgY29tbWFuZDogc3RyaW5nO1xuICAgIHNob3dPblNjcmVlbktleWJvYXJkOiBib29sZWFuO1xuICAgIHg6IG51bWJlcjtcbiAgICB5OiBudW1iZXI7XG59XG4iLCIvLyBDb3B5cmlnaHQgRXBpYyBHYW1lcywgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuXG5pbXBvcnQgeyBMb2dnZXIgfSBmcm9tICcuLi9Mb2dnZXIvTG9nZ2VyJztcblxuLyoqXG4gKiBUaGUgU2VuZCBUeXBlcyB0aGF0IGFyZSBwdXNoZWQgZnJvbSB0aGUgc2lnbmFsaW5nIHNlcnZlclxuICovXG5leHBvcnQgZW51bSBNZXNzYWdlU2VuZFR5cGVzIHtcbiAgICBMSVNUX1NUUkVBTUVSUyA9ICdsaXN0U3RyZWFtZXJzJyxcbiAgICBTVUJTQ1JJQkUgPSAnc3Vic2NyaWJlJyxcbiAgICBVTlNVQlNDUklCRSA9ICd1bnN1YnNjcmliZScsXG4gICAgSUNFX0NBTkRJREFURSA9ICdpY2VDYW5kaWRhdGUnLFxuICAgIE9GRkVSID0gJ29mZmVyJyxcbiAgICBBTlNXRVIgPSAnYW5zd2VyJyxcbiAgICBEQVRBQ0hBTk5FTFJFUVVFU1QgPSAnZGF0YUNoYW5uZWxSZXF1ZXN0JyxcbiAgICBTRlVSRUNWREFUQUNIQU5ORUxSRUFEWSA9ICdwZWVyRGF0YUNoYW5uZWxzUmVhZHknLFxuICAgIFBPTkcgPSAncG9uZydcbn1cblxuLyoqXG4gKiBBIFdyYXBwZXIgZm9yIHRoZSBtZXNzYWdlIHRvIHNlbmQgdG8gdGhlIHNpZ25hbGluZyBzZXJ2ZXJcbiAqL1xuZXhwb3J0IGNsYXNzIE1lc3NhZ2VTZW5kIGltcGxlbWVudHMgU2VuZCB7XG4gICAgdHlwZTogc3RyaW5nO1xuICAgIHBlZXJDb25uZWN0aW9uT3B0aW9uczogb2JqZWN0O1xuXG4gICAgLyoqXG4gICAgICogVHVybnMgdGhlIHdyYXBwZXIgaW50byBhIEpTT04gU3RyaW5nXG4gICAgICogQHJldHVybnMgLSBKU09OIFN0cmluZyBvZiB0aGUgTWVzc2FnZSB0byBzZW5kXG4gICAgICovXG4gICAgcGF5bG9hZCgpIHtcbiAgICAgICAgTG9nZ2VyLkxvZyhcbiAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAnU2VuZGluZyA9PiBcXG4nICsgSlNPTi5zdHJpbmdpZnkodGhpcywgdW5kZWZpbmVkLCA0KSxcbiAgICAgICAgICAgIDZcbiAgICAgICAgKTtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHRoaXMpO1xuICAgIH1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBTZW5kIHtcbiAgICAvKipcbiAgICAgKiBUdXJucyB0aGUgd3JhcHBlciBpbnRvIGEgSlNPTiBTdHJpbmdcbiAgICAgKiBAcmV0dXJucyAtIEpTT04gU3RyaW5nIG9mIHRoZSBNZXNzYWdlIHRvIHNlbmRcbiAgICAgKi9cbiAgICBwYXlsb2FkOiAoKSA9PiBzdHJpbmc7XG59XG5cbmV4cG9ydCBjbGFzcyBNZXNzYWdlTGlzdFN0cmVhbWVycyBleHRlbmRzIE1lc3NhZ2VTZW5kIHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy50eXBlID0gTWVzc2FnZVNlbmRUeXBlcy5MSVNUX1NUUkVBTUVSUztcbiAgICB9XG59XG5cbmV4cG9ydCBjbGFzcyBNZXNzYWdlU3Vic2NyaWJlIGV4dGVuZHMgTWVzc2FnZVNlbmQge1xuICAgIHN0cmVhbWVySWQ6IHN0cmluZztcblxuICAgIGNvbnN0cnVjdG9yKHN0cmVhbWVyaWQ6IHN0cmluZykge1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICB0aGlzLnR5cGUgPSBNZXNzYWdlU2VuZFR5cGVzLlNVQlNDUklCRTtcbiAgICAgICAgdGhpcy5zdHJlYW1lcklkID0gc3RyZWFtZXJpZDtcbiAgICB9XG59XG5cbmV4cG9ydCBjbGFzcyBNZXNzYWdlVW5zdWJzY3JpYmUgZXh0ZW5kcyBNZXNzYWdlU2VuZCB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMudHlwZSA9IE1lc3NhZ2VTZW5kVHlwZXMuVU5TVUJTQ1JJQkU7XG4gICAgfVxufVxuXG4vKipcbiAqIEluc3RhbmNlIFJlcXVlc3QgTWVzc2FnZSBXcmFwcGVyXG4gKi9cbmV4cG9ydCBjbGFzcyBNZXNzYWdlUG9uZyBleHRlbmRzIE1lc3NhZ2VTZW5kIHtcbiAgICB0aW1lOiBudW1iZXI7XG5cbiAgICBjb25zdHJ1Y3Rvcih0aW1lOiBudW1iZXIpIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy50eXBlID0gTWVzc2FnZVNlbmRUeXBlcy5QT05HO1xuICAgICAgICB0aGlzLnRpbWUgPSB0aW1lO1xuICAgIH1cbn1cblxuLyoqXG4gKiAgV2ViIFJUQyBPZmZlciBtZXNzYWdlIHdyYXBwZXJcbiAqL1xuZXhwb3J0IGNsYXNzIE1lc3NhZ2VXZWJSVENPZmZlciBleHRlbmRzIE1lc3NhZ2VTZW5kIHtcbiAgICBzZHA6IHN0cmluZztcblxuICAgIC8qKlxuICAgICAqIEBwYXJhbSBvZmZlciAtIEdlbmVyYXRlZCBXZWIgUlRDIE9mZmVyXG4gICAgICovXG4gICAgY29uc3RydWN0b3Iob2ZmZXI/OiBSVENTZXNzaW9uRGVzY3JpcHRpb25Jbml0KSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMudHlwZSA9IE1lc3NhZ2VTZW5kVHlwZXMuT0ZGRVI7XG5cbiAgICAgICAgaWYgKG9mZmVyKSB7XG4gICAgICAgICAgICB0aGlzLnR5cGUgPSBvZmZlci50eXBlIGFzIE1lc3NhZ2VTZW5kVHlwZXM7XG4gICAgICAgICAgICB0aGlzLnNkcCA9IG9mZmVyLnNkcDtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuLyoqXG4gKiAgV2ViIFJUQyBBbnN3ZXIgbWVzc2FnZSB3cmFwcGVyXG4gKi9cbmV4cG9ydCBjbGFzcyBNZXNzYWdlV2ViUlRDQW5zd2VyIGV4dGVuZHMgTWVzc2FnZVNlbmQge1xuICAgIHNkcDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGFuc3dlciAtIEdlbmVyYXRlZCBXZWIgUlRDIE9mZmVyXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoYW5zd2VyPzogUlRDU2Vzc2lvbkRlc2NyaXB0aW9uSW5pdCkge1xuICAgICAgICBzdXBlcigpO1xuICAgICAgICB0aGlzLnR5cGUgPSBNZXNzYWdlU2VuZFR5cGVzLkFOU1dFUjtcblxuICAgICAgICBpZiAoYW5zd2VyKSB7XG4gICAgICAgICAgICB0aGlzLnR5cGUgPSBhbnN3ZXIudHlwZSBhcyBNZXNzYWdlU2VuZFR5cGVzO1xuICAgICAgICAgICAgdGhpcy5zZHAgPSBhbnN3ZXIuc2RwO1xuICAgICAgICB9XG4gICAgfVxufVxuXG4vKipcbiAqICBXZWIgUlRDIERhdGEgY2hhbm5lbCByZXF1ZXN0IG1lc3NhZ2Ugd3JhcHBlclxuICovXG5leHBvcnQgY2xhc3MgTWVzc2FnZVdlYlJUQ0RhdGFjaGFubmVsUmVxdWVzdCBleHRlbmRzIE1lc3NhZ2VTZW5kIHtcbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy50eXBlID0gTWVzc2FnZVNlbmRUeXBlcy5EQVRBQ0hBTk5FTFJFUVVFU1Q7XG4gICAgfVxufVxuXG4vKipcbiAqICBXZWIgUlRDIFNGVSBEYXRhIGNoYW5uZWwgcmVhZHkgbWVzc2FnZSB3cmFwcGVyXG4gKi9cbmV4cG9ydCBjbGFzcyBNZXNzYWdlU0ZVUmVjdkRhdGFDaGFubmVsUmVhZHkgZXh0ZW5kcyBNZXNzYWdlU2VuZCB7XG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMudHlwZSA9IE1lc3NhZ2VTZW5kVHlwZXMuU0ZVUkVDVkRBVEFDSEFOTkVMUkVBRFk7XG4gICAgfVxufVxuXG4vKipcbiAqIFJUQyBJY2UgQ2FuZGlkYXRlIFdyYXBwZXJcbiAqL1xuZXhwb3J0IGNsYXNzIE1lc3NhZ2VJY2VDYW5kaWRhdGUgaW1wbGVtZW50cyBTZW5kIHtcbiAgICBjYW5kaWRhdGU6IFJUQ0ljZUNhbmRpZGF0ZTtcbiAgICB0eXBlOiBNZXNzYWdlU2VuZFR5cGVzO1xuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGNhbmRpZGF0ZSAtIFJUQyBJY2UgQ2FuZGlkYXRlXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoY2FuZGlkYXRlOiBSVENJY2VDYW5kaWRhdGUpIHtcbiAgICAgICAgdGhpcy50eXBlID0gTWVzc2FnZVNlbmRUeXBlcy5JQ0VfQ0FORElEQVRFO1xuICAgICAgICB0aGlzLmNhbmRpZGF0ZSA9IGNhbmRpZGF0ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUdXJucyB0aGUgd3JhcHBlciBpbnRvIGEgSlNPTiBTdHJpbmdcbiAgICAgKiBAcmV0dXJucyAtIEpTT04gU3RyaW5nIG9mIHRoZSBNZXNzYWdlIHRvIHNlbmRcbiAgICAgKi9cbiAgICBwYXlsb2FkKCkge1xuICAgICAgICBMb2dnZXIuTG9nKFxuICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICdTZW5kaW5nID0+IFxcbicgKyBKU09OLnN0cmluZ2lmeSh0aGlzLCB1bmRlZmluZWQsIDQpLFxuICAgICAgICAgICAgNlxuICAgICAgICApO1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodGhpcyk7XG4gICAgfVxufVxuIiwiLy8gQ29weXJpZ2h0IEVwaWMgR2FtZXMsIEluYy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cblxuaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSAnLi4vTG9nZ2VyL0xvZ2dlcic7XG5pbXBvcnQgeyBXZWJTb2NrZXRDb250cm9sbGVyIH0gZnJvbSAnLi9XZWJTb2NrZXRDb250cm9sbGVyJztcbmltcG9ydCB7XG4gICAgTWVzc2FnZVJlY3ZUeXBlcyxcbiAgICBNZXNzYWdlQ29uZmlnLFxuICAgIE1lc3NhZ2VTdHJlYW1lckxpc3QsXG4gICAgTWVzc2FnZVBsYXllckNvdW50LFxuICAgIE1lc3NhZ2VBbnN3ZXIsXG4gICAgTWVzc2FnZU9mZmVyLFxuICAgIE1lc3NhZ2VJY2VDYW5kaWRhdGUsXG4gICAgTWVzc2FnZVBlZXJEYXRhQ2hhbm5lbHNcbn0gZnJvbSAnLi9NZXNzYWdlUmVjZWl2ZSc7XG5pbXBvcnQgeyBNZXNzYWdlUG9uZyB9IGZyb20gJy4vTWVzc2FnZVNlbmQnO1xuXG4vKipcbiAqIFNpZ25hbGxpbmcgcHJvdG9jb2wgZm9yIGhhbmRsaW5nIG1lc3NhZ2VzIGZyb20gdGhlIHNpZ25hbGxpbmcgc2VydmVyLlxuICovXG5leHBvcnQgY2xhc3MgU2lnbmFsbGluZ1Byb3RvY29sIHtcbiAgICBwcml2YXRlIEZyb21VRU1lc3NhZ2VIYW5kbGVyczogTWFwPHN0cmluZywgKHBheWxvYWQ6IHN0cmluZykgPT4gdm9pZD47XG5cbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5Gcm9tVUVNZXNzYWdlSGFuZGxlcnMgPSBuZXcgTWFwPFxuICAgICAgICAgICAgc3RyaW5nLFxuICAgICAgICAgICAgKHBheWxvYWQ6IHN0cmluZykgPT4gdm9pZFxuICAgICAgICA+KCk7XG4gICAgfVxuXG4gICAgYWRkTWVzc2FnZUhhbmRsZXIoXG4gICAgICAgIG1lc3NhZ2VJZDogc3RyaW5nLFxuICAgICAgICBtZXNzYWdlSGFuZGxlcjogKHBheWxvYWQ6IHN0cmluZykgPT4gdm9pZFxuICAgICkge1xuICAgICAgICB0aGlzLkZyb21VRU1lc3NhZ2VIYW5kbGVycy5zZXQobWVzc2FnZUlkLCBtZXNzYWdlSGFuZGxlcik7XG4gICAgfVxuXG4gICAgaGFuZGxlTWVzc2FnZShtZXNzYWdlSWQ6IHN0cmluZywgbWVzc2FnZURhdGE6IHN0cmluZykge1xuICAgICAgICBpZiAodGhpcy5Gcm9tVUVNZXNzYWdlSGFuZGxlcnMuaGFzKG1lc3NhZ2VJZCkpIHtcbiAgICAgICAgICAgIHRoaXMuRnJvbVVFTWVzc2FnZUhhbmRsZXJzLmdldChtZXNzYWdlSWQpKG1lc3NhZ2VEYXRhKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIExvZ2dlci5FcnJvcihcbiAgICAgICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgICAgIGBNZXNzYWdlIHR5cGUgb2YgJHttZXNzYWdlSWR9IGRvZXMgbm90IGhhdmUgYSBtZXNzYWdlIGhhbmRsZXIgcmVnaXN0ZXJlZCBvbiB0aGUgZnJvbnRlbmQgLSBpZ25vcmluZyBtZXNzYWdlLmBcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXR1cCBhbnkgZGVmYXVsdCBzaWduYWxsaW5nIG1lc3NhZ2UgaGFuZGxpbmcsIHRoZXNlIGNhbiBiZSBvdmVycmlkZGVuIG9yIGFkZGl0aW9uYWwgaGFuZGxlcnMgYWRkZWQgd2l0aCBgYWRkTWVzc2FnZUhhbmRsZXJgLlxuICAgICAqIEBwYXJhbSB3ZWJzb2NrZXRDb250cm9sbGVyIFRoZSBjb250cm9sbGVyIHRvIHNldHVwIHRoZXNlIGhhbmRsZXJzIG9uLlxuICAgICAqL1xuICAgIHN0YXRpYyBzZXR1cERlZmF1bHRIYW5kbGVycyh3ZWJzb2NrZXRDb250cm9sbGVyOiBXZWJTb2NrZXRDb250cm9sbGVyKSB7XG4gICAgICAgIC8vIFBJTkdcbiAgICAgICAgd2Vic29ja2V0Q29udHJvbGxlci5zaWduYWxsaW5nUHJvdG9jb2wuYWRkTWVzc2FnZUhhbmRsZXIoXG4gICAgICAgICAgICBNZXNzYWdlUmVjdlR5cGVzLlBJTkcsXG4gICAgICAgICAgICAocGluZ1BheWxvYWQ6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgICAgIC8vIHNlbmQgb3VyIHBvbmcgcGF5bG9hZCBiYWNrIHRvIHRoZSBzaWduYWxsaW5nIHNlcnZlclxuICAgICAgICAgICAgICAgIGNvbnN0IHBvbmdQYXlsb2FkID0gbmV3IE1lc3NhZ2VQb25nKFxuICAgICAgICAgICAgICAgICAgICBuZXcgRGF0ZSgpLmdldFRpbWUoKVxuICAgICAgICAgICAgICAgICkucGF5bG9hZCgpO1xuICAgICAgICAgICAgICAgIExvZ2dlci5Mb2coXG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAgICAgICAgIE1lc3NhZ2VSZWN2VHlwZXMuUElORyArICc6ICcgKyBwaW5nUGF5bG9hZCxcbiAgICAgICAgICAgICAgICAgICAgNlxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgd2Vic29ja2V0Q29udHJvbGxlci53ZWJTb2NrZXQuc2VuZChwb25nUGF5bG9hZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gQ09ORklHXG4gICAgICAgIHdlYnNvY2tldENvbnRyb2xsZXIuc2lnbmFsbGluZ1Byb3RvY29sLmFkZE1lc3NhZ2VIYW5kbGVyKFxuICAgICAgICAgICAgTWVzc2FnZVJlY3ZUeXBlcy5DT05GSUcsXG4gICAgICAgICAgICAoY29uZmlnUGF5bG9hZDogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLkxvZyhMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLCBNZXNzYWdlUmVjdlR5cGVzLkNPTkZJRywgNik7XG4gICAgICAgICAgICAgICAgY29uc3QgY29uZmlnOiBNZXNzYWdlQ29uZmlnID0gSlNPTi5wYXJzZShjb25maWdQYXlsb2FkKTtcbiAgICAgICAgICAgICAgICB3ZWJzb2NrZXRDb250cm9sbGVyLm9uQ29uZmlnKGNvbmZpZyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gU1RSRUFNRVJfTElTVFxuICAgICAgICB3ZWJzb2NrZXRDb250cm9sbGVyLnNpZ25hbGxpbmdQcm90b2NvbC5hZGRNZXNzYWdlSGFuZGxlcihcbiAgICAgICAgICAgIE1lc3NhZ2VSZWN2VHlwZXMuU1RSRUFNRVJfTElTVCxcbiAgICAgICAgICAgIChsaXN0UGF5bG9hZDogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLkxvZyhcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICAgICAgICAgTWVzc2FnZVJlY3ZUeXBlcy5TVFJFQU1FUl9MSVNULFxuICAgICAgICAgICAgICAgICAgICA2XG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICBjb25zdCBzdHJlYW1lckxpc3Q6IE1lc3NhZ2VTdHJlYW1lckxpc3QgPVxuICAgICAgICAgICAgICAgICAgICBKU09OLnBhcnNlKGxpc3RQYXlsb2FkKTtcbiAgICAgICAgICAgICAgICB3ZWJzb2NrZXRDb250cm9sbGVyLm9uU3RyZWFtZXJMaXN0KHN0cmVhbWVyTGlzdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gUExBWUVSX0NPVU5UXG4gICAgICAgIHdlYnNvY2tldENvbnRyb2xsZXIuc2lnbmFsbGluZ1Byb3RvY29sLmFkZE1lc3NhZ2VIYW5kbGVyKFxuICAgICAgICAgICAgTWVzc2FnZVJlY3ZUeXBlcy5QTEFZRVJfQ09VTlQsXG4gICAgICAgICAgICAocGxheWVyQ291bnRQYXlsb2FkOiBzdHJpbmcpID0+IHtcbiAgICAgICAgICAgICAgICBMb2dnZXIuTG9nKFxuICAgICAgICAgICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgICAgICAgICBNZXNzYWdlUmVjdlR5cGVzLlBMQVlFUl9DT1VOVCxcbiAgICAgICAgICAgICAgICAgICAgNlxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgY29uc3QgcGxheWVyQ291bnQ6IE1lc3NhZ2VQbGF5ZXJDb3VudCA9XG4gICAgICAgICAgICAgICAgICAgIEpTT04ucGFyc2UocGxheWVyQ291bnRQYXlsb2FkKTtcbiAgICAgICAgICAgICAgICBMb2dnZXIuTG9nKFxuICAgICAgICAgICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgICAgICAgICAnUGxheWVyIENvdW50OiAnICsgcGxheWVyQ291bnQuY291bnQsXG4gICAgICAgICAgICAgICAgICAgIDZcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIHdlYnNvY2tldENvbnRyb2xsZXIub25QbGF5ZXJDb3VudChwbGF5ZXJDb3VudClcbiAgICAgICAgICAgIH1cbiAgICAgICAgKTtcblxuICAgICAgICAvLyBBTlNXRVJcbiAgICAgICAgd2Vic29ja2V0Q29udHJvbGxlci5zaWduYWxsaW5nUHJvdG9jb2wuYWRkTWVzc2FnZUhhbmRsZXIoXG4gICAgICAgICAgICBNZXNzYWdlUmVjdlR5cGVzLkFOU1dFUixcbiAgICAgICAgICAgIChhbnN3ZXJQYXlsb2FkOiBzdHJpbmcpID0+IHtcbiAgICAgICAgICAgICAgICAvLyBzZW5kIG91ciBwb25nIHBheWxvYWQgYmFjayB0byB0aGUgc2lnbmFsbGluZyBzZXJ2ZXJcbiAgICAgICAgICAgICAgICBMb2dnZXIuTG9nKExvZ2dlci5HZXRTdGFja1RyYWNlKCksIE1lc3NhZ2VSZWN2VHlwZXMuQU5TV0VSLCA2KTtcbiAgICAgICAgICAgICAgICBjb25zdCBhbnN3ZXI6IE1lc3NhZ2VBbnN3ZXIgPSBKU09OLnBhcnNlKGFuc3dlclBheWxvYWQpO1xuICAgICAgICAgICAgICAgIHdlYnNvY2tldENvbnRyb2xsZXIub25XZWJSdGNBbnN3ZXIoYW5zd2VyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgKTtcblxuICAgICAgICAvLyBPRkZFUlxuICAgICAgICB3ZWJzb2NrZXRDb250cm9sbGVyLnNpZ25hbGxpbmdQcm90b2NvbC5hZGRNZXNzYWdlSGFuZGxlcihcbiAgICAgICAgICAgIE1lc3NhZ2VSZWN2VHlwZXMuT0ZGRVIsXG4gICAgICAgICAgICAob2ZmZXJQYXlsb2FkOiBzdHJpbmcpID0+IHtcbiAgICAgICAgICAgICAgICAvLyBzZW5kIG91ciBwb25nIHBheWxvYWQgYmFjayB0byB0aGUgc2lnbmFsbGluZyBzZXJ2ZXJcbiAgICAgICAgICAgICAgICBMb2dnZXIuTG9nKExvZ2dlci5HZXRTdGFja1RyYWNlKCksIE1lc3NhZ2VSZWN2VHlwZXMuT0ZGRVIsIDYpO1xuICAgICAgICAgICAgICAgIGNvbnN0IG9mZmVyOiBNZXNzYWdlT2ZmZXIgPSBKU09OLnBhcnNlKG9mZmVyUGF5bG9hZCk7XG4gICAgICAgICAgICAgICAgd2Vic29ja2V0Q29udHJvbGxlci5vbldlYlJ0Y09mZmVyKG9mZmVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgKTtcblxuICAgICAgICAvLyBJQ0UgQ0FORElEQVRFXG4gICAgICAgIHdlYnNvY2tldENvbnRyb2xsZXIuc2lnbmFsbGluZ1Byb3RvY29sLmFkZE1lc3NhZ2VIYW5kbGVyKFxuICAgICAgICAgICAgTWVzc2FnZVJlY3ZUeXBlcy5JQ0VfQ0FORElEQVRFLFxuICAgICAgICAgICAgKGljZUNhbmRpZGF0ZVBheWxvYWQ6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgICAgIC8vIHNlbmQgb3VyIHBvbmcgcGF5bG9hZCBiYWNrIHRvIHRoZSBzaWduYWxsaW5nIHNlcnZlclxuICAgICAgICAgICAgICAgIExvZ2dlci5Mb2coXG4gICAgICAgICAgICAgICAgICAgIExvZ2dlci5HZXRTdGFja1RyYWNlKCksXG4gICAgICAgICAgICAgICAgICAgIE1lc3NhZ2VSZWN2VHlwZXMuSUNFX0NBTkRJREFURSxcbiAgICAgICAgICAgICAgICAgICAgNlxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgY29uc3QgaWNlQ2FuZGlkYXRlOiBNZXNzYWdlSWNlQ2FuZGlkYXRlID1cbiAgICAgICAgICAgICAgICAgICAgSlNPTi5wYXJzZShpY2VDYW5kaWRhdGVQYXlsb2FkKTtcbiAgICAgICAgICAgICAgICB3ZWJzb2NrZXRDb250cm9sbGVyLm9uSWNlQ2FuZGlkYXRlKGljZUNhbmRpZGF0ZS5jYW5kaWRhdGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICApO1xuXG4gICAgICAgIC8vIFdBUk5JTkdcbiAgICAgICAgd2Vic29ja2V0Q29udHJvbGxlci5zaWduYWxsaW5nUHJvdG9jb2wuYWRkTWVzc2FnZUhhbmRsZXIoXG4gICAgICAgICAgICBNZXNzYWdlUmVjdlR5cGVzLldBUk5JTkcsXG4gICAgICAgICAgICAod2FybmluZ1BheWxvYWQ6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgICAgIExvZ2dlci5XYXJuaW5nKFxuICAgICAgICAgICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgICAgICAgICBgV2FybmluZyByZWNlaXZlZDogJHt3YXJuaW5nUGF5bG9hZH1gXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgKTtcblxuICAgICAgICAvLyBQRUVSIERBVEEgQ0hBTk5FTFNcbiAgICAgICAgd2Vic29ja2V0Q29udHJvbGxlci5zaWduYWxsaW5nUHJvdG9jb2wuYWRkTWVzc2FnZUhhbmRsZXIoXG4gICAgICAgICAgICBNZXNzYWdlUmVjdlR5cGVzLlBFRVJfREFUQV9DSEFOTkVMUyxcbiAgICAgICAgICAgIChwZWVyRGF0YUNoYW5uZWxzUGF5bG9hZDogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICAgICAgTG9nZ2VyLkxvZyhcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICAgICAgICAgTWVzc2FnZVJlY3ZUeXBlcy5QRUVSX0RBVEFfQ0hBTk5FTFMsXG4gICAgICAgICAgICAgICAgICAgIDZcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIGNvbnN0IHBlZXJEYXRhQ2hhbm5lbHM6IE1lc3NhZ2VQZWVyRGF0YUNoYW5uZWxzID0gSlNPTi5wYXJzZShcbiAgICAgICAgICAgICAgICAgICAgcGVlckRhdGFDaGFubmVsc1BheWxvYWRcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIHdlYnNvY2tldENvbnRyb2xsZXIub25XZWJSdGNQZWVyRGF0YUNoYW5uZWxzKHBlZXJEYXRhQ2hhbm5lbHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICApO1xuICAgIH1cbn1cbiIsIi8vIENvcHlyaWdodCBFcGljIEdhbWVzLCBJbmMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG5cbmltcG9ydCB7IExvZ2dlciB9IGZyb20gJy4uL0xvZ2dlci9Mb2dnZXInO1xuaW1wb3J0ICogYXMgTWVzc2FnZVJlY2VpdmUgZnJvbSAnLi9NZXNzYWdlUmVjZWl2ZSc7XG5pbXBvcnQgKiBhcyBNZXNzYWdlU2VuZCBmcm9tICcuL01lc3NhZ2VTZW5kJztcbmltcG9ydCB7IFNpZ25hbGxpbmdQcm90b2NvbCB9IGZyb20gJy4vU2lnbmFsbGluZ1Byb3RvY29sJztcblxuLy8gZGVjbGFyZSB0aGUgbmV3IG1ldGhvZCBmb3IgdGhlIHdlYnNvY2tldCBpbnRlcmZhY2VcbmRlY2xhcmUgZ2xvYmFsIHtcbiAgICBpbnRlcmZhY2UgV2ViU29ja2V0IHtcbiAgICAgICAgb25tZXNzYWdlYmluYXJ5PyhldmVudD86IE1lc3NhZ2VFdmVudCk6IHZvaWQ7XG4gICAgfVxufVxuXG4vKipcbiAqIFRoZSBjb250cm9sbGVyIGZvciB0aGUgV2ViU29ja2V0IGFuZCBhbGwgYXNzb2NpYXRlZCBtZXRob2RzXG4gKi9cbmV4cG9ydCBjbGFzcyBXZWJTb2NrZXRDb250cm9sbGVyIHtcbiAgICBXU19PUEVOX1NUQVRFID0gMTtcbiAgICB3ZWJTb2NrZXQ6IFdlYlNvY2tldDtcbiAgICBvbk9wZW46IEV2ZW50VGFyZ2V0O1xuICAgIG9uQ2xvc2U6IEV2ZW50VGFyZ2V0O1xuICAgIHNpZ25hbGxpbmdQcm90b2NvbDogU2lnbmFsbGluZ1Byb3RvY29sO1xuXG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIHRoaXMub25PcGVuID0gbmV3IEV2ZW50VGFyZ2V0KCk7XG4gICAgICAgIHRoaXMub25DbG9zZSA9IG5ldyBFdmVudFRhcmdldCgpO1xuICAgICAgICB0aGlzLnNpZ25hbGxpbmdQcm90b2NvbCA9IG5ldyBTaWduYWxsaW5nUHJvdG9jb2woKTtcbiAgICAgICAgU2lnbmFsbGluZ1Byb3RvY29sLnNldHVwRGVmYXVsdEhhbmRsZXJzKHRoaXMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbm5lY3QgdG8gdGhlIHNpZ25hbGluZyBzZXJ2ZXJcbiAgICAgKiBAcGFyYW0gY29ubmVjdGlvblVSTCAtIFRoZSBBZGRyZXNzIG9mIHRoZSBzaWduYWxpbmcgc2VydmVyXG4gICAgICogQHJldHVybnMgLSBJZiB0aGVyZSBpcyBhIGNvbm5lY3Rpb25cbiAgICAgKi9cbiAgICBjb25uZWN0KGNvbm5lY3Rpb25VUkw6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgICAgICBMb2dnZXIuTG9nKExvZ2dlci5HZXRTdGFja1RyYWNlKCksIGNvbm5lY3Rpb25VUkwsIDYpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgdGhpcy53ZWJTb2NrZXQgPSBuZXcgV2ViU29ja2V0KGNvbm5lY3Rpb25VUkwpO1xuICAgICAgICAgICAgdGhpcy53ZWJTb2NrZXQub25vcGVuID0gKGV2ZW50KSA9PiB0aGlzLmhhbmRsZU9uT3BlbihldmVudCk7XG4gICAgICAgICAgICB0aGlzLndlYlNvY2tldC5vbmVycm9yID0gKCkgPT4gdGhpcy5oYW5kbGVPbkVycm9yKCk7XG4gICAgICAgICAgICB0aGlzLndlYlNvY2tldC5vbmNsb3NlID0gKGV2ZW50KSA9PiB0aGlzLmhhbmRsZU9uQ2xvc2UoZXZlbnQpO1xuICAgICAgICAgICAgdGhpcy53ZWJTb2NrZXQub25tZXNzYWdlID0gKGV2ZW50KSA9PiB0aGlzLmhhbmRsZU9uTWVzc2FnZShldmVudCk7XG4gICAgICAgICAgICB0aGlzLndlYlNvY2tldC5vbm1lc3NhZ2ViaW5hcnkgPSAoZXZlbnQpID0+XG4gICAgICAgICAgICAgICAgdGhpcy5oYW5kbGVPbk1lc3NhZ2VCaW5hcnkoZXZlbnQpO1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICBMb2dnZXIuRXJyb3IoZXJyb3IsIGVycm9yKTtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXMgd2hhdCBoYXBwZW5zIHdoZW4gYSBtZXNzYWdlIGlzIHJlY2VpdmVkIGluIGJpbmFyeSBmb3JtXG4gICAgICogQHBhcmFtIGV2ZW50IC0gTWVzc2FnZSBSZWNlaXZlZFxuICAgICAqL1xuICAgIGhhbmRsZU9uTWVzc2FnZUJpbmFyeShldmVudDogTWVzc2FnZUV2ZW50KSB7XG4gICAgICAgIC8vIGlmIHRoZSBldmVudCBpcyBlbXB0eSByZXR1cm5cbiAgICAgICAgaWYgKCFldmVudCB8fCAhZXZlbnQuZGF0YSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gaGFuZGxlIHRoZSBiaW5hcnkgYW5kIHRoZW4gaGFuZGxlIHRoZSBtZXNzYWdlXG4gICAgICAgIGV2ZW50LmRhdGFcbiAgICAgICAgICAgIC50ZXh0KClcbiAgICAgICAgICAgIC50aGVuKChtZXNzYWdlU3RyaW5nOiB1bmtub3duKSA9PiB7XG4gICAgICAgICAgICAgICAgLy8gYnVpbGQgYSBuZXcgbWVzc2FnZVxuICAgICAgICAgICAgICAgIGNvbnN0IGNvbnN0cnVjdGVkTWVzc2FnZSA9IG5ldyBNZXNzYWdlRXZlbnQoXG4gICAgICAgICAgICAgICAgICAgICdtZXNzYWdlRnJvbUJpbmFyeScsXG4gICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGE6IG1lc3NhZ2VTdHJpbmdcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICAvLyBzZW5kIHRoZSBuZXcgc3RyaW5naWZpZWQgZXZlbnQgYmFjayBpbnRvIGBvbm1lc3NhZ2VgXG4gICAgICAgICAgICAgICAgdGhpcy5oYW5kbGVPbk1lc3NhZ2UoY29uc3RydWN0ZWRNZXNzYWdlKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2goKGVycm9yOiBFcnJvcikgPT4ge1xuICAgICAgICAgICAgICAgIExvZ2dlci5FcnJvcihcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICAgICAgICAgYEZhaWxlZCB0byBwYXJzZSBiaW5hcnkgYmxvYiBmcm9tIHdlYnNvY2tldCwgcmVhc29uOiAke2Vycm9yfWBcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlcyB3aGF0IGhhcHBlbnMgd2hlbiBhIG1lc3NhZ2UgaXMgcmVjZWl2ZWRcbiAgICAgKiBAcGFyYW0gZXZlbnQgLSBNZXNzYWdlIFJlY2VpdmVkXG4gICAgICovXG4gICAgaGFuZGxlT25NZXNzYWdlKGV2ZW50OiBNZXNzYWdlRXZlbnQpIHtcbiAgICAgICAgLy8gQ2hlY2sgaWYgd2Vic29ja2V0IG1lc3NhZ2UgaXMgYmluYXJ5LCBpZiBzbywgc3RyaW5naWZ5IGl0LlxuICAgICAgICBpZiAoZXZlbnQuZGF0YSAmJiBldmVudC5kYXRhIGluc3RhbmNlb2YgQmxvYikge1xuICAgICAgICAgICAgdGhpcy5oYW5kbGVPbk1lc3NhZ2VCaW5hcnkoZXZlbnQpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgbWVzc2FnZTogTWVzc2FnZVJlY2VpdmUuTWVzc2FnZVJlY3YgPSBKU09OLnBhcnNlKGV2ZW50LmRhdGEpO1xuICAgICAgICBMb2dnZXIuTG9nKFxuICAgICAgICAgICAgTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSxcbiAgICAgICAgICAgICdyZWNlaXZlZCA9PiBcXG4nICtcbiAgICAgICAgICAgICAgICBKU09OLnN0cmluZ2lmeShKU09OLnBhcnNlKGV2ZW50LmRhdGEpLCB1bmRlZmluZWQsIDQpLFxuICAgICAgICAgICAgNlxuICAgICAgICApO1xuXG4gICAgICAgIC8vIFNlbmQgdG8gb3VyIHNpZ25hbGxpbmcgcHJvdG9jb2wgdG8gaGFuZGxlIHRoZSBpbmNvbWluZyBtZXNzYWdlXG4gICAgICAgIHRoaXMuc2lnbmFsbGluZ1Byb3RvY29sLmhhbmRsZU1lc3NhZ2UobWVzc2FnZS50eXBlLCBldmVudC5kYXRhKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVzIHdoZW4gdGhlIFdlYnNvY2tldCBpcyBvcGVuZWRcbiAgICAgKiBAcGFyYW0gZXZlbnQgLSBOb3QgVXNlZFxuICAgICAqL1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnNcbiAgICBoYW5kbGVPbk9wZW4oZXZlbnQ6IEV2ZW50KSB7XG4gICAgICAgIExvZ2dlci5Mb2coXG4gICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgJ0Nvbm5lY3RlZCB0byB0aGUgc2lnbmFsbGluZyBzZXJ2ZXIgdmlhIFdlYlNvY2tldCcsXG4gICAgICAgICAgICA2XG4gICAgICAgICk7XG4gICAgICAgIHRoaXMub25PcGVuLmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50KCdvcGVuJykpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXMgd2hlbiB0aGVyZSBpcyBhbiBlcnJvciBvbiB0aGUgd2Vic29ja2V0XG4gICAgICogQHBhcmFtIGV2ZW50IC0gRXJyb3IgUGF5bG9hZFxuICAgICAqL1xuICAgIGhhbmRsZU9uRXJyb3IoKSB7XG4gICAgICAgIExvZ2dlci5FcnJvcihMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLCAnV2ViU29ja2V0IGVycm9yJyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlcyB3aGVuIHRoZSBXZWJzb2NrZXQgaXMgY2xvc2VkXG4gICAgICogQHBhcmFtIGV2ZW50IC0gQ2xvc2UgRXZlbnRcbiAgICAgKi9cbiAgICBoYW5kbGVPbkNsb3NlKGV2ZW50OiBDbG9zZUV2ZW50KSB7XG4gICAgICAgIExvZ2dlci5Mb2coXG4gICAgICAgICAgICBMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLFxuICAgICAgICAgICAgJ0Rpc2Nvbm5lY3RlZCB0byB0aGUgc2lnbmFsbGluZyBzZXJ2ZXIgdmlhIFdlYlNvY2tldDogJyArXG4gICAgICAgICAgICAgICAgSlNPTi5zdHJpbmdpZnkoZXZlbnQuY29kZSkgK1xuICAgICAgICAgICAgICAgICcgLSAnICtcbiAgICAgICAgICAgICAgICBldmVudC5yZWFzb25cbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5vbkNsb3NlLmRpc3BhdGNoRXZlbnQobmV3IEN1c3RvbUV2ZW50KCdjbG9zZScsIHsgJ2RldGFpbCc6IGV2ZW50IH0pKTtcbiAgICB9XG5cbiAgICByZXF1ZXN0U3RyZWFtZXJMaXN0KCkge1xuICAgICAgICBjb25zdCBwYXlsb2FkID0gbmV3IE1lc3NhZ2VTZW5kLk1lc3NhZ2VMaXN0U3RyZWFtZXJzKCk7XG4gICAgICAgIHRoaXMud2ViU29ja2V0LnNlbmQocGF5bG9hZC5wYXlsb2FkKCkpO1xuICAgIH1cblxuICAgIHNlbmRTdWJzY3JpYmUoc3RyZWFtZXJpZDogc3RyaW5nKSB7XG4gICAgICAgIGNvbnN0IHBheWxvYWQgPSBuZXcgTWVzc2FnZVNlbmQuTWVzc2FnZVN1YnNjcmliZShzdHJlYW1lcmlkKTtcbiAgICAgICAgdGhpcy53ZWJTb2NrZXQuc2VuZChwYXlsb2FkLnBheWxvYWQoKSk7XG4gICAgfVxuXG4gICAgc2VuZFVuc3Vic2NyaWJlKCkge1xuICAgICAgICBjb25zdCBwYXlsb2FkID0gbmV3IE1lc3NhZ2VTZW5kLk1lc3NhZ2VVbnN1YnNjcmliZSgpO1xuICAgICAgICB0aGlzLndlYlNvY2tldC5zZW5kKHBheWxvYWQucGF5bG9hZCgpKTtcbiAgICB9XG5cbiAgICBzZW5kV2ViUnRjT2ZmZXIob2ZmZXI6IFJUQ1Nlc3Npb25EZXNjcmlwdGlvbkluaXQpIHtcbiAgICAgICAgY29uc3QgcGF5bG9hZCA9IG5ldyBNZXNzYWdlU2VuZC5NZXNzYWdlV2ViUlRDT2ZmZXIob2ZmZXIpO1xuICAgICAgICB0aGlzLndlYlNvY2tldC5zZW5kKHBheWxvYWQucGF5bG9hZCgpKTtcbiAgICB9XG5cbiAgICBzZW5kV2ViUnRjQW5zd2VyKGFuc3dlcjogUlRDU2Vzc2lvbkRlc2NyaXB0aW9uSW5pdCkge1xuICAgICAgICBjb25zdCBwYXlsb2FkID0gbmV3IE1lc3NhZ2VTZW5kLk1lc3NhZ2VXZWJSVENBbnN3ZXIoYW5zd2VyKTtcbiAgICAgICAgdGhpcy53ZWJTb2NrZXQuc2VuZChwYXlsb2FkLnBheWxvYWQoKSk7XG4gICAgfVxuXG4gICAgc2VuZFdlYlJ0Y0RhdGFjaGFubmVsUmVxdWVzdCgpIHtcbiAgICAgICAgY29uc3QgcGF5bG9hZCA9IG5ldyBNZXNzYWdlU2VuZC5NZXNzYWdlV2ViUlRDRGF0YWNoYW5uZWxSZXF1ZXN0KCk7XG4gICAgICAgIHRoaXMud2ViU29ja2V0LnNlbmQocGF5bG9hZC5wYXlsb2FkKCkpO1xuICAgIH1cblxuICAgIHNlbmRTRlVSZWN2RGF0YUNoYW5uZWxSZWFkeSgpIHtcbiAgICAgICAgY29uc3QgcGF5bG9hZCA9IG5ldyBNZXNzYWdlU2VuZC5NZXNzYWdlU0ZVUmVjdkRhdGFDaGFubmVsUmVhZHkoKTtcbiAgICAgICAgdGhpcy53ZWJTb2NrZXQuc2VuZChwYXlsb2FkLnBheWxvYWQoKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VuZHMgYW4gUlRDIEljZSBDYW5kaWRhdGUgdG8gdGhlIFNlcnZlclxuICAgICAqIEBwYXJhbSBjYW5kaWRhdGUgLSBSVEMgSWNlIENhbmRpZGF0ZVxuICAgICAqL1xuICAgIHNlbmRJY2VDYW5kaWRhdGUoY2FuZGlkYXRlOiBSVENJY2VDYW5kaWRhdGUpIHtcbiAgICAgICAgTG9nZ2VyLkxvZyhMb2dnZXIuR2V0U3RhY2tUcmFjZSgpLCAnU2VuZGluZyBJY2UgQ2FuZGlkYXRlJyk7XG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIHRoaXMud2ViU29ja2V0ICYmXG4gICAgICAgICAgICB0aGlzLndlYlNvY2tldC5yZWFkeVN0YXRlID09PSB0aGlzLldTX09QRU5fU1RBVEVcbiAgICAgICAgKSB7XG4gICAgICAgICAgICAvL3dzLnNlbmQoSlNPTi5zdHJpbmdpZnkoeyB0eXBlOiAnaWNlQ2FuZGlkYXRlJywgY2FuZGlkYXRlOiBjYW5kaWRhdGUgfSkpO1xuICAgICAgICAgICAgY29uc3QgSWNlQ2FuZGlkYXRlID0gbmV3IE1lc3NhZ2VTZW5kLk1lc3NhZ2VJY2VDYW5kaWRhdGUoY2FuZGlkYXRlKTtcblxuICAgICAgICAgICAgdGhpcy53ZWJTb2NrZXQuc2VuZChJY2VDYW5kaWRhdGUucGF5bG9hZCgpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENsb3NlcyB0aGUgV2Vic29ja2V0IGNvbm5lY3Rpb25cbiAgICAgKi9cbiAgICBjbG9zZSgpIHtcbiAgICAgICAgdGhpcy53ZWJTb2NrZXQ/LmNsb3NlKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIE1lc3NhZ2UgQ29udGFpbnMgdGhlIHBheWxvYWQgb2YgdGhlIHBlZXIgY29ubmVjdGlvbiBvcHRpb25zIHVzZWQgZm9yIHRoZSBSVEMgUGVlciBoYW5kIHNoYWtlXG4gICAgICogQHBhcmFtIG1lc3NhZ2VDb25maWcgLSBDb25maWcgTWVzc2FnZSByZWNlaXZlZCBmcm9tIGhlIHNpZ25hbGluZyBzZXJ2ZXJcbiAgICAgKi9cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzLCBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZW1wdHktZnVuY3Rpb25cbiAgICBvbkNvbmZpZyhtZXNzYWdlQ29uZmlnOiBNZXNzYWdlUmVjZWl2ZS5NZXNzYWdlQ29uZmlnKSB7fVxuXG4gICAgLyoqXG4gICAgICogVGhlIE1lc3NhZ2UgQ29udGFpbnMgdGhlIHBheWxvYWQgb2YgdGhlIHBlZXIgY29ubmVjdGlvbiBvcHRpb25zIHVzZWQgZm9yIHRoZSBSVEMgUGVlciBoYW5kIHNoYWtlXG4gICAgICogQHBhcmFtIG1lc3NhZ2VDb25maWcgLSBDb25maWcgTWVzc2FnZSByZWNlaXZlZCBmcm9tIGhlIHNpZ25hbGluZyBzZXJ2ZXJcbiAgICAgKi9cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzLCBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZW1wdHktZnVuY3Rpb25cbiAgICBvblN0cmVhbWVyTGlzdChtZXNzYWdlU3RyZWFtZXJMaXN0OiBNZXNzYWdlUmVjZWl2ZS5NZXNzYWdlU3RyZWFtZXJMaXN0KSB7fVxuXG4gICAgLyoqXG4gICAgICogQHBhcmFtIGljZUNhbmRpZGF0ZSAtIEljZSBDYW5kaWRhdGUgc2VudCBmcm9tIHRoZSBTaWduYWxpbmcgc2VydmVyIHNlcnZlcidzIFJUQyBoYW5kIHNoYWtlXG4gICAgICovXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnVzZWQtdmFycywgQHR5cGVzY3JpcHQtZXNsaW50L25vLWVtcHR5LWZ1bmN0aW9uXG4gICAgb25JY2VDYW5kaWRhdGUoaWNlQ2FuZGlkYXRlOiBSVENJY2VDYW5kaWRhdGVJbml0KSB7fVxuXG4gICAgLyoqXG4gICAgICogRXZlbnQgaXMgZmlyZWQgd2hlbiB0aGUgd2Vic29ja2V0IHJlY2VpdmVzIHRoZSBhbnN3ZXIgZm9yIHRoZSBSVEMgcGVlciBDb25uZWN0aW9uXG4gICAgICogQHBhcmFtIG1lc3NhZ2VBbnN3ZXIgLSBUaGUgUlRDIEFuc3dlciBwYXlsb2FkIGZyb20gdGhlIHNpZ25hbGluZyBzZXJ2ZXJcbiAgICAgKi9cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzLCBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZW1wdHktZnVuY3Rpb25cbiAgICBvbldlYlJ0Y0Fuc3dlcihtZXNzYWdlQW5zd2VyOiBNZXNzYWdlUmVjZWl2ZS5NZXNzYWdlQW5zd2VyKSB7fVxuXG4gICAgLyoqXG4gICAgICogRXZlbnQgaXMgZmlyZWQgd2hlbiB0aGUgd2Vic29ja2V0IHJlY2VpdmVzIHRoZSBvZmZlciBmb3IgdGhlIFJUQyBwZWVyIENvbm5lY3Rpb25cbiAgICAgKiBAcGFyYW0gbWVzc2FnZU9mZmVyIC0gVGhlIHNkcCBvZmZlclxuICAgICAqL1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnMsIEB0eXBlc2NyaXB0LWVzbGludC9uby1lbXB0eS1mdW5jdGlvblxuICAgIG9uV2ViUnRjT2ZmZXIobWVzc2FnZU9mZmVyOiBNZXNzYWdlUmVjZWl2ZS5NZXNzYWdlT2ZmZXIpIHt9XG5cbiAgICAvKipcbiAgICAgKiBFdmVudCBpcyBmaXJlZCB3aGVuIHRoZSB3ZWJzb2NrZXQgcmVjZWl2ZXMgdGhlIGRhdGEgY2hhbm5lbHMgZm9yIHRoZSBSVEMgcGVlciBDb25uZWN0aW9uIGZyb20gdGhlIFNGVVxuICAgICAqIEBwYXJhbSBtZXNzYWdlRGF0YUNoYW5uZWxzIC0gVGhlIGRhdGEgY2hhbm5lbHMgZGV0YWlsc1xuICAgICAqL1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnMsIEB0eXBlc2NyaXB0LWVzbGludC9uby1lbXB0eS1mdW5jdGlvblxuICAgIG9uV2ViUnRjUGVlckRhdGFDaGFubmVscyhtZXNzYWdlRGF0YUNoYW5uZWxzOiBNZXNzYWdlUmVjZWl2ZS5NZXNzYWdlUGVlckRhdGFDaGFubmVscykge31cblxuICAgIC8qKlxuICAgICAqIEV2ZW50IGlzIGZpcmVkIHdoZW4gdGhlIHdlYnNvY2tldCByZWNlaXZlcyB0aGUgYW4gdXBkYXRlZCBwbGF5ZXIgY291bnQgZnJvbSBjaXJydXNcbiAgICAgKiBAcGFyYW0gTWVzc2FnZVBsYXllckNvdW50IC0gVGhlIG5ldyBwbGF5ZXIgY291bnRcbiAgICAgKi9cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzLCBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZW1wdHktZnVuY3Rpb25cbiAgICBvblBsYXllckNvdW50KHBsYXllckNvdW50OiBNZXNzYWdlUmVjZWl2ZS5NZXNzYWdlUGxheWVyQ291bnQpIHt9XG59XG4iLCIvLyBDb3B5cmlnaHQgRXBpYyBHYW1lcywgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuXG5pbXBvcnQgeyBMb2dnZXIgfSBmcm9tICcuLi9Mb2dnZXIvTG9nZ2VyJztcbmltcG9ydCB7IFdlYlJ0Y1BsYXllckNvbnRyb2xsZXIgfSBmcm9tICcuLi9XZWJSdGNQbGF5ZXIvV2ViUnRjUGxheWVyQ29udHJvbGxlcic7XG5pbXBvcnQgeyBXZWJHTFV0aWxzIH0gZnJvbSAnLi4vVXRpbC9XZWJHTFV0aWxzJztcbmltcG9ydCB7IENvbnRyb2xsZXIgfSBmcm9tICcuLi9JbnB1dHMvR2FtZXBhZFR5cGVzJztcbmltcG9ydCB7IFhSR2FtZXBhZENvbnRyb2xsZXIgfSBmcm9tICcuLi9JbnB1dHMvWFJHYW1lcGFkQ29udHJvbGxlcic7XG5pbXBvcnQgeyBYckZyYW1lRXZlbnQgfSBmcm9tICcuLi9VdGlsL0V2ZW50RW1pdHRlcidcbmltcG9ydCB7IEZsYWdzIH0gZnJvbSAnLi4vcGl4ZWxzdHJlYW1pbmdmcm9udGVuZCc7XG5cbmV4cG9ydCBjbGFzcyBXZWJYUkNvbnRyb2xsZXIge1xuICAgIHByaXZhdGUgeHJTZXNzaW9uOiBYUlNlc3Npb247XG4gICAgcHJpdmF0ZSB4clJlZlNwYWNlOiBYUlJlZmVyZW5jZVNwYWNlO1xuICAgIHByaXZhdGUgZ2w6IFdlYkdMMlJlbmRlcmluZ0NvbnRleHQ7XG5cbiAgICBwcml2YXRlIHBvc2l0aW9uTG9jYXRpb246IG51bWJlcjtcbiAgICBwcml2YXRlIHRleGNvb3JkTG9jYXRpb246IG51bWJlcjtcbiAgICBwcml2YXRlIHJlc29sdXRpb25Mb2NhdGlvbjogV2ViR0xVbmlmb3JtTG9jYXRpb247XG4gICAgcHJpdmF0ZSBvZmZzZXRMb2NhdGlvbjogV2ViR0xVbmlmb3JtTG9jYXRpb247XG5cbiAgICBwcml2YXRlIHBvc2l0aW9uQnVmZmVyOiBXZWJHTEJ1ZmZlcjtcbiAgICBwcml2YXRlIHRleGNvb3JkQnVmZmVyOiBXZWJHTEJ1ZmZlcjtcblxuICAgIHByaXZhdGUgd2ViUnRjQ29udHJvbGxlcjogV2ViUnRjUGxheWVyQ29udHJvbGxlcjtcbiAgICBwcml2YXRlIHhyR2FtZXBhZENvbnRyb2xsZXI6IFhSR2FtZXBhZENvbnRyb2xsZXI7XG4gICAgcHJpdmF0ZSB4ckNvbnRyb2xsZXJzOiBBcnJheTxDb250cm9sbGVyPjtcblxuICAgIG9uU2Vzc2lvblN0YXJ0ZWQ6IEV2ZW50VGFyZ2V0O1xuICAgIG9uU2Vzc2lvbkVuZGVkOiBFdmVudFRhcmdldDtcbiAgICBvbkZyYW1lOiBFdmVudFRhcmdldDtcblxuICAgIGNvbnN0cnVjdG9yKHdlYlJ0Y1BsYXllckNvbnRyb2xsZXI6IFdlYlJ0Y1BsYXllckNvbnRyb2xsZXIpIHtcbiAgICAgICAgdGhpcy54clNlc3Npb24gPSBudWxsO1xuICAgICAgICB0aGlzLndlYlJ0Y0NvbnRyb2xsZXIgPSB3ZWJSdGNQbGF5ZXJDb250cm9sbGVyO1xuICAgICAgICB0aGlzLnhyQ29udHJvbGxlcnMgPSBbXTtcbiAgICAgICAgdGhpcy54ckdhbWVwYWRDb250cm9sbGVyID0gbmV3IFhSR2FtZXBhZENvbnRyb2xsZXIoXG4gICAgICAgICAgICB0aGlzLndlYlJ0Y0NvbnRyb2xsZXIuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXJcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5vblNlc3Npb25FbmRlZCA9IG5ldyBFdmVudFRhcmdldCgpO1xuICAgICAgICB0aGlzLm9uU2Vzc2lvblN0YXJ0ZWQgPSBuZXcgRXZlbnRUYXJnZXQoKTtcbiAgICAgICAgdGhpcy5vbkZyYW1lID0gbmV3IEV2ZW50VGFyZ2V0KCk7XG4gICAgfVxuXG4gICAgcHVibGljIHhyQ2xpY2tlZCgpIHtcbiAgICAgICAgaWYgKCF0aGlzLnhyU2Vzc2lvbikge1xuICAgICAgICAgICAgbmF2aWdhdG9yLnhyXG4gICAgICAgICAgICAgICAgLnJlcXVlc3RTZXNzaW9uKCdpbW1lcnNpdmUtdnInKVxuICAgICAgICAgICAgICAgIC50aGVuKChzZXNzaW9uOiBYUlNlc3Npb24pID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vblhyU2Vzc2lvblN0YXJ0ZWQoc2Vzc2lvbik7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnhyU2Vzc2lvbi5lbmQoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIG9uWHJTZXNzaW9uRW5kZWQoKSB7XG4gICAgICAgIExvZ2dlci5Mb2coTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSwgJ1hSIFNlc3Npb24gZW5kZWQnKTtcbiAgICAgICAgdGhpcy54clNlc3Npb24gPSBudWxsO1xuICAgICAgICB0aGlzLm9uU2Vzc2lvbkVuZGVkLmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50KCd4clNlc3Npb25FbmRlZCcpKTtcbiAgICB9XG5cbiAgICBvblhyU2Vzc2lvblN0YXJ0ZWQoc2Vzc2lvbjogWFJTZXNzaW9uKSB7XG4gICAgICAgIExvZ2dlci5Mb2coTG9nZ2VyLkdldFN0YWNrVHJhY2UoKSwgJ1hSIFNlc3Npb24gc3RhcnRlZCcpO1xuXG4gICAgICAgIHRoaXMueHJTZXNzaW9uID0gc2Vzc2lvbjtcbiAgICAgICAgdGhpcy54clNlc3Npb24uYWRkRXZlbnRMaXN0ZW5lcignZW5kJywgKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5vblhyU2Vzc2lvbkVuZGVkKCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGNvbnN0IGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuICAgICAgICB0aGlzLmdsID0gY2FudmFzLmdldENvbnRleHQoJ3dlYmdsMicsIHtcbiAgICAgICAgICAgIHhyQ29tcGF0aWJsZTogdHJ1ZVxuICAgICAgICB9KTtcblxuICAgICAgICB0aGlzLnhyU2Vzc2lvbi51cGRhdGVSZW5kZXJTdGF0ZSh7XG4gICAgICAgICAgICBiYXNlTGF5ZXI6IG5ldyBYUldlYkdMTGF5ZXIodGhpcy54clNlc3Npb24sIHRoaXMuZ2wpXG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIHNldHVwIHZlcnRleCBzaGFkZXJcbiAgICAgICAgY29uc3QgdmVydGV4U2hhZGVyID0gdGhpcy5nbC5jcmVhdGVTaGFkZXIodGhpcy5nbC5WRVJURVhfU0hBREVSKTtcbiAgICAgICAgdGhpcy5nbC5zaGFkZXJTb3VyY2UodmVydGV4U2hhZGVyLCBXZWJHTFV0aWxzLnZlcnRleFNoYWRlcigpKTtcbiAgICAgICAgdGhpcy5nbC5jb21waWxlU2hhZGVyKHZlcnRleFNoYWRlcik7XG5cbiAgICAgICAgLy8gc2V0dXAgZnJhZ21lbnQgc2hhZGVyXG4gICAgICAgIGNvbnN0IGZyYWdtZW50U2hhZGVyID0gdGhpcy5nbC5jcmVhdGVTaGFkZXIodGhpcy5nbC5GUkFHTUVOVF9TSEFERVIpO1xuICAgICAgICB0aGlzLmdsLnNoYWRlclNvdXJjZShmcmFnbWVudFNoYWRlciwgV2ViR0xVdGlscy5mcmFnbWVudFNoYWRlcigpKTtcbiAgICAgICAgdGhpcy5nbC5jb21waWxlU2hhZGVyKGZyYWdtZW50U2hhZGVyKTtcblxuICAgICAgICAvLyBzZXR1cCBHTFNMIHByb2dyYW1cbiAgICAgICAgY29uc3Qgc2hhZGVyUHJvZ3JhbSA9IHRoaXMuZ2wuY3JlYXRlUHJvZ3JhbSgpO1xuICAgICAgICB0aGlzLmdsLmF0dGFjaFNoYWRlcihzaGFkZXJQcm9ncmFtLCB2ZXJ0ZXhTaGFkZXIpO1xuICAgICAgICB0aGlzLmdsLmF0dGFjaFNoYWRlcihzaGFkZXJQcm9ncmFtLCBmcmFnbWVudFNoYWRlcik7XG4gICAgICAgIHRoaXMuZ2wubGlua1Byb2dyYW0oc2hhZGVyUHJvZ3JhbSk7XG4gICAgICAgIHRoaXMuZ2wudXNlUHJvZ3JhbShzaGFkZXJQcm9ncmFtKTtcblxuICAgICAgICAvLyBsb29rIHVwIHdoZXJlIHZlcnRleCBkYXRhIG5lZWRzIHRvIGdvXG4gICAgICAgIHRoaXMucG9zaXRpb25Mb2NhdGlvbiA9IHRoaXMuZ2wuZ2V0QXR0cmliTG9jYXRpb24oXG4gICAgICAgICAgICBzaGFkZXJQcm9ncmFtLFxuICAgICAgICAgICAgJ2FfcG9zaXRpb24nXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMudGV4Y29vcmRMb2NhdGlvbiA9IHRoaXMuZ2wuZ2V0QXR0cmliTG9jYXRpb24oXG4gICAgICAgICAgICBzaGFkZXJQcm9ncmFtLFxuICAgICAgICAgICAgJ2FfdGV4Q29vcmQnXG4gICAgICAgICk7XG4gICAgICAgIC8vIENyZWF0ZSBhIGJ1ZmZlciB0byBwdXQgdGhyZWUgMmQgY2xpcCBzcGFjZSBwb2ludHMgaW5cbiAgICAgICAgdGhpcy5wb3NpdGlvbkJ1ZmZlciA9IHRoaXMuZ2wuY3JlYXRlQnVmZmVyKCk7XG4gICAgICAgIC8vIEJpbmQgaXQgdG8gQVJSQVlfQlVGRkVSICh0aGluayBvZiBpdCBhcyBBUlJBWV9CVUZGRVIgPSBwb3NpdGlvbkJ1ZmZlcilcbiAgICAgICAgdGhpcy5nbC5iaW5kQnVmZmVyKHRoaXMuZ2wuQVJSQVlfQlVGRkVSLCB0aGlzLnBvc2l0aW9uQnVmZmVyKTtcblxuICAgICAgICAvLyBUdXJuIG9uIHRoZSBwb3NpdGlvbiBhdHRyaWJ1dGVcbiAgICAgICAgdGhpcy5nbC5lbmFibGVWZXJ0ZXhBdHRyaWJBcnJheSh0aGlzLnBvc2l0aW9uTG9jYXRpb24pO1xuICAgICAgICAvLyBDcmVhdGUgYSB0ZXh0dXJlLlxuICAgICAgICBjb25zdCB0ZXh0dXJlID0gdGhpcy5nbC5jcmVhdGVUZXh0dXJlKCk7XG4gICAgICAgIHRoaXMuZ2wuYmluZFRleHR1cmUodGhpcy5nbC5URVhUVVJFXzJELCB0ZXh0dXJlKTtcbiAgICAgICAgLy8gU2V0IHRoZSBwYXJhbWV0ZXJzIHNvIHdlIGNhbiByZW5kZXIgYW55IHNpemUgaW1hZ2UuXG4gICAgICAgIHRoaXMuZ2wudGV4UGFyYW1ldGVyaShcbiAgICAgICAgICAgIHRoaXMuZ2wuVEVYVFVSRV8yRCxcbiAgICAgICAgICAgIHRoaXMuZ2wuVEVYVFVSRV9XUkFQX1MsXG4gICAgICAgICAgICB0aGlzLmdsLkNMQU1QX1RPX0VER0VcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5nbC50ZXhQYXJhbWV0ZXJpKFxuICAgICAgICAgICAgdGhpcy5nbC5URVhUVVJFXzJELFxuICAgICAgICAgICAgdGhpcy5nbC5URVhUVVJFX1dSQVBfVCxcbiAgICAgICAgICAgIHRoaXMuZ2wuQ0xBTVBfVE9fRURHRVxuICAgICAgICApO1xuICAgICAgICB0aGlzLmdsLnRleFBhcmFtZXRlcmkoXG4gICAgICAgICAgICB0aGlzLmdsLlRFWFRVUkVfMkQsXG4gICAgICAgICAgICB0aGlzLmdsLlRFWFRVUkVfTUlOX0ZJTFRFUixcbiAgICAgICAgICAgIHRoaXMuZ2wuTkVBUkVTVFxuICAgICAgICApO1xuICAgICAgICB0aGlzLmdsLnRleFBhcmFtZXRlcmkoXG4gICAgICAgICAgICB0aGlzLmdsLlRFWFRVUkVfMkQsXG4gICAgICAgICAgICB0aGlzLmdsLlRFWFRVUkVfTUFHX0ZJTFRFUixcbiAgICAgICAgICAgIHRoaXMuZ2wuTkVBUkVTVFxuICAgICAgICApO1xuXG4gICAgICAgIHRoaXMudGV4Y29vcmRCdWZmZXIgPSB0aGlzLmdsLmNyZWF0ZUJ1ZmZlcigpO1xuICAgICAgICAvLyBsb29rdXAgdW5pZm9ybXNcbiAgICAgICAgdGhpcy5yZXNvbHV0aW9uTG9jYXRpb24gPSB0aGlzLmdsLmdldFVuaWZvcm1Mb2NhdGlvbihcbiAgICAgICAgICAgIHNoYWRlclByb2dyYW0sXG4gICAgICAgICAgICAndV9yZXNvbHV0aW9uJ1xuICAgICAgICApO1xuICAgICAgICB0aGlzLm9mZnNldExvY2F0aW9uID0gdGhpcy5nbC5nZXRVbmlmb3JtTG9jYXRpb24oXG4gICAgICAgICAgICBzaGFkZXJQcm9ncmFtLFxuICAgICAgICAgICAgJ3Vfb2Zmc2V0J1xuICAgICAgICApO1xuXG4gICAgICAgIHNlc3Npb24ucmVxdWVzdFJlZmVyZW5jZVNwYWNlKCdsb2NhbCcpLnRoZW4oKHJlZlNwYWNlKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnhyUmVmU3BhY2UgPSByZWZTcGFjZTtcbiAgICAgICAgICAgIHRoaXMueHJTZXNzaW9uLnJlcXVlc3RBbmltYXRpb25GcmFtZShcbiAgICAgICAgICAgICAgICAodGltZTogRE9NSGlnaFJlc1RpbWVTdGFtcCwgZnJhbWU6IFhSRnJhbWUpID0+XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub25YckZyYW1lKHRpbWUsIGZyYW1lKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdGhpcy5vblNlc3Npb25TdGFydGVkLmRpc3BhdGNoRXZlbnQobmV3IEV2ZW50KCd4clNlc3Npb25TdGFydGVkJykpO1xuICAgIH1cblxuICAgIG9uWHJGcmFtZSh0aW1lOiBET01IaWdoUmVzVGltZVN0YW1wLCBmcmFtZTogWFJGcmFtZSkge1xuICAgICAgICBjb25zdCBwb3NlID0gZnJhbWUuZ2V0Vmlld2VyUG9zZSh0aGlzLnhyUmVmU3BhY2UpO1xuICAgICAgICBpZiAocG9zZSkge1xuICAgICAgICAgICAgY29uc3QgbWF0cml4ID0gcG9zZS50cmFuc2Zvcm0ubWF0cml4O1xuICAgICAgICAgICAgY29uc3QgbWF0ID0gW107XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IDE2OyBpKyspIHtcbiAgICAgICAgICAgICAgICBtYXRbaV0gPSBuZXcgRmxvYXQzMkFycmF5KFttYXRyaXhbaV1dKVswXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gcHJldHRpZXItaWdub3JlXG4gICAgICAgICAgICB0aGlzLndlYlJ0Y0NvbnRyb2xsZXIuc3RyZWFtTWVzc2FnZUNvbnRyb2xsZXIudG9TdHJlYW1lckhhbmRsZXJzLmdldCgnWFJITURUcmFuc2Zvcm0nKShbXG4gICAgICAgICAgICAgICAgbWF0WzBdLCBtYXRbNF0sIG1hdFs4XSwgbWF0WzEyXSxcbiAgICAgICAgICAgICAgICBtYXRbMV0sIG1hdFs1XSwgbWF0WzldLCBtYXRbMTNdLCBcbiAgICAgICAgICAgICAgICBtYXRbMl0sIG1hdFs2XSwgbWF0WzEwXSwgbWF0WzE0XSwgXG4gICAgICAgICAgICAgICAgbWF0WzNdLCBtYXRbN10sIG1hdFsxMV0sIG1hdFsxNV1cbiAgICAgICAgICAgIF0pO1xuXG4gICAgICAgICAgICBjb25zdCBnbExheWVyID0gdGhpcy54clNlc3Npb24ucmVuZGVyU3RhdGUuYmFzZUxheWVyO1xuICAgICAgICAgICAgLy8gSWYgd2UgZG8gaGF2ZSBhIHZhbGlkIHBvc2UsIGJpbmQgdGhlIFdlYkdMIGxheWVyJ3MgZnJhbWVidWZmZXIsXG4gICAgICAgICAgICAvLyB3aGljaCBpcyB3aGVyZSBhbnkgY29udGVudCB0byBiZSBkaXNwbGF5ZWQgb24gdGhlIFhSRGV2aWNlIG11c3QgYmVcbiAgICAgICAgICAgIC8vIHJlbmRlcmVkLlxuICAgICAgICAgICAgdGhpcy5nbC5iaW5kRnJhbWVidWZmZXIodGhpcy5nbC5GUkFNRUJVRkZFUiwgZ2xMYXllci5mcmFtZWJ1ZmZlcik7XG5cbiAgICAgICAgICAgIC8vIFVwbG9hZCB0aGUgaW1hZ2UgaW50byB0aGUgdGV4dHVyZS4gV2ViR0wga25vd3MgaG93IHRvIGV4dHJhY3QgdGhlIGN1cnJlbnQgZnJhbWUgZnJvbSB0aGUgdmlkZW8gZWxlbWVudFxuICAgICAgICAgICAgdGhpcy5nbC50ZXhJbWFnZTJEKFxuICAgICAgICAgICAgICAgIHRoaXMuZ2wuVEVYVFVSRV8yRCxcbiAgICAgICAgICAgICAgICAwLFxuICAgICAgICAgICAgICAgIHRoaXMuZ2wuUkdCQSxcbiAgICAgICAgICAgICAgICB0aGlzLmdsLlJHQkEsXG4gICAgICAgICAgICAgICAgdGhpcy5nbC5VTlNJR05FRF9CWVRFLFxuICAgICAgICAgICAgICAgIHRoaXMud2ViUnRjQ29udHJvbGxlci52aWRlb1BsYXllci5nZXRWaWRlb0VsZW1lbnQoKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHRoaXMucmVuZGVyKHRoaXMud2ViUnRjQ29udHJvbGxlci52aWRlb1BsYXllci5nZXRWaWRlb0VsZW1lbnQoKSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy53ZWJSdGNDb250cm9sbGVyLmNvbmZpZy5pc0ZsYWdFbmFibGVkKEZsYWdzLlhSQ29udHJvbGxlcklucHV0KSkge1xuICAgICAgICAgICAgdGhpcy54clNlc3Npb24uaW5wdXRTb3VyY2VzLmZvckVhY2goXG4gICAgICAgICAgICAgICAgKHNvdXJjZTogWFJJbnB1dFNvdXJjZSwgaW5kZXg6IG51bWJlciwgYXJyYXk6IFhSSW5wdXRTb3VyY2VbXSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnhyR2FtZXBhZENvbnRyb2xsZXIudXBkYXRlU3RhdHVzKFxuICAgICAgICAgICAgICAgICAgICAgICAgc291cmNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgZnJhbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnhyUmVmU3BhY2VcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHRoaXNcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnhyU2Vzc2lvbi5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUoXG4gICAgICAgICAgICAodGltZTogRE9NSGlnaFJlc1RpbWVTdGFtcCwgZnJhbWU6IFhSRnJhbWUpID0+XG4gICAgICAgICAgICAgICAgdGhpcy5vblhyRnJhbWUodGltZSwgZnJhbWUpXG4gICAgICAgICk7XG5cbiAgICAgICAgdGhpcy5vbkZyYW1lLmRpc3BhdGNoRXZlbnQobmV3IFhyRnJhbWVFdmVudCh7XG4gICAgICAgICAgICB0aW1lLFxuICAgICAgICAgICAgZnJhbWVcbiAgICAgICAgfSkpO1xuICAgIH1cblxuICAgIHByaXZhdGUgcmVuZGVyKHZpZGVvRWxlbWVudDogSFRNTFZpZGVvRWxlbWVudCkge1xuICAgICAgICBpZiAoIXRoaXMuZ2wpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGdsTGF5ZXIgPSB0aGlzLnhyU2Vzc2lvbi5yZW5kZXJTdGF0ZS5iYXNlTGF5ZXI7XG4gICAgICAgIHRoaXMuZ2wudmlld3BvcnQoXG4gICAgICAgICAgICAwLFxuICAgICAgICAgICAgMCxcbiAgICAgICAgICAgIGdsTGF5ZXIuZnJhbWVidWZmZXJXaWR0aCxcbiAgICAgICAgICAgIGdsTGF5ZXIuZnJhbWVidWZmZXJIZWlnaHRcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5nbC51bmlmb3JtNGYodGhpcy5vZmZzZXRMb2NhdGlvbiwgMS4wLCAxLjAsIDAuMCwgMC4wKTtcblxuICAgICAgICAvLyBTZXQgcmVjdGFuZ2xlXG4gICAgICAgIC8vIHByZXR0aWVyLWlnbm9yZVxuICAgICAgICB0aGlzLmdsLmJ1ZmZlckRhdGEoXG4gICAgICAgICAgICB0aGlzLmdsLkFSUkFZX0JVRkZFUixcbiAgICAgICAgICAgIG5ldyBGbG9hdDMyQXJyYXkoW1xuICAgICAgICAgICAgICAgIDAsIDAsIFxuICAgICAgICAgICAgICAgIHZpZGVvRWxlbWVudC52aWRlb1dpZHRoLCAwLFxuICAgICAgICAgICAgICAgIDAsIHZpZGVvRWxlbWVudC52aWRlb0hlaWdodCwgXG4gICAgICAgICAgICAgICAgMCwgdmlkZW9FbGVtZW50LnZpZGVvSGVpZ2h0LFxuICAgICAgICAgICAgICAgIHZpZGVvRWxlbWVudC52aWRlb1dpZHRoLCAwLFxuICAgICAgICAgICAgICAgIHZpZGVvRWxlbWVudC52aWRlb1dpZHRoLCB2aWRlb0VsZW1lbnQudmlkZW9IZWlnaHRcbiAgICAgICAgICAgIF0pLFxuICAgICAgICAgICAgdGhpcy5nbC5TVEFUSUNfRFJBV1xuICAgICAgICApO1xuXG4gICAgICAgIC8vIFByb3ZpZGUgdGV4dHVyZSBjb29yZGluYXRlcyBmb3IgdGhlIHJlY3RhbmdsZVxuICAgICAgICB0aGlzLmdsLmJpbmRCdWZmZXIodGhpcy5nbC5BUlJBWV9CVUZGRVIsIHRoaXMudGV4Y29vcmRCdWZmZXIpO1xuICAgICAgICB0aGlzLmdsLmJ1ZmZlckRhdGEoXG4gICAgICAgICAgICB0aGlzLmdsLkFSUkFZX0JVRkZFUixcbiAgICAgICAgICAgIG5ldyBGbG9hdDMyQXJyYXkoW1xuICAgICAgICAgICAgICAgIDAuMCwgMC4wLCAxLjAsIDAuMCwgMC4wLCAxLjAsIDAuMCwgMS4wLCAxLjAsIDAuMCwgMS4wLCAxLjBcbiAgICAgICAgICAgIF0pLFxuICAgICAgICAgICAgdGhpcy5nbC5TVEFUSUNfRFJBV1xuICAgICAgICApO1xuXG4gICAgICAgIGxldCBzaXplOyAvLyBjb21wb25lbnRzIHBlciBpdGVyYXRpb25cbiAgICAgICAgbGV0IHR5cGU7IC8vIHRoZSBkYXRhIHR5cGVcbiAgICAgICAgbGV0IG5vcm1hbGl6ZTsgLy8gbm9ybWFsaXplIHRoZSBkYXRhXG4gICAgICAgIGxldCBzdHJpZGU7IC8vIDAgPSBtb3ZlIGZvcndhcmQgc2l6ZSAqIHNpemVvZih0eXBlKSBlYWNoIGl0ZXJhdGlvbiB0byBnZXQgdGhlIG5leHQgcG9zaXRpb25cbiAgICAgICAgbGV0IG9mZnNldDsgLy8gc3RhcnQgcG9zaXRpb24gb2YgdGhlIGJ1ZmZlclxuXG4gICAgICAgIC8vIEJpbmQgdGhlIHBvc2l0aW9uIGJ1ZmZlci5cbiAgICAgICAgdGhpcy5nbC5iaW5kQnVmZmVyKHRoaXMuZ2wuQVJSQVlfQlVGRkVSLCB0aGlzLnBvc2l0aW9uQnVmZmVyKTtcbiAgICAgICAgLy8gVGVsbCB0aGUgcG9zaXRpb24gYXR0cmlidXRlIGhvdyB0byBnZXQgZGF0YSBvdXQgb2YgcG9zaXRpb25CdWZmZXIgKEFSUkFZX0JVRkZFUilcbiAgICAgICAgc2l6ZSA9IDI7IC8vIDIgY29tcG9uZW50cyBwZXIgaXRlcmF0aW9uXG4gICAgICAgIHR5cGUgPSB0aGlzLmdsLkZMT0FUOyAvLyB0aGUgZGF0YSBpcyAzMmJpdCBmbG9hdHNcbiAgICAgICAgbm9ybWFsaXplID0gZmFsc2U7IC8vIGRvbid0IG5vcm1hbGl6ZSB0aGUgZGF0YVxuICAgICAgICBzdHJpZGUgPSAwOyAvLyAwID0gbW92ZSBmb3J3YXJkIHNpemUgKiBzaXplb2YodHlwZSkgZWFjaCBpdGVyYXRpb24gdG8gZ2V0IHRoZSBuZXh0IHBvc2l0aW9uXG4gICAgICAgIG9mZnNldCA9IDA7IC8vIHN0YXJ0IGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIGJ1ZmZlclxuICAgICAgICB0aGlzLmdsLnZlcnRleEF0dHJpYlBvaW50ZXIoXG4gICAgICAgICAgICB0aGlzLnBvc2l0aW9uTG9jYXRpb24sXG4gICAgICAgICAgICBzaXplLFxuICAgICAgICAgICAgdHlwZSxcbiAgICAgICAgICAgIG5vcm1hbGl6ZSxcbiAgICAgICAgICAgIHN0cmlkZSxcbiAgICAgICAgICAgIG9mZnNldFxuICAgICAgICApO1xuICAgICAgICAvLyBUdXJuIG9uIHRoZSB0ZXhjb29yZCBhdHRyaWJ1dGVcbiAgICAgICAgdGhpcy5nbC5lbmFibGVWZXJ0ZXhBdHRyaWJBcnJheSh0aGlzLnRleGNvb3JkTG9jYXRpb24pO1xuICAgICAgICAvLyBiaW5kIHRoZSB0ZXhjb29yZCBidWZmZXIuXG4gICAgICAgIHRoaXMuZ2wuYmluZEJ1ZmZlcih0aGlzLmdsLkFSUkFZX0JVRkZFUiwgdGhpcy50ZXhjb29yZEJ1ZmZlcik7XG4gICAgICAgIC8vIFRlbGwgdGhlIHRleGNvb3JkIGF0dHJpYnV0ZSBob3cgdG8gZ2V0IGRhdGEgb3V0IG9mIHRleGNvb3JkQnVmZmVyIChBUlJBWV9CVUZGRVIpXG4gICAgICAgIHNpemUgPSAyOyAvLyAyIGNvbXBvbmVudHMgcGVyIGl0ZXJhdGlvblxuICAgICAgICB0eXBlID0gdGhpcy5nbC5GTE9BVDsgLy8gdGhlIGRhdGEgaXMgMzJiaXQgZmxvYXRzXG4gICAgICAgIG5vcm1hbGl6ZSA9IGZhbHNlOyAvLyBkb24ndCBub3JtYWxpemUgdGhlIGRhdGFcbiAgICAgICAgc3RyaWRlID0gMDsgLy8gMCA9IG1vdmUgZm9yd2FyZCBzaXplICogc2l6ZW9mKHR5cGUpIGVhY2ggaXRlcmF0aW9uIHRvIGdldCB0aGUgbmV4dCBwb3NpdGlvblxuICAgICAgICBvZmZzZXQgPSAwOyAvLyBzdGFydCBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSBidWZmZXJcbiAgICAgICAgdGhpcy5nbC52ZXJ0ZXhBdHRyaWJQb2ludGVyKFxuICAgICAgICAgICAgdGhpcy50ZXhjb29yZExvY2F0aW9uLFxuICAgICAgICAgICAgc2l6ZSxcbiAgICAgICAgICAgIHR5cGUsXG4gICAgICAgICAgICBub3JtYWxpemUsXG4gICAgICAgICAgICBzdHJpZGUsXG4gICAgICAgICAgICBvZmZzZXRcbiAgICAgICAgKTtcbiAgICAgICAgLy8gc2V0IHRoZSByZXNvbHV0aW9uXG4gICAgICAgIHRoaXMuZ2wudW5pZm9ybTJmKFxuICAgICAgICAgICAgdGhpcy5yZXNvbHV0aW9uTG9jYXRpb24sXG4gICAgICAgICAgICB2aWRlb0VsZW1lbnQudmlkZW9XaWR0aCxcbiAgICAgICAgICAgIHZpZGVvRWxlbWVudC52aWRlb0hlaWdodFxuICAgICAgICApO1xuICAgICAgICAvLyBkcmF3IHRoZSByZWN0YW5nbGUuXG4gICAgICAgIGNvbnN0IHByaW1pdGl2ZVR5cGUgPSB0aGlzLmdsLlRSSUFOR0xFUztcbiAgICAgICAgY29uc3QgY291bnQgPSA2O1xuICAgICAgICBvZmZzZXQgPSAwO1xuICAgICAgICB0aGlzLmdsLmRyYXdBcnJheXMocHJpbWl0aXZlVHlwZSwgb2Zmc2V0LCBjb3VudCk7XG4gICAgfVxuXG4gICAgc3RhdGljIGlzU2Vzc2lvblN1cHBvcnRlZChtb2RlOiBYUlNlc3Npb25Nb2RlKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgICAgIGlmIChuYXZpZ2F0b3IueHIpIHtcbiAgICAgICAgICAgIHJldHVybiBuYXZpZ2F0b3IueHIuaXNTZXNzaW9uU3VwcG9ydGVkKG1vZGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlPGJvb2xlYW4+KCgpID0+IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cbn1cbiIsInZhciB4ID0geSA9PiB7IHZhciB4ID0ge307IF9fd2VicGFja19yZXF1aXJlX18uZCh4LCB5KTsgcmV0dXJuIHg7IH1cbnZhciB5ID0geCA9PiAoKSA9PiB4XG5tb2R1bGUuZXhwb3J0cyA9IF9fV0VCUEFDS19FWFRFUk5BTF9NT0RVTEVfc2RwX187IiwiLy8gVGhlIG1vZHVsZSBjYWNoZVxudmFyIF9fd2VicGFja19tb2R1bGVfY2FjaGVfXyA9IHt9O1xuXG4vLyBUaGUgcmVxdWlyZSBmdW5jdGlvblxuZnVuY3Rpb24gX193ZWJwYWNrX3JlcXVpcmVfXyhtb2R1bGVJZCkge1xuXHQvLyBDaGVjayBpZiBtb2R1bGUgaXMgaW4gY2FjaGVcblx0dmFyIGNhY2hlZE1vZHVsZSA9IF9fd2VicGFja19tb2R1bGVfY2FjaGVfX1ttb2R1bGVJZF07XG5cdGlmIChjYWNoZWRNb2R1bGUgIT09IHVuZGVmaW5lZCkge1xuXHRcdHJldHVybiBjYWNoZWRNb2R1bGUuZXhwb3J0cztcblx0fVxuXHQvLyBDcmVhdGUgYSBuZXcgbW9kdWxlIChhbmQgcHV0IGl0IGludG8gdGhlIGNhY2hlKVxuXHR2YXIgbW9kdWxlID0gX193ZWJwYWNrX21vZHVsZV9jYWNoZV9fW21vZHVsZUlkXSA9IHtcblx0XHQvLyBubyBtb2R1bGUuaWQgbmVlZGVkXG5cdFx0Ly8gbm8gbW9kdWxlLmxvYWRlZCBuZWVkZWRcblx0XHRleHBvcnRzOiB7fVxuXHR9O1xuXG5cdC8vIEV4ZWN1dGUgdGhlIG1vZHVsZSBmdW5jdGlvblxuXHRfX3dlYnBhY2tfbW9kdWxlc19fW21vZHVsZUlkXShtb2R1bGUsIG1vZHVsZS5leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKTtcblxuXHQvLyBSZXR1cm4gdGhlIGV4cG9ydHMgb2YgdGhlIG1vZHVsZVxuXHRyZXR1cm4gbW9kdWxlLmV4cG9ydHM7XG59XG5cbiIsIi8vIGRlZmluZSBnZXR0ZXIgZnVuY3Rpb25zIGZvciBoYXJtb255IGV4cG9ydHNcbl9fd2VicGFja19yZXF1aXJlX18uZCA9IChleHBvcnRzLCBkZWZpbml0aW9uKSA9PiB7XG5cdGZvcih2YXIga2V5IGluIGRlZmluaXRpb24pIHtcblx0XHRpZihfX3dlYnBhY2tfcmVxdWlyZV9fLm8oZGVmaW5pdGlvbiwga2V5KSAmJiAhX193ZWJwYWNrX3JlcXVpcmVfXy5vKGV4cG9ydHMsIGtleSkpIHtcblx0XHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBrZXksIHsgZW51bWVyYWJsZTogdHJ1ZSwgZ2V0OiBkZWZpbml0aW9uW2tleV0gfSk7XG5cdFx0fVxuXHR9XG59OyIsIl9fd2VicGFja19yZXF1aXJlX18ubyA9IChvYmosIHByb3ApID0+IChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBwcm9wKSkiLCIvLyBkZWZpbmUgX19lc01vZHVsZSBvbiBleHBvcnRzXG5fX3dlYnBhY2tfcmVxdWlyZV9fLnIgPSAoZXhwb3J0cykgPT4ge1xuXHRpZih0eXBlb2YgU3ltYm9sICE9PSAndW5kZWZpbmVkJyAmJiBTeW1ib2wudG9TdHJpbmdUYWcpIHtcblx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgU3ltYm9sLnRvU3RyaW5nVGFnLCB7IHZhbHVlOiAnTW9kdWxlJyB9KTtcblx0fVxuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xufTsiLCIvLyBDb3B5cmlnaHQgRXBpYyBHYW1lcywgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuXG5leHBvcnQgeyBXZWJSdGNQbGF5ZXJDb250cm9sbGVyIH0gZnJvbSAnLi9XZWJSdGNQbGF5ZXIvV2ViUnRjUGxheWVyQ29udHJvbGxlcic7XG5leHBvcnQgeyBXZWJYUkNvbnRyb2xsZXIgfSBmcm9tICcuL1dlYlhSL1dlYlhSQ29udHJvbGxlcic7XG5leHBvcnQge1xuICAgIENvbmZpZyxcbiAgICBDb250cm9sU2NoZW1lVHlwZSxcbiAgICBGbGFncyxcbiAgICBOdW1lcmljUGFyYW1ldGVycyxcbiAgICBUZXh0UGFyYW1ldGVycyxcbiAgICBPcHRpb25QYXJhbWV0ZXJzLFxuICAgIEZsYWdzSWRzLFxuICAgIE51bWVyaWNQYXJhbWV0ZXJzSWRzLFxuICAgIFRleHRQYXJhbWV0ZXJzSWRzLFxuICAgIE9wdGlvblBhcmFtZXRlcnNJZHMsXG4gICAgQWxsU2V0dGluZ3Ncbn0gZnJvbSAnLi9Db25maWcvQ29uZmlnJztcbmV4cG9ydCB7IFNldHRpbmdCYXNlIH0gZnJvbSAnLi9Db25maWcvU2V0dGluZ0Jhc2UnO1xuZXhwb3J0IHsgU2V0dGluZ0ZsYWcgfSBmcm9tICcuL0NvbmZpZy9TZXR0aW5nRmxhZyc7XG5leHBvcnQgeyBTZXR0aW5nTnVtYmVyIH0gZnJvbSAnLi9Db25maWcvU2V0dGluZ051bWJlcic7XG5leHBvcnQgeyBTZXR0aW5nT3B0aW9uIH0gZnJvbSAnLi9Db25maWcvU2V0dGluZ09wdGlvbic7XG5leHBvcnQgeyBTZXR0aW5nVGV4dCB9IGZyb20gJy4vQ29uZmlnL1NldHRpbmdUZXh0JztcbmV4cG9ydCB7IFBpeGVsU3RyZWFtaW5nIH0gZnJvbSAnLi9QaXhlbFN0cmVhbWluZy9QaXhlbFN0cmVhbWluZyc7XG5cbmV4cG9ydCB7IEFGS0NvbnRyb2xsZXIgYXMgQWZrTG9naWMgfSBmcm9tICcuL0FGSy9BRktDb250cm9sbGVyJztcblxuZXhwb3J0IHsgTGF0ZW5jeVRlc3RSZXN1bHRzIH0gZnJvbSAnLi9EYXRhQ2hhbm5lbC9MYXRlbmN5VGVzdFJlc3VsdHMnO1xuZXhwb3J0IHtcbiAgICBFbmNvZGVyU2V0dGluZ3MsXG4gICAgSW5pdGlhbFNldHRpbmdzLFxuICAgIFdlYlJUQ1NldHRpbmdzXG59IGZyb20gJy4vRGF0YUNoYW5uZWwvSW5pdGlhbFNldHRpbmdzJztcbmV4cG9ydCB7IEFnZ3JlZ2F0ZWRTdGF0cyB9IGZyb20gJy4vUGVlckNvbm5lY3Rpb25Db250cm9sbGVyL0FnZ3JlZ2F0ZWRTdGF0cyc7XG5leHBvcnQgeyBMb2dnZXIgfSBmcm9tICcuL0xvZ2dlci9Mb2dnZXInO1xuZXhwb3J0IHsgVW5xdWFudGl6ZWREZW5vcm1hbGl6ZWRVbnNpZ25lZENvb3JkIGFzIFVucXVhbnRpemVkQW5kRGVub3JtYWxpemVVbnNpZ25lZCB9IGZyb20gJy4vVXRpbC9Db29yZGluYXRlQ29udmVydGVyJztcbmV4cG9ydCB7IE1lc3NhZ2VEaXJlY3Rpb24gfSBmcm9tICcuL1VlSW5zdGFuY2VNZXNzYWdlL1N0cmVhbU1lc3NhZ2VDb250cm9sbGVyJztcbmV4cG9ydCB7IE1lc3NhZ2VTZW5kIH0gZnJvbSAnLi9XZWJTb2NrZXRzL01lc3NhZ2VTZW5kJztcbmV4cG9ydCB7IE1lc3NhZ2VSZWN2LCBNZXNzYWdlU3RyZWFtZXJMaXN0IH0gZnJvbSAnLi9XZWJTb2NrZXRzL01lc3NhZ2VSZWNlaXZlJztcbmV4cG9ydCB7IFdlYlNvY2tldENvbnRyb2xsZXIgfSBmcm9tICcuL1dlYlNvY2tldHMvV2ViU29ja2V0Q29udHJvbGxlcic7XG5leHBvcnQgeyBTaWduYWxsaW5nUHJvdG9jb2wgfSBmcm9tICcuL1dlYlNvY2tldHMvU2lnbmFsbGluZ1Byb3RvY29sJztcblxuZXhwb3J0IHsgQ2FuZGlkYXRlUGFpclN0YXRzIH0gZnJvbSAnLi9QZWVyQ29ubmVjdGlvbkNvbnRyb2xsZXIvQ2FuZGlkYXRlUGFpclN0YXRzJztcbmV4cG9ydCB7IENhbmRpZGF0ZVN0YXQgfSBmcm9tICcuL1BlZXJDb25uZWN0aW9uQ29udHJvbGxlci9DYW5kaWRhdGVTdGF0JztcbmV4cG9ydCB7IERhdGFDaGFubmVsU3RhdHMgfSBmcm9tICcuL1BlZXJDb25uZWN0aW9uQ29udHJvbGxlci9EYXRhQ2hhbm5lbFN0YXRzJztcbmV4cG9ydCB7XG4gICAgSW5ib3VuZEF1ZGlvU3RhdHMsXG4gICAgSW5ib3VuZFZpZGVvU3RhdHNcbn0gZnJvbSAnLi9QZWVyQ29ubmVjdGlvbkNvbnRyb2xsZXIvSW5ib3VuZFJUUFN0YXRzJztcbmV4cG9ydCB7IE91dEJvdW5kVmlkZW9TdGF0cyB9IGZyb20gJy4vUGVlckNvbm5lY3Rpb25Db250cm9sbGVyL091dEJvdW5kUlRQU3RhdHMnO1xuZXhwb3J0ICogZnJvbSAnLi9VdGlsL0V2ZW50RW1pdHRlcic7XG4iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=