webdriverio-automation
Version:
WebdriverIO-Automation android ios project
404 lines (310 loc) • 57.1 kB
JavaScript
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.routeConfiguringFunction = routeConfiguringFunction;
exports.isSessionCommand = isSessionCommand;
exports.driverShouldDoJwpProxy = driverShouldDoJwpProxy;
Object.defineProperty(exports, "MJSONWP_ELEMENT_KEY", {
enumerable: true,
get: function () {
return _helpers.MJSONWP_ELEMENT_KEY;
}
});
Object.defineProperty(exports, "W3C_ELEMENT_KEY", {
enumerable: true,
get: function () {
return _helpers.W3C_ELEMENT_KEY;
}
});
exports.IMAGE_ELEMENT_PREFIX = exports.Protocol = void 0;
require("source-map-support/register");
var _lodash = _interopRequireDefault(require("lodash"));
var _appiumSupport = require("appium-support");
var _validators = require("./validators");
var _errors = require("./errors");
var _routes = require("./routes");
var _bluebird = _interopRequireDefault(require("bluebird"));
var _driver = _interopRequireDefault(require("../basedriver/driver"));
var _helpers = require("./helpers");
var _sessionsCache = _interopRequireDefault(require("./sessions-cache"));
const LOG_OBJ_LENGTH = 1024;
const IMAGE_ELEMENT_PREFIX = 'appium-image-element-';
exports.IMAGE_ELEMENT_PREFIX = IMAGE_ELEMENT_PREFIX;
const CREATE_SESSION_COMMAND = 'createSession';
const DELETE_SESSION_COMMAND = 'deleteSession';
const IMG_EL_BODY_RE = new RegExp(`"(${_helpers.W3C_ELEMENT_KEY}|${_helpers.MJSONWP_ELEMENT_KEY})":\s*` + `"${IMAGE_ELEMENT_PREFIX}[^"]+"`);
const IMG_EL_URL_RE = new RegExp(`/(element|screenshot)` + `/${IMAGE_ELEMENT_PREFIX}[^/]+`);
class Protocol {}
exports.Protocol = Protocol;
function extractProtocol(driver, sessionId = null) {
const dstDriver = _lodash.default.isFunction(driver.driverForSession) ? driver.driverForSession(sessionId) : driver;
if (dstDriver === driver) {
return driver.protocol;
}
return dstDriver ? dstDriver.protocol : _sessionsCache.default.getProtocol(sessionId);
}
function isSessionCommand(command) {
return !_lodash.default.includes(_routes.NO_SESSION_ID_COMMANDS, command);
}
function wrapParams(paramSets, jsonObj) {
let res = jsonObj;
if (_lodash.default.isArray(jsonObj) || !_lodash.default.isObject(jsonObj)) {
res = {};
res[paramSets.wrap] = jsonObj;
}
return res;
}
function unwrapParams(paramSets, jsonObj) {
let res = jsonObj;
if (_lodash.default.isObject(jsonObj)) {
if (jsonObj[paramSets.unwrap]) {
res = jsonObj[paramSets.unwrap];
}
}
return res;
}
function checkParams(paramSets, jsonObj, protocol) {
let requiredParams = [];
let optionalParams = [];
let receivedParams = _lodash.default.keys(jsonObj);
if (paramSets) {
if (paramSets.required) {
if (!_lodash.default.isArray(_lodash.default.first(paramSets.required))) {
requiredParams = [paramSets.required];
} else {
requiredParams = paramSets.required;
}
}
if (paramSets.optional) {
optionalParams = paramSets.optional;
}
if (paramSets.validate) {
let message = paramSets.validate(jsonObj, protocol);
if (message) {
throw new _errors.errors.BadParametersError(message, jsonObj);
}
}
}
if (requiredParams.length === 0) {
return;
}
if (optionalParams.indexOf('sessionId') === -1) {
optionalParams.push('sessionId');
}
if (optionalParams.indexOf('id') === -1) {
optionalParams.push('id');
}
for (let params of requiredParams) {
if (_lodash.default.difference(receivedParams, params, optionalParams).length === 0 && _lodash.default.difference(params, receivedParams).length === 0) {
return;
}
}
throw new _errors.errors.BadParametersError(paramSets, receivedParams);
}
function makeArgs(requestParams, jsonObj, payloadParams, protocol) {
let urlParams = _lodash.default.keys(requestParams).reverse();
let requiredParams = payloadParams.required;
if (_lodash.default.isArray(_lodash.default.first(payloadParams.required))) {
let keys = _lodash.default.keys(jsonObj);
for (let params of payloadParams.required) {
if (_lodash.default.without(params, ...keys).length === 0) {
requiredParams = params;
break;
}
}
}
let args;
if (_lodash.default.isFunction(payloadParams.makeArgs)) {
args = payloadParams.makeArgs(jsonObj, protocol);
} else {
args = _lodash.default.flatten(requiredParams).map(p => jsonObj[p]);
if (payloadParams.optional) {
args = args.concat(_lodash.default.flatten(payloadParams.optional).map(p => jsonObj[p]));
}
}
args = args.concat(urlParams.map(u => requestParams[u]));
return args;
}
function routeConfiguringFunction(driver) {
if (!driver.sessionExists) {
throw new Error('Drivers used with MJSONWP must implement `sessionExists`');
}
if (!(driver.executeCommand || driver.execute)) {
throw new Error('Drivers used with MJSONWP must implement `executeCommand` or `execute`');
}
return function addRoutes(app) {
for (const [path, methods] of _lodash.default.toPairs(_routes.METHOD_MAP)) {
for (const [method, spec] of _lodash.default.toPairs(methods)) {
buildHandler(app, method, path, spec, driver, isSessionCommand(spec.command));
}
}
};
}
function buildHandler(app, method, path, spec, driver, isSessCmd) {
let asyncHandler = async (req, res) => {
let jsonObj = req.body;
let httpResBody = {};
let httpStatus = 200;
let newSessionId;
let currentProtocol = extractProtocol(driver, req.params.sessionId);
try {
if (isSessCmd && !driver.sessionExists(req.params.sessionId)) {
throw new _errors.errors.NoSuchDriverError();
}
if (isSessCmd && driverShouldDoJwpProxy(driver, req, spec.command)) {
await doJwpProxy(driver, req, res);
return;
}
if (!spec.command) {
throw new _errors.errors.NotImplementedError();
}
if (spec.payloadParams && spec.payloadParams.wrap) {
jsonObj = wrapParams(spec.payloadParams, jsonObj);
}
if (spec.payloadParams && spec.payloadParams.unwrap) {
jsonObj = unwrapParams(spec.payloadParams, jsonObj);
}
if (spec.command === CREATE_SESSION_COMMAND) {
currentProtocol = _driver.default.determineProtocol(...makeArgs(req.params, jsonObj, spec.payloadParams || {}));
}
checkParams(spec.payloadParams, jsonObj, currentProtocol);
let args = makeArgs(req.params, jsonObj, spec.payloadParams || {}, currentProtocol);
let driverRes;
if (_validators.validators[spec.command]) {
_validators.validators[spec.command](...args);
}
_sessionsCache.default.getLogger(req.params.sessionId, currentProtocol).debug(`Calling ` + `${driver.constructor.name}.${spec.command}() with args: ` + _lodash.default.truncate(JSON.stringify(args), {
length: LOG_OBJ_LENGTH
}));
if (driver.executeCommand) {
driverRes = await driver.executeCommand(spec.command, ...args);
} else {
driverRes = await driver.execute(spec.command, ...args);
}
currentProtocol = extractProtocol(driver, req.params.sessionId) || currentProtocol;
if (_lodash.default.isPlainObject(driverRes) && _lodash.default.has(driverRes, 'protocol')) {
currentProtocol = driverRes.protocol || currentProtocol;
if (driverRes.error) {
throw driverRes.error;
}
driverRes = driverRes.value;
}
if (spec.command === CREATE_SESSION_COMMAND) {
newSessionId = driverRes[0];
_sessionsCache.default.putSession(newSessionId, currentProtocol);
_sessionsCache.default.getLogger(newSessionId, currentProtocol).debug(`Cached the protocol value '${currentProtocol}' for the new session ${newSessionId}`);
if (currentProtocol === _driver.default.DRIVER_PROTOCOL.MJSONWP) {
driverRes = driverRes[1];
} else if (currentProtocol === _driver.default.DRIVER_PROTOCOL.W3C) {
driverRes = {
capabilities: driverRes[1]
};
}
}
driverRes = (0, _helpers.formatResponseValue)(driverRes);
if (spec.command === DELETE_SESSION_COMMAND) {
_sessionsCache.default.getLogger(req.params.sessionId, currentProtocol).debug(`Received response: ${_lodash.default.truncate(JSON.stringify(driverRes), {
length: LOG_OBJ_LENGTH
})}`);
_sessionsCache.default.getLogger(req.params.sessionId, currentProtocol).debug('But deleting session, so not returning');
driverRes = null;
}
if (_appiumSupport.util.hasValue(driverRes)) {
if (_appiumSupport.util.hasValue(driverRes.status) && !isNaN(driverRes.status) && parseInt(driverRes.status, 10) !== 0) {
throw (0, _errors.errorFromMJSONWPStatusCode)(driverRes.status, driverRes.value);
} else if (_lodash.default.isPlainObject(driverRes.value) && driverRes.value.error) {
throw (0, _errors.errorFromW3CJsonCode)(driverRes.value.error, driverRes.value.message, driverRes.value.stacktrace);
}
}
httpResBody = (0, _helpers.formatStatus)(httpResBody, currentProtocol);
httpResBody.value = driverRes;
_sessionsCache.default.getLogger(req.params.sessionId || newSessionId, currentProtocol).debug(`Responding ` + `to client with driver.${spec.command}() result: ${_lodash.default.truncate(JSON.stringify(driverRes), {
length: LOG_OBJ_LENGTH
})}`);
if (spec.command === DELETE_SESSION_COMMAND) {
_sessionsCache.default.resetLogger(req.params.sessionId);
}
} catch (err) {
let actualErr = err;
currentProtocol = currentProtocol || extractProtocol(driver, req.params.sessionId || newSessionId);
let errMsg = err.stacktrace || err.stack;
if (!_lodash.default.includes(errMsg, err.message)) {
errMsg = `${err.message}${errMsg ? '\n' + errMsg : ''}`;
}
_sessionsCache.default.getLogger(req.params.sessionId || newSessionId, currentProtocol).debug(`Encountered ` + `internal error running command: ${errMsg}`);
if ((0, _errors.isErrorType)(err, _errors.errors.ProxyRequestError)) {
actualErr = err.getActualError();
}
if (currentProtocol === _driver.default.DRIVER_PROTOCOL.W3C) {
[httpStatus, httpResBody] = (0, _errors.getResponseForW3CError)(actualErr);
} else if (currentProtocol === _driver.default.DRIVER_PROTOCOL.MJSONWP) {
[httpStatus, httpResBody] = (0, _errors.getResponseForJsonwpError)(actualErr);
} else {
let jsonwpRes = (0, _errors.getResponseForJsonwpError)(actualErr);
let w3cRes = (0, _errors.getResponseForW3CError)(actualErr);
httpResBody = { ...jsonwpRes[1],
...w3cRes[1]
};
httpStatus = jsonwpRes[0];
}
}
if (_lodash.default.isString(httpResBody)) {
res.status(httpStatus).send(httpResBody);
} else {
if (newSessionId) {
if (currentProtocol === _driver.default.DRIVER_PROTOCOL.W3C) {
httpResBody.value.sessionId = newSessionId;
} else {
httpResBody.sessionId = newSessionId;
}
} else {
httpResBody.sessionId = req.params.sessionId || null;
}
if (currentProtocol === _driver.default.DRIVER_PROTOCOL.W3C) {
delete httpResBody.sessionId;
}
res.status(httpStatus).json(httpResBody);
}
};
app[method.toLowerCase()](path, (req, res) => {
_bluebird.default.resolve(asyncHandler(req, res)).done();
});
}
function driverShouldDoJwpProxy(driver, req, command) {
if (!driver.proxyActive(req.params.sessionId)) {
return false;
}
if (command === 'deleteSession') {
return false;
}
if (driver.proxyRouteIsAvoided(req.params.sessionId, req.method, req.originalUrl)) {
return false;
}
if (IMG_EL_URL_RE.test(req.originalUrl)) {
return false;
}
const stringBody = JSON.stringify(req.body);
if (stringBody && IMG_EL_BODY_RE.test(stringBody)) {
return false;
}
return true;
}
async function doJwpProxy(driver, req, res) {
_sessionsCache.default.getLogger(req.params.sessionId, extractProtocol(driver, req.params.sessionId)).info('Driver proxy active, passing request on via HTTP proxy');
if (!driver.canProxy(req.params.sessionId)) {
throw new Error('Trying to proxy to a JSONWP server but driver is unable to proxy');
}
try {
const proxiedRes = await driver.executeCommand('proxyReqRes', req, res, req.params.sessionId);
if (proxiedRes && proxiedRes.error) throw proxiedRes.error;
} catch (err) {
if ((0, _errors.isErrorType)(err, _errors.errors.ProxyRequestError)) {
throw err;
} else {
throw new Error(`Could not proxy. Proxy error: ${err.message}`);
}
}
}require('source-map-support').install();
//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxpYi9wcm90b2NvbC9wcm90b2NvbC5qcyJdLCJuYW1lcyI6WyJMT0dfT0JKX0xFTkdUSCIsIklNQUdFX0VMRU1FTlRfUFJFRklYIiwiQ1JFQVRFX1NFU1NJT05fQ09NTUFORCIsIkRFTEVURV9TRVNTSU9OX0NPTU1BTkQiLCJJTUdfRUxfQk9EWV9SRSIsIlJlZ0V4cCIsIlczQ19FTEVNRU5UX0tFWSIsIk1KU09OV1BfRUxFTUVOVF9LRVkiLCJJTUdfRUxfVVJMX1JFIiwiUHJvdG9jb2wiLCJleHRyYWN0UHJvdG9jb2wiLCJkcml2ZXIiLCJzZXNzaW9uSWQiLCJkc3REcml2ZXIiLCJfIiwiaXNGdW5jdGlvbiIsImRyaXZlckZvclNlc3Npb24iLCJwcm90b2NvbCIsIlNFU1NJT05TX0NBQ0hFIiwiZ2V0UHJvdG9jb2wiLCJpc1Nlc3Npb25Db21tYW5kIiwiY29tbWFuZCIsImluY2x1ZGVzIiwiTk9fU0VTU0lPTl9JRF9DT01NQU5EUyIsIndyYXBQYXJhbXMiLCJwYXJhbVNldHMiLCJqc29uT2JqIiwicmVzIiwiaXNBcnJheSIsImlzT2JqZWN0Iiwid3JhcCIsInVud3JhcFBhcmFtcyIsInVud3JhcCIsImNoZWNrUGFyYW1zIiwicmVxdWlyZWRQYXJhbXMiLCJvcHRpb25hbFBhcmFtcyIsInJlY2VpdmVkUGFyYW1zIiwia2V5cyIsInJlcXVpcmVkIiwiZmlyc3QiLCJvcHRpb25hbCIsInZhbGlkYXRlIiwibWVzc2FnZSIsImVycm9ycyIsIkJhZFBhcmFtZXRlcnNFcnJvciIsImxlbmd0aCIsImluZGV4T2YiLCJwdXNoIiwicGFyYW1zIiwiZGlmZmVyZW5jZSIsIm1ha2VBcmdzIiwicmVxdWVzdFBhcmFtcyIsInBheWxvYWRQYXJhbXMiLCJ1cmxQYXJhbXMiLCJyZXZlcnNlIiwid2l0aG91dCIsImFyZ3MiLCJmbGF0dGVuIiwibWFwIiwicCIsImNvbmNhdCIsInUiLCJyb3V0ZUNvbmZpZ3VyaW5nRnVuY3Rpb24iLCJzZXNzaW9uRXhpc3RzIiwiRXJyb3IiLCJleGVjdXRlQ29tbWFuZCIsImV4ZWN1dGUiLCJhZGRSb3V0ZXMiLCJhcHAiLCJwYXRoIiwibWV0aG9kcyIsInRvUGFpcnMiLCJNRVRIT0RfTUFQIiwibWV0aG9kIiwic3BlYyIsImJ1aWxkSGFuZGxlciIsImlzU2Vzc0NtZCIsImFzeW5jSGFuZGxlciIsInJlcSIsImJvZHkiLCJodHRwUmVzQm9keSIsImh0dHBTdGF0dXMiLCJuZXdTZXNzaW9uSWQiLCJjdXJyZW50UHJvdG9jb2wiLCJOb1N1Y2hEcml2ZXJFcnJvciIsImRyaXZlclNob3VsZERvSndwUHJveHkiLCJkb0p3cFByb3h5IiwiTm90SW1wbGVtZW50ZWRFcnJvciIsIkJhc2VEcml2ZXIiLCJkZXRlcm1pbmVQcm90b2NvbCIsImRyaXZlclJlcyIsInZhbGlkYXRvcnMiLCJnZXRMb2dnZXIiLCJkZWJ1ZyIsImNvbnN0cnVjdG9yIiwibmFtZSIsInRydW5jYXRlIiwiSlNPTiIsInN0cmluZ2lmeSIsImlzUGxhaW5PYmplY3QiLCJoYXMiLCJlcnJvciIsInZhbHVlIiwicHV0U2Vzc2lvbiIsIkRSSVZFUl9QUk9UT0NPTCIsIk1KU09OV1AiLCJXM0MiLCJjYXBhYmlsaXRpZXMiLCJ1dGlsIiwiaGFzVmFsdWUiLCJzdGF0dXMiLCJpc05hTiIsInBhcnNlSW50Iiwic3RhY2t0cmFjZSIsInJlc2V0TG9nZ2VyIiwiZXJyIiwiYWN0dWFsRXJyIiwiZXJyTXNnIiwic3RhY2siLCJQcm94eVJlcXVlc3RFcnJvciIsImdldEFjdHVhbEVycm9yIiwianNvbndwUmVzIiwidzNjUmVzIiwiaXNTdHJpbmciLCJzZW5kIiwianNvbiIsInRvTG93ZXJDYXNlIiwiQiIsInJlc29sdmUiLCJkb25lIiwicHJveHlBY3RpdmUiLCJwcm94eVJvdXRlSXNBdm9pZGVkIiwib3JpZ2luYWxVcmwiLCJ0ZXN0Iiwic3RyaW5nQm9keSIsImluZm8iLCJjYW5Qcm94eSIsInByb3hpZWRSZXMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7O0FBQ0E7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UUFBSTZILFVBQVUsSUFBSUEsVUFBVSxDQUFDcEMsS0FBN0IsRUFBb0MsTUFBTW9DLFVBQVUsQ0FBQ3BDLEtBQWpCO0FBQ3JDLEdBSEQsQ0FHRSxPQUFPYyxHQUFQLEVBQVk7QUFDWixRQUFJLHlCQUFZQSxHQUFaLEVBQWlCeEUsZUFBTzRFLGlCQUF4QixDQUFKLEVBQWdEO0FBQzlDLFlBQU1KLEdBQU47QUFDRCxLQUZELE1BRU87QUFDTCxZQUFNLElBQUluRCxLQUFKLENBQVcsaUNBQWdDbUQsR0FBRyxDQUFDekUsT0FBUSxFQUF2RCxDQUFOO0FBQ0Q7QUFDRjtBQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IF8gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB7IHV0aWwgfSBmcm9tICdhcHBpdW0tc3VwcG9ydCc7XG5pbXBvcnQgeyB2YWxpZGF0b3JzIH0gZnJvbSAnLi92YWxpZGF0b3JzJztcbmltcG9ydCB7XG4gIGVycm9ycywgaXNFcnJvclR5cGUsIGdldFJlc3BvbnNlRm9yVzNDRXJyb3IsIGdldFJlc3BvbnNlRm9ySnNvbndwRXJyb3IsXG4gIGVycm9yRnJvbU1KU09OV1BTdGF0dXNDb2RlLCBlcnJvckZyb21XM0NKc29uQ29kZSxcbn0gZnJvbSAnLi9lcnJvcnMnO1xuaW1wb3J0IHsgTUVUSE9EX01BUCwgTk9fU0VTU0lPTl9JRF9DT01NQU5EUyB9IGZyb20gJy4vcm91dGVzJztcbmltcG9ydCBCIGZyb20gJ2JsdWViaXJkJztcbmltcG9ydCBCYXNlRHJpdmVyIGZyb20gJy4uL2Jhc2Vkcml2ZXIvZHJpdmVyJztcbmltcG9ydCB7XG4gIE1KU09OV1BfRUxFTUVOVF9LRVksIFczQ19FTEVNRU5UX0tFWSwgZm9ybWF0UmVzcG9uc2VWYWx1ZSwgZm9ybWF0U3RhdHVzLFxufSBmcm9tICcuL2hlbHBlcnMnO1xuaW1wb3J0IFNFU1NJT05TX0NBQ0hFIGZyb20gJy4vc2Vzc2lvbnMtY2FjaGUnO1xuXG4vLyBUT0RPOiBNYWtlIHRoaXMgdmFsdWUgY29uZmlndXJhYmxlIGFzIGEgc2VydmVyIHNpZGUgY2FwYWJpbGl0eVxuY29uc3QgTE9HX09CSl9MRU5HVEggPSAxMDI0OyAvLyBNQVggTEVOR1RIIExvZ2dlZCB0byBmaWxlIC8gY29uc29sZVxuXG5jb25zdCBJTUFHRV9FTEVNRU5UX1BSRUZJWCA9ICdhcHBpdW0taW1hZ2UtZWxlbWVudC0nO1xuXG5jb25zdCBDUkVBVEVfU0VTU0lPTl9DT01NQU5EID0gJ2NyZWF0ZVNlc3Npb24nO1xuY29uc3QgREVMRVRFX1NFU1NJT05fQ09NTUFORCA9ICdkZWxldGVTZXNzaW9uJztcblxuY29uc3QgSU1HX0VMX0JPRFlfUkUgPSBuZXcgUmVnRXhwKFxuICBgXCIoJHtXM0NfRUxFTUVOVF9LRVl9fCR7TUpTT05XUF9FTEVNRU5UX0tFWX0pXCI6XFxzKmAgKyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVzZWxlc3MtZXNjYXBlXG4gIGBcIiR7SU1BR0VfRUxFTUVOVF9QUkVGSVh9W15cIl0rXCJgXG4pO1xuY29uc3QgSU1HX0VMX1VSTF9SRSA9IG5ldyBSZWdFeHAoXG4gIGAvKGVsZW1lbnR8c2NyZWVuc2hvdClgICtcbiAgYC8ke0lNQUdFX0VMRU1FTlRfUFJFRklYfVteL10rYFxuKTtcblxuY2xhc3MgUHJvdG9jb2wge31cblxuZnVuY3Rpb24gZXh0cmFjdFByb3RvY29sIChkcml2ZXIsIHNlc3Npb25JZCA9IG51bGwpIHtcbiAgY29uc3QgZHN0RHJpdmVyID0gXy5pc0Z1bmN0aW9uKGRyaXZlci5kcml2ZXJGb3JTZXNzaW9uKVxuICAgID8gZHJpdmVyLmRyaXZlckZvclNlc3Npb24oc2Vzc2lvbklkKVxuICAgIDogZHJpdmVyO1xuICBpZiAoZHN0RHJpdmVyID09PSBkcml2ZXIpIHtcbiAgICAvLyBTaG9ydGNpcmN1aXQgaWYgdGhlIGRyaXZlciBpbnN0YW5jZSBpcyBub3QgYW4gdW1icmVsbGEgZHJpdmVyXG4gICAgLy8gb3IgaXQgaXMgRmFrZSBkcml2ZXIgaW5zdGFuY2UsIHdoZXJlIGBkcml2ZXIuZHJpdmVyRm9yU2Vzc2lvbmBcbiAgICAvLyBhbHdheXMgcmV0dXJucyBzZWxmIGluc3RhbmNlXG4gICAgcmV0dXJuIGRyaXZlci5wcm90b2NvbDtcbiAgfVxuXG4gIC8vIEV4dHJhY3QgdGhlIHByb3RvY29sIGZvciB0aGUgY3VycmVudCBzZXNzaW9uIGlmIHRoZSBnaXZlbiBkcml2ZXIgaXMgdGhlIHVtYnJlbGxhIG9uZVxuICByZXR1cm4gZHN0RHJpdmVyID8gZHN0RHJpdmVyLnByb3RvY29sIDogU0VTU0lPTlNfQ0FDSEUuZ2V0UHJvdG9jb2woc2Vzc2lvbklkKTtcbn1cblxuZnVuY3Rpb24gaXNTZXNzaW9uQ29tbWFuZCAoY29tbWFuZCkge1xuICByZXR1cm4gIV8uaW5jbHVkZXMoTk9fU0VTU0lPTl9JRF9DT01NQU5EUywgY29tbWFuZCk7XG59XG5cbmZ1bmN0aW9uIHdyYXBQYXJhbXMgKHBhcmFtU2V0cywganNvbk9iaikge1xuICAvKiBUaGVyZSBhcmUgY29tbWFuZHMgbGlrZSBwZXJmb3JtVG91Y2ggd2hpY2ggdGFrZSBhIHNpbmdsZSBwYXJhbWV0ZXIgKHByaW1pdGl2ZSB0eXBlIG9yIGFycmF5KS5cbiAgICogU29tZSBkcml2ZXJzIGNob29zZSB0byBwYXNzIHRoaXMgcGFyYW1ldGVyIGFzIGEgdmFsdWUgKGVnLiBbYWN0aW9uMSwgYWN0aW9uMi4uLl0pIHdoaWxlIG90aGVycyB0b1xuICAgKiB3cmFwIGl0IHdpdGhpbiBhbiBvYmplY3QoZWcnIHtnZXN0dXJlOiAgW2FjdGlvbjEsIGFjdGlvbjIuLi5dfSksIHdoaWNoIG1ha2VzIGl0IGhhcmQgdG8gdmFsaWRhdGUuXG4gICAqIFRoZSB3cmFwIG9wdGlvbiBpbiB0aGUgc3BlYyBlbmZvcmNlIHdyYXBwaW5nIGJlZm9yZSB2YWxpZGF0aW9uLCBzbyB0aGF0IGFsbCBwYXJhbXMgYXJlIHdyYXBwZWQgYXRcbiAgICogdGhlIHRpbWUgdGhleSBhcmUgdmFsaWRhdGVkIGFuZCBsYXRlciBwYXNzZWQgdG8gdGhlIGNvbW1hbmRzLlxuICAgKi9cbiAgbGV0IHJlcyA9IGpzb25PYmo7XG4gIGlmIChfLmlzQXJyYXkoanNvbk9iaikgfHwgIV8uaXNPYmplY3QoanNvbk9iaikpIHtcbiAgICByZXMgPSB7fTtcbiAgICByZXNbcGFyYW1TZXRzLndyYXBdID0ganNvbk9iajtcbiAgfVxuICByZXR1cm4gcmVzO1xufVxuXG5mdW5jdGlvbiB1bndyYXBQYXJhbXMgKHBhcmFtU2V0cywganNvbk9iaikge1xuICAvKiBUaGVyZSBhcmUgY29tbWFuZHMgbGlrZSBzZXROZXR3b3JrQ29ubmVjdGlvbiB3aGljaCBzZW5kIHBhcmFtZXRlcnMgd3JhcHBlZCBpbnNpZGUgYSBrZXkgc3VjaCBhc1xuICAgKiBcInBhcmFtZXRlcnNcIi4gVGhpcyBmdW5jdGlvbiB1bndyYXBzIHRoZW0gKGVnLiB7XCJwYXJhbWV0ZXJzXCI6IHtcInR5cGVcIjogMX19IGJlY29tZXMge1widHlwZVwiOiAxfSkuXG4gICAqL1xuICBsZXQgcmVzID0ganNvbk9iajtcbiAgaWYgKF8uaXNPYmplY3QoanNvbk9iaikpIHtcbiAgICAvLyBzb21lIGNsaWVudHMsIGxpa2UgcnVieSwgZG9uJ3Qgd3JhcFxuICAgIGlmIChqc29uT2JqW3BhcmFtU2V0cy51bndyYXBdKSB7XG4gICAgICByZXMgPSBqc29uT2JqW3BhcmFtU2V0cy51bndyYXBdO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzO1xufVxuXG5mdW5jdGlvbiBjaGVja1BhcmFtcyAocGFyYW1TZXRzLCBqc29uT2JqLCBwcm90b2NvbCkge1xuICBsZXQgcmVxdWlyZWRQYXJhbXMgPSBbXTtcbiAgbGV0IG9wdGlvbmFsUGFyYW1zID0gW107XG4gIGxldCByZWNlaXZlZFBhcmFtcyA9IF8ua2V5cyhqc29uT2JqKTtcblxuICBpZiAocGFyYW1TZXRzKSB7XG4gICAgaWYgKHBhcmFtU2V0cy5yZXF1aXJlZCkge1xuICAgICAgLy8gd2UgbWlnaHQgaGF2ZSBhbiBhcnJheSBvZiBwYXJhbWV0ZXJzLFxuICAgICAgLy8gb3IgYW4gYXJyYXkgb2YgYXJyYXlzIG9mIHBhcmFtZXRlcnMsIHNvIHN0YW5kYXJkaXplXG4gICAgICBpZiAoIV8uaXNBcnJheShfLmZpcnN0KHBhcmFtU2V0cy5yZXF1aXJlZCkpKSB7XG4gICAgICAgIHJlcXVpcmVkUGFyYW1zID0gW3BhcmFtU2V0cy5yZXF1aXJlZF07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXF1aXJlZFBhcmFtcyA9IHBhcmFtU2V0cy5yZXF1aXJlZDtcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gb3B0aW9uYWwgcGFyYW1ldGVycyBhcmUganVzdCBhbiBhcnJheVxuICAgIGlmIChwYXJhbVNldHMub3B0aW9uYWwpIHtcbiAgICAgIG9wdGlvbmFsUGFyYW1zID0gcGFyYW1TZXRzLm9wdGlvbmFsO1xuICAgIH1cblxuICAgIC8vIElmIGEgZnVuY3Rpb24gd2FzIHByb3ZpZGVkIGFzIHRoZSAndmFsaWRhdGUnIGtleSwgaXQgd2lsbCBoZXJlIGJlIGNhbGxlZCB3aXRoXG4gICAgLy8ganNvbk9iaiBhcyB0aGUgcGFyYW0uIElmIGl0IHJldHVybnMgc29tZXRoaW5nIGZhbHN5LCB2ZXJpZmljYXRpb24gd2lsbCBiZVxuICAgIC8vIGNvbnNpZGVyZWQgdG8gaGF2ZSBwYXNzZWQuIElmIGl0IHJldHVybnMgc29tZXRoaW5nIGVsc2UsIHRoYXQgd2lsbCBiZSB0aGVcbiAgICAvLyBhcmd1bWVudCB0byBhbiBlcnJvciB3aGljaCBpcyB0aHJvd24gdG8gdGhlIHVzZXJcbiAgICBpZiAocGFyYW1TZXRzLnZhbGlkYXRlKSB7XG4gICAgICBsZXQgbWVzc2FnZSA9IHBhcmFtU2V0cy52YWxpZGF0ZShqc29uT2JqLCBwcm90b2NvbCk7XG4gICAgICBpZiAobWVzc2FnZSkge1xuICAgICAgICB0aHJvdyBuZXcgZXJyb3JzLkJhZFBhcmFtZXRlcnNFcnJvcihtZXNzYWdlLCBqc29uT2JqKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBpZiB3ZSBoYXZlIG5vIHJlcXVpcmVkIHBhcmFtZXRlcnMsIGFsbCBpcyB3ZWxsXG4gIGlmIChyZXF1aXJlZFBhcmFtcy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm47XG4gIH1cblxuICAvLyBzb21lIGNsaWVudHMgcGFzcyBpbiB0aGUgc2Vzc2lvbiBpZCBpbiB0aGUgcGFyYW1zXG4gIGlmIChvcHRpb25hbFBhcmFtcy5pbmRleE9mKCdzZXNzaW9uSWQnKSA9PT0gLTEpIHtcbiAgICBvcHRpb25hbFBhcmFtcy5wdXNoKCdzZXNzaW9uSWQnKTtcbiAgfVxuXG4gIC8vIHNvbWUgY2xpZW50cyBwYXNzIGluIGFuIGVsZW1lbnQgaWQgaW4gdGhlIHBhcmFtc1xuICBpZiAob3B0aW9uYWxQYXJhbXMuaW5kZXhPZignaWQnKSA9PT0gLTEpIHtcbiAgICBvcHRpb25hbFBhcmFtcy5wdXNoKCdpZCcpO1xuICB9XG5cbiAgLy8gZ28gdGhyb3VnaCB0aGUgcmVxdWlyZWQgcGFyYW1ldGVycyBhbmQgY2hlY2sgYWdhaW5zdCBvdXIgYXJndW1lbnRzXG4gIGZvciAobGV0IHBhcmFtcyBvZiByZXF1aXJlZFBhcmFtcykge1xuICAgIGlmIChfLmRpZmZlcmVuY2UocmVjZWl2ZWRQYXJhbXMsIHBhcmFtcywgb3B0aW9uYWxQYXJhbXMpLmxlbmd0aCA9PT0gMCAmJlxuICAgICAgICBfLmRpZmZlcmVuY2UocGFyYW1zLCByZWNlaXZlZFBhcmFtcykubGVuZ3RoID09PSAwKSB7XG4gICAgICAvLyB3ZSBoYXZlIGEgc2V0IG9mIHBhcmFtZXRlcnMgdGhhdCBpcyBjb3JyZWN0XG4gICAgICAvLyBzbyBzaG9ydC1jaXJjdWl0XG4gICAgICByZXR1cm47XG4gICAgfVxuICB9XG4gIHRocm93IG5ldyBlcnJvcnMuQmFkUGFyYW1ldGVyc0Vycm9yKHBhcmFtU2V0cywgcmVjZWl2ZWRQYXJhbXMpO1xufVxuXG4vKlxuICogVGhpcyBtZXRob2QgdGFrZXMgMyBwaWVjZXMgb2YgZGF0YTogcmVxdWVzdCBwYXJhbWV0ZXJzICgncmVxdWVzdFBhcmFtcycpLFxuICogYSByZXF1ZXN0IEpTT04gYm9keSAoJ2pzb25PYmonKSwgYW5kICdwYXlsb2FkUGFyYW1zJywgd2hpY2ggaXMgdGhlIHNlY3Rpb25cbiAqIGZyb20gdGhlIHJvdXRlIGRlZmluaXRpb24gZm9yIGEgcGFydGljdWxhciBlbmRwb2ludCB3aGljaCBoYXMgaW5zdHJ1Y3Rpb25zXG4gKiBvbiBoYW5kbGluZyBwYXJhbWV0ZXJzLiBUaGlzIG1ldGhvZCByZXR1cm5zIGFuIGFycmF5IG9mIGFyZ3VtZW50cyB3aGljaCB3aWxsXG4gKiBiZSBhcHBsaWVkIHRvIGEgY29tbWFuZC5cbiAqL1xuZnVuY3Rpb24gbWFrZUFyZ3MgKHJlcXVlc3RQYXJhbXMsIGpzb25PYmosIHBheWxvYWRQYXJhbXMsIHByb3RvY29sKSB7XG4gIC8vIFdlIHdhbnQgdG8gcGFzcyB0aGUgXCJ1cmxcIiBwYXJhbWV0ZXJzIHRvIHRoZSBjb21tYW5kcyBpbiByZXZlcnNlIG9yZGVyXG4gIC8vIHNpbmNlIHRoZSBjb21tYW5kIHdpbGwgc29tZXRpbWVzIHdhbnQgdG8gaWdub3JlLCBzYXksIHRoZSBzZXNzaW9uSWQuXG4gIC8vIFRoaXMgaGFzIHRoZSBlZmZlY3Qgb2YgcHV0dGluZyBzZXNzaW9uSWQgbGFzdCwgd2hpY2ggbWVhbnMgaW4gSlMgd2UgY2FuXG4gIC8vIG9taXQgaXQgZnJvbSB0aGUgZnVuY3Rpb24gc2lnbmF0dXJlIGlmIHdlJ3JlIG5vdCBnb2luZyB0byB1c2UgaXQuXG4gIGxldCB1cmxQYXJhbXMgPSBfLmtleXMocmVxdWVzdFBhcmFtcykucmV2ZXJzZSgpO1xuXG4gIC8vIEluIHRoZSBzaW1wbGUgY2FzZSwgdGhlIHJlcXVpcmVkIHBhcmFtZXRlcnMgYXJlIGEgYmFzaWMgYXJyYXkgaW5cbiAgLy8gcGF5bG9hZFBhcmFtcy5yZXF1aXJlZCwgc28gc3RhcnQgdGhlcmUuIEl0J3MgcG9zc2libGUgdGhhdCB0aGVyZSBhcmVcbiAgLy8gbXVsdGlwbGUgb3B0aW9uYWwgc2V0cyBvZiByZXF1aXJlZCBwYXJhbXMsIHRob3VnaCwgc28gaGFuZGxlIHRoYXQgY2FzZVxuICAvLyB0b28uXG4gIGxldCByZXF1aXJlZFBhcmFtcyA9IHBheWxvYWRQYXJhbXMucmVxdWlyZWQ7XG4gIGlmIChfLmlzQXJyYXkoXy5maXJzdChwYXlsb2FkUGFyYW1zLnJlcXVpcmVkKSkpIHtcbiAgICAvLyBJZiB0aGVyZSBhcmUgb3B0aW9uYWwgc2V0cyBvZiByZXF1aXJlZCBwYXJhbXMsIHRoZW4gd2Ugd2lsbCBoYXZlIGFuXG4gICAgLy8gYXJyYXkgb2YgYXJyYXlzIGluIHBheWxvYWRQYXJhbXMucmVxdWlyZWQsIHNvIGxvb3AgdGhyb3VnaCBlYWNoIHNldCBhbmRcbiAgICAvLyBwaWNrIHRoZSBvbmUgdGhhdCBtYXRjaGVzIHdoaWNoIEpTT04gcGFyYW1zIHdlcmUgYWN0dWFsbHkgc2VudC4gV2UndmVcbiAgICAvLyBhbHJlYWR5IGJlZW4gdGhyb3VnaCB2YWxpZGF0aW9uIHNvIHdlJ3JlIGd1YXJhbnRlZWQgdG8gZmluZCBhIG1hdGNoLlxuICAgIGxldCBrZXlzID0gXy5rZXlzKGpzb25PYmopO1xuICAgIGZvciAobGV0IHBhcmFtcyBvZiBwYXlsb2FkUGFyYW1zLnJlcXVpcmVkKSB7XG4gICAgICBpZiAoXy53aXRob3V0KHBhcmFtcywgLi4ua2V5cykubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJlcXVpcmVkUGFyYW1zID0gcGFyYW1zO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyBOb3cgd2UgY29uc3RydWN0IG91ciBsaXN0IG9mIGFyZ3VtZW50cyB3aGljaCB3aWxsIGJlIHBhc3NlZCB0byB0aGUgY29tbWFuZFxuICBsZXQgYXJncztcbiAgaWYgKF8uaXNGdW5jdGlvbihwYXlsb2FkUGFyYW1zLm1ha2VBcmdzKSkge1xuICAgIC8vIEluIHRoZSByb3V0ZSBzcGVjLCBhIHBhcnRpY3VsYXIgcm91dGUgbWlnaHQgZGVmaW5lIGEgJ21ha2VBcmdzJyBmdW5jdGlvblxuICAgIC8vIGlmIGl0IHdhbnRzIGZ1bGwgY29udHJvbCBvdmVyIGhvdyB0byB0dXJuIEpTT04gcGFyYW1ldGVycyBpbnRvIGNvbW1hbmRcbiAgICAvLyBhcmd1bWVudHMuIFNvIHdlIHBhc3MgaXQgdGhlIEpTT04gcGFyYW1ldGVycyBhbmQgaXQgcmV0dXJucyBhbiBhcnJheVxuICAgIC8vIHdoaWNoIHdpbGwgYmUgYXBwbGllZCB0byB0aGUgaGFuZGxpbmcgY29tbWFuZC4gRm9yIGV4YW1wbGUgaWYgaXQgcmV0dXJuc1xuICAgIC8vIFsxLCAyLCAzXSwgd2Ugd2lsbCBjYWxsIGBjb21tYW5kKDEsIDIsIDMsIC4uLilgICh1cmwgcGFyYW1zIGFyZSBzZXBhcmF0ZVxuICAgIC8vIGZyb20gSlNPTiBwYXJhbXMgYW5kIGdldCBjb25jYXRlbmF0ZWQgYmVsb3cpLlxuICAgIGFyZ3MgPSBwYXlsb2FkUGFyYW1zLm1ha2VBcmdzKGpzb25PYmosIHByb3RvY29sKTtcbiAgfSBlbHNlIHtcbiAgICAvLyBPdGhlcndpc2UsIGNvbGxlY3QgYWxsIHRoZSByZXF1aXJlZCBhbmQgb3B0aW9uYWwgcGFyYW1zIGFuZCBmbGF0dGVuIHRoZW1cbiAgICAvLyBpbnRvIGFuIGFyZ3VtZW50IGFycmF5XG4gICAgYXJncyA9IF8uZmxhdHRlbihyZXF1aXJlZFBhcmFtcykubWFwKChwKSA9PiBqc29uT2JqW3BdKTtcbiAgICBpZiAocGF5bG9hZFBhcmFtcy5vcHRpb25hbCkge1xuICAgICAgYXJncyA9IGFyZ3MuY29uY2F0KF8uZmxhdHRlbihwYXlsb2FkUGFyYW1zLm9wdGlvbmFsKS5tYXAoKHApID0+IGpzb25PYmpbcF0pKTtcbiAgICB9XG4gIH1cbiAgLy8gRmluYWxseSwgZ2V0IG91ciB1cmwgcGFyYW1zIChzZXNzaW9uIGlkLCBlbGVtZW50IGlkLCBldGMuLi4pIG9uIHRoZSBlbmQgb2ZcbiAgLy8gdGhlIGxpc3RcbiAgYXJncyA9IGFyZ3MuY29uY2F0KHVybFBhcmFtcy5tYXAoKHUpID0+IHJlcXVlc3RQYXJhbXNbdV0pKTtcbiAgcmV0dXJuIGFyZ3M7XG59XG5cbmZ1bmN0aW9uIHJvdXRlQ29uZmlndXJpbmdGdW5jdGlvbiAoZHJpdmVyKSB7XG4gIGlmICghZHJpdmVyLnNlc3Npb25FeGlzdHMpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0RyaXZlcnMgdXNlZCB3aXRoIE1KU09OV1AgbXVzdCBpbXBsZW1lbnQgYHNlc3Npb25FeGlzdHNgJyk7XG4gIH1cblxuICBpZiAoIShkcml2ZXIuZXhlY3V0ZUNvbW1hbmQgfHwgZHJpdmVyLmV4ZWN1dGUpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdEcml2ZXJzIHVzZWQgd2l0aCBNSlNPTldQIG11c3QgaW1wbGVtZW50IGBleGVjdXRlQ29tbWFuZGAgb3IgYGV4ZWN1dGVgJyk7XG4gIH1cblxuICAvLyByZXR1cm4gYSBmdW5jdGlvbiB3aGljaCB3aWxsIGFkZCBhbGwgdGhlIHJvdXRlcyB0byB0aGUgZHJpdmVyXG4gIHJldHVybiBmdW5jdGlvbiBhZGRSb3V0ZXMgKGFwcCkge1xuICAgIGZvciAoY29uc3QgW3BhdGgsIG1ldGhvZHNdIG9mIF8udG9QYWlycyhNRVRIT0RfTUFQKSkge1xuICAgICAgZm9yIChjb25zdCBbbWV0aG9kLCBzcGVjXSBvZiBfLnRvUGFpcnMobWV0aG9kcykpIHtcbiAgICAgICAgLy8gc2V0IHVwIHRoZSBleHByZXNzIHJvdXRlIGhhbmRsZXJcbiAgICAgICAgYnVpbGRIYW5kbGVyKGFwcCwgbWV0aG9kLCBwYXRoLCBzcGVjLCBkcml2ZXIsIGlzU2Vzc2lvbkNvbW1hbmQoc3BlYy5jb21tYW5kKSk7XG4gICAgICB9XG4gICAgfVxuICB9O1xufVxuXG5mdW5jdGlvbiBidWlsZEhhbmRsZXIgKGFwcCwgbWV0aG9kLCBwYXRoLCBzcGVjLCBkcml2ZXIsIGlzU2Vzc0NtZCkge1xuICBsZXQgYXN5bmNIYW5kbGVyID0gYXN5bmMgKHJlcSwgcmVzKSA9PiB7XG4gICAgbGV0IGpzb25PYmogPSByZXEuYm9keTtcbiAgICBsZXQgaHR0cFJlc0JvZHkgPSB7fTtcbiAgICBsZXQgaHR0cFN0YXR1cyA9IDIwMDtcbiAgICBsZXQgbmV3U2Vzc2lvbklkO1xuICAgIGxldCBjdXJyZW50UHJvdG9jb2wgPSBleHRyYWN0UHJvdG9jb2woZHJpdmVyLCByZXEucGFyYW1zLnNlc3Npb25JZCk7XG5cbiAgICB0cnkge1xuICAgICAgLy8gaWYgdGhpcyBpcyBhIHNlc3Npb24gY29tbWFuZCBidXQgd2UgZG9uJ3QgaGF2ZSBhIHNlc3Npb24sXG4gICAgICAvLyBlcnJvciBvdXQgZWFybHkgKGVzcGVjaWFsbHkgYmVmb3JlIHByb3h5aW5nKVxuICAgICAgaWYgKGlzU2Vzc0NtZCAmJiAhZHJpdmVyLnNlc3Npb25FeGlzdHMocmVxLnBhcmFtcy5zZXNzaW9uSWQpKSB7XG4gICAgICAgIHRocm93IG5ldyBlcnJvcnMuTm9TdWNoRHJpdmVyRXJyb3IoKTtcbiAgICAgIH1cblxuICAgICAgLy8gaWYgdGhlIGRyaXZlciBpcyBjdXJyZW50bHkgcHJveHlpbmcgY29tbWFuZHMgdG8gYW5vdGhlciBKU09OV1BcbiAgICAgIC8vIHNlcnZlciwgYnlwYXNzIGFsbCBvdXIgY2hlY2tzIGFuZCBhc3N1bWUgdGhlIHVwc3RyZWFtIHNlcnZlciBrbm93c1xuICAgICAgLy8gd2hhdCBpdCdzIGRvaW5nLiBCdXQga2VlcCB0aGlzIGluIHRoZSB0cnkvY2F0Y2ggYmxvY2sgc28gaWYgcHJveHlpbmdcbiAgICAgIC8vIGl0c2VsZiBmYWlscywgd2UgZ2l2ZSBhIG1lc3NhZ2UgdG8gdGhlIGNsaWVudC4gT2YgY291cnNlIHdlIG9ubHlcbiAgICAgIC8vIHdhbnQgdG8gZG8gdGhlc2Ugd2hlbiB3ZSBoYXZlIGEgc2Vzc2lvbiBjb21tYW5kOyB0aGUgQXBwaXVtIGRyaXZlclxuICAgICAgLy8gbXVzdCBiZSByZXNwb25zaWJsZSBmb3Igc3RhcnQvc3RvcCBzZXNzaW9uLCBldGMuLi5cbiAgICAgIGlmIChpc1Nlc3NDbWQgJiYgZHJpdmVyU2hvdWxkRG9Kd3BQcm94eShkcml2ZXIsIHJlcSwgc3BlYy5jb21tYW5kKSkge1xuICAgICAgICBhd2FpdCBkb0p3cFByb3h5KGRyaXZlciwgcmVxLCByZXMpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIC8vIGlmIGEgY29tbWFuZCBpcyBub3QgaW4gb3VyIG1ldGhvZCBtYXAsIGl0J3MgYmVjYXVzZSB3ZVxuICAgICAgLy8gaGF2ZSBubyBwbGFucyB0byBldmVyIGltcGxlbWVudCBpdFxuICAgICAgaWYgKCFzcGVjLmNvbW1hbmQpIHtcbiAgICAgICAgdGhyb3cgbmV3IGVycm9ycy5Ob3RJbXBsZW1lbnRlZEVycm9yKCk7XG4gICAgICB9XG5cbiAgICAgIC8vIHdyYXAgcGFyYW1zIGlmIG5lY2Vzc2FyeVxuICAgICAgaWYgKHNwZWMucGF5bG9hZFBhcmFtcyAmJiBzcGVjLnBheWxvYWRQYXJhbXMud3JhcCkge1xuICAgICAgICBqc29uT2JqID0gd3JhcFBhcmFtcyhzcGVjLnBheWxvYWRQYXJhbXMsIGpzb25PYmopO1xuICAgICAgfVxuXG4gICAgICAvLyB1bndyYXAgcGFyYW1zIGlmIG5lY2Vzc2FyeVxuICAgICAgaWYgKHNwZWMucGF5bG9hZFBhcmFtcyAmJiBzcGVjLnBheWxvYWRQYXJhbXMudW53cmFwKSB7XG4gICAgICAgIGpzb25PYmogPSB1bndyYXBQYXJhbXMoc3BlYy5wYXlsb2FkUGFyYW1zLCBqc29uT2JqKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHNwZWMuY29tbWFuZCA9PT0gQ1JFQVRFX1NFU1NJT05fQ09NTUFORCkge1xuICAgICAgICAvLyB0cnkgdG8gZGV0ZXJtaW5lIHByb3RvY29sIGJ5IHNlc3Npb24gY3JlYXRpb24gYXJncywgc28gd2UgY2FuIHRocm93IGFcbiAgICAgICAgLy8gcHJvcGVybHkgZm9ybWF0dGVkIGVycm9yIGlmIGFyZ3VtZW50cyB2YWxpZGF0aW9uIGZhaWxzXG4gICAgICAgIGN1cnJlbnRQcm90b2NvbCA9IEJhc2VEcml2ZXIuZGV0ZXJtaW5lUHJvdG9jb2woLi4ubWFrZUFyZ3MocmVxLnBhcmFtcywganNvbk9iaiwgc3BlYy5wYXlsb2FkUGFyYW1zIHx8IHt9KSk7XG4gICAgICB9XG5cbiAgICAgIC8vIGVuc3VyZSB0aGF0IHRoZSBqc29uIHBheWxvYWQgY29uZm9ybXMgdG8gdGhlIHNwZWNcbiAgICAgIGNoZWNrUGFyYW1zKHNwZWMucGF5bG9hZFBhcmFtcywganNvbk9iaiwgY3VycmVudFByb3RvY29sKTtcblxuICAgICAgLy8gdHVybiB0aGUgY29tbWFuZCBhbmQganNvbiBwYXlsb2FkIGludG8gYW4gYXJndW1lbnQgbGlzdCBmb3JcbiAgICAgIC8vIHRoZSBkcml2ZXIgbWV0aG9kc1xuICAgICAgbGV0IGFyZ3MgPSBtYWtlQXJncyhyZXEucGFyYW1zLCBqc29uT2JqLCBzcGVjLnBheWxvYWRQYXJhbXMgfHwge30sIGN1cnJlbnRQcm90b2NvbCk7XG4gICAgICBsZXQgZHJpdmVyUmVzO1xuICAgICAgLy8gdmFsaWRhdGUgY29tbWFuZCBhcmdzIGFjY29yZGluZyB0byBNSlNPTldQXG4gICAgICBpZiAodmFsaWRhdG9yc1tzcGVjLmNvbW1hbmRdKSB7XG4gICAgICAgIHZhbGlkYXRvcnNbc3BlYy5jb21tYW5kXSguLi5hcmdzKTtcbiAgICAgIH1cblxuICAgICAgLy8gcnVuIHRoZSBkcml2ZXIgY29tbWFuZCB3cmFwcGVkIGluc2lkZSB0aGUgYXJndW1lbnQgdmFsaWRhdG9yc1xuICAgICAgU0VTU0lPTlNfQ0FDSEUuZ2V0TG9nZ2VyKHJlcS5wYXJhbXMuc2Vzc2lvbklkLCBjdXJyZW50UHJvdG9jb2wpLmRlYnVnKGBDYWxsaW5nIGAgK1xuICAgICAgICBgJHtkcml2ZXIuY29uc3RydWN0b3IubmFtZX0uJHtzcGVjLmNvbW1hbmR9KCkgd2l0aCBhcmdzOiBgICtcbiAgICAgICAgXy50cnVuY2F0ZShKU09OLnN0cmluZ2lmeShhcmdzKSwge2xlbmd0aDogTE9HX09CSl9MRU5HVEh9KSk7XG5cbiAgICAgIGlmIChkcml2ZXIuZXhlY3V0ZUNvbW1hbmQpIHtcbiAgICAgICAgZHJpdmVyUmVzID0gYXdhaXQgZHJpdmVyLmV4ZWN1dGVDb21tYW5kKHNwZWMuY29tbWFuZCwgLi4uYXJncyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkcml2ZXJSZXMgPSBhd2FpdCBkcml2ZXIuZXhlY3V0ZShzcGVjLmNvbW1hbmQsIC4uLmFyZ3MpO1xuICAgICAgfVxuXG4gICAgICAvLyBHZXQgdGhlIHByb3RvY29sIGFmdGVyIGV4ZWN1dGVDb21tYW5kXG4gICAgICBjdXJyZW50UHJvdG9jb2wgPSBleHRyYWN0UHJvdG9jb2woZHJpdmVyLCByZXEucGFyYW1zLnNlc3Npb25JZCkgfHwgY3VycmVudFByb3RvY29sO1xuXG4gICAgICAvLyBJZiBgZXhlY3V0ZUNvbW1hbmRgIHdhcyBvdmVycmlkZGVuIGFuZCB0aGUgbWV0aG9kIHJldHVybnMgYW4gb2JqZWN0XG4gICAgICAvLyB3aXRoIGEgcHJvdG9jb2wgYW5kIHZhbHVlL2Vycm9yIHByb3BlcnR5LCByZS1hc3NpZ24gdGhlIHByb3RvY29sXG4gICAgICBpZiAoXy5pc1BsYWluT2JqZWN0KGRyaXZlclJlcykgJiYgXy5oYXMoZHJpdmVyUmVzLCAncHJvdG9jb2wnKSkge1xuICAgICAgICBjdXJyZW50UHJvdG9jb2wgPSBkcml2ZXJSZXMucHJvdG9jb2wgfHwgY3VycmVudFByb3RvY29sO1xuICAgICAgICBpZiAoZHJpdmVyUmVzLmVycm9yKSB7XG4gICAgICAgICAgdGhyb3cgZHJpdmVyUmVzLmVycm9yO1xuICAgICAgICB9XG4gICAgICAgIGRyaXZlclJlcyA9IGRyaXZlclJlcy52YWx1ZTtcbiAgICAgIH1cblxuICAgICAgLy8gdW5wYWNrIGNyZWF0ZVNlc3Npb24gcmVzcG9uc2VcbiAgICAgIGlmIChzcGVjLmNvbW1hbmQgPT09IENSRUFURV9TRVNTSU9OX0NPTU1BTkQpIHtcbiAgICAgICAgbmV3U2Vzc2lvbklkID0gZHJpdmVyUmVzWzBdO1xuICAgICAgICBTRVNTSU9OU19DQUNIRS5wdXRTZXNzaW9uKG5ld1Nlc3Npb25JZCwgY3VycmVudFByb3RvY29sKTtcbiAgICAgICAgU0VTU0lPTlNfQ0FDSEUuZ2V0TG9nZ2VyKG5ld1Nlc3Npb25JZCwgY3VycmVudFByb3RvY29sKVxuICAgICAgICAgIC5kZWJ1ZyhgQ2FjaGVkIHRoZSBwcm90b2NvbCB2YWx1ZSAnJHtjdXJyZW50UHJvdG9jb2x9JyBmb3IgdGhlIG5ldyBzZXNzaW9uICR7bmV3U2Vzc2lvbklkfWApO1xuICAgICAgICBpZiAoY3VycmVudFByb3RvY29sID09PSBCYXNlRHJpdmVyLkRSSVZFUl9QUk9UT0NPTC5NSlNPTldQKSB7XG4gICAgICAgICAgZHJpdmVyUmVzID0gZHJpdmVyUmVzWzFdO1xuICAgICAgICB9IGVsc2UgaWYgKGN1cnJlbnRQcm90b2NvbCA9PT0gQmFzZURyaXZlci5EUklWRVJfUFJPVE9DT0wuVzNDKSB7XG4gICAgICAgICAgZHJpdmVyUmVzID0ge1xuICAgICAgICAgICAgY2FwYWJpbGl0aWVzOiBkcml2ZXJSZXNbMV0sXG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBkcml2ZXJSZXMgPSBmb3JtYXRSZXNwb25zZVZhbHVlKGRyaXZlclJlcyk7XG5cbiAgICAgIC8vIGRlbGV0ZSBzaG91bGQgbm90IHJldHVybiBhbnl0aGluZyBldmVuIGlmIHN1Y2Nlc3NmdWxcbiAgICAgIGlmIChzcGVjLmNvbW1hbmQgPT09IERFTEVURV9TRVNTSU9OX0NPTU1BTkQpIHtcbiAgICAgICAgU0VTU0lPTlNfQ0FDSEUuZ2V0TG9nZ2VyKHJlcS5wYXJhbXMuc2Vzc2lvbklkLCBjdXJyZW50UHJvdG9jb2wpXG4gICAgICAgICAgLmRlYnVnKGBSZWNlaXZlZCByZXNwb25zZTogJHtfLnRydW5jYXRlKEpTT04uc3RyaW5naWZ5KGRyaXZlclJlcyksIHtsZW5ndGg6IExPR19PQkpfTEVOR1RIfSl9YCk7XG4gICAgICAgIFNFU1NJT05TX0NBQ0hFLmdldExvZ2dlcihyZXEucGFyYW1zLnNlc3Npb25JZCwgY3VycmVudFByb3RvY29sKS5kZWJ1ZygnQnV0IGRlbGV0aW5nIHNlc3Npb24sIHNvIG5vdCByZXR1cm5pbmcnKTtcbiAgICAgICAgZHJpdmVyUmVzID0gbnVsbDtcbiAgICAgIH1cblxuICAgICAgLy8gaWYgdGhlIHN0YXR1cyBpcyBub3QgMCwgIHRocm93IHRoZSBhcHByb3ByaWF0ZSBlcnJvciBmb3Igc3RhdHVzIGNvZGUuXG4gICAgICBpZiAodXRpbC5oYXNWYWx1ZShkcml2ZXJSZXMpKSB7XG4gICAgICAgIGlmICh1dGlsLmhhc1ZhbHVlKGRyaXZlclJlcy5zdGF0dXMpICYmICFpc05hTihkcml2ZXJSZXMuc3RhdHVzKSAmJiBwYXJzZUludChkcml2ZXJSZXMuc3RhdHVzLCAxMCkgIT09IDApIHtcbiAgICAgICAgICB0aHJvdyBlcnJvckZyb21NSlNPTldQU3RhdHVzQ29kZShkcml2ZXJSZXMuc3RhdHVzLCBkcml2ZXJSZXMudmFsdWUpO1xuICAgICAgICB9IGVsc2UgaWYgKF8uaXNQbGFpbk9iamVjdChkcml2ZXJSZXMudmFsdWUpICYmIGRyaXZlclJlcy52YWx1ZS5lcnJvcikge1xuICAgICAgICAgIHRocm93IGVycm9yRnJvbVczQ0pzb25Db2RlKGRyaXZlclJlcy52YWx1ZS5lcnJvciwgZHJpdmVyUmVzLnZhbHVlLm1lc3NhZ2UsIGRyaXZlclJlcy52YWx1ZS5zdGFja3RyYWNlKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBodHRwUmVzQm9keSA9IGZvcm1hdFN0YXR1cyhodHRwUmVzQm9keSwgY3VycmVudFByb3RvY29sKTtcbiAgICAgIGh0dHBSZXNCb2R5LnZhbHVlID0gZHJpdmVyUmVzO1xuICAgICAgU0VTU0lPTlNfQ0FDSEUuZ2V0TG9nZ2VyKHJlcS5wYXJhbXMuc2Vzc2lvbklkIHx8IG5ld1Nlc3Npb25JZCwgY3VycmVudFByb3RvY29sKS5kZWJ1ZyhgUmVzcG9uZGluZyBgICtcbiAgICAgICAgYHRvIGNsaWVud