@aws-cdk/core
Version:
AWS Cloud Development Kit Core Library
424 lines • 46 kB
JavaScript
"use strict";
/**
* Constructs compatibility layer.
*
* This file includes types that shadow types in the "constructs" module in
* order to allow backwards-compatiblity in the AWS CDK v1.0 release line.
*
* There are pretty ugly hacks here, which mostly involve downcasting types to
* adhere to legacy AWS CDK APIs.
*
* This file, in its entirety, is expected to be removed in v2.0.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConstructNode = exports.ConstructOrder = exports.Construct = void 0;
const cxapi = require("@aws-cdk/cx-api");
const constructs = require("constructs");
const annotations_1 = require("./annotations");
const aspect_1 = require("./aspect");
const token_1 = require("./token");
const ORIGINAL_CONSTRUCT_NODE_SYMBOL = Symbol.for('@aws-cdk/core.ConstructNode');
const CONSTRUCT_SYMBOL = Symbol.for('@aws-cdk/core.Construct');
/**
* Represents the building block of the construct graph.
*
* All constructs besides the root construct must be created within the scope of
* another construct.
*/
class Construct extends constructs.Construct {
/**
*
*/
constructor(scope, id) {
super(scope, id, {
nodeFactory: {
createNode: (h, s, i) => new ConstructNode(h, s, i)._actualNode,
},
});
if (token_1.Token.isUnresolved(id)) {
throw new Error(`Cannot use tokens in construct ID: ${id}`);
}
Object.defineProperty(this, CONSTRUCT_SYMBOL, { value: true });
this.node = ConstructNode._unwrap(constructs.Node.of(this));
const disableTrace = this.node.tryGetContext(cxapi.DISABLE_METADATA_STACK_TRACE) ||
this.node.tryGetContext(constructs.ConstructMetadata.DISABLE_STACK_TRACE_IN_METADATA) ||
process.env.CDK_DISABLE_STACK_TRACE;
if (disableTrace) {
this.node.setContext(cxapi.DISABLE_METADATA_STACK_TRACE, true);
this.node.setContext(constructs.ConstructMetadata.DISABLE_STACK_TRACE_IN_METADATA, true);
process.env.CDK_DISABLE_STACK_TRACE = '1';
}
}
/**
* Return whether the given object is a Construct.
*/
static isConstruct(x) {
return typeof x === 'object' && x !== null && CONSTRUCT_SYMBOL in x;
}
/**
* Validate the current construct.
*
* This method can be implemented by derived constructs in order to perform
* validation logic. It is called on all constructs before synthesis.
*
* @returns An array of validation error messages, or an empty array if the construct is valid.
*/
onValidate() {
return this.validate();
}
/**
* Perform final modifications before synthesis.
*
* This method can be implemented by derived constructs in order to perform
* final changes before synthesis. prepare() will be called after child
* constructs have been prepared.
*
* This is an advanced framework feature. Only use this if you
* understand the implications.
*/
onPrepare() {
this.prepare();
}
/**
* Allows this construct to emit artifacts into the cloud assembly during synthesis.
*
* This method is usually implemented by framework-level constructs such as `Stack` and `Asset`
* as they participate in synthesizing the cloud assembly.
*
* @param session The synthesis session.
*/
onSynthesize(session) {
this.synthesize({
outdir: session.outdir,
assembly: session.assembly,
});
}
/**
* Validate the current construct.
*
* This method can be implemented by derived constructs in order to perform
* validation logic. It is called on all constructs before synthesis.
*
* @returns An array of validation error messages, or an empty array if the construct is valid.
*/
validate() {
return [];
}
/**
* Perform final modifications before synthesis.
*
* This method can be implemented by derived constructs in order to perform
* final changes before synthesis. prepare() will be called after child
* constructs have been prepared.
*
* This is an advanced framework feature. Only use this if you
* understand the implications.
*/
prepare() {
return;
}
/**
* Allows this construct to emit artifacts into the cloud assembly during synthesis.
*
* This method is usually implemented by framework-level constructs such as `Stack` and `Asset`
* as they participate in synthesizing the cloud assembly.
*
* @param session The synthesis session.
*/
synthesize(session) {
ignore(session);
}
}
exports.Construct = Construct;
/**
* In what order to return constructs.
*/
var ConstructOrder;
(function (ConstructOrder) {
ConstructOrder[ConstructOrder["PREORDER"] = 0] = "PREORDER";
ConstructOrder[ConstructOrder["POSTORDER"] = 1] = "POSTORDER";
})(ConstructOrder = exports.ConstructOrder || (exports.ConstructOrder = {}));
/**
* Represents the construct node in the scope tree.
*/
class ConstructNode {
/**
*
*/
constructor(host, scope, id) {
this.host = host;
this._actualNode = new constructs.Node(host, scope, id);
// store a back reference on _actualNode so we can our ConstructNode from it
Object.defineProperty(this._actualNode, ORIGINAL_CONSTRUCT_NODE_SYMBOL, {
value: this,
configurable: false,
enumerable: false,
});
}
/**
* Returns the wrapping `@aws-cdk/core.ConstructNode` instance from a `constructs.ConstructNode`.
*
* @internal
*/
static _unwrap(c) {
const x = c[ORIGINAL_CONSTRUCT_NODE_SYMBOL];
if (!x) {
throw new Error('invalid ConstructNode type');
}
return x;
}
/**
* (deprecated) Synthesizes a CloudAssembly from a construct tree.
*
* @param node The root of the construct tree.
* @param options Synthesis options.
* @deprecated Use `app.synth()` or `stage.synth()` instead
*/
static synth(node, options = {}) {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const a = require('./private/synthesis');
return a.synthesize(node.root, options);
}
/**
* (deprecated) Invokes "prepare" on all constructs (depth-first, post-order) in the tree under `node`.
*
* @param node The root node.
* @deprecated Use `app.synth()` instead
*/
static prepare(node) {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const p = require('./private/prepare-app');
p.prepareApp(node.root); // resolve cross refs and nested stack assets.
return node._actualNode.prepare();
}
/**
* Invokes "validate" on all constructs in the tree (depth-first, pre-order) and returns the list of all errors.
*
* An empty list indicates that there are no errors.
*
* @param node The root node.
*/
static validate(node) {
return node._actualNode.validate().map(e => ({ source: e.source, message: e.message }));
}
/**
* Returns the scope in which this construct is defined.
*
* The value is `undefined` at the root of the construct scope tree.
*/
get scope() {
return this._actualNode.scope;
}
/**
* The id of this construct within the current scope.
*
* This is a a scope-unique id. To obtain an app-unique id for this construct, use `uniqueId`.
*/
get id() { return this._actualNode.id; }
/**
* The full, absolute path of this construct in the tree.
*
* Components are separated by '/'.
*/
get path() { return this._actualNode.path; }
/**
* A tree-global unique alphanumeric identifier for this construct.
*
* Includes all components of the tree.
*/
get uniqueId() { return this._actualNode.uniqueId; }
/**
* Return a direct child by id, or undefined.
*
* @param id Identifier of direct child.
* @returns the child if found, or undefined
*/
tryFindChild(id) { return this._actualNode.tryFindChild(id); }
/**
* Return a direct child by id.
*
* Throws an error if the child is not found.
*
* @param id Identifier of direct child.
* @returns Child with the given id.
*/
findChild(id) { return this._actualNode.findChild(id); }
/**
* Returns the child construct that has the id `Default` or `Resource"`.
*
* This is usually the construct that provides the bulk of the underlying functionality.
* Useful for modifications of the underlying construct that are not available at the higher levels.
* Override the defaultChild property.
*
* This should only be used in the cases where the correct
* default child is not named 'Resource' or 'Default' as it
* should be.
*
* If you set this to undefined, the default behavior of finding
* the child named 'Resource' or 'Default' will be used.
*
* @returns a construct or undefined if there is no default child
* @throws if there is more than one child
*/
get defaultChild() { return this._actualNode.defaultChild; }
/**
* Returns the child construct that has the id `Default` or `Resource"`.
*
* This is usually the construct that provides the bulk of the underlying functionality.
* Useful for modifications of the underlying construct that are not available at the higher levels.
* Override the defaultChild property.
*
* This should only be used in the cases where the correct
* default child is not named 'Resource' or 'Default' as it
* should be.
*
* If you set this to undefined, the default behavior of finding
* the child named 'Resource' or 'Default' will be used.
*
* @returns a construct or undefined if there is no default child
* @throws if there is more than one child
*/
set defaultChild(value) { this._actualNode.defaultChild = value; }
/**
* All direct children of this construct.
*/
get children() { return this._actualNode.children; }
/**
* Return this construct and all of its children in the given order.
*/
findAll(order = ConstructOrder.PREORDER) { return this._actualNode.findAll(order); }
/**
* This can be used to set contextual values.
*
* Context must be set before any children are added, since children may consult context info during construction.
* If the key already exists, it will be overridden.
*
* @param key The context key.
* @param value The context value.
*/
setContext(key, value) {
if (token_1.Token.isUnresolved(key)) {
throw new Error('Invalid context key: context keys can\'t include tokens');
}
this._actualNode.setContext(key, value);
}
/**
* Retrieves a value from tree context.
*
* Context is usually initialized at the root, but can be overridden at any point in the tree.
*
* @param key The context key.
* @returns The context value or `undefined` if there is no context value for the key.
*/
tryGetContext(key) {
if (token_1.Token.isUnresolved(key)) {
throw new Error('Invalid context key: context keys can\'t include tokens');
}
return this._actualNode.tryGetContext(key);
}
/**
* An immutable array of metadata objects associated with this construct.
*
* This can be used, for example, to implement support for deprecation notices, source mapping, etc.
*/
get metadata() { return this._actualNode.metadata; }
/**
* Adds a metadata entry to this construct.
*
* Entries are arbitrary values and will also include a stack trace to allow tracing back to
* the code location for when the entry was added. It can be used, for example, to include source
* mapping in CloudFormation templates to improve diagnostics.
*
* @param type a string denoting the type of metadata.
* @param data the value of the metadata (can be a Token).
* @param fromFunction a function under which to restrict the metadata entry's stack trace (defaults to this.addMetadata).
*/
addMetadata(type, data, fromFunction) { this._actualNode.addMetadata(type, data, fromFunction); }
/**
* (deprecated) DEPRECATED: Adds a { "info": <message> } metadata entry to this construct.
*
* The toolkit will display the info message when apps are synthesized.
*
* @param message The info message.
* @deprecated use `Annotations.of(construct).addInfo()`
*/
addInfo(message) {
annotations_1.Annotations.of(this.host).addInfo(message);
}
/**
* (deprecated) DEPRECATED: Adds a { "warning": <message> } metadata entry to this construct.
*
* The toolkit will display the warning when an app is synthesized, or fail
* if run in --strict mode.
*
* @param message The warning message.
* @deprecated use `Annotations.of(construct).addWarning()`
*/
addWarning(message) {
annotations_1.Annotations.of(this.host).addWarning(message);
}
/**
* (deprecated) DEPRECATED: Adds an { "error": <message> } metadata entry to this construct.
*
* The toolkit will fail synthesis when errors are reported.
*
* @param message The error message.
* @deprecated use `Annotations.of(construct).addError()`
*/
addError(message) {
annotations_1.Annotations.of(this.host).addError(message);
}
/**
* (deprecated) DEPRECATED: Applies the aspect to this Constructs node.
*
* @deprecated This API is going to be removed in the next major version of
* the AWS CDK. Please use `Aspects.of(scope).add()` instead.
*/
applyAspect(aspect) {
annotations_1.Annotations.of(this.host).addDeprecation('@aws-cdk/core.ConstructNode.applyAspect', 'Use "Aspects.of(construct).add(aspect)" instead');
aspect_1.Aspects.of(this.host).add(aspect);
}
/**
* All parent scopes of this construct.
*
* @returns a list of parent scopes. The last element in the list will always
* be the current construct and the first element will be the root of the
* tree.
*/
get scopes() { return this._actualNode.scopes; }
/**
* @returns The root of the construct tree.
*/
get root() { return this._actualNode.root; }
/**
* Returns true if this construct or the scopes in which it is defined are locked.
*/
get locked() { return this._actualNode.locked; }
/**
* Add an ordering dependency on another Construct.
*
* All constructs in the dependency's scope will be deployed before any
* construct in this construct's scope.
*/
addDependency(...dependencies) { this._actualNode.addDependency(...dependencies); }
/**
* Return all dependencies registered on this node or any of its children.
*/
get dependencies() { return this._actualNode.dependencies; }
/**
* (experimental) Remove the child with the given name, if present.
*
* @returns Whether a child with the given name was deleted.
* @experimental
*/
tryRemoveChild(childName) { return this._actualNode.tryRemoveChild(childName); }
}
exports.ConstructNode = ConstructNode;
/**
* Separator used to delimit construct path components.
*/
ConstructNode.PATH_SEP = '/';
function ignore(_x) {
return;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RydWN0LWNvbXBhdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNvbnN0cnVjdC1jb21wYXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7O0dBVUc7OztBQUVILHlDQUF5QztBQUN6Qyx5Q0FBeUM7QUFDekMsK0NBQTRDO0FBQzVDLHFDQUE0QztBQUU1QyxtQ0FBZ0M7QUFFaEMsTUFBTSw4QkFBOEIsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLDZCQUE2QixDQUFDLENBQUM7QUFDakYsTUFBTSxnQkFBZ0IsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLHlCQUF5QixDQUFDLENBQUM7Ozs7Ozs7QUFpQy9ELE1BQWEsU0FBVSxTQUFRLFVBQVUsQ0FBQyxTQUFTOzs7O0lBYWpELFlBQVksS0FBMkIsRUFBRSxFQUFVO1FBQ2pELEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFO1lBQ2YsV0FBVyxFQUFFO2dCQUNYLFVBQVUsRUFBRSxDQUFDLENBQXVCLEVBQUUsQ0FBd0IsRUFBRSxDQUFTLEVBQUUsRUFBRSxDQUMzRSxJQUFJLGFBQWEsQ0FBQyxDQUFjLEVBQUUsQ0FBZSxFQUFFLENBQUMsQ0FBQyxDQUFDLFdBQVc7YUFDcEU7U0FDRixDQUFDLENBQUM7UUFFSCxJQUFJLGFBQUssQ0FBQyxZQUFZLENBQUMsRUFBRSxDQUFDLEVBQUU7WUFDMUIsTUFBTSxJQUFJLEtBQUssQ0FBQyxzQ0FBc0MsRUFBRSxFQUFFLENBQUMsQ0FBQztTQUM3RDtRQUVELE1BQU0sQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLGdCQUFnQixFQUFFLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7UUFDL0QsSUFBSSxDQUFDLElBQUksR0FBRyxhQUFhLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFFNUQsTUFBTSxZQUFZLEdBQ2hCLElBQUksQ0FBQyxJ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QUFhLENBQUMsR0FBRyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUM7Ozs7SUFLekcsSUFBVyxZQUFZLEtBQW1CLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxZQUE0QixDQUFDLENBQUMsQ0FBQzs7Ozs7OztJQVExRixjQUFjLENBQUMsU0FBaUIsSUFBYSxPQUFPLElBQUksQ0FBQyxXQUFXLENBQUMsY0FBYyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQzs7QUEzUjFHLHNDQTRSQzs7OztBQXhSd0Isc0JBQVEsR0FBRyxHQUFHLENBQUM7QUF3VHhDLFNBQVMsTUFBTSxDQUFDLEVBQU87SUFDckIsT0FBTztBQUNULENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvbnN0cnVjdHMgY29tcGF0aWJpbGl0eSBsYXllci5cbiAqXG4gKiBUaGlzIGZpbGUgaW5jbHVkZXMgdHlwZXMgdGhhdCBzaGFkb3cgdHlwZXMgaW4gdGhlIFwiY29uc3RydWN0c1wiIG1vZHVsZSBpblxuICogb3JkZXIgdG8gYWxsb3cgYmFja3dhcmRzLWNvbXBhdGlibGl0eSBpbiB0aGUgQVdTIENESyB2MS4wIHJlbGVhc2UgbGluZS5cbiAqXG4gKiBUaGVyZSBhcmUgcHJldHR5IHVnbHkgaGFja3MgaGVyZSwgd2hpY2ggbW9zdGx5IGludm9sdmUgZG93bmNhc3RpbmcgdHlwZXMgdG9cbiAqIGFkaGVyZSB0byBsZWdhY3kgQVdTIENESyBBUElzLlxuICpcbiAqIFRoaXMgZmlsZSwgaW4gaXRzIGVudGlyZXR5LCBpcyBleHBlY3RlZCB0byBiZSByZW1vdmVkIGluIHYyLjAuXG4gKi9cblxuaW1wb3J0ICogYXMgY3hhcGkgZnJvbSAnQGF3cy1jZGsvY3gtYXBpJztcbmltcG9ydCAqIGFzIGNvbnN0cnVjdHMgZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBBbm5vdGF0aW9ucyB9IGZyb20gJy4vYW5ub3RhdGlvbnMnO1xuaW1wb3J0IHsgSUFzcGVjdCwgQXNwZWN0cyB9IGZyb20gJy4vYXNwZWN0JztcbmltcG9ydCB7IElEZXBlbmRhYmxlIH0gZnJvbSAnLi9kZXBlbmRlbmN5JztcbmltcG9ydCB7IFRva2VuIH0gZnJvbSAnLi90b2tlbic7XG5cbmNvbnN0IE9SSUdJTkFMX0NPTlNUUlVDVF9OT0RFX1NZTUJPTCA9IFN5bWJvbC5mb3IoJ0Bhd3MtY2RrL2NvcmUuQ29uc3RydWN0Tm9kZScpO1xuY29uc3QgQ09OU1RSVUNUX1NZTUJPTCA9IFN5bWJvbC5mb3IoJ0Bhd3MtY2RrL2NvcmUuQ29uc3RydWN0Jyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbmV4cG9ydCBpbnRlcmZhY2UgSUNvbnN0cnVjdCBleHRlbmRzIGNvbnN0cnVjdHMuSUNvbnN0cnVjdCwgSURlcGVuZGFibGUge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHJlYWRvbmx5IG5vZGU6IENvbnN0cnVjdE5vZGU7XG59XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG5leHBvcnQgaW50ZXJmYWNlIElTeW50aGVzaXNTZXNzaW9uIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIG91dGRpcjogc3RyaW5nO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIGFzc2VtYmx5OiBjeGFwaS5DbG91ZEFzc2VtYmx5QnVpbGRlcjtcbn1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbmV4cG9ydCBjbGFzcyBDb25zdHJ1Y3QgZXh0ZW5kcyBjb25zdHJ1Y3RzLkNvbnN0cnVjdCBpbXBsZW1lbnRzIElDb25zdHJ1Y3Qge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyBzdGF0aWMgaXNDb25zdHJ1Y3QoeDogYW55KTogeCBpcyBDb25zdHJ1Y3Qge1xuICAgIHJldHVybiB0eXBlb2YgeCA9PT0gJ29iamVjdCcgJiYgeCAhPT0gbnVsbCAmJiBDT05TVFJVQ1RfU1lNQk9MIGluIHg7XG4gIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyByZWFkb25seSBub2RlOiBDb25zdHJ1Y3ROb2RlO1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBjb25zdHJ1Y3RzLkNvbnN0cnVjdCwgaWQ6IHN0cmluZykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCwge1xuICAgICAgbm9kZUZhY3Rvcnk6IHtcbiAgICAgICAgY3JlYXRlTm9kZTogKGg6IGNvbnN0cnVjdHMuQ29uc3RydWN0LCBzOiBjb25zdHJ1Y3RzLklDb25zdHJ1Y3QsIGk6IHN0cmluZykgPT5cbiAgICAgICAgICBuZXcgQ29uc3RydWN0Tm9kZShoIGFzIENvbnN0cnVjdCwgcyBhcyBJQ29uc3RydWN0LCBpKS5fYWN0dWFsTm9kZSxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICBpZiAoVG9rZW4uaXNVbnJlc29sdmVkKGlkKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgdXNlIHRva2VucyBpbiBjb25zdHJ1Y3QgSUQ6ICR7aWR9YCk7XG4gICAgfVxuXG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMsIENPTlNUUlVDVF9TWU1CT0wsIHsgdmFsdWU6IHRydWUgfSk7XG4gICAgdGhpcy5ub2RlID0gQ29uc3RydWN0Tm9kZS5fdW53cmFwKGNvbnN0cnVjdHMuTm9kZS5vZih0aGlzKSk7XG5cbiAgICBjb25zdCBkaXNhYmxlVHJhY2UgPVxuICAgICAgdGhpcy5ub2RlLnRyeUdldENvbnRleHQoY3hhcGkuRElTQUJMRV9NRVRBREFUQV9TVEFDS19UUkFDRSkgfHxcbiAgICAgIHRoaXMubm9kZS50cnlHZXRDb250ZXh0KGNvbnN0cnVjdHMuQ29uc3RydWN0TWV0YWRhdGEuRElTQUJMRV9TVEFDS19UUkFDRV9JTl9NRVRBREFUQSkgfHxcbiAgICAgIHByb2Nlc3MuZW52LkNES19ESVNBQkxFX1NUQUNLX1RSQUNFO1xuXG4gICAgaWYgKGRpc2FibGVUcmFjZSkge1xuICAgICAgdGhpcy5ub2RlLnNldENvbnRleHQoY3hhcGkuRElTQUJMRV9NRVRBREFUQV9TVEFDS19UUkFDRSwgdHJ1ZSk7XG4gICAgICB0aGlzLm5vZGUuc2V0Q29udGV4dChjb25zdHJ1Y3RzLkNvbnN0cnVjdE1ldGFkYXRhLkRJU0FCTEVfU1RBQ0tfVFJBQ0VfSU5fTUVUQURBVEEsIHRydWUpO1xuICAgICAgcHJvY2Vzcy5lbnYuQ0RLX0RJU0FCTEVfU1RBQ0tfVFJBQ0UgPSAnMSc7XG4gICAgfVxuICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwcm90ZWN0ZWQgb25WYWxpZGF0ZSgpOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIHRoaXMudmFsaWRhdGUoKTtcbiAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHByb3RlY3RlZCBvblByZXBhcmUoKTogdm9pZCB7XG4gICAgdGhpcy5wcmVwYXJlKCk7XG4gIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwcm90ZWN0ZWQgb25TeW50aGVzaXplKHNlc3Npb246IGNvbnN0cnVjdHMuSVN5bnRoZXNpc1Nlc3Npb24pOiB2b2lkIHtcbiAgICB0aGlzLnN5bnRoZXNpemUoe1xuICAgICAgb3V0ZGlyOiBzZXNzaW9uLm91dGRpcixcbiAgICAgIGFzc2VtYmx5OiBzZXNzaW9uLmFzc2VtYmx5ISxcbiAgICB9KTtcbiAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHJvdGVjdGVkIHZhbGlkYXRlKCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gW107XG4gIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwcm90ZWN0ZWQgcHJlcGFyZSgpOiB2b2lkIHtcbiAgICByZXR1cm47XG4gIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwcm90ZWN0ZWQgc3ludGhlc2l6ZShzZXNzaW9uOiBJU3ludGhlc2lzU2Vzc2lvbik6IHZvaWQge1xuICAgIGlnbm9yZShzZXNzaW9uKTtcbiAgfVxufVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbmV4cG9ydCBlbnVtIENvbnN0cnVjdE9yZGVyIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBQUkVPUkRFUixcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgUE9TVE9SREVSXG59XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuZXhwb3J0IGludGVyZmFjZSBTeW50aGVzaXNPcHRpb25zIGV4dGVuZHMgY3hhcGkuQXNzZW1ibHlCdWlsZE9wdGlvbnMge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcmVhZG9ubHkgb3V0ZGlyPzogc3RyaW5nO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHJlYWRvbmx5IHNraXBWYWxpZGF0aW9uPzogYm9vbGVhbjtcbn1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbmV4cG9ydCBjbGFzcyBDb25zdHJ1Y3ROb2RlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IFBBVEhfU0VQID0gJy8nO1xuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSB3cmFwcGluZyBgQGF3cy1jZGsvY29yZS5Db25zdHJ1Y3ROb2RlYCBpbnN0YW5jZSBmcm9tIGEgYGNvbnN0cnVjdHMuQ29uc3RydWN0Tm9kZWAuXG4gICAqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBfdW53cmFwKGM6IGNvbnN0cnVjdHMuTm9kZSk6IENvbnN0cnVjdE5vZGUge1xuICAgIGNvbnN0IHggPSAoYyBhcyBhbnkpW09SSUdJTkFMX0NPTlNUUlVDVF9OT0RFX1NZTUJPTF07XG4gICAgaWYgKCF4KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmFsaWQgQ29uc3RydWN0Tm9kZSB0eXBlJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHg7XG4gIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgc3RhdGljIHN5bnRoKG5vZGU6IENvbnN0cnVjdE5vZGUsIG9wdGlvbnM6IFN5bnRoZXNpc09wdGlvbnMgPSB7IH0pOiBjeGFwaS5DbG91ZEFzc2VtYmx5IHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0c1xuICAgIGNvbnN0IGE6IHR5cGVvZiBpbXBvcnQoJy4vLi9wcml2YXRlL3N5bnRoZXNpcycpID0gcmVxdWlyZSgnLi9wcml2YXRlL3N5bnRoZXNpcycpO1xuICAgIHJldHVybiBhLnN5bnRoZXNpemUobm9kZS5yb290LCBvcHRpb25zKTtcbiAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyBzdGF0aWMgcHJlcGFyZShub2RlOiBDb25zdHJ1Y3ROb2RlKSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcbiAgICBjb25zdCBwOiB0eXBlb2YgaW1wb3J0KCcuL3ByaXZhdGUvcHJlcGFyZS1hcHAnKSA9IHJlcXVpcmUoJy4vcHJpdmF0ZS9wcmVwYXJlLWFwcCcpO1xuICAgIHAucHJlcGFyZUFwcChub2RlLnJvb3QpOyAvLyByZXNvbHZlIGNyb3NzIHJlZnMgYW5kIG5lc3RlZCBzdGFjayBhc3NldHMuXG4gICAgcmV0dXJuIG5vZGUuX2FjdHVhbE5vZGUucHJlcGFyZSgpO1xuICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIHN0YXRpYyB2YWxpZGF0ZShub2RlOiBDb25zdHJ1Y3ROb2RlKTogVmFsaWRhdGlvbkVycm9yW10ge1xuICAgIHJldHVybiBub2RlLl9hY3R1YWxOb2RlLnZhbGlkYXRlKCkubWFwKGUgPT4gKHsgc291cmNlOiBlLnNvdXJjZSBhcyBDb25zdHJ1Y3QsIG1lc3NhZ2U6IGUubWVzc2FnZSB9KSk7XG4gIH1cblxuICAvKipcbiAgICogQGludGVybmFsXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgX2FjdHVhbE5vZGU6IGNvbnN0cnVjdHMuTm9kZTtcblxuICAvKipcbiAgICogVGhlIENvbnN0cnVjdCBjbGFzcyB0aGF0IGhvc3RzIHRoaXMgQVBJLlxuICAgKi9cbiAgcHJpdmF0ZSByZWFkb25seSBob3N0OiBDb25zdHJ1Y3Q7XG5cbiAgY29uc3RydWN0b3IoaG9zdDogQ29uc3RydWN0LCBzY29wZTogSUNvbnN0cnVjdCwgaWQ6IHN0cmluZykge1xuICAgIHRoaXMuaG9zdCA9IGhvc3Q7XG4gICAgdGhpcy5fYWN0dWFsTm9kZSA9IG5ldyBjb25zdHJ1Y3RzLk5vZGUoaG9zdCwgc2NvcGUsIGlkKTtcblxuICAgIC8vIHN0b3JlIGEgYmFjayByZWZlcmVuY2Ugb24gX2FjdHVhbE5vZGUgc28gd2UgY2FuIG91ciBDb25zdHJ1Y3ROb2RlIGZyb20gaXRcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcy5fYWN0dWFsTm9kZSwgT1JJR0lOQUxfQ09OU1RSVUNUX05PREVfU1lNQk9MLCB7XG4gICAgICB2YWx1ZTogdGhpcyxcbiAgICAgIGNvbmZpZ3VyYWJsZTogZmFsc2UsXG4gICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICB9KTtcbiAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgZ2V0IHNjb3BlKCk6IElDb25zdHJ1Y3QgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLl9hY3R1YWxOb2RlLnNjb3BlIGFzIElDb25zdHJ1Y3Q7XG4gIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgZ2V0IGlkKCkgeyByZXR1cm4gdGhpcy5fYWN0dWFsTm9kZS5pZDsgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIGdldCBwYXRoKCk6IHN0cmluZyB7IHJldHVybiB0aGlzLl9hY3R1YWxOb2RlLnBhdGg7IH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyBnZXQgdW5pcXVlSWQoKTogc3RyaW5nIHsgcmV0dXJuIHRoaXMuX2FjdHVhbE5vZGUudW5pcXVlSWQ7IH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIHRyeUZpbmRDaGlsZChpZDogc3RyaW5nKTogSUNvbnN0cnVjdCB8IHVuZGVmaW5lZCB7IHJldHVybiB0aGlzLl9hY3R1YWxOb2RlLnRyeUZpbmRDaGlsZChpZCkgYXMgSUNvbnN0cnVjdDsgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIGZpbmRDaGlsZChpZDogc3RyaW5nKTogSUNvbnN0cnVjdCB7IHJldHVybiB0aGlzLl9hY3R1YWxOb2RlLmZpbmRDaGlsZChpZCkgYXMgSUNvbnN0cnVjdDsgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgZ2V0IGRlZmF1bHRDaGlsZCgpOiBJQ29uc3RydWN0IHwgdW5kZWZpbmVkIHsgcmV0dXJuIHRoaXMuX2FjdHVhbE5vZGUuZGVmYXVsdENoaWxkIGFzIElDb25zdHJ1Y3Q7IH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyBzZXQgZGVmYXVsdENoaWxkKHZhbHVlOiBJQ29uc3RydWN0IHwgdW5kZWZpbmVkKSB7IHRoaXMuX2FjdHVhbE5vZGUuZGVmYXVsdENoaWxkID0gdmFsdWU7IH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgZ2V0IGNoaWxkcmVuKCk6IElDb25zdHJ1Y3RbXSB7IHJldHVybiB0aGlzLl9hY3R1YWxOb2RlLmNoaWxkcmVuIGFzIElDb25zdHJ1Y3RbXTsgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIGZpbmRBbGwob3JkZXI6IENvbnN0cnVjdE9yZGVyID0gQ29uc3RydWN0T3JkZXIuUFJFT1JERVIpOiBJQ29uc3RydWN0W10geyByZXR1cm4gdGhpcy5fYWN0dWFsTm9kZS5maW5kQWxsKG9yZGVyKSBhcyBJQ29uc3RydWN0W107IH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIHNldENvbnRleHQoa2V5OiBzdHJpbmcsIHZhbHVlOiBhbnkpIHtcbiAgICBpZiAoVG9rZW4uaXNVbnJlc29sdmVkKGtleSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBjb250ZXh0IGtleTogY29udGV4dCBrZXlzIGNhblxcJ3QgaW5jbHVkZSB0b2tlbnMnKTtcbiAgICB9XG4gICAgdGhpcy5fYWN0dWFsTm9kZS5zZXRDb250ZXh0KGtleSwgdmFsdWUpO1xuICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyB0cnlHZXRDb250ZXh0KGtleTogc3RyaW5nKTogYW55IHtcbiAgICBpZiAoVG9rZW4uaXNVbnJlc29sdmVkKGtleSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBjb250ZXh0IGtleTogY29udGV4dCBrZXlzIGNhblxcJ3QgaW5jbHVkZSB0b2tlbnMnKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX2FjdHVhbE5vZGUudHJ5R2V0Q29udGV4dChrZXkpO1xuICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIGdldCBtZXRhZGF0YSgpIHsgcmV0dXJuIHRoaXMuX2FjdHVhbE5vZGUubWV0YWRhdGEgYXMgY3hhcGkuTWV0YWRhdGFFbnRyeVtdOyB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIGFkZE1ldGFkYXRhKHR5cGU6IHN0cmluZywgZGF0YTogYW55LCBmcm9tRnVuY3Rpb24/OiBhbnkpOiB2b2lkIHsgdGhpcy5fYWN0dWFsTm9kZS5hZGRNZXRhZGF0YSh0eXBlLCBkYXRhLCBmcm9tRnVuY3Rpb24pOyB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIGFkZEluZm8obWVzc2FnZTogc3RyaW5nKTogdm9pZCB7XG4gICAgQW5ub3RhdGlvbnMub2YodGhpcy5ob3N0KS5hZGRJbmZvKG1lc3NhZ2UpO1xuICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyBhZGRXYXJuaW5nKG1lc3NhZ2U6IHN0cmluZyk6IHZvaWQge1xuICAgIEFubm90YXRpb25zLm9mKHRoaXMuaG9zdCkuYWRkV2FybmluZyhtZXNzYWdlKTtcbiAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIGFkZEVycm9yKG1lc3NhZ2U6IHN0cmluZykge1xuICAgIEFubm90YXRpb25zLm9mKHRoaXMuaG9zdCkuYWRkRXJyb3IobWVzc2FnZSk7XG4gIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcHVibGljIGFwcGx5QXNwZWN0KGFzcGVjdDogSUFzcGVjdCk6IHZvaWQge1xuICAgIEFubm90YXRpb25zLm9mKHRoaXMuaG9zdCkuYWRkRGVwcmVjYXRpb24oJ0Bhd3MtY2RrL2NvcmUuQ29uc3RydWN0Tm9kZS5hcHBseUFzcGVjdCcsICdVc2UgXCJBc3BlY3RzLm9mKGNvbnN0cnVjdCkuYWRkKGFzcGVjdClcIiBpbnN0ZWFkJyk7XG4gICAgQXNwZWN0cy5vZih0aGlzLmhvc3QpLmFkZChhc3BlY3QpO1xuICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgZ2V0IHNjb3BlcygpOiBJQ29uc3RydWN0W10geyByZXR1cm4gdGhpcy5fYWN0dWFsTm9kZS5zY29wZXMgYXMgSUNvbnN0cnVjdFtdOyB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgZ2V0IHJvb3QoKTogSUNvbnN0cnVjdCB7IHJldHVybiB0aGlzLl9hY3R1YWxOb2RlLnJvb3QgYXMgSUNvbnN0cnVjdDsgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgZ2V0IGxvY2tlZCgpIHsgcmV0dXJuIHRoaXMuX2FjdHVhbE5vZGUubG9ja2VkOyB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICBwdWJsaWMgYWRkRGVwZW5kZW5jeSguLi5kZXBlbmRlbmNpZXM6IElEZXBlbmRhYmxlW10pIHsgdGhpcy5fYWN0dWFsTm9kZS5hZGREZXBlbmRlbmN5KC4uLmRlcGVuZGVuY2llcyk7IH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyBnZXQgZGVwZW5kZW5jaWVzKCk6IERlcGVuZGVuY3lbXSB7IHJldHVybiB0aGlzLl9hY3R1YWxOb2RlLmRlcGVuZGVuY2llcyBhcyBEZXBlbmRlbmN5W107IH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHB1YmxpYyB0cnlSZW1vdmVDaGlsZChjaGlsZE5hbWU6IHN0cmluZyk6IGJvb2xlYW4geyByZXR1cm4gdGhpcy5fYWN0dWFsTm9kZS50cnlSZW1vdmVDaGlsZChjaGlsZE5hbWUpOyB9XG59XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuZXhwb3J0IGludGVyZmFjZSBWYWxpZGF0aW9uRXJyb3Ige1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICByZWFkb25seSBzb3VyY2U6IENvbnN0cnVjdDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbiAgcmVhZG9ubHkgbWVzc2FnZTogc3RyaW5nO1xufVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcbmV4cG9ydCBpbnRlcmZhY2UgRGVwZW5kZW5jeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFxuICByZWFkb25seSBzb3VyY2U6IElDb25zdHJ1Y3Q7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHJlYWRvbmx5IHRhcmdldDogSUNvbnN0cnVjdDtcbn1cblxuZnVuY3Rpb24gaWdub3JlKF94OiBhbnkpIHtcbiAgcmV0dXJuO1xufVxuIl19