blob: 04e1d3355bd662d6d51b638ee442d8da68b8850b [file] [log] [blame]
'use strict';
var _ExportMap = require('../ExportMap');
var _ExportMap2 = _interopRequireDefault(_ExportMap);
var _resolve = require('eslint-module-utils/resolve');
var _resolve2 = _interopRequireDefault(_resolve);
var _docsUrl = require('../docsUrl');
var _docsUrl2 = _interopRequireDefault(_docsUrl);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } } /**
* @fileOverview Ensures that modules contain exports and/or all
* modules are consumed within other modules.
* @author René Fermann
*/
// eslint/lib/util/glob-util has been moved to eslint/lib/util/glob-utils with version 5.3
// and has been moved to eslint/lib/cli-engine/file-enumerator in version 6
let listFilesToProcess;
try {
var FileEnumerator = require('eslint/lib/cli-engine/file-enumerator').FileEnumerator;
listFilesToProcess = function (src) {
var e = new FileEnumerator();
return Array.from(e.iterateFiles(src), (_ref) => {
let filePath = _ref.filePath,
ignored = _ref.ignored;
return {
ignored,
filename: filePath
};
});
};
} catch (e1) {
try {
listFilesToProcess = require('eslint/lib/util/glob-utils').listFilesToProcess;
} catch (e2) {
listFilesToProcess = require('eslint/lib/util/glob-util').listFilesToProcess;
}
}
const EXPORT_DEFAULT_DECLARATION = 'ExportDefaultDeclaration';
const EXPORT_NAMED_DECLARATION = 'ExportNamedDeclaration';
const EXPORT_ALL_DECLARATION = 'ExportAllDeclaration';
const IMPORT_DECLARATION = 'ImportDeclaration';
const IMPORT_NAMESPACE_SPECIFIER = 'ImportNamespaceSpecifier';
const IMPORT_DEFAULT_SPECIFIER = 'ImportDefaultSpecifier';
const VARIABLE_DECLARATION = 'VariableDeclaration';
const FUNCTION_DECLARATION = 'FunctionDeclaration';
const CLASS_DECLARATION = 'ClassDeclaration';
const DEFAULT = 'default';
let preparationDone = false;
const importList = new Map();
const exportList = new Map();
const ignoredFiles = new Set();
const isNodeModule = path => {
return (/\/(node_modules)\//.test(path)
);
};
/**
* read all files matching the patterns in src and ignoreExports
*
* return all files matching src pattern, which are not matching the ignoreExports pattern
*/
const resolveFiles = (src, ignoreExports) => {
const srcFiles = new Set();
const srcFileList = listFilesToProcess(src);
// prepare list of ignored files
const ignoredFilesList = listFilesToProcess(ignoreExports);
ignoredFilesList.forEach((_ref2) => {
let filename = _ref2.filename;
return ignoredFiles.add(filename);
});
// prepare list of source files, don't consider files from node_modules
srcFileList.filter((_ref3) => {
let filename = _ref3.filename;
return !isNodeModule(filename);
}).forEach((_ref4) => {
let filename = _ref4.filename;
srcFiles.add(filename);
});
return srcFiles;
};
/**
* parse all source files and build up 2 maps containing the existing imports and exports
*/
const prepareImportsAndExports = (srcFiles, context) => {
const exportAll = new Map();
srcFiles.forEach(file => {
const exports = new Map();
const imports = new Map();
const currentExports = _ExportMap2.default.get(file, context);
if (currentExports) {
const dependencies = currentExports.dependencies,
reexports = currentExports.reexports,
localImportList = currentExports.imports,
namespace = currentExports.namespace;
// dependencies === export * from
const currentExportAll = new Set();
dependencies.forEach(value => {
currentExportAll.add(value().path);
});
exportAll.set(file, currentExportAll);
reexports.forEach((value, key) => {
if (key === DEFAULT) {
exports.set(IMPORT_DEFAULT_SPECIFIER, { whereUsed: new Set() });
} else {
exports.set(key, { whereUsed: new Set() });
}
const reexport = value.getImport();
if (!reexport) {
return;
}
let localImport = imports.get(reexport.path);
let currentValue;
if (value.local === DEFAULT) {
currentValue = IMPORT_DEFAULT_SPECIFIER;
} else {
currentValue = value.local;
}
if (typeof localImport !== 'undefined') {
localImport = new Set([].concat(_toConsumableArray(localImport), [currentValue]));
} else {
localImport = new Set([currentValue]);
}
imports.set(reexport.path, localImport);
});
localImportList.forEach((value, key) => {
if (isNodeModule(key)) {
return;
}
imports.set(key, value.importedSpecifiers);
});
importList.set(file, imports);
// build up export list only, if file is not ignored
if (ignoredFiles.has(file)) {
return;
}
namespace.forEach((value, key) => {
if (key === DEFAULT) {
exports.set(IMPORT_DEFAULT_SPECIFIER, { whereUsed: new Set() });
} else {
exports.set(key, { whereUsed: new Set() });
}
});
}
exports.set(EXPORT_ALL_DECLARATION, { whereUsed: new Set() });
exports.set(IMPORT_NAMESPACE_SPECIFIER, { whereUsed: new Set() });
exportList.set(file, exports);
});
exportAll.forEach((value, key) => {
value.forEach(val => {
const currentExports = exportList.get(val);
const currentExport = currentExports.get(EXPORT_ALL_DECLARATION);
currentExport.whereUsed.add(key);
});
});
};
/**
* traverse through all imports and add the respective path to the whereUsed-list
* of the corresponding export
*/
const determineUsage = () => {
importList.forEach((listValue, listKey) => {
listValue.forEach((value, key) => {
const exports = exportList.get(key);
if (typeof exports !== 'undefined') {
value.forEach(currentImport => {
let specifier;
if (currentImport === IMPORT_NAMESPACE_SPECIFIER) {
specifier = IMPORT_NAMESPACE_SPECIFIER;
} else if (currentImport === IMPORT_DEFAULT_SPECIFIER) {
specifier = IMPORT_DEFAULT_SPECIFIER;
} else {
specifier = currentImport;
}
if (typeof specifier !== 'undefined') {
const exportStatement = exports.get(specifier);
if (typeof exportStatement !== 'undefined') {
const whereUsed = exportStatement.whereUsed;
whereUsed.add(listKey);
exports.set(specifier, { whereUsed });
}
}
});
}
});
});
};
const getSrc = src => {
if (src) {
return src;
}
return [process.cwd()];
};
/**
* prepare the lists of existing imports and exports - should only be executed once at
* the start of a new eslint run
*/
const doPreparation = (src, ignoreExports, context) => {
const srcFiles = resolveFiles(getSrc(src), ignoreExports);
prepareImportsAndExports(srcFiles, context);
determineUsage();
preparationDone = true;
};
const newNamespaceImportExists = specifiers => specifiers.some((_ref5) => {
let type = _ref5.type;
return type === IMPORT_NAMESPACE_SPECIFIER;
});
const newDefaultImportExists = specifiers => specifiers.some((_ref6) => {
let type = _ref6.type;
return type === IMPORT_DEFAULT_SPECIFIER;
});
module.exports = {
meta: {
docs: { url: (0, _docsUrl2.default)('no-unused-modules') },
schema: [{
properties: {
src: {
description: 'files/paths to be analyzed (only for unused exports)',
type: 'array',
minItems: 1,
items: {
type: 'string',
minLength: 1
}
},
ignoreExports: {
description: 'files/paths for which unused exports will not be reported (e.g module entry points)',
type: 'array',
minItems: 1,
items: {
type: 'string',
minLength: 1
}
},
missingExports: {
description: 'report modules without any exports',
type: 'boolean'
},
unusedExports: {
description: 'report exports without any usage',
type: 'boolean'
}
},
not: {
properties: {
unusedExports: { enum: [false] },
missingExports: { enum: [false] }
}
},
anyOf: [{
not: {
properties: {
unusedExports: { enum: [true] }
}
},
required: ['missingExports']
}, {
not: {
properties: {
missingExports: { enum: [true] }
}
},
required: ['unusedExports']
}, {
properties: {
unusedExports: { enum: [true] }
},
required: ['unusedExports']
}, {
properties: {
missingExports: { enum: [true] }
},
required: ['missingExports']
}]
}]
},
create: context => {
var _ref7 = context.options[0] || {};
const src = _ref7.src;
var _ref7$ignoreExports = _ref7.ignoreExports;
const ignoreExports = _ref7$ignoreExports === undefined ? [] : _ref7$ignoreExports,
missingExports = _ref7.missingExports,
unusedExports = _ref7.unusedExports;
if (unusedExports && !preparationDone) {
doPreparation(src, ignoreExports, context);
}
const file = context.getFilename();
const checkExportPresence = node => {
if (!missingExports) {
return;
}
if (ignoredFiles.has(file)) {
return;
}
const exportCount = exportList.get(file);
const exportAll = exportCount.get(EXPORT_ALL_DECLARATION);
const namespaceImports = exportCount.get(IMPORT_NAMESPACE_SPECIFIER);
exportCount.delete(EXPORT_ALL_DECLARATION);
exportCount.delete(IMPORT_NAMESPACE_SPECIFIER);
if (missingExports && exportCount.size < 1) {
// node.body[0] === 'undefined' only happens, if everything is commented out in the file
// being linted
context.report(node.body[0] ? node.body[0] : node, 'No exports found');
}
exportCount.set(EXPORT_ALL_DECLARATION, exportAll);
exportCount.set(IMPORT_NAMESPACE_SPECIFIER, namespaceImports);
};
const checkUsage = (node, exportedValue) => {
if (!unusedExports) {
return;
}
if (ignoredFiles.has(file)) {
return;
}
// refresh list of source files
const srcFiles = resolveFiles(getSrc(src), ignoreExports);
// make sure file to be linted is included in source files
if (!srcFiles.has(file)) {
return;
}
exports = exportList.get(file);
// special case: export * from
const exportAll = exports.get(EXPORT_ALL_DECLARATION);
if (typeof exportAll !== 'undefined' && exportedValue !== IMPORT_DEFAULT_SPECIFIER) {
if (exportAll.whereUsed.size > 0) {
return;
}
}
// special case: namespace import
const namespaceImports = exports.get(IMPORT_NAMESPACE_SPECIFIER);
if (typeof namespaceImports !== 'undefined') {
if (namespaceImports.whereUsed.size > 0) {
return;
}
}
const exportStatement = exports.get(exportedValue);
const value = exportedValue === IMPORT_DEFAULT_SPECIFIER ? DEFAULT : exportedValue;
if (typeof exportStatement !== 'undefined') {
if (exportStatement.whereUsed.size < 1) {
context.report(node, `exported declaration '${value}' not used within other modules`);
}
} else {
context.report(node, `exported declaration '${value}' not used within other modules`);
}
};
/**
* only useful for tools like vscode-eslint
*
* update lists of existing exports during runtime
*/
const updateExportUsage = node => {
if (ignoredFiles.has(file)) {
return;
}
let exports = exportList.get(file);
// new module has been created during runtime
// include it in further processing
if (typeof exports === 'undefined') {
exports = new Map();
}
const newExports = new Map();
const newExportIdentifiers = new Set();
node.body.forEach((_ref8) => {
let type = _ref8.type,
declaration = _ref8.declaration,
specifiers = _ref8.specifiers;
if (type === EXPORT_DEFAULT_DECLARATION) {
newExportIdentifiers.add(IMPORT_DEFAULT_SPECIFIER);
}
if (type === EXPORT_NAMED_DECLARATION) {
if (specifiers.length > 0) {
specifiers.forEach(specifier => {
if (specifier.exported) {
newExportIdentifiers.add(specifier.exported.name);
}
});
}
if (declaration) {
if (declaration.type === FUNCTION_DECLARATION || declaration.type === CLASS_DECLARATION) {
newExportIdentifiers.add(declaration.id.name);
}
if (declaration.type === VARIABLE_DECLARATION) {
declaration.declarations.forEach((_ref9) => {
let id = _ref9.id;
newExportIdentifiers.add(id.name);
});
}
}
}
});
// old exports exist within list of new exports identifiers: add to map of new exports
exports.forEach((value, key) => {
if (newExportIdentifiers.has(key)) {
newExports.set(key, value);
}
});
// new export identifiers added: add to map of new exports
newExportIdentifiers.forEach(key => {
if (!exports.has(key)) {
newExports.set(key, { whereUsed: new Set() });
}
});
// preserve information about namespace imports
let exportAll = exports.get(EXPORT_ALL_DECLARATION);
let namespaceImports = exports.get(IMPORT_NAMESPACE_SPECIFIER);
if (typeof namespaceImports === 'undefined') {
namespaceImports = { whereUsed: new Set() };
}
newExports.set(EXPORT_ALL_DECLARATION, exportAll);
newExports.set(IMPORT_NAMESPACE_SPECIFIER, namespaceImports);
exportList.set(file, newExports);
};
/**
* only useful for tools like vscode-eslint
*
* update lists of existing imports during runtime
*/
const updateImportUsage = node => {
if (!unusedExports) {
return;
}
let oldImportPaths = importList.get(file);
if (typeof oldImportPaths === 'undefined') {
oldImportPaths = new Map();
}
const oldNamespaceImports = new Set();
const newNamespaceImports = new Set();
const oldExportAll = new Set();
const newExportAll = new Set();
const oldDefaultImports = new Set();
const newDefaultImports = new Set();
const oldImports = new Map();
const newImports = new Map();
oldImportPaths.forEach((value, key) => {
if (value.has(EXPORT_ALL_DECLARATION)) {
oldExportAll.add(key);
}
if (value.has(IMPORT_NAMESPACE_SPECIFIER)) {
oldNamespaceImports.add(key);
}
if (value.has(IMPORT_DEFAULT_SPECIFIER)) {
oldDefaultImports.add(key);
}
value.forEach(val => {
if (val !== IMPORT_NAMESPACE_SPECIFIER && val !== IMPORT_DEFAULT_SPECIFIER) {
oldImports.set(val, key);
}
});
});
node.body.forEach(astNode => {
let resolvedPath;
// support for export { value } from 'module'
if (astNode.type === EXPORT_NAMED_DECLARATION) {
if (astNode.source) {
resolvedPath = (0, _resolve2.default)(astNode.source.raw.replace(/('|")/g, ''), context);
astNode.specifiers.forEach(specifier => {
let name;
if (specifier.exported.name === DEFAULT) {
name = IMPORT_DEFAULT_SPECIFIER;
} else {
name = specifier.local.name;
}
newImports.set(name, resolvedPath);
});
}
}
if (astNode.type === EXPORT_ALL_DECLARATION) {
resolvedPath = (0, _resolve2.default)(astNode.source.raw.replace(/('|")/g, ''), context);
newExportAll.add(resolvedPath);
}
if (astNode.type === IMPORT_DECLARATION) {
resolvedPath = (0, _resolve2.default)(astNode.source.raw.replace(/('|")/g, ''), context);
if (!resolvedPath) {
return;
}
if (isNodeModule(resolvedPath)) {
return;
}
if (newNamespaceImportExists(astNode.specifiers)) {
newNamespaceImports.add(resolvedPath);
}
if (newDefaultImportExists(astNode.specifiers)) {
newDefaultImports.add(resolvedPath);
}
astNode.specifiers.forEach(specifier => {
if (specifier.type === IMPORT_DEFAULT_SPECIFIER || specifier.type === IMPORT_NAMESPACE_SPECIFIER) {
return;
}
newImports.set(specifier.imported.name, resolvedPath);
});
}
});
newExportAll.forEach(value => {
if (!oldExportAll.has(value)) {
let imports = oldImportPaths.get(value);
if (typeof imports === 'undefined') {
imports = new Set();
}
imports.add(EXPORT_ALL_DECLARATION);
oldImportPaths.set(value, imports);
let exports = exportList.get(value);
let currentExport;
if (typeof exports !== 'undefined') {
currentExport = exports.get(EXPORT_ALL_DECLARATION);
} else {
exports = new Map();
exportList.set(value, exports);
}
if (typeof currentExport !== 'undefined') {
currentExport.whereUsed.add(file);
} else {
const whereUsed = new Set();
whereUsed.add(file);
exports.set(EXPORT_ALL_DECLARATION, { whereUsed });
}
}
});
oldExportAll.forEach(value => {
if (!newExportAll.has(value)) {
const imports = oldImportPaths.get(value);
imports.delete(EXPORT_ALL_DECLARATION);
const exports = exportList.get(value);
if (typeof exports !== 'undefined') {
const currentExport = exports.get(EXPORT_ALL_DECLARATION);
if (typeof currentExport !== 'undefined') {
currentExport.whereUsed.delete(file);
}
}
}
});
newDefaultImports.forEach(value => {
if (!oldDefaultImports.has(value)) {
let imports = oldImportPaths.get(value);
if (typeof imports === 'undefined') {
imports = new Set();
}
imports.add(IMPORT_DEFAULT_SPECIFIER);
oldImportPaths.set(value, imports);
let exports = exportList.get(value);
let currentExport;
if (typeof exports !== 'undefined') {
currentExport = exports.get(IMPORT_DEFAULT_SPECIFIER);
} else {
exports = new Map();
exportList.set(value, exports);
}
if (typeof currentExport !== 'undefined') {
currentExport.whereUsed.add(file);
} else {
const whereUsed = new Set();
whereUsed.add(file);
exports.set(IMPORT_DEFAULT_SPECIFIER, { whereUsed });
}
}
});
oldDefaultImports.forEach(value => {
if (!newDefaultImports.has(value)) {
const imports = oldImportPaths.get(value);
imports.delete(IMPORT_DEFAULT_SPECIFIER);
const exports = exportList.get(value);
if (typeof exports !== 'undefined') {
const currentExport = exports.get(IMPORT_DEFAULT_SPECIFIER);
if (typeof currentExport !== 'undefined') {
currentExport.whereUsed.delete(file);
}
}
}
});
newNamespaceImports.forEach(value => {
if (!oldNamespaceImports.has(value)) {
let imports = oldImportPaths.get(value);
if (typeof imports === 'undefined') {
imports = new Set();
}
imports.add(IMPORT_NAMESPACE_SPECIFIER);
oldImportPaths.set(value, imports);
let exports = exportList.get(value);
let currentExport;
if (typeof exports !== 'undefined') {
currentExport = exports.get(IMPORT_NAMESPACE_SPECIFIER);
} else {
exports = new Map();
exportList.set(value, exports);
}
if (typeof currentExport !== 'undefined') {
currentExport.whereUsed.add(file);
} else {
const whereUsed = new Set();
whereUsed.add(file);
exports.set(IMPORT_NAMESPACE_SPECIFIER, { whereUsed });
}
}
});
oldNamespaceImports.forEach(value => {
if (!newNamespaceImports.has(value)) {
const imports = oldImportPaths.get(value);
imports.delete(IMPORT_NAMESPACE_SPECIFIER);
const exports = exportList.get(value);
if (typeof exports !== 'undefined') {
const currentExport = exports.get(IMPORT_NAMESPACE_SPECIFIER);
if (typeof currentExport !== 'undefined') {
currentExport.whereUsed.delete(file);
}
}
}
});
newImports.forEach((value, key) => {
if (!oldImports.has(key)) {
let imports = oldImportPaths.get(value);
if (typeof imports === 'undefined') {
imports = new Set();
}
imports.add(key);
oldImportPaths.set(value, imports);
let exports = exportList.get(value);
let currentExport;
if (typeof exports !== 'undefined') {
currentExport = exports.get(key);
} else {
exports = new Map();
exportList.set(value, exports);
}
if (typeof currentExport !== 'undefined') {
currentExport.whereUsed.add(file);
} else {
const whereUsed = new Set();
whereUsed.add(file);
exports.set(key, { whereUsed });
}
}
});
oldImports.forEach((value, key) => {
if (!newImports.has(key)) {
const imports = oldImportPaths.get(value);
imports.delete(key);
const exports = exportList.get(value);
if (typeof exports !== 'undefined') {
const currentExport = exports.get(key);
if (typeof currentExport !== 'undefined') {
currentExport.whereUsed.delete(file);
}
}
}
});
};
return {
'Program:exit': node => {
updateExportUsage(node);
updateImportUsage(node);
checkExportPresence(node);
},
'ExportDefaultDeclaration': node => {
checkUsage(node, IMPORT_DEFAULT_SPECIFIER);
},
'ExportNamedDeclaration': node => {
node.specifiers.forEach(specifier => {
checkUsage(node, specifier.exported.name);
});
if (node.declaration) {
if (node.declaration.type === FUNCTION_DECLARATION || node.declaration.type === CLASS_DECLARATION) {
checkUsage(node, node.declaration.id.name);
}
if (node.declaration.type === VARIABLE_DECLARATION) {
node.declaration.declarations.forEach(declaration => {
checkUsage(node, declaration.id.name);
});
}
}
}
};
}
};
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9ydWxlcy9uby11bnVzZWQtbW9kdWxlcy5qcyJdLCJuYW1lcyI6WyJsaXN0RmlsZXNUb1Byb2Nlc3MiLCJGaWxlRW51bWVyYXRvciIsInJlcXVpcmUiLCJzcmMiLCJlIiwiQXJyYXkiLCJmcm9tIiwiaXRlcmF0ZUZpbGVzIiwiZmlsZVBhdGgiLCJpZ25vcmVkIiwiZmlsZW5hbWUiLCJlMSIsImUyIiwiRVhQT1JUX0RFRkFVTFRfREVDTEFSQVRJT04iLCJFWFBPUlRfTkFNRURfREVDTEFSQVRJT04iLCJFWFBPUlRfQUxMX0RFQ0xBUkFUSU9OIiwiSU1QT1JUX0RFQ0xBUkFUSU9OIiwiSU1QT1JUX05BTUVTUEFDRV9TUEVDSUZJRVIiLCJJTVBPUlRfREVGQVVMVF9TUEVDSUZJRVIiLCJWQVJJQUJMRV9ERUNMQVJBVElPTiIsIkZVTkNUSU9OX0RFQ0xBUkFUSU9OIiwiQ0xBU1NfREVDTEFSQVRJT04iLCJERUZBVUxUIiwicHJlcGFyYXRpb25Eb25lIiwiaW1wb3J0TGlzdCIsIk1hcCIsImV4cG9ydExpc3QiLCJpZ25vcmVkRmlsZXMiLCJTZXQiLCJpc05vZGVNb2R1bGUiLCJwYXRoIiwidGVzdCIsInJlc29sdmVGaWxlcyIsImlnbm9yZUV4cG9ydHMiLCJzcmNGaWxlcyIsInNyY0ZpbGVMaXN0IiwiaWdub3JlZEZpbGVzTGlzdCIsImZvckVhY2giLCJhZGQiLCJmaWx0ZXIiLCJwcmVwYXJlSW1wb3J0c0FuZEV4cG9ydHMiLCJjb250ZXh0IiwiZXhwb3J0QWxsIiwiZmlsZSIsImV4cG9ydHMiLCJpbXBvcnRzIiwiY3VycmVudEV4cG9ydHMiLCJFeHBvcnRzIiwiZ2V0IiwiZGVwZW5kZW5jaWVzIiwicmVleHBvcnRzIiwibG9jYWxJbXBvcnRMaXN0IiwibmFtZXNwYWNlIiwiY3VycmVudEV4cG9ydEFsbCIsInZhbHVlIiwic2V0Iiwia2V5Iiwid2hlcmVVc2VkIiwicmVleHBvcnQiLCJnZXRJbXBvcnQiLCJsb2NhbEltcG9ydCIsImN1cnJlbnRWYWx1ZSIsImxvY2FsIiwiaW1wb3J0ZWRTcGVjaWZpZXJzIiwiaGFzIiwidmFsIiwiY3VycmVudEV4cG9ydCIsImRldGVybWluZVVzYWdlIiwibGlzdFZhbHVlIiwibGlzdEtleSIsImN1cnJlbnRJbXBvcnQiLCJzcGVjaWZpZXIiLCJleHBvcnRTdGF0ZW1lbnQiLCJnZXRTcmMiLCJwcm9jZXNzIiwiY3dkIiwiZG9QcmVwYXJhdGlvbiIsIm5ld05hbWVzcGFjZUltcG9ydEV4aXN0cyIsInNwZWNpZmllcnMiLCJzb21lIiwidHlwZSIsIm5ld0RlZmF1bHRJbXBvcnRFeGlzdHMiLCJtb2R1bGUiLCJtZXRhIiwiZG9jcyIsInVybCIsInNjaGVtYSIsInByb3BlcnRpZXMiLCJkZXNjcmlwdGlvbiIsIm1pbkl0ZW1zIiwiaXRlbXMiLCJtaW5MZW5ndGgiLCJtaXNzaW5nRXhwb3J0cyIsInVudXNlZEV4cG9ydHMiLCJub3QiLCJlbnVtIiwiYW55T2YiLCJyZXF1aXJlZCIsImNyZWF0ZSIsIm9wdGlvbnMiLCJnZXRGaWxlbmFtZSIsImNoZWNrRXhwb3J0UHJlc2VuY2UiLCJub2RlIiwiZXhwb3J0Q291bnQiLCJuYW1lc3BhY2VJbXBvcnRzIiwiZGVsZXRlIiwic2l6ZSIsInJlcG9ydCIsImJvZHkiLCJjaGVja1VzYWdlIiwiZXhwb3J0ZWRWYWx1ZSIsInVwZGF0ZUV4cG9ydFVzYWdlIiwibmV3RXhwb3J0cyIsIm5ld0V4cG9ydElkZW50aWZpZXJzIiwiZGVjbGFyYXRpb24iLCJsZW5ndGgiLCJleHBvcnRlZCIsIm5hbWUiLCJpZCIsImRlY2xhcmF0aW9ucyIsInVwZGF0ZUltcG9ydFVzYWdlIiwib2xkSW1wb3J0UGF0aHMiLCJvbGROYW1lc3BhY2VJbXBvcnRzIiwibmV3TmFtZXNwYWNlSW1wb3J0cyIsIm9sZEV4cG9ydEFsbCIsIm5ld0V4cG9ydEFsbCIsIm9sZERlZmF1bHRJbXBvcnRzIiwibmV3RGVmYXVsdEltcG9ydHMiLCJvbGRJbXBvcnRzIiwibmV3SW1wb3J0cyIsImFzdE5vZGUiLCJyZXNvbHZlZFBh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LEtBQXlCLFdBQTdCLEVBQTBDO0FBQ3hDQSw0QkFBY1QsU0FBZCxDQUF3QmdELE1BQXhCLENBQStCOUQsSUFBL0I7QUFDRDtBQUNGO0FBQ0Y7QUFDRixPQWJEO0FBY0QsS0F0UUQ7O0FBd1FBLFdBQU87QUFDTCxzQkFBZ0IyRCxRQUFRO0FBQ3RCUywwQkFBa0JULElBQWxCO0FBQ0FrQiwwQkFBa0JsQixJQUFsQjtBQUNBRCw0QkFBb0JDLElBQXBCO0FBQ0QsT0FMSTtBQU1MLGtDQUE0QkEsUUFBUTtBQUNsQ08sbUJBQVdQLElBQVgsRUFBaUJwRix3QkFBakI7QUFDRCxPQVJJO0FBU0wsZ0NBQTBCb0YsUUFBUTtBQUNoQ0EsYUFBS3hCLFVBQUwsQ0FBZ0J6QyxPQUFoQixDQUF3QmtDLGFBQWE7QUFDakNzQyxxQkFBV1AsSUFBWCxFQUFpQi9CLFVBQVU2QyxRQUFWLENBQW1CQyxJQUFwQztBQUNILFNBRkQ7QUFHQSxZQUFJZixLQUFLWSxXQUFULEVBQXNCO0FBQ3BCLGNBQ0VaLEtBQUtZLFdBQUwsQ0FBaUJsQyxJQUFqQixLQUEwQjVELG9CQUExQixJQUNBa0YsS0FBS1ksV0FBTCxDQUFpQmxDLElBQWpCLEtBQTBCM0QsaUJBRjVCLEVBR0U7QUFDQXdGLHVCQUFXUCxJQUFYLEVBQWlCQSxLQUFLWSxXQUFMLENBQWlCSSxFQUFqQixDQUFvQkQsSUFBckM7QUFDRDtBQUNELGNBQUlmLEtBQUtZLFdBQUwsQ0FBaUJsQyxJQUFqQixLQUEwQjdELG9CQUE5QixFQUFvRDtBQUNsRG1GLGlCQUFLWSxXQUFMLENBQWlCSyxZQUFqQixDQUE4QmxGLE9BQTlCLENBQXNDNkUsZUFBZTtBQUNuREwseUJBQVdQLElBQVgsRUFBaUJZLFlBQVlJLEVBQVosQ0FBZUQsSUFBaEM7QUFDRCxhQUZEO0FBR0Q7QUFDRjtBQUNGO0FBMUJJLEtBQVA7QUE0QkQ7QUFwaEJjLENBQWpCIiwiZmlsZSI6Im5vLXVudXNlZC1tb2R1bGVzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAZmlsZU92ZXJ2aWV3IEVuc3VyZXMgdGhhdCBtb2R1bGVzIGNvbnRhaW4gZXhwb3J0cyBhbmQvb3IgYWxsXG4gKiBtb2R1bGVzIGFyZSBjb25zdW1lZCB3aXRoaW4gb3RoZXIgbW9kdWxlcy5cbiAqIEBhdXRob3IgUmVuw6kgRmVybWFublxuICovXG5cbmltcG9ydCBFeHBvcnRzIGZyb20gJy4uL0V4cG9ydE1hcCdcbmltcG9ydCByZXNvbHZlIGZyb20gJ2VzbGludC1tb2R1bGUtdXRpbHMvcmVzb2x2ZSdcbmltcG9ydCBkb2NzVXJsIGZyb20gJy4uL2RvY3NVcmwnXG5cbi8vIGVzbGludC9saWIvdXRpbC9nbG9iLXV0aWwgaGFzIGJlZW4gbW92ZWQgdG8gZXNsaW50L2xpYi91dGlsL2dsb2ItdXRpbHMgd2l0aCB2ZXJzaW9uIDUuM1xuLy8gYW5kIGhhcyBiZWVuIG1vdmVkIHRvIGVzbGludC9saWIvY2xpLWVuZ2luZS9maWxlLWVudW1lcmF0b3IgaW4gdmVyc2lvbiA2XG5sZXQgbGlzdEZpbGVzVG9Qcm9jZXNzXG50cnkge1xuICB2YXIgRmlsZUVudW1lcmF0b3IgPSByZXF1aXJlKCdlc2xpbnQvbGliL2NsaS1lbmdpbmUvZmlsZS1lbnVtZXJhdG9yJykuRmlsZUVudW1lcmF0b3JcbiAgbGlzdEZpbGVzVG9Qcm9jZXNzID0gZnVuY3Rpb24gKHNyYykge1xuICAgIHZhciBlID0gbmV3IEZpbGVFbnVtZXJhdG9yKClcbiAgICByZXR1cm4gQXJyYXkuZnJvbShlLml0ZXJhdGVGaWxlcyhzcmMpLCAoeyBmaWxlUGF0aCwgaWdub3JlZCB9KSA9PiAoe1xuICAgICAgaWdub3JlZCxcbiAgICAgIGZpbGVuYW1lOiBmaWxlUGF0aCxcbiAgICB9KSlcbiAgfVxufSBjYXRjaCAoZTEpIHtcbiAgdHJ5IHtcbiAgICBsaXN0RmlsZXNUb1Byb2Nlc3MgPSByZXF1aXJlKCdlc2xpbnQvbGliL3V0aWwvZ2xvYi11dGlscycpLmxpc3RGaWxlc1RvUHJvY2Vzc1xuICB9IGNhdGNoIChlMikge1xuICAgIGxpc3RGaWxlc1RvUHJvY2VzcyA9IHJlcXVpcmUoJ2VzbGludC9saWIvdXRpbC9nbG9iLXV0aWwnKS5saXN0RmlsZXNUb1Byb2Nlc3NcbiAgfVxufVxuXG5jb25zdCBFWFBPUlRfREVGQVVMVF9ERUNMQVJBVElPTiA9ICdFeHBvcnREZWZhdWx0RGVjbGFyYXRpb24nXG5jb25zdCBFWFBPUlRfTkFNRURfREVDTEFSQVRJT04gPSAnRXhwb3J0TmFtZWREZWNsYXJhdGlvbidcbmNvbnN0IEVYUE9SVF9BTExfREVDTEFSQVRJT04gPSAnRXhwb3J0QWxsRGVjbGFyYXRpb24nXG5jb25zdCBJTVBPUlRfREVDTEFSQVRJT04gPSAnSW1wb3J0RGVjbGFyYXRpb24nXG5jb25zdCBJTVBPUlRfTkFNRVNQQUNFX1NQRUNJRklFUiA9ICdJbXBvcnROYW1lc3BhY2VTcGVjaWZpZXInXG5jb25zdCBJTVBPUlRfREVGQVVMVF9TUEVDSUZJRVIgPSAnSW1wb3J0RGVmYXVsdFNwZWNpZmllcidcbmNvbnN0IFZBUklBQkxFX0RFQ0xBUkFUSU9OID0gJ1ZhcmlhYmxlRGVjbGFyYXRpb24nXG5jb25zdCBGVU5DVElPTl9ERUNMQVJBVElPTiA9ICdGdW5jdGlvbkRlY2xhcmF0aW9uJ1xuY29uc3QgQ0xBU1NfREVDTEFSQVRJT04gPSAnQ2xhc3NEZWNsYXJhdGlvbidcbmNvbnN0IERFRkFVTFQgPSAnZGVmYXVsdCdcblxubGV0IHByZXBhcmF0aW9uRG9uZSA9IGZhbHNlXG5jb25zdCBpbXBvcnRMaXN0ID0gbmV3IE1hcCgpXG5jb25zdCBleHBvcnRMaXN0ID0gbmV3IE1hcCgpXG5jb25zdCBpZ25vcmVkRmlsZXMgPSBuZXcgU2V0KClcblxuY29uc3QgaXNOb2RlTW9kdWxlID0gcGF0aCA9PiB7XG4gIHJldHVybiAvXFwvKG5vZGVfbW9kdWxlcylcXC8vLnRlc3QocGF0aClcbn1cblxuLyoqXG4gKiByZWFkIGFsbCBmaWxlcyBtYXRjaGluZyB0aGUgcGF0dGVybnMgaW4gc3JjIGFuZCBpZ25vcmVFeHBvcnRzXG4gKlxuICogcmV0dXJuIGFsbCBmaWxlcyBtYXRjaGluZyBzcmMgcGF0dGVybiwgd2hpY2ggYXJlIG5vdCBtYXRjaGluZyB0aGUgaWdub3JlRXhwb3J0cyBwYXR0ZXJuXG4gKi9cbmNvbnN0IHJlc29sdmVGaWxlcyA9IChzcmMsIGlnbm9yZUV4cG9ydHMpID0+IHtcbiAgY29uc3Qgc3JjRmlsZXMgPSBuZXcgU2V0KClcbiAgY29uc3Qgc3JjRmlsZUxpc3QgPSBsaXN0RmlsZXNUb1Byb2Nlc3Moc3JjKVxuXG4gIC8vIHByZXBhcmUgbGlzdCBvZiBpZ25vcmVkIGZpbGVzXG4gIGNvbnN0IGlnbm9yZWRGaWxlc0xpc3QgPSAgbGlzdEZpbGVzVG9Qcm9jZXNzKGlnbm9yZUV4cG9ydHMpXG4gIGlnbm9yZWRGaWxlc0xpc3QuZm9yRWFjaCgoeyBmaWxlbmFtZSB9KSA9PiBpZ25vcmVkRmlsZXMuYWRkKGZpbGVuYW1lKSlcblxuICAvLyBwcmVwYXJlIGxpc3Qgb2Ygc291cmNlIGZpbGVzLCBkb24ndCBjb25zaWRlciBmaWxlcyBmcm9tIG5vZGVfbW9kdWxlc1xuICBzcmNGaWxlTGlzdC5maWx0ZXIoKHsgZmlsZW5hbWUgfSkgPT4gIWlzTm9kZU1vZHVsZShmaWxlbmFtZSkpLmZvckVhY2goKHsgZmlsZW5hbWUgfSkgPT4ge1xuICAgIHNyY0ZpbGVzLmFkZChmaWxlbmFtZSlcbiAgfSlcbiAgcmV0dXJuIHNyY0ZpbGVzXG59XG5cbi8qKlxuICogcGFyc2UgYWxsIHNvdXJjZSBmaWxlcyBhbmQgYnVpbGQgdXAgMiBtYXBzIGNvbnRhaW5pbmcgdGhlIGV4aXN0aW5nIGltcG9ydHMgYW5kIGV4cG9ydHNcbiAqL1xuY29uc3QgcHJlcGFyZUltcG9ydHNBbmRFeHBvcnRzID0gKHNyY0ZpbGVzLCBjb250ZXh0KSA9PiB7XG4gIGNvbnN0IGV4cG9ydEFsbCA9IG5ldyBNYXAoKVxuICBzcmNGaWxlcy5mb3JFYWNoKGZpbGUgPT4ge1xuICAgIGNvbnN0IGV4cG9ydHMgPSBuZXcgTWFwKClcbiAgICBjb25zdCBpbXBvcnRzID0gbmV3IE1hcCgpXG4gICAgY29uc3QgY3VycmVudEV4cG9ydHMgPSBFeHBvcnRzLmdldChmaWxlLCBjb250ZXh0KVxuICAgIGlmIChjdXJyZW50RXhwb3J0cykge1xuICAgICAgY29uc3QgeyBkZXBlbmRlbmNpZXMsIHJlZXhwb3J0cywgaW1wb3J0czogbG9jYWxJbXBvcnRMaXN0LCBuYW1lc3BhY2UgIH0gPSBjdXJyZW50RXhwb3J0c1xuXG4gICAgICAvLyBkZXBlbmRlbmNpZXMgPT09IGV4cG9ydCAqIGZyb20gXG4gICAgICBjb25zdCBjdXJyZW50RXhwb3J0QWxsID0gbmV3IFNldCgpXG4gICAgICBkZXBlbmRlbmNpZXMuZm9yRWFjaCh2YWx1ZSA9PiB7XG4gICAgICAgIGN1cnJlbnRFeHBvcnRBbGwuYWRkKHZhbHVlKCkucGF0aClcbiAgICAgIH0pXG4gICAgICBleHBvcnRBbGwuc2V0KGZpbGUsIGN1cnJlbnRFeHBvcnRBbGwpXG5cbiAgICAgIHJlZXhwb3J0cy5mb3JFYWNoKCh2YWx1ZSwga2V5KSA9PiB7XG4gICAgICAgIGlmIChrZXkgPT09IERFRkFVTFQpIHtcbiAgICAgICAgICBleHBvcnRzLnNldChJTVBPUlRfREVGQVVMVF9TUEVDSUZJRVIsIHsgd2hlcmVVc2VkOiBuZXcgU2V0KCkgfSlcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBleHBvcnRzLnNldChrZXksIHsgd2hlcmVVc2VkOiBuZXcgU2V0KCkgfSlcbiAgICAgICAgfVxuICAgICAgICBjb25zdCByZWV4cG9ydCA9ICB2YWx1ZS5nZXRJbXBvcnQoKVxuICAgICAgICBpZiAoIXJlZXhwb3J0KSB7XG4gICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cbiAgICAgICAgbGV0IGxvY2FsSW1wb3J0ID0gaW1wb3J0cy5nZXQocmVleHBvcnQucGF0aClcbiAgICAgICAgbGV0IGN1cnJlbnRWYWx1ZVxuICAgICAgICBpZiAodmFsdWUubG9jYWwgPT09IERFRkFVTFQpIHtcbiAgICAgICAgICBjdXJyZW50VmFsdWUgPSBJTVBPUlRfREVGQVVMVF9TUEVDSUZJRVJcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjdXJyZW50VmFsdWUgPSB2YWx1ZS5sb2NhbFxuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2YgbG9jYWxJbXBvcnQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgbG9jYWxJbXBvcnQgPSBuZXcgU2V0KFsuLi5sb2NhbEltcG9ydCwgY3VycmVudFZhbHVlXSlcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBsb2NhbEltcG9ydCA9IG5ldyBTZXQoW2N1cnJlbnRWYWx1ZV0pXG4gICAgICAgIH1cbiAgICAgICAgaW1wb3J0cy5zZXQocmVleHBvcnQucGF0aCwgbG9jYWxJbXBvcnQpXG4gICAgICB9KVxuXG4gICAgICBsb2NhbEltcG9ydExpc3QuZm9yRWFjaCgodmFsdWUsIGtleSkgPT4ge1xuICAgICAgICBpZiAoaXNOb2RlTW9kdWxlKGtleSkpIHtcbiAgICAgICAgICByZXR1cm5cbiAgICAgICAgfVxuICAgICAgICBpbXBvcnRzLnNldChrZXksIHZhbHVlLmltcG9ydGVkU3BlY2lmaWVycylcbiAgICAgIH0pXG4gICAgICBpbXBvcnRMaXN0LnNldChmaWxlLCBpbXBvcnRzKVxuXG4gICAgICAvLyBidWlsZCB1cCBleHBvcnQgbGlzdCBvbmx5LCBpZiBmaWxlIGlzIG5vdCBpZ25vcmVkXG4gICAgICBpZiAoaWdub3JlZEZpbGVzLmhhcyhmaWxlKSkge1xuICAgICAgICByZXR1cm5cbiAgICAgIH1cbiAgICAgIG5hbWVzcGFjZS5mb3JFYWNoKCh2YWx1ZSwga2V5KSA9PiB7XG4gICAgICAgIGlmIChrZXkgPT09IERFRkFVTFQpIHtcbiAgICAgICAgICBleHBvcnRzLnNldChJTVBPUlRfREVGQVVMVF9TUEVDSUZJRVIsIHsgd2hlcmVVc2VkOiBuZXcgU2V0KCkgfSlcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBleHBvcnRzLnNldChrZXksIHsgd2hlcmVVc2VkOiBuZXcgU2V0KCkgfSlcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICB9XG4gICAgZXhwb3J0cy5zZXQoRVhQT1JUX0FMTF9ERUNMQVJBVElPTiwgeyB3aGVyZVVzZWQ6IG5ldyBTZXQoKSB9KVxuICAgIGV4cG9ydHMuc2V0KElNUE9SVF9OQU1FU1BBQ0VfU1BFQ0lGSUVSLCB7IHdoZXJlVXNlZDogbmV3IFNldCgpIH0pXG4gICAgZXhwb3J0TGlzdC5zZXQoZmlsZSwgZXhwb3J0cylcbiAgfSlcbiAgZXhwb3J0QWxsLmZvckVhY2goKHZhbHVlLCBrZXkpID0+IHtcbiAgICB2YWx1ZS5mb3JFYWNoKHZhbCA9PiB7XG4gICAgICBjb25zdCBjdXJyZW50RXhwb3J0cyA9IGV4cG9ydExpc3QuZ2V0KHZhbClcbiAgICAgIGNvbnN0IGN1cnJlbnRFeHBvcnQgPSBjdXJyZW50RXhwb3J0cy5nZXQoRVhQT1JUX0FMTF9ERUNMQVJBVElPTilcbiAgICAgIGN1cnJlbnRFeHBvcnQud2hlcmVVc2VkLmFkZChrZXkpXG4gICAgfSlcbiAgfSlcbn1cblxuLyoqXG4gKiB0cmF2ZXJzZSB0aHJvdWdoIGFsbCBpbXBvcnRzIGFuZCBhZGQgdGhlIHJlc3BlY3RpdmUgcGF0aCB0byB0aGUgd2hlcmVVc2VkLWxpc3QgXG4gKiBvZiB0aGUgY29ycmVzcG9uZGluZyBleHBvcnRcbiAqL1xuY29uc3QgZGV0ZXJtaW5lVXNhZ2UgPSAoKSA9PiB7XG4gIGltcG9ydExpc3QuZm9yRWFjaCgobGlzdFZhbHVlLCBsaXN0S2V5KSA9PiB7XG4gICAgbGlzdFZhbHVlLmZvckVhY2goKHZhbHVlLCBrZXkpID0+IHtcbiAgICAgIGNvbnN0IGV4cG9ydHMgPSBleHBvcnRMaXN0LmdldChrZXkpXG4gICAgICBpZiAodHlwZW9mIGV4cG9ydHMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHZhbHVlLmZvckVhY2goY3VycmVudEltcG9ydCA9PiB7XG4gICAgICAgICAgbGV0IHNwZWNpZmllclxuICAgICAgICAgIGlmIChjdXJyZW50SW1wb3J0ID09PSBJTVBPUlRfTkFNRVNQQUNFX1NQRUNJRklFUikge1xuICAgICAgICAgICAgc3BlY2lmaWVyID0gSU1QT1JUX05BTUVTUEFDRV9TUEVDSUZJRVJcbiAgICAgICAgICB9IGVsc2UgaWYgKGN1cnJlbnRJbXBvcnQgPT09IElNUE9SVF9ERUZBVUxUX1NQRUNJRklFUikge1xuICAgICAgICAgICAgc3BlY2lmaWVyID0gSU1QT1JUX0RFRkFVTFRfU1BFQ0lGSUVSXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNwZWNpZmllciA9IGN1cnJlbnRJbXBvcnRcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHR5cGVvZiBzcGVjaWZpZXIgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBjb25zdCBleHBvcnRTdGF0ZW1lbnQgPSBleHBvcnRzLmdldChzcGVjaWZpZXIpXG4gICAgICAgICAgICBpZiAodHlwZW9mIGV4cG9ydFN0YXRlbWVudCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgY29uc3QgeyB3aGVyZVVzZWQgfSA9IGV4cG9ydFN0YXRlbWVudFxuICAgICAgICAgICAgICB3aGVyZVVzZWQuYWRkKGxpc3RLZXkpXG4gICAgICAgICAgICAgIGV4cG9ydHMuc2V0KHNwZWNpZmllciwgeyB3aGVyZVVzZWQgfSlcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICB9XG4gICAgfSlcbiAgfSlcbn1cblxuY29uc3QgZ2V0U3JjID0gc3JjID0+IHtcbiAgaWYgKHNyYykge1xuICAgIHJldHVybiBzcmNcbiAgfVxuICByZXR1cm4gW3Byb2Nlc3MuY3dkKCldXG59XG5cbi8qKlxuICogcHJlcGFyZSB0aGUgbGlzdHMgb2YgZXhpc3RpbmcgaW1wb3J0cyBhbmQgZXhwb3J0cyAtIHNob3VsZCBvbmx5IGJlIGV4ZWN1dGVkIG9uY2UgYXRcbiAqIHRoZSBzdGFydCBvZiBhIG5ldyBlc2xpbnQgcnVuXG4gKi9cbmNvbnN0IGRvUHJlcGFyYXRpb24gPSAoc3JjLCBpZ25vcmVFeHBvcnRzLCBjb250ZXh0KSA9PiB7XG4gIGNvbnN0IHNyY0ZpbGVzID0gcmVzb2x2ZUZpbGVzKGdldFNyYyhzcmMpLCBpZ25vcmVFeHBvcnRzKVxuICBwcmVwYXJlSW1wb3J0c0FuZEV4cG9ydHMoc3JjRmlsZXMsIGNvbnRleHQpXG4gIGRldGVybWluZVVzYWdlKClcbiAgcHJlcGFyYXRpb25Eb25lID0gdHJ1ZVxufVxuXG5jb25zdCBuZXdOYW1lc3BhY2VJbXBvcnRFeGlzdHMgPSBzcGVjaWZpZXJzID0+XG4gIHNwZWNpZmllcnMuc29tZSgoeyB0eXBlIH0pID0+IHR5cGUgPT09IElNUE9SVF9OQU1FU1BBQ0VfU1BFQ0lGSUVSKVxuXG5jb25zdCBuZXdEZWZhdWx0SW1wb3J0RXhpc3RzID0gc3BlY2lmaWVycyA9PlxuICBzcGVjaWZpZXJzLnNvbWUoKHsgdHlwZSB9KSA9PiB0eXBlID09PSBJTVBPUlRfREVGQVVMVF9TUEVDSUZJRVIpXG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBtZXRhOiB7XG4gICAgZG9jczogeyB1cmw6IGRvY3NVcmwoJ25vLXVudXNlZC1tb2R1bGVzJykgfSxcbiAgICBzY2hlbWE6IFt7XG4gICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgIHNyYzoge1xuICAgICAgICAgIGRlc2NyaXB0aW9uOiAnZmlsZXMvcGF0aHMgdG8gYmUgYW5hbHl6ZWQgKG9ubHkgZm9yIHVudXNlZCBleHBvcnRzKScsXG4gICAgICAgICAgdHlwZTogJ2FycmF5JyxcbiAgICAgICAgICBtaW5JdGVtczogMSxcbiAgICAgICAgICBpdGVtczoge1xuICAgICAgICAgICAgdHlwZTogJ3N0cmluZycsXG4gICAgICAgICAgICBtaW5MZW5ndGg6IDEsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgaWdub3JlRXhwb3J0czoge1xuICAgICAgICAgIGRlc2NyaXB0aW9uOlxuICAgICAgICAgICAgJ2ZpbGVzL3BhdGhzIGZvciB3aGljaCB1bnVzZWQgZXhwb3J0cyB3aWxsIG5vdCBiZSByZXBvcnRlZCAoZS5nIG1vZHVsZSBlbnRyeSBwb2ludHMpJyxcbiAgICAgICAgICB0eXBlOiAnYXJyYXknLFxuICAgICAgICAgIG1pbkl0ZW1zOiAxLFxuICAgICAgICAgIGl0ZW1zOiB7XG4gICAgICAgICAgICB0eXBlOiAnc3RyaW5nJyxcbiAgICAgICAgICAgIG1pbkxlbmd0aDogMSxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICBtaXNzaW5nRXhwb3J0czoge1xuICAgICAgICAgIGRlc2NyaXB0aW9uOiAncmVwb3J0IG1vZHVsZXMgd2l0aG91dCBhbnkgZXhwb3J0cycsXG4gICAgICAgICAgdHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICB9LFxuICAgICAgICB1bnVzZWRFeHBvcnRzOiB7XG4gICAgICAgICAgZGVzY3JpcHRpb246ICdyZXBvcnQgZXhwb3J0cyB3aXRob3V0IGFueSB1c2FnZScsXG4gICAgICAgICAgdHlwZTogJ2Jvb2xlYW4nLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIG5vdDoge1xuICAgICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgdW51c2VkRXhwb3J0czogeyBlbnVtOiBbZmFsc2VdIH0sXG4gICAgICAgICAgbWlzc2luZ0V4cG9ydHM6IHsgZW51bTogW2ZhbHNlXSB9LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIGFueU9mOlt7XG4gICAgICAgIG5vdDoge1xuICAgICAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgICAgIHVudXNlZEV4cG9ydHM6IHsgZW51bTogW3RydWVdIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgcmVxdWlyZWQ6IFsnbWlzc2luZ0V4cG9ydHMnXSxcbiAgICAgIH0sIHtcbiAgICAgICAgbm90OiB7XG4gICAgICAgICAgcHJvcGVydGllczoge1xuICAgICAgICAgICAgbWlzc2luZ0V4cG9ydHM6IHsgZW51bTogW3RydWVdIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgcmVxdWlyZWQ6IFsndW51c2VkRXhwb3J0cyddLFxuICAgICAgfSwge1xuICAgICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgdW51c2VkRXhwb3J0czogeyBlbnVtOiBbdHJ1ZV0gfSxcbiAgICAgICAgfSxcbiAgICAgICAgcmVxdWlyZWQ6IFsndW51c2VkRXhwb3J0cyddLFxuICAgICAgfSwge1xuICAgICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgbWlzc2luZ0V4cG9ydHM6IHsgZW51bTogW3RydWVdIH0sXG4gICAgICAgIH0sXG4gICAgICAgIHJlcXVpcmVkOiBbJ21pc3NpbmdFeHBvcnRzJ10sXG4gICAgICB9XSxcbiAgICB9XSxcbiAgfSxcblxuICBjcmVhdGU6IGNvbnRleHQgPT4ge1xuICAgIGNvbnN0IHtcbiAgICAgIHNyYyxcbiAgICAgIGlnbm9yZUV4cG9ydHMgPSBbXSxcbiAgICAgIG1pc3NpbmdFeHBvcnRzLFxuICAgICAgdW51c2VkRXhwb3J0cyxcbiAgICB9ID0gY29udGV4dC5vcHRpb25zWzBdIHx8IHt9XG5cbiAgICBpZiAodW51c2VkRXhwb3J0cyAmJiAhcHJlcGFyYXRpb25Eb25lKSB7XG4gICAgICBkb1ByZXBhcmF0aW9uKHNyYywgaWdub3JlRXhwb3J0cywgY29udGV4dClcbiAgICB9XG5cbiAgICBjb25zdCBmaWxlID0gY29udGV4dC5nZXRGaWxlbmFtZSgpXG5cbiAgICBjb25zdCBjaGVja0V4cG9ydFByZXNlbmNlID0gbm9kZSA9PiB7XG4gICAgICBpZiAoIW1pc3NpbmdFeHBvcnRzKSB7XG4gICAgICAgIHJldHVyblxuICAgICAgfVxuXG4gICAgICBpZiAoaWdub3JlZEZpbGVzLmhhcyhmaWxlKSkge1xuICAgICAgICByZXR1cm5cbiAgICAgIH1cblxuICAgICAgY29uc3QgZXhwb3J0Q291bnQgPSBleHBvcnRMaXN0LmdldChmaWxlKVxuICAgICAgY29uc3QgZXhwb3J0QWxsID0gZXhwb3J0Q291bnQuZ2V0KEVYUE9SVF9BTExfREVDTEFSQVRJT04pXG4gICAgICBjb25zdCBuYW1lc3BhY2VJbXBvcnRzID0gZXhwb3J0Q291bnQuZ2V0KElNUE9SVF9OQU1FU1BBQ0VfU1BFQ0lGSUVSKVxuXG4gICAgICBleHBvcnRDb3VudC5kZWxldGUoRVhQT1JUX0FMTF9ERUNMQVJBVElPTilcbiAgICAgIGV4cG9ydENvdW50LmRlbGV0ZShJTVBPUlRfTkFNRVNQQUNFX1NQRUNJRklFUilcbiAgICAgIGlmIChtaXNzaW5nRXhwb3J0cyAmJiBleHBvcnRDb3VudC5zaXplIDwgMSkge1xuICAgICAgICAvLyBub2RlLmJvZHlbMF0gPT09ICd1bmRlZmluZWQnIG9ubHkgaGFwcGVucywgaWYgZXZlcnl0aGluZyBpcyBjb21tZW50ZWQgb3V0IGluIHRoZSBmaWxlXG4gICAgICAgIC8vIGJlaW5nIGxpbnRlZFxuICAgICAgICBjb250ZXh0LnJlcG9ydChub2RlLmJvZHlbMF0gPyBub2RlLmJvZHlbMF0gOiBub2RlLCAnTm8gZXhwb3J0cyBmb3VuZCcpXG4gICAgICB9XG4gICAgICBleHBvcnRDb3VudC5zZXQoRVhQT1JUX0FMTF9ERUNMQVJBVElPTiwgZXhwb3J0QWxsKVxuICAgICAgZXhwb3J0Q291bnQuc2V0KElNUE9SVF9OQU1FU1BBQ0VfU1BFQ0lGSUVSLCBuYW1lc3BhY2VJbXBvcnRzKVxuICAgIH1cblxuICAgIGNvbnN0IGNoZWNrVXNhZ2UgPSAobm9kZSwgZXhwb3J0ZWRWYWx1ZSkgPT4ge1xuICAgICAgaWYgKCF1bnVzZWRFeHBvcnRzKSB7XG4gICAgICAgIHJldHVyblxuICAgICAgfVxuXG4gICAgICBpZiAoaWdub3JlZEZpbGVzLmhhcyhmaWxlKSkge1xuICAgICAgICByZXR1cm5cbiAgICAgIH1cblxuICAgICAgLy8gcmVmcmVzaCBsaXN0IG9mIHNvdXJjZSBmaWxlc1xuICAgICAgY29uc3Qgc3JjRmlsZXMgPSByZXNvbHZlRmlsZXMoZ2V0U3JjKHNyYyksIGlnbm9yZUV4cG9ydHMpXG5cbiAgICAgIC8vIG1ha2Ugc3VyZSBmaWxlIHRvIGJlIGxpbnRlZCBpcyBpbmNsdWRlZCBpbiBzb3VyY2UgZmlsZXNcbiAgICAgIGlmICghc3JjRmlsZXMuaGFzKGZpbGUpKSB7XG4gICAgICAgIHJldHVyblxuICAgICAgfVxuXG4gICAgICBleHBvcnRzID0gZXhwb3J0TGlzdC5nZXQoZmlsZSlcblxuICAgICAgLy8gc3BlY2lhbCBjYXNlOiBleHBvcnQgKiBmcm9tIFxuICAgICAgY29uc3QgZXhwb3J0QWxsID0gZXhwb3J0cy5nZXQoRVhQT1JUX0FMTF9ERUNMQVJBVElPTilcbiAgICAgIGlmICh0eXBlb2YgZXhwb3J0QWxsICE9PSAndW5kZWZpbmVkJyAmJiBleHBvcnRlZFZhbHVlICE9PSBJTVBPUlRfREVGQVVMVF9TUEVDSUZJRVIpIHtcbiAgICAgICAgaWYgKGV4cG9ydEFsbC53aGVyZVVzZWQuc2l6ZSA+IDApIHtcbiAgICAgICAgICByZXR1cm5cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBzcGVjaWFsIGNhc2U6IG5hbWVzcGFjZSBpbXBvcnRcbiAgICAgIGNvbnN0IG5hbWVzcGFjZUltcG9ydHMgPSBleHBvcnRzLmdldChJTVBPUlRfTkFNRVNQQUNFX1NQRUNJRklFUilcbiAgICAgIGlmICh0eXBlb2YgbmFtZXNwYWNlSW1wb3J0cyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgaWYgKG5hbWVzcGFjZUltcG9ydHMud2hlcmVVc2VkLnNpemUgPiAwKSB7XG4gICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3QgZXhwb3J0U3RhdGVtZW50ID0gZXhwb3J0cy5nZXQoZXhwb3J0ZWRWYWx1ZSlcblxuICAgICAgY29uc3QgdmFsdWUgPSBleHBvcnRlZFZhbHVlID09PSBJTVBPUlRfREVGQVVMVF9TUEVDSUZJRVIgPyBERUZBVUxUIDogZXhwb3J0ZWRWYWx1ZVxuXG4gICAgICBpZiAodHlwZW9mIGV4cG9ydFN0YXRlbWVudCAhPT0gJ3VuZGVmaW5lZCcpe1xuICAgICAgICBpZiAoZXhwb3J0U3RhdGVtZW50LndoZXJlVXNlZC5zaXplIDwgMSkge1xuICAgICAgICAgIGNvbnRleHQucmVwb3J0KFxuICAgICAgICAgICAgbm9kZSxcbiAgICAgICAgICAgIGBleHBvcnRlZCBkZWNsYXJhdGlvbiAnJHt2YWx1ZX0nIG5vdCB1c2VkIHdpdGhpbiBvdGhlciBtb2R1bGVzYFxuICAgICAgICAgIClcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29udGV4dC5yZXBvcnQoXG4gICAgICAgICAgbm9kZSxcbiAgICAgICAgICBgZXhwb3J0ZWQgZGVjbGFyYXRpb24gJyR7dmFsdWV9JyBub3QgdXNlZCB3aXRoaW4gb3RoZXIgbW9kdWxlc2BcbiAgICAgICAgKVxuICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIG9ubHkgdXNlZnVsIGZvciB0b29scyBsaWtlIHZzY29kZS1lc2xpbnRcbiAgICAgKiBcbiAgICAgKiB1cGRhdGUgbGlzdHMgb2YgZXhpc3RpbmcgZXhwb3J0cyBkdXJpbmcgcnVudGltZVxuICAgICAqL1xuICAgIGNvbnN0IHVwZGF0ZUV4cG9ydFVzYWdlID0gbm9kZSA9PiB7XG4gICAgICBpZiAoaWdub3JlZEZpbGVzLmhhcyhmaWxlKSkge1xuICAgICAgICByZXR1cm5cbiAgICAgIH1cblxuICAgICAgbGV0IGV4cG9ydHMgPSBleHBvcnRMaXN0LmdldChmaWxlKVxuXG4gICAgICAvLyBuZXcgbW9kdWxlIGhhcyBiZWVuIGNyZWF0ZWQgZHVyaW5nIHJ1bnRpbWVcbiAgICAgIC8vIGluY2x1ZGUgaXQgaW4gZnVydGhlciBwcm9jZXNzaW5nXG4gICAgICBpZiAodHlwZW9mIGV4cG9ydHMgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIGV4cG9ydHMgPSBuZXcgTWFwKClcbiAgICAgIH1cblxuICAgICAgY29uc3QgbmV3RXhwb3J0cyA9IG5ldyBNYXAoKVxuICAgICAgY29uc3QgbmV3RXhwb3J0SWRlbnRpZmllcnMgPSBuZXcgU2V0KClcblxuICAgICAgbm9kZS5ib2R5LmZvckVhY2goKHsgdHlwZSwgZGVjbGFyYXRpb24sIHNwZWNpZmllcnMgfSkgPT4ge1xuICAgICAgICBpZiAodHlwZSA9PT0gRVhQT1JUX0RFRkFVTFRfREVDTEFSQVRJT04pIHtcbiAgICAgICAgICBuZXdFeHBvcnRJZGVudGlmaWVycy5hZGQoSU1QT1JUX0RFRkFVTFRfU1BFQ0lGSUVSKVxuICAgICAgICB9IFxuICAgICAgICBpZiAodHlwZSA9PT0gRVhQT1JUX05BTUVEX0RFQ0xBUkFUSU9OKSB7XG4gICAgICAgICAgaWYgKHNwZWNpZmllcnMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgc3BlY2lmaWVycy5mb3JFYWNoKHNwZWNpZmllciA9PiB7XG4gICAgICAgICAgICAgIGlmIChzcGVjaWZpZXIuZXhwb3J0ZWQpIHtcbiAgICAgICAgICAgICAgICBuZXdFeHBvcnRJZGVudGlmaWVycy5hZGQoc3BlY2lmaWVyLmV4cG9ydGVkLm5hbWUpXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgfVxuICAgICAgICAgIGlmIChkZWNsYXJhdGlvbikge1xuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICBkZWNsYXJhdGlvbi50eXBlID09PSBGVU5DVElPTl9ERUNMQVJBVElPTiB8fFxuICAgICAgICAgICAgICBkZWNsYXJhdGlvbi50eXBlID09PSBDTEFTU19ERUNMQVJBVElPTlxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgIG5ld0V4cG9ydElkZW50aWZpZXJzLmFkZChkZWNsYXJhdGlvbi5pZC5uYW1lKVxuICAgICAgICAgICAgfSAgIFxuICAgICAgICAgICAgaWYgKGRlY2xhcmF0aW9uLnR5cGUgPT09IFZBUklBQkxFX0RFQ0xBUkFUSU9OKSB7XG4gICAgICAgICAgICAgIGRlY2xhcmF0aW9uLmRlY2xhcmF0aW9ucy5mb3JFYWNoKCh7IGlkIH0pID0+IHtcbiAgICAgICAgICAgICAgICBuZXdFeHBvcnRJZGVudGlmaWVycy5hZGQoaWQubmFtZSlcbiAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pXG5cbiAgICAgIC8vIG9sZCBleHBvcnRzIGV4aXN0IHdpdGhpbiBsaXN0IG9mIG5ldyBleHBvcnRzIGlkZW50aWZpZXJzOiBhZGQgdG8gbWFwIG9mIG5ldyBleHBvcnRzXG4gICAgICBleHBvcnRzLmZvckVhY2goKHZhbHVlLCBrZXkpID0+IHtcbiAgICAgICAgaWYgKG5ld0V4cG9ydElkZW50aWZpZXJzLmhhcyhrZXkpKSB7XG4gICAgICAgICAgbmV3RXhwb3J0cy5zZXQoa2V5LCB2YWx1ZSlcbiAgICAgICAgfVxuICAgICAgfSlcblxuICAgICAgLy8gbmV3IGV4cG9ydCBpZGVudGlmaWVycyBhZGRlZDogYWRkIHRvIG1hcCBvZiBuZXcgZXhwb3J0c1xuICAgICAgbmV3RXhwb3J0SWRlbnRpZmllcnMuZm9yRWFjaChrZXkgPT4ge1xuICAgICAgICBpZiAoIWV4cG9ydHMuaGFzKGtleSkpIHtcbiAgICAgICAgICBuZXdFeHBvcnRzLnNldChrZXksIHsgd2hlcmVVc2VkOiBuZXcgU2V0KCkgfSlcbiAgICAgICAgfVxuICAgICAgfSlcblxuICAgICAgLy8gcHJlc2VydmUgaW5mb3JtYXRpb24gYWJvdXQgbmFtZXNwYWNlIGltcG9ydHNcbiAgICAgIGxldCBleHBvcnRBbGwgPSBleHBvcnRzLmdldChFWFBPUlRfQUxMX0RFQ0xBUkFUSU9OKVxuICAgICAgbGV0IG5hbWVzcGFjZUltcG9ydHMgPSBleHBvcnRzLmdldChJTVBPUlRfTkFNRVNQQUNFX1NQRUNJRklFUilcblxuICAgICAgaWYgKHR5cGVvZiBuYW1lc3BhY2VJbXBvcnRzID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICBuYW1lc3BhY2VJbXBvcnRzID0geyB3aGVyZVVzZWQ6IG5ldyBTZXQoKSB9XG4gICAgICB9XG5cbiAgICAgIG5ld0V4cG9ydHMuc2V0KEVYUE9SVF9BTExfREVDTEFSQVRJT04sIGV4cG9ydEFsbClcbiAgICAgIG5ld0V4cG9ydHMuc2V0KElNUE9SVF9OQU1FU1BBQ0VfU1BFQ0lGSUVSLCBuYW1lc3BhY2VJbXBvcnRzKVxuICAgICAgZXhwb3J0TGlzdC5zZXQoZmlsZSwgbmV3RXhwb3J0cylcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBvbmx5IHVzZWZ1bCBmb3IgdG9vbHMgbGlrZSB2c2NvZGUtZXNsaW50XG4gICAgICogXG4gICAgICogdXBkYXRlIGxpc3RzIG9mIGV4aXN0aW5nIGltcG9ydHMgZHVyaW5nIHJ1bnRpbWVcbiAgICAgKi9cbiAgICBjb25zdCB1cGRhdGVJbXBvcnRVc2FnZSA9IG5vZGUgPT4ge1xuICAgICAgaWYgKCF1bnVzZWRFeHBvcnRzKSB7XG4gICAgICAgIHJldHVyblxuICAgICAgfVxuXG4gICAgICBsZXQgb2xkSW1wb3J0UGF0aHMgPSBpbXBvcnRMaXN0LmdldChmaWxlKVxuICAgICAgaWYgKHR5cGVvZiBvbGRJbXBvcnRQYXRocyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgb2xkSW1wb3J0UGF0aHMgPSBuZXcgTWFwKClcbiAgICAgIH1cblxuICAgICAgY29uc3Qgb2xkTmFtZXNwYWNlSW1wb3J0cyA9IG5ldyBTZXQoKVxuICAgICAgY29uc3QgbmV3TmFtZXNwYWNlSW1wb3J0cyA9IG5ldyBTZXQoKVxuXG4gICAgICBjb25zdCBvbGRFeHBvcnRBbGwgPSBuZXcgU2V0KClcbiAgICAgIGNvbnN0IG5ld0V4cG9ydEFsbCA9IG5ldyBTZXQoKVxuXG4gICAgICBjb25zdCBvbGREZWZhdWx0SW1wb3J0cyA9IG5ldyBTZXQoKVxuICAgICAgY29uc3QgbmV3RGVmYXVsdEltcG9ydHMgPSBuZXcgU2V0KClcblxuICAgICAgY29uc3Qgb2xkSW1wb3J0cyA9IG5ldyBNYXAoKVxuICAgICAgY29uc3QgbmV3SW1wb3J0cyA9IG5ldyBNYXAoKVxuICAgICAgb2xkSW1wb3J0UGF0aHMuZm9yRWFjaCgodmFsdWUsIGtleSkgPT4ge1xuICAgICAgICBpZiAodmFsdWUuaGFzKEVYUE9SVF9BTExfREVDTEFSQVRJT04pKSB7XG4gICAgICAgICAgb2xkRXhwb3J0QWxsLmFkZChrZXkpXG4gICAgICAgIH1cbiAgICAgICAgaWYgKHZhbHVlLmhhcyhJTVBPUlRfTkFNRVNQQUNFX1NQRUNJRklFUikpIHtcbiAgICAgICAgICBvbGROYW1lc3BhY2VJbXBvcnRzLmFkZChrZXkpXG4gICAgICAgIH1cbiAgICAgICAgaWYgKHZhbHVlLmhhcyhJTVBPUlRfREVGQVVMVF9TUEVDSUZJRVIpKSB7XG4gICAgICAgICAgb2xkRGVmYXVsdEltcG9ydHMuYWRkKGtleSlcbiAgICAgICAgfVxuICAgICAgICB2YWx1ZS5mb3JFYWNoKHZhbCA9PiB7XG4gICAgICAgICAgaWYgKHZhbCAhPT0gSU1QT1JUX05BTUVTUEFDRV9TUEVDSUZJRVIgJiZcbiAgICAgICAgICAgICAgdmFsICE9PSBJTVBPUlRfREVGQVVMVF9TUEVDSUZJRVIpIHtcbiAgICAgICAgICAgICAgIG9sZEltcG9ydHMuc2V0KHZhbCwga2V5KVxuICAgICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgIH0pXG5cbiAgICAgIG5vZGUuYm9keS5mb3JFYWNoKGFzdE5vZGUgPT4ge1xuICAgICAgICBsZXQgcmVzb2x2ZWRQYXRoXG5cbiAgICAgICAgLy8gc3VwcG9ydCBmb3IgZXhwb3J0IHsgdmFsdWUgfSBmcm9tICdtb2R1bGUnXG4gICAgICAgIGlmIChhc3ROb2RlLnR5cGUgPT09IEVYUE9SVF9OQU1FRF9ERUNMQVJBVElPTikge1xuICAgICAgICAgIGlmIChhc3ROb2RlLnNvdXJjZSkge1xuICAgICAgICAgICAgcmVzb2x2ZWRQYXRoID0gcmVzb2x2ZShhc3ROb2RlLnNvdXJjZS5yYXcucmVwbGFjZSgvKCd8XCIpL2csICcnKSwgY29udGV4dClcbiAgICAgICAgICAgIGFzdE5vZGUuc3BlY2lmaWVycy5mb3JFYWNoKHNwZWNpZmllciA9PiB7XG4gICAgICAgICAgICAgIGxldCBuYW1lXG4gICAgICAgICAgICAgIGlmIChzcGVjaWZpZXIuZXhwb3J0ZWQubmFtZSA9PT0gREVGQVVMVCkge1xuICAgICAgICAgICAgICAgIG5hbWUgPSBJTVBPUlRfREVGQVVMVF9TUEVDSUZJRVJcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBuYW1lID0gc3BlY2lmaWVyLmxvY2FsLm5hbWVcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBuZXdJbXBvcnRzLnNldChuYW1lLCByZXNvbHZlZFBhdGgpXG4gICAgICAgICAgICB9KVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChhc3ROb2RlLnR5cGUgPT09IEVYUE9SVF9BTExfREVDTEFSQVRJT04pIHtcbiAgICAgICAgICByZXNvbHZlZFBhdGggPSByZXNvbHZlKGFzdE5vZGUuc291cmNlLnJhdy5yZXBsYWNlKC8oJ3xcIikvZywgJycpLCBjb250ZXh0KVxuICAgICAgICAgIG5ld0V4cG9ydEFsbC5hZGQocmVzb2x2ZWRQYXRoKVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGFzdE5vZGUudHlwZSA9PT0gSU1QT1JUX0RFQ0xBUkFUSU9OKSB7XG4gICAgICAgICAgcmVzb2x2ZWRQYXRoID0gcmVzb2x2ZShhc3ROb2RlLnNvdXJjZS5yYXcucmVwbGFjZSgvKCd8XCIpL2csICcnKSwgY29udGV4dClcbiAgICAgICAgICBpZiAoIXJlc29sdmVkUGF0aCkge1xuICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKGlzTm9kZU1vZHVsZShyZXNvbHZlZFBhdGgpKSB7XG4gICAgICAgICAgICByZXR1cm5cbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAobmV3TmFtZXNwYWNlSW1wb3J0RXhpc3RzKGFzdE5vZGUuc3BlY2lmaWVycykpIHtcbiAgICAgICAgICAgIG5ld05hbWVzcGFjZUltcG9ydHMuYWRkKHJlc29sdmVkUGF0aClcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAobmV3RGVmYXVsdEltcG9ydEV4aXN0cyhhc3ROb2RlLnNwZWNpZmllcnMpKSB7XG4gICAgICAgICAgICBuZXdEZWZhdWx0SW1wb3J0cy5hZGQocmVzb2x2ZWRQYXRoKVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGFzdE5vZGUuc3BlY2lmaWVycy5mb3JFYWNoKHNwZWNpZmllciA9PiB7XG4gICAgICAgICAgICBpZiAoc3BlY2lmaWVyLnR5cGUgPT09IElNUE9SVF9ERUZBVUxUX1NQRUNJRklFUiB8fFxuICAgICAgICAgICAgICAgIHNwZWNpZmllci50eXBlID09PSBJTVBPUlRfTkFNRVNQQUNFX1NQRUNJRklFUikge1xuICAgICAgICAgICAgICByZXR1cm5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG5ld0ltcG9ydHMuc2V0KHNwZWNpZmllci5pbXBvcnRlZC5uYW1lLCByZXNvbHZlZFBhdGgpXG4gICAgICAgICAgfSlcbiAgICAgICAgfVxuICAgICAgfSlcblxuICAgICAgbmV3RXhwb3J0QWxsLmZvckVhY2godmFsdWUgPT4ge1xuICAgICAgICBpZiAoIW9sZEV4cG9ydEFsbC5oYXModmFsdWUpKSB7XG4gICAgICAgICAgbGV0IGltcG9ydHMgPSBvbGRJbXBvcnRQYXRocy5nZXQodmFsdWUpXG4gICAgICAgICAgaWYgKHR5cGVvZiBpbXBvcnRzID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgaW1wb3J0cyA9IG5ldyBTZXQoKVxuICAgICAgICAgIH1cbiAgICAgICAgICBpbXBvcnRzLmFkZChFWFBPUlRfQUxMX0RFQ0xBUkFUSU9OKVxuICAgICAgICAgIG9sZEltcG9ydFBhdGhzLnNldCh2YWx1ZSwgaW1wb3J0cylcblxuICAgICAgICAgIGxldCBleHBvcnRzID0gZXhwb3J0TGlzdC5nZXQodmFsdWUpXG4gICAgICAgICAgbGV0IGN1cnJlbnRFeHBvcnRcbiAgICAgICAgICBpZiAodHlwZW9mIGV4cG9ydHMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBjdXJyZW50RXhwb3J0ID0gZXhwb3J0cy5nZXQoRVhQT1JUX0FMTF9ERUNMQVJBVElPTilcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZXhwb3J0cyA9IG5ldyBNYXAoKVxuICAgICAgICAgICAgZXhwb3J0TGlzdC5zZXQodmFsdWUsIGV4cG9ydHMpXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHR5cGVvZiBjdXJyZW50RXhwb3J0ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgY3VycmVudEV4cG9ydC53aGVyZVVzZWQuYWRkKGZpbGUpXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IHdoZXJlVXNlZCA9IG5ldyBTZXQoKVxuICAgICAgICAgICAgd2hlcmVVc2VkLmFkZChmaWxlKVxuICAgICAgICAgICAgZXhwb3J0cy5zZXQoRVhQT1JUX0FMTF9ERUNMQVJBVElPTiwgeyB3aGVyZVVzZWQgfSlcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pXG5cbiAgICAgIG9sZEV4cG9ydEFsbC5mb3JFYWNoKHZhbHVlID0+IHtcbiAgICAgICAgaWYgKCFuZXdFeHBvcnRBbGwuaGFzKHZhbHVlKSkge1xuICAgICAgICAgIGNvbnN0IGltcG9ydHMgPSBvbGRJbXBvcnRQYXRocy5nZXQodmFsdWUpXG4gICAgICAgICAgaW1wb3J0cy5kZWxldGUoRVhQT1JUX0FMTF9ERUNMQVJBVElPTilcblxuICAgICAgICAgIGNvbnN0IGV4cG9ydHMgPSBleHBvcnRMaXN0LmdldCh2YWx1ZSlcbiAgICAgICAgICBpZiAodHlwZW9mIGV4cG9ydHMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBjb25zdCBjdXJyZW50RXhwb3J0ID0gZXhwb3J0cy5nZXQoRVhQT1JUX0FMTF9ERUNMQVJBVElPTilcbiAgICAgICAgICAgIGlmICh0eXBlb2YgY3VycmVudEV4cG9ydCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgY3VycmVudEV4cG9ydC53aGVyZVVzZWQuZGVsZXRlKGZpbGUpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KVxuXG4gICAgICBuZXdEZWZhdWx0SW1wb3J0cy5mb3JFYWNoKHZhbHVlID0+IHtcbiAgICAgICAgaWYgKCFvbGREZWZhdWx0SW1wb3J0cy5oYXModmFsdWUpKSB7XG4gICAgICAgICAgbGV0IGltcG9ydHMgPSBvbGRJbXBvcnRQYXRocy5nZXQodmFsdWUpXG4gICAgICAgICAgaWYgKHR5cGVvZiBpbXBvcnRzID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgaW1wb3J0cyA9IG5ldyBTZXQoKVxuICAgICAgICAgIH1cbiAgICAgICAgICBpbXBvcnRzLmFkZChJTVBPUlRfREVGQVVMVF9TUEVDSUZJRVIpXG4gICAgICAgICAgb2xkSW1wb3J0UGF0aHMuc2V0KHZhbHVlLCBpbXBvcnRzKVxuXG4gICAgICAgICAgbGV0IGV4cG9ydHMgPSBleHBvcnRMaXN0LmdldCh2YWx1ZSlcbiAgICAgICAgICBsZXQgY3VycmVudEV4cG9ydFxuICAgICAgICAgIGlmICh0eXBlb2YgZXhwb3J0cyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIGN1cnJlbnRFeHBvcnQgPSBleHBvcnRzLmdldChJTVBPUlRfREVGQVVMVF9TUEVDSUZJRVIpXG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGV4cG9ydHMgPSBuZXcgTWFwKClcbiAgICAgICAgICAgIGV4cG9ydExpc3Quc2V0KHZhbHVlLCBleHBvcnRzKVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICh0eXBlb2YgY3VycmVudEV4cG9ydCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIGN1cnJlbnRFeHBvcnQud2hlcmVVc2VkLmFkZChmaWxlKVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCB3aGVyZVVzZWQgPSBuZXcgU2V0KClcbiAgICAgICAgICAgIHdoZXJlVXNlZC5hZGQoZmlsZSlcbiAgICAgICAgICAgIGV4cG9ydHMuc2V0KElNUE9SVF9ERUZBVUxUX1NQRUNJRklFUiwgeyB3aGVyZVVzZWQgfSlcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pXG5cbiAgICAgIG9sZERlZmF1bHRJbXBvcnRzLmZvckVhY2godmFsdWUgPT4ge1xuICAgICAgICBpZiAoIW5ld0RlZmF1bHRJbXBvcnRzLmhhcyh2YWx1ZSkpIHtcbiAgICAgICAgICBjb25zdCBpbXBvcnRzID0gb2xkSW1wb3J0UGF0aHMuZ2V0KHZhbHVlKVxuICAgICAgICAgIGltcG9ydHMuZGVsZXRlKElNUE9SVF9ERUZBVUxUX1NQRUNJRklFUilcblxuICAgICAgICAgIGNvbnN0IGV4cG9ydHMgPSBleHBvcnRMaXN0LmdldCh2YWx1ZSlcbiAgICAgICAgICBpZiAodHlwZW9mIGV4cG9ydHMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBjb25zdCBjdXJyZW50RXhwb3J0ID0gZXhwb3J0cy5nZXQoSU1QT1JUX0RFRkFVTFRfU1BFQ0lGSUVSKVxuICAgICAgICAgICAgaWYgKHR5cGVvZiBjdXJyZW50RXhwb3J0ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICBjdXJyZW50RXhwb3J0LndoZXJlVXNlZC5kZWxldGUoZmlsZSlcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pXG5cbiAgICAgIG5ld05hbWVzcGFjZUltcG9ydHMuZm9yRWFjaCh2YWx1ZSA9PiB7XG4gICAgICAgIGlmICghb2xkTmFtZXNwYWNlSW1wb3J0cy5oYXModmFsdWUpKSB7XG4gICAgICAgICAgbGV0IGltcG9ydHMgPSBvbGRJbXBvcnRQYXRocy5nZXQodmFsdWUpXG4gICAgICAgICAgaWYgKHR5cGVvZiBpbXBvcnRzID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgaW1wb3J0cyA9IG5ldyBTZXQoKVxuICAgICAgICAgIH1cbiAgICAgICAgICBpbXBvcnRzLmFkZChJTVBPUlRfTkFNRVNQQUNFX1NQRUNJRklFUilcbiAgICAgICAgICBvbGRJbXBvcnRQYXRocy5zZXQodmFsdWUsIGltcG9ydHMpXG5cbiAgICAgICAgICBsZXQgZXhwb3J0cyA9IGV4cG9ydExpc3QuZ2V0KHZhbHVlKVxuICAgICAgICAgIGxldCBjdXJyZW50RXhwb3J0XG4gICAgICAgICAgaWYgKHR5cGVvZiBleHBvcnRzICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgY3VycmVudEV4cG9ydCA9IGV4cG9ydHMuZ2V0KElNUE9SVF9OQU1FU1BBQ0VfU1BFQ0lGSUVSKVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBleHBvcnRzID0gbmV3IE1hcCgpXG4gICAgICAgICAgICBleHBvcnRMaXN0LnNldCh2YWx1ZSwgZXhwb3J0cylcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAodHlwZW9mIGN1cnJlbnRFeHBvcnQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBjdXJyZW50RXhwb3J0LndoZXJlVXNlZC5hZGQoZmlsZSlcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3Qgd2hlcmVVc2VkID0gbmV3IFNldCgpXG4gICAgICAgICAgICB3aGVyZVVzZWQuYWRkKGZpbGUpXG4gICAgICAgICAgICBleHBvcnRzLnNldChJTVBPUlRfTkFNRVNQQUNFX1NQRUNJRklFUiwgeyB3aGVyZVVzZWQgfSlcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pXG5cbiAgICAgIG9sZE5hbWVzcGFjZUltcG9ydHMuZm9yRWFjaCh2YWx1ZSA9PiB7XG4gICAgICAgIGlmICghbmV3TmFtZXNwYWNlSW1wb3J0cy5oYXModmFsdWUpKSB7XG4gICAgICAgICAgY29uc3QgaW1wb3J0cyA9IG9sZEltcG9ydFBhdGhzLmdldCh2YWx1ZSlcbiAgICAgICAgICBpbXBvcnRzLmRlbGV0ZShJTVBPUlRfTkFNRVNQQUNFX1NQRUNJRklFUilcblxuICAgICAgICAgIGNvbnN0IGV4cG9ydHMgPSBleHBvcnRMaXN0LmdldCh2YWx1ZSlcbiAgICAgICAgICBpZiAodHlwZW9mIGV4cG9ydHMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBjb25zdCBjdXJyZW50RXhwb3J0ID0gZXhwb3J0cy5nZXQoSU1QT1JUX05BTUVTUEFDRV9TUEVDSUZJRVIpXG4gICAgICAgICAgICBpZiAodHlwZW9mIGN1cnJlbnRFeHBvcnQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgIGN1cnJlbnRFeHBvcnQud2hlcmVVc2VkLmRlbGV0ZShmaWxlKVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSlcblxuICAgICAgbmV3SW1wb3J0cy5mb3JFYWNoKCh2YWx1ZSwga2V5KSA9PiB7XG4gICAgICAgIGlmICghb2xkSW1wb3J0cy5oYXMoa2V5KSkge1xuICAgICAgICAgIGxldCBpbXBvcnRzID0gb2xkSW1wb3J0UGF0aHMuZ2V0KHZhbHVlKVxuICAgICAgICAgIGlmICh0eXBlb2YgaW1wb3J0cyA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIGltcG9ydHMgPSBuZXcgU2V0KClcbiAgICAgICAgICB9XG4gICAgICAgICAgaW1wb3J0cy5hZGQoa2V5KVxuICAgICAgICAgIG9sZEltcG9ydFBhdGhzLnNldCh2YWx1ZSwgaW1wb3J0cylcblxuICAgICAgICAgIGxldCBleHBvcnRzID0gZXhwb3J0TGlzdC5nZXQodmFsdWUpXG4gICAgICAgICAgbGV0IGN1cnJlbnRFeHBvcnRcbiAgICAgICAgICBpZiAodHlwZW9mIGV4cG9ydHMgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBjdXJyZW50RXhwb3J0ID0gZXhwb3J0cy5nZXQoa2V5KVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBleHBvcnRzID0gbmV3IE1hcCgpXG4gICAgICAgICAgICBleHBvcnRMaXN0LnNldCh2YWx1ZSwgZXhwb3J0cylcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAodHlwZW9mIGN1cnJlbnRFeHBvcnQgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICBjdXJyZW50RXhwb3J0LndoZXJlVXNlZC5hZGQoZmlsZSlcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY29uc3Qgd2hlcmVVc2VkID0gbmV3IFNldCgpXG4gICAgICAgICAgICB3aGVyZVVzZWQuYWRkKGZpbGUpXG4gICAgICAgICAgICBleHBvcnRzLnNldChrZXksIHsgd2hlcmVVc2VkIH0pXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KVxuXG4gICAgICBvbGRJbXBvcnRzLmZvckVhY2goKHZhbHVlLCBrZXkpID0+IHtcbiAgICAgICAgaWYgKCFuZXdJbXBvcnRzLmhhcyhrZXkpKSB7XG4gICAgICAgICAgY29uc3QgaW1wb3J0cyA9IG9sZEltcG9ydFBhdGhzLmdldCh2YWx1ZSlcbiAgICAgICAgICBpbXBvcnRzLmRlbGV0ZShrZXkpXG5cbiAgICAgICAgICBjb25zdCBleHBvcnRzID0gZXhwb3J0TGlzdC5nZXQodmFsdWUpXG4gICAgICAgICAgaWYgKHR5cGVvZiBleHBvcnRzICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgY29uc3QgY3VycmVudEV4cG9ydCA9IGV4cG9ydHMuZ2V0KGtleSlcbiAgICAgICAgICAgIGlmICh0eXBlb2YgY3VycmVudEV4cG9ydCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgY3VycmVudEV4cG9ydC53aGVyZVVzZWQuZGVsZXRlKGZpbGUpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAnUHJvZ3JhbTpleGl0Jzogbm9kZSA9PiB7XG4gICAgICAgIHVwZGF0ZUV4cG9ydFVzYWdlKG5vZGUpXG4gICAgICAgIHVwZGF0ZUltcG9ydFVzYWdlKG5vZGUpXG4gICAgICAgIGNoZWNrRXhwb3J0UHJlc2VuY2Uobm9kZSlcbiAgICAgIH0sXG4gICAgICAnRXhwb3J0RGVmYXVsdERlY2xhcmF0aW9uJzogbm9kZSA9PiB7XG4gICAgICAgIGNoZWNrVXNhZ2Uobm9kZSwgSU1QT1JUX0RFRkFVTFRfU1BFQ0lGSUVSKVxuICAgICAgfSxcbiAgICAgICdFeHBvcnROYW1lZERlY2xhcmF0aW9uJzogbm9kZSA9PiB7XG4gICAgICAgIG5vZGUuc3BlY2lmaWVycy5mb3JFYWNoKHNwZWNpZmllciA9PiB7XG4gICAgICAgICAgICBjaGVja1VzYWdlKG5vZGUsIHNwZWNpZmllci5leHBvcnRlZC5uYW1lKVxuICAgICAgICB9KVxuICAgICAgICBpZiAobm9kZS5kZWNsYXJhdGlvbikge1xuICAgICAgICAgIGlmIChcbiAgICAgICAgICAgIG5vZGUuZGVjbGFyYXRpb24udHlwZSA9PT0gRlVOQ1RJT05fREVDTEFSQVRJT04gfHxcbiAgICAgICAgICAgIG5vZGUuZGVjbGFyYXRpb24udHlwZSA9PT0gQ0xBU1NfREVDTEFSQVRJT05cbiAgICAgICAgICApIHtcbiAgICAgICAgICAgIGNoZWNrVXNhZ2Uobm9kZSwgbm9kZS5kZWNsYXJhdGlvbi5pZC5uYW1lKVxuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAobm9kZS5kZWNsYXJhdGlvbi50eXBlID09PSBWQVJJQUJMRV9ERUNMQVJBVElPTikge1xuICAgICAgICAgICAgbm9kZS5kZWNsYXJhdGlvbi5kZWNsYXJhdGlvbnMuZm9yRWFjaChkZWNsYXJhdGlvbiA9PiB7XG4gICAgICAgICAgICAgIGNoZWNrVXNhZ2Uobm9kZSwgZGVjbGFyYXRpb24uaWQubmFtZSlcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9LFxuICAgIH1cbiAgfSxcbn1cbiJdfQ==