UNPKG

@aws-cdk/core

Version:

AWS Cloud Development Kit Core Library

551 lines 54.9 kB
"use strict"; var _a, _b; Object.defineProperty(exports, "__esModule", { value: true }); exports.ConstructNode = exports.ConstructOrder = exports.Construct = void 0; const jsiiDeprecationWarnings = require("../.warnings.jsii.js"); const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); /** * 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. */ 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) { try { jsiiDeprecationWarnings._aws_cdk_core_ISynthesisSession(session); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.synthesize); } throw error; } ignore(session); } } exports.Construct = Construct; _a = JSII_RTTI_SYMBOL_1; Construct[_a] = { fqn: "@aws-cdk/core.Construct", version: "1.204.0" }; /** * In what order to return constructs */ var ConstructOrder; (function (ConstructOrder) { /** * Depth-first, pre-order */ ConstructOrder[ConstructOrder["PREORDER"] = 0] = "PREORDER"; /** * Depth-first, post-order (leaf nodes first) */ ConstructOrder[ConstructOrder["POSTORDER"] = 1] = "POSTORDER"; })(ConstructOrder = exports.ConstructOrder || (exports.ConstructOrder = {})); /** * Represents the construct node in the scope tree. */ class ConstructNode { constructor(host, scope, id) { try { jsiiDeprecationWarnings._aws_cdk_core_Construct(host); jsiiDeprecationWarnings._aws_cdk_core_IConstruct(scope); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, ConstructNode); } throw error; } 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; } /** * 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 = {}) { try { jsiiDeprecationWarnings.print("@aws-cdk/core.ConstructNode#synth", "Use `app.synth()` or `stage.synth()` instead"); jsiiDeprecationWarnings._aws_cdk_core_ConstructNode(node); jsiiDeprecationWarnings._aws_cdk_core_SynthesisOptions(options); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.synth); } throw error; } // eslint-disable-next-line @typescript-eslint/no-require-imports const a = require('./private/synthesis'); return a.synthesize(node.root, options); } /** * 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) { try { jsiiDeprecationWarnings.print("@aws-cdk/core.ConstructNode#prepare", "Use `app.synth()` instead"); jsiiDeprecationWarnings._aws_cdk_core_ConstructNode(node); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.prepare); } throw error; } // 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) { try { jsiiDeprecationWarnings._aws_cdk_core_ConstructNode(node); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.validate); } throw error; } 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. * * @deprecated use `node.addr` to obtain a consistent 42 character address for * this node (see https://github.com/aws/constructs/pull/314). * Alternatively, to get a CloudFormation-compatible unique identifier, use * `Names.uniqueId()`. */ get uniqueId() { try { jsiiDeprecationWarnings.print("@aws-cdk/core.ConstructNode#uniqueId", "use `node.addr` to obtain a consistent 42 character address for\nthis node (see https://github.com/aws/constructs/pull/314).\nAlternatively, to get a CloudFormation-compatible unique identifier, use\n`Names.uniqueId()`."); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, jsiiDeprecationWarnings.getPropertyDescriptor(this, "uniqueId").get); } throw error; } return this._actualNode.uniqueId; } /** * Returns an opaque tree-unique address for this construct. * * Addresses are 42 characters hexadecimal strings. They begin with "c8" * followed by 40 lowercase hexadecimal characters (0-9a-f). * * Addresses are calculated using a SHA-1 of the components of the construct * path. * * To enable refactorings of construct trees, constructs with the ID `Default` * will be excluded from the calculation. In those cases constructs in the * same tree may have the same addreess. * * Example value: `c83a2846e506bcc5f10682b564084bca2d275709ee` */ get addr() { return this._actualNode.addr; } /** * 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. * * @throws if there is more than one child * @returns a construct or undefined if there is no default child */ get defaultChild() { return this._actualNode.defaultChild; } /** * 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. */ 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) { try { jsiiDeprecationWarnings._aws_cdk_core_ConstructOrder(order); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.findAll); } throw error; } 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); } /** * DEPRECATED * @deprecated use `metadataEntry` */ get metadata() { try { jsiiDeprecationWarnings.print("@aws-cdk/core.ConstructNode#metadata", "use `metadataEntry`"); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, jsiiDeprecationWarnings.getPropertyDescriptor(this, "metadata").get); } throw error; } return this._actualNode.metadata; } /** * 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 metadataEntry() { 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). If null/undefined, metadata will not be added. * @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: 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) { try { jsiiDeprecationWarnings.print("@aws-cdk/core.ConstructNode#addInfo", "use `Annotations.of(construct).addInfo()`"); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.addInfo); } throw error; } annotations_1.Annotations.of(this.host).addInfo(message); } /** * 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) { try { jsiiDeprecationWarnings.print("@aws-cdk/core.ConstructNode#addWarning", "use `Annotations.of(construct).addWarning()`"); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.addWarning); } throw error; } annotations_1.Annotations.of(this.host).addWarning(message); } /** * 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) { try { jsiiDeprecationWarnings.print("@aws-cdk/core.ConstructNode#addError", "use `Annotations.of(construct).addError()`"); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.addError); } throw error; } annotations_1.Annotations.of(this.host).addError(message); } /** * 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) { try { jsiiDeprecationWarnings.print("@aws-cdk/core.ConstructNode#applyAspect", "This API is going to be removed in the next major version of\nthe AWS CDK. Please use `Aspects.of(scope).add()` instead."); jsiiDeprecationWarnings._aws_cdk_core_IAspect(aspect); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.applyAspect); } throw error; } 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); } /** * Add a validator to this construct Node */ addValidation(validation) { this._actualNode.addValidation(validation); } /** * 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) { try { jsiiDeprecationWarnings._aws_cdk_core_IDependable(dependencies); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.addDependency); } throw error; } this._actualNode.addDependency(...dependencies); } /** * Return all dependencies registered on this node or any of its children */ get dependencies() { return this._actualNode.dependencies; } /** * Remove the child with the given name, if present. * * @returns Whether a child with the given name was deleted. */ tryRemoveChild(childName) { return this._actualNode.tryRemoveChild(childName); } } exports.ConstructNode = ConstructNode; _b = JSII_RTTI_SYMBOL_1; ConstructNode[_b] = { fqn: "@aws-cdk/core.ConstructNode", version: "1.204.0" }; /** * Separator used to delimit construct path components. */ ConstructNode.PATH_SEP = '/'; function ignore(_x) { return; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uc3RydWN0LWNvbXBhdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImNvbnN0cnVjdC1jb21wYXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUE7Ozs7Ozs7Ozs7R0FVRztBQUVILHlDQUF5QztBQUN6Qyx5Q0FBeUM7QUFDekMsK0NBQTRDO0FBQzVDLHFDQUE0QztBQUU1QyxtQ0FBZ0M7QUFFaEMsTUFBTSw4QkFBOEIsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLDZCQUE2QixDQUFDLENBQUM7QUFDakYsTUFBTSxnQkFBZ0IsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLHlCQUF5QixDQUFDLENBQUM7QUFrQy9EOzs7OztHQUtHO0FBQ0gsTUFBYSxTQUFVLFNBQVEsVUFBVSxDQUFDLFNBQVM7SUFhakQsWUFBWSxLQUEyQixFQUFFLEVBQVU7UUFDakQsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUU7WUFDZixXQUFXLEVBQUU7Z0JBQ1gsVUFBVSxFQUFFLENBQUMsQ0FBdUIsRUFBRSxDQUF3QixFQUFFLENBQVMsRUFBRSxFQUFFLENBQzNFLElBQUksYUFBYSxDQUFDLENBQWMsRUFBRSxDQUFlLEVBQUUsQ0FBQyxDQUFDLENBQUMsV0FBVzthQUNwRTtTQUNGLENBQUMsQ0FBQztRQUVILElBQUksYUFBSyxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUMsRUFBRTtZQUMxQixNQUFNLElBQUksS0FBSyxDQUFDLHNDQUFzQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1NBQzdEO1FBRUQsTUFBTSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsZ0JBQWdCLEVBQUUsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztRQUMvRCxJQUFJLENBQUMsSUFBSSxHQUFHLGFBQWEsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUU1RCxNQUFNLFlBQVksR0FDaEIsSUFB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LENBQUM7UUFDdkksZ0JBQU8sQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQztLQUNuQztJQUVEOztPQUVHO0lBQ0ksYUFBYSxDQUFDLFVBQWtDO1FBQ3JELElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0tBQzVDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsSUFBVyxNQUFNLEtBQW1CLE9BQU8sSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFzQixDQUFDLEVBQUU7SUFFckY7O09BRUc7SUFDSCxJQUFXLElBQUksS0FBaUIsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQWtCLENBQUMsRUFBRTtJQUU3RTs7O09BR0c7SUFDSCxJQUFXLE1BQU0sS0FBSyxPQUFPLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLEVBQUU7SUFFdkQ7Ozs7O09BS0c7SUFDSSxhQUFhLENBQUMsR0FBRyxZQUEyQjs7Ozs7Ozs7TUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLGFBQWEsQ0FBQyxHQUFHLFlBQVksQ0FBQyxDQUFDLEVBQUU7SUFFekc7O09BRUc7SUFDSCxJQUFXLFlBQVksS0FBbUIsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLFlBQTRCLENBQUMsRUFBRTtJQUVqRzs7OztPQUlHO0lBQ0ksY0FBYyxDQUFDLFNBQWlCLElBQWEsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUFDLGNBQWMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFOztBQTdUMUcsc0NBOFRDOzs7QUE3VEM7O0dBRUc7QUFDb0Isc0JBQVEsR0FBRyxHQUFHLENBQUM7QUEwVnhDLFNBQVMsTUFBTSxDQUFDLEVBQU87SUFDckIsT0FBTztBQUNULENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvbnN0cnVjdHMgY29tcGF0aWJpbGl0eSBsYXllci5cbiAqXG4gKiBUaGlzIGZpbGUgaW5jbHVkZXMgdHlwZXMgdGhhdCBzaGFkb3cgdHlwZXMgaW4gdGhlIFwiY29uc3RydWN0c1wiIG1vZHVsZSBpblxuICogb3JkZXIgdG8gYWxsb3cgYmFja3dhcmRzLWNvbXBhdGlibGl0eSBpbiB0aGUgQVdTIENESyB2MS4wIHJlbGVhc2UgbGluZS5cbiAqXG4gKiBUaGVyZSBhcmUgcHJldHR5IHVnbHkgaGFja3MgaGVyZSwgd2hpY2ggbW9zdGx5IGludm9sdmUgZG93bmNhc3RpbmcgdHlwZXMgdG9cbiAqIGFkaGVyZSB0byBsZWdhY3kgQVdTIENESyBBUElzLlxuICpcbiAqIFRoaXMgZmlsZSwgaW4gaXRzIGVudGlyZXR5LCBpcyBleHBlY3RlZCB0byBiZSByZW1vdmVkIGluIHYyLjAuXG4gKi9cblxuaW1wb3J0ICogYXMgY3hhcGkgZnJvbSAnQGF3cy1jZGsvY3gtYXBpJztcbmltcG9ydCAqIGFzIGNvbnN0cnVjdHMgZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBBbm5vdGF0aW9ucyB9IGZyb20gJy4vYW5ub3RhdGlvbnMnO1xuaW1wb3J0IHsgSUFzcGVjdCwgQXNwZWN0cyB9IGZyb20gJy4vYXNwZWN0JztcbmltcG9ydCB7IElEZXBlbmRhYmxlIH0gZnJvbSAnLi9kZXBlbmRlbmN5JztcbmltcG9ydCB7IFRva2VuIH0gZnJvbSAnLi90b2tlbic7XG5cbmNvbnN0IE9SSUdJTkFMX0NPTlNUUlVDVF9OT0RFX1NZTUJPTCA9IFN5bWJvbC5mb3IoJ0Bhd3MtY2RrL2NvcmUuQ29uc3RydWN0Tm9kZScpO1xuY29uc3QgQ09OU1RSVUNUX1NZTUJPTCA9IFN5bWJvbC5mb3IoJ0Bhd3MtY2RrL2NvcmUuQ29uc3RydWN0Jyk7XG5cbi8qKlxuICogUmVwcmVzZW50cyBhIGNvbnN0cnVjdC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJQ29uc3RydWN0IGV4dGVuZHMgY29uc3RydWN0cy5JQ29uc3RydWN0LCBJRGVwZW5kYWJsZSB7XG4gIC8qKlxuICAgKiBUaGUgY29uc3RydWN0IHRyZWUgbm9kZSBmb3IgdGhpcyBjb25zdHJ1Y3QuXG4gICAqL1xuICByZWFkb25seSBub2RlOiBDb25zdHJ1Y3ROb2RlO1xufVxuXG4vKipcbiAqIFJlcHJlc2VudHMgYSBzaW5nbGUgc2Vzc2lvbiBvZiBzeW50aGVzaXMuIFBhc3NlZCBpbnRvIGBDb25zdHJ1Y3Quc3ludGhlc2l6ZSgpYCBtZXRob2RzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIElTeW50aGVzaXNTZXNzaW9uIHtcbiAgLyoqXG4gICAqIFRoZSBvdXRwdXQgZGlyZWN0b3J5IGZvciB0aGlzIHN5bnRoZXNpcyBzZXNzaW9uLlxuICAgKi9cbiAgb3V0ZGlyOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIENsb3VkIGFzc2VtYmx5IGJ1aWxkZXIuXG4gICAqL1xuICBhc3NlbWJseTogY3hhcGkuQ2xvdWRBc3NlbWJseUJ1aWxkZXI7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhlIHN0YWNrIHNob3VsZCBiZSB2YWxpZGF0ZWQgYWZ0ZXIgc3ludGhlc2lzIHRvIGNoZWNrIGZvciBlcnJvciBtZXRhZGF0YVxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGZhbHNlXG4gICAqL1xuICB2YWxpZGF0ZU9uU3ludGg/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIFJlcHJlc2VudHMgdGhlIGJ1aWxkaW5nIGJsb2NrIG9mIHRoZSBjb25zdHJ1Y3QgZ3JhcGguXG4gKlxuICogQWxsIGNvbnN0cnVjdHMgYmVzaWRlcyB0aGUgcm9vdCBjb25zdHJ1Y3QgbXVzdCBiZSBjcmVhdGVkIHdpdGhpbiB0aGUgc2NvcGUgb2ZcbiAqIGFub3RoZXIgY29uc3RydWN0LlxuICovXG5leHBvcnQgY2xhc3MgQ29uc3RydWN0IGV4dGVuZHMgY29uc3RydWN0cy5Db25zdHJ1Y3QgaW1wbGVtZW50cyBJQ29uc3RydWN0IHtcbiAgLyoqXG4gICAqIFJldHVybiB3aGV0aGVyIHRoZSBnaXZlbiBvYmplY3QgaXMgYSBDb25zdHJ1Y3RcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgaXNDb25zdHJ1Y3QoeDogYW55KTogeCBpcyBDb25zdHJ1Y3Qge1xuICAgIHJldHVybiB0eXBlb2YgeCA9PT0gJ29iamVjdCcgJiYgeCAhPT0gbnVsbCAmJiBDT05TVFJVQ1RfU1lNQk9MIGluIHg7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGNvbnN0cnVjdCB0cmVlIG5vZGUgYXNzb2NpYXRlZCB3aXRoIHRoaXMgY29uc3RydWN0LlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IG5vZGU6IENvbnN0cnVjdE5vZGU7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IGNvbnN0cnVjdHMuQ29uc3RydWN0LCBpZDogc3RyaW5nKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkLCB7XG4gICAgICBub2RlRmFjdG9yeToge1xuICAgICAgICBjcmVhdGVOb2RlOiAoaDogY29uc3RydWN0cy5Db25zdHJ1Y3QsIHM6IGNvbnN0cnVjdHMuSUNvbnN0cnVjdCwgaTogc3RyaW5nKSA9PlxuICAgICAgICAgIG5ldyBDb25zdHJ1Y3ROb2RlKGggYXMgQ29uc3RydWN0LCBzIGFzIElDb25zdHJ1Y3QsIGkpLl9hY3R1YWxOb2RlLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIGlmIChUb2tlbi5pc1VucmVzb2x2ZWQoaWQpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCB1c2UgdG9rZW5zIGluIGNvbnN0cnVjdCBJRDogJHtpZH1gKTtcbiAgICB9XG5cbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgQ09OU1RSVUNUX1NZTUJPTCwgeyB2YWx1ZTogdHJ1ZSB9KTtcbiAgICB0aGlzLm5vZGUgPSBDb25zdHJ1Y3ROb2RlLl91bndyYXAoY29uc3RydWN0cy5Ob2RlLm9mKHRoaXMpKTtcblxuICAgIGNvbnN0IGRpc2FibGVUcmFjZSA9XG4gICAgICB0aGlzLm5vZGUudHJ5R2V0Q29udGV4dChjeGFwaS5ESVNBQkxFX01FVEFEQVRBX1NUQUNLX1RSQUNFKSB8fFxuICAgICAgdGhpcy5ub2RlLnRyeUdldENvbnRleHQoY29uc3RydWN0cy5Db25zdHJ1Y3RNZXRhZGF0YS5ESVNBQkxFX1NUQUNLX1RSQUNFX0lOX01FVEFEQVRBKSB8fFxuICAgICAgcHJvY2Vzcy5lbnYuQ0RLX0RJU0FCTEVfU1RBQ0tfVFJBQ0U7XG5cbiAgICBpZiAoZGlzYWJsZVRyYWNlKSB7XG4gICAgICB0aGlzLm5vZGUuc2V0Q29udGV4dChjeGFwaS5ESVNBQkxFX01FVEFEQVRBX1NUQUNLX1RSQUNFLCB0cnVlKTtcbiAgICAgIHRoaXMubm9kZS5zZXRDb250ZXh0KGNvbnN0cnVjdHMuQ29uc3RydWN0TWV0YWRhdGEuRElTQUJMRV9TVEFDS19UUkFDRV9JTl9NRVRBREFUQSwgdHJ1ZSk7XG4gICAgICBwcm9jZXNzLmVudi5DREtfRElTQUJMRV9TVEFDS19UUkFDRSA9ICcxJztcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgdGhlIGN1cnJlbnQgY29uc3RydWN0LlxuICAgKlxuICAgKiBUaGlzIG1ldGhvZCBjYW4gYmUgaW1wbGVtZW50ZWQgYnkgZGVyaXZlZCBjb25zdHJ1Y3RzIGluIG9yZGVyIHRvIHBlcmZvcm1cbiAgICogdmFsaWRhdGlvbiBsb2dpYy4gSXQgaXMgY2FsbGVkIG9uIGFsbCBjb25zdHJ1Y3RzIGJlZm9yZSBzeW50aGVzaXMuXG4gICAqXG4gICAqIEByZXR1cm5zIEFuIGFycmF5IG9mIHZhbGlkYXRpb24gZXJyb3IgbWVzc2FnZXMsIG9yIGFuIGVtcHR5IGFycmF5IGlmIHRoZSBjb25zdHJ1Y3QgaXMgdmFsaWQuXG4gICAqL1xuICBwcm90ZWN0ZWQgb25WYWxpZGF0ZSgpOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIHRoaXMudmFsaWRhdGUoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtIGZpbmFsIG1vZGlmaWNhdGlvbnMgYmVmb3JlIHN5bnRoZXNpc1xuICAgKlxuICAgKiBUaGlzIG1ldGhvZCBjYW4gYmUgaW1wbGVtZW50ZWQgYnkgZGVyaXZlZCBjb25zdHJ1Y3RzIGluIG9yZGVyIHRvIHBlcmZvcm1cbiAgICogZmluYWwgY2hhbmdlcyBiZWZvcmUgc3ludGhlc2lzLiBwcmVwYXJlKCkgd2lsbCBiZSBjYWxsZWQgYWZ0ZXIgY2hpbGRcbiAgICogY29uc3RydWN0cyBoYXZlIGJlZW4gcHJlcGFyZWQuXG4gICAqXG4gICAqIFRoaXMgaXMgYW4gYWR2YW5jZWQgZnJhbWV3b3JrIGZlYXR1cmUuIE9ubHkgdXNlIHRoaXMgaWYgeW91XG4gICAqIHVuZGVyc3RhbmQgdGhlIGltcGxpY2F0aW9ucy5cbiAgICovXG4gIHByb3RlY3RlZCBvblByZXBhcmUoKTogdm9pZCB7XG4gICAgdGhpcy5wcmVwYXJlKCk7XG4gIH1cblxuICAvKipcbiAgICogQWxsb3dzIHRoaXMgY29uc3RydWN0IHRvIGVtaXQgYXJ0aWZhY3RzIGludG8gdGhlIGNsb3VkIGFzc2VtYmx5IGR1cmluZyBzeW50aGVzaXMuXG4gICAqXG4gICAqIFRoaXMgbWV0aG9kIGlzIHVzdWFsbHkgaW1wbGVtZW50ZWQgYnkgZnJhbWV3b3JrLWxldmVsIGNvbnN0cnVjdHMgc3VjaCBhcyBgU3RhY2tgIGFuZCBgQXNzZXRgXG4gICAqIGFzIHRoZXkgcGFydGljaXBhdGUgaW4gc3ludGhlc2l6aW5nIHRoZSBjbG91ZCBhc3NlbWJseS5cbiAgICpcbiAgICogQHBhcmFtIHNlc3Npb24gVGhlIHN5bnRoZXNpcyBzZXNzaW9uLlxuICAgKi9cbiAgcHJvdGVjdGVkIG9uU3ludGhlc2l6ZShzZXNzaW9uOiBjb25zdHJ1Y3RzLklTeW50aGVzaXNTZXNzaW9uKTogdm9pZCB7XG4gICAgdGhpcy5zeW50aGVzaXplKHtcbiAgICAgIG91dGRpcjogc2Vzc2lvbi5vdXRkaXIsXG4gICAgICBhc3NlbWJseTogc2Vzc2lvbi5hc3NlbWJseSEsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgdGhlIGN1cnJlbnQgY29uc3RydWN0LlxuICAgKlxuICAgKiBUaGlzIG1ldGhvZCBjYW4gYmUgaW1wbGVtZW50ZWQgYnkgZGVyaXZlZCBjb25zdHJ1Y3RzIGluIG9yZGVyIHRvIHBlcmZvcm1cbiAgICogdmFsaWRhdGlvbiBsb2dpYy4gSXQgaXMgY2FsbGVkIG9uIGFsbCBjb25zdHJ1Y3RzIGJlZm9yZSBzeW50aGVzaXMuXG4gICAqXG4gICAqIEByZXR1cm5zIEFuIGFycmF5IG9mIHZhbGlkYXRpb24gZXJyb3IgbWVzc2FnZXMsIG9yIGFuIGVtcHR5IGFycmF5IGlmIHRoZSBjb25zdHJ1Y3QgaXMgdmFsaWQuXG4gICAqL1xuICBwcm90ZWN0ZWQgdmFsaWRhdGUoKTogc3RyaW5nW10ge1xuICAgIHJldHVybiBbXTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJmb3JtIGZpbmFsIG1vZGlmaWNhdGlvbnMgYmVmb3JlIHN5bnRoZXNpc1xuICAgKlxuICAgKiBUaGlzIG1ldGhvZCBjYW4gYmUgaW1wbGVtZW50ZWQgYnkgZGVyaXZlZCBjb25zdHJ1Y3RzIGluIG9yZGVyIHRvIHBlcmZvcm1cbiAgICogZmluYWwgY2hhbmdlcyBiZWZvcmUgc3ludGhlc2lzLiBwcmVwYXJlKCkgd2lsbCBiZSBjYWxsZWQgYWZ0ZXIgY2hpbGRcbiAgICogY29uc3RydWN0cyBoYXZlIGJlZW4gcHJlcGFyZWQuXG4gICAqXG4gICAqIFRoaXMgaXMgYW4gYWR2YW5jZWQgZnJhbWV3b3JrIGZlYXR1cmUuIE9ubHkgdXNlIHRoaXMgaWYgeW91XG4gICAqIHVuZGVyc3RhbmQgdGhlIGltcGxpY2F0aW9ucy5cbiAgICovXG4gIHByb3RlY3RlZCBwcmVwYXJlKCk6IHZvaWQge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIC8qKlxuICAgKiBBbGxvd3MgdGhpcyBjb25zdHJ1Y3QgdG8gZW1pdCBhcnRpZmFjdHMgaW50byB0aGUgY2xvdWQgYXNzZW1ibHkgZHVyaW5nIHN5bnRoZXNpcy5cbiAgICpcbiAgICogVGhpcyBtZXRob2QgaXMgdXN1YWxseSBpbXBsZW1lbnRlZCBieSBmcmFtZXdvcmstbGV2ZWwgY29uc3RydWN0cyBzdWNoIGFzIGBTdGFja2AgYW5kIGBBc3NldGBcbiAgICogYXMgdGhleSBwYXJ0aWNpcGF0ZSBpbiBzeW50aGVzaXppbmcgdGhlIGNsb3VkIGFzc2VtYmx5LlxuICAgKlxuICAgKiBAcGFyYW0gc2Vzc2lvbiBUaGUgc3ludGhlc2lzIHNlc3Npb24uXG4gICAqL1xuICBwcm90ZWN0ZWQgc3ludGhlc2l6ZShzZXNzaW9uOiBJU3ludGhlc2lzU2Vzc2lvbik6IHZvaWQge1xuICAgIGlnbm9yZShzZXNzaW9uKTtcbiAgfVxufVxuXG4vKipcbiAqIEluIHdoYXQgb3JkZXIgdG8gcmV0dXJuIGNvbnN0cnVjdHNcbiAqL1xuZXhwb3J0IGVudW0gQ29uc3RydWN0T3JkZXIge1xuICAvKipcbiAgICogRGVwdGgtZmlyc3QsIHByZS1vcmRlclxuICAgKi9cbiAgUFJFT1JERVIsXG5cbiAgLyoqXG4gICAqIERlcHRoLWZpcnN0LCBwb3N0LW9yZGVyIChsZWFmIG5vZGVzIGZpcnN0KVxuICAgKi9cbiAgUE9TVE9SREVSXG59XG5cbi8qKlxuICogT3B0aW9ucyBmb3Igc3ludGhlc2lzLlxuICpcbiAqIEBkZXByZWNhdGVkIHVzZSBgYXBwLnN5bnRoKClgIG9yIGBzdGFnZS5zeW50aCgpYCBpbnN0ZWFkXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3ludGhlc2lzT3B0aW9ucyBleHRlbmRzIGN4YXBpLkFzc2VtYmx5QnVpbGRPcHRpb25zIHtcbiAgLyoqXG4gICAqIFRoZSBvdXRwdXQgZGlyZWN0b3J5IGludG8gd2hpY2ggdG8gc3ludGhlc2l6ZSB0aGUgY2xvdWQgYXNzZW1ibHkuXG4gICAqIEBkZWZhdWx0IC0gY3JlYXRlcyBhIHRlbXBvcmFyeSBkaXJlY3RvcnlcbiAgICovXG4gIHJlYWRvbmx5IG91dGRpcj86IHN0cmluZztcblxuICAvKipcbiAgICogV2hldGhlciBzeW50aGVzaXMgc2hvdWxkIHNraXAgdGhlIHZhbGlkYXRpb24gcGhhc2UuXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBza2lwVmFsaWRhdGlvbj86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhlIHN0YWNrIHNob3VsZCBiZSB2YWxpZGF0ZWQgYWZ0ZXIgc3ludGhlc2lzIHRvIGNoZWNrIGZvciBlcnJvciBtZXRhZGF0YVxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGZhbHNlXG4gICAqL1xuICByZWFkb25seSB2YWxpZGF0ZU9uU3ludGhlc2lzPzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBSZXByZXNlbnRzIHRoZSBjb25zdHJ1Y3Qgbm9kZSBpbiB0aGUgc2NvcGUgdHJlZS5cbiAqL1xuZXhwb3J0IGNsYXNzIENvbnN0cnVjdE5vZGUge1xuICAvKipcbiAgICogU2VwYXJhdG9yIHVzZWQgdG8gZGVsaW1pdCBjb25zdHJ1Y3QgcGF0aCBjb21wb25lbnRzLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBQQVRIX1NFUCA9ICcvJztcblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgd3JhcHBpbmcgYEBhd3MtY2RrL2NvcmUuQ29uc3RydWN0Tm9kZWAgaW5zdGFuY2UgZnJvbSBhIGBjb25zdHJ1Y3RzLkNvbnN0cnVjdE5vZGVgLlxuICAgKlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgX3Vud3JhcChjOiBjb25zdHJ1Y3RzLk5vZGUpOiBDb25zdHJ1Y3ROb2RlIHtcbiAgICBjb25zdCB4ID0gKGMgYXMgYW55KVtPUklHSU5BTF9DT05TVFJVQ1RfTk9ERV9TWU1CT0xdO1xuICAgIGlmICgheCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIENvbnN0cnVjdE5vZGUgdHlwZScpO1xuICAgIH1cblxuICAgIHJldHVybiB4O1xuICB9XG5cbiAgLyoqXG4gICAqIFN5bnRoZXNpemVzIGEgQ2xvdWRBc3NlbWJseSBmcm9tIGEgY29uc3RydWN0IHRyZWUuXG4gICAqIEBwYXJhbSBub2RlIFRoZSByb290IG9mIHRoZSBjb25zdHJ1Y3QgdHJlZS5cbiAgICogQHBhcmFtIG9wdGlvbnMgU3ludGhlc2lzIG9wdGlvbnMuXG4gICAqIEBkZXByZWNhdGVkIFVzZSBgYXBwLnN5bnRoKClgIG9yIGBzdGFnZS5zeW50aCgpYCBpbnN0ZWFkXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHN5bnRoKG5vZGU6IENvbnN0cnVjdE5vZGUsIG9wdGlvbnM6IFN5bnRoZXNpc09wdGlvbnMgPSB7IH0pOiBjeGFwaS5DbG91ZEFzc2VtYmx5IHtcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXJlcXVpcmUtaW1wb3J0c1xuICAgIGNvbnN0IGE6IHR5cGVvZiBpbXBvcnQoJy4vLi9wcml2YXRlL3N5bnRoZXNpcycpID0gcmVxdWlyZSgnLi9wcml2YXRlL3N5bnRoZXNpcycpO1xuICAgIHJldHVybiBhLnN5bnRoZXNpemUobm9kZS5yb290LCBvcHRpb25zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbnZva2VzIFwicHJlcGFyZVwiIG9uIGFsbCBjb25zdHJ1Y3RzIChkZXB0aC1maXJzdCwgcG9zdC1vcmRlcikgaW4gdGhlIHRyZWUgdW5kZXIgYG5vZGVgLlxuICAgKiBAcGFyYW0gbm9kZSBUaGUgcm9vdCBub2RlXG4gICAqIEBkZXByZWNhdGVkIFVzZSBgYXBwLnN5bnRoKClgIGluc3RlYWRcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcHJlcGFyZShub2RlOiBDb25zdHJ1Y3ROb2RlKSB7XG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1yZXF1aXJlLWltcG9ydHNcbiAgICBjb25zdCBwOiB0eXBlb2YgaW1wb3J0KCcuL3ByaXZhdGUvcHJlcGFyZS1hcHAnKSA9IHJlcXVpcmUoJy4vcHJpdmF0ZS9wcmVwYXJlLWFwcCcpO1xuICAgIHAucHJlcGFyZUFwcChub2RlLnJvb3QpOyAvLyByZXNvbHZlIGNyb3NzIHJlZnMgYW5kIG5lc3RlZCBzdGFjayBhc3NldHMuXG4gICAgcmV0dXJuIG5vZGUuX2FjdHVhbE5vZGUucHJlcGFyZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIEludm9rZXMgXCJ2YWxpZGF0ZVwiIG9uIGFsbCBjb25zdHJ1Y3RzIGluIHRoZSB0cmVlIChkZXB0aC1maXJzdCwgcHJlLW9yZGVyKSBhbmQgcmV0dXJuc1xuICAgKiB0aGUgbGlzdCBvZiBhbGwgZXJyb3JzLiBBbiBlbXB0eSBsaXN0IGluZGljYXRlcyB0aGF0IHRoZXJlIGFyZSBubyBlcnJvcnMuXG4gICAqXG4gICAqIEBwYXJhbSBub2RlIFRoZSByb290IG5vZGVcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgdmFsaWRhdGUobm9kZTogQ29uc3RydWN0Tm9kZSk6IFZhbGlkYXRpb25FcnJvcltdIHtcbiAgICByZXR1cm4gbm9kZS5fYWN0dWFsTm9kZS52YWxpZGF0ZSgpLm1hcChlID0+ICh7IHNvdXJjZTogZS5zb3VyY2UgYXMgQ29uc3RydWN0LCBtZXNzYWdlOiBlLm1lc3NhZ2UgfSkpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IF9hY3R1YWxOb2RlOiBjb25zdHJ1Y3RzLk5vZGU7XG5cbiAgLyoqXG4gICAqIFRoZSBDb25zdHJ1Y3QgY2xhc3MgdGhhdCBob3N0cyB0aGlzIEFQSS5cbiAgICovXG4gIHByaXZhdGUgcmVhZG9ubHkgaG9zdDogQ29uc3RydWN0O1xuXG4gIGNvbnN0cnVjdG9yKGhvc3Q6IENvbnN0cnVjdCwgc2NvcGU6IElDb25zdHJ1Y3QsIGlkOiBzdHJpbmcpIHtcbiAgICB0aGlzLmhvc3QgPSBob3N0O1xuICAgIHRoaXMuX2FjdHVhbE5vZGUgPSBuZXcgY29uc3RydWN0cy5Ob2RlKGhvc3QsIHNjb3BlLCBpZCk7XG5cbiAgICAvLyBzdG9yZSBhIGJhY2sgcmVmZXJlbmNlIG9uIF9hY3R1YWxOb2RlIHNvIHdlIGNhbiBvdXIgQ29uc3RydWN0Tm9kZSBmcm9tIGl0XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMuX2FjdHVhbE5vZGUsIE9SSUdJTkFMX0NPTlNUUlVDVF9OT0RFX1NZTUJPTCwge1xuICAgICAgdmFsdWU6IHRoaXMsXG4gICAgICBjb25maWd1cmFibGU6IGZhbHNlLFxuICAgICAgZW51bWVyYWJsZTogZmFsc2UsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgc2NvcGUgaW4gd2hpY2ggdGhpcyBjb25zdHJ1Y3QgaXMgZGVmaW5lZC5cbiAgICpcbiAgICogVGhlIHZhbHVlIGlzIGB1bmRlZmluZWRgIGF0IHRoZSByb290IG9mIHRoZSBjb25zdHJ1Y3Qgc2NvcGUgdHJlZS5cbiAgICovXG4gIHB1YmxpYyBnZXQgc2NvcGUoKTogSUNvbnN0cnVjdCB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuX2FjdHVhbE5vZGUuc2NvcGUgYXMgSUNvbnN0cnVjdDtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgaWQgb2YgdGhpcyBjb25zdHJ1Y3Qgd2l0aGluIHRoZSBjdXJyZW50IHNjb3BlLlxuICAgKlxuICAgKiBUaGlzIGlzIGEgYSBzY29wZS11bmlxdWUgaWQuIFRvIG9idGFpbiBhbiBhcHAtdW5pcXVlIGlkIGZvciB0aGlzIGNvbnN0cnVjdCwgdXNlIGB1bmlxdWVJZGAuXG4gICAqL1xuICBwdWJsaWMgZ2V0IGlkKCkgeyByZXR1cm4gdGhpcy5fYWN0dWFsTm9kZS5pZDsgfVxuXG4gIC8qKlxuICAgKiBUaGUgZnVsbCwgYWJzb2x1dGUgcGF0aCBvZiB0aGlzIGNvbnN0cnVjdCBpbiB0aGUgdHJlZS5cbiAgICpcbiAgICogQ29tcG9uZW50cyBhcmUgc2VwYXJhdGVkIGJ5ICcvJy5cbiAgICovXG4gIHB1YmxpYyBnZXQgcGF0aCgpOiBzdHJpbmcgeyByZXR1cm4gdGhpcy5fYWN0dWFsTm9kZS5wYXRoOyB9XG5cbiAgLyoqXG4gICAqIEEgdHJlZS1nbG9iYWwgdW5pcXVlIGFscGhhbnVtZXJpYyBpZGVudGlmaWVyIGZvciB0aGlzIGNvbnN0cnVjdC4gSW5jbHVkZXNcbiAgICogYWxsIGNvbXBvbmVudHMgb2YgdGhlIHRyZWUuXG4gICAqXG4gICAqIEBkZXByZWNhdGVkIHVzZSBgbm9kZS5hZGRyYCB0byBvYnRhaW4gYSBjb25zaXN0ZW50IDQyIGNoYXJhY3RlciBhZGRyZXNzIGZvclxuICAgKiB0aGlzIG5vZGUgKHNlZSBodHRwczovL2dpdGh1Yi5jb20vYXdzL2NvbnN0cnVjdHMvcHVsbC8zMTQpLlxuICAgKiBBbHRlcm5hdGl2ZWx5LCB0byBnZXQgYSBDbG91ZEZvcm1hdGlvbi1jb21wYXRpYmxlIHVuaXF1ZSBpZGVudGlmaWVyLCB1c2VcbiAgICogYE5hbWVzLnVuaXF1ZUlkKClgLlxuICAgKi9cbiAgcHVibGljIGdldCB1bmlxdWVJZCgpOiBzdHJpbmcgeyByZXR1cm4gdGhpcy5fYWN0dWFsTm9kZS51bmlxdWVJZDsgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGFuIG9wYXF1ZSB0cmVlLXVuaXF1ZSBhZGRyZXNzIGZvciB0aGlzIGNvbnN0cnVjdC5cbiAgICpcbiAgICogQWRkcmVzc2VzIGFyZSA0MiBjaGFyYWN0ZXJzIGhleGFkZWNpbWFsIHN0cmluZ3MuIFRoZXkgYmVnaW4gd2l0aCBcImM4XCJcbiAgICogZm9sbG93ZWQgYnkgNDAgbG93ZXJjYXNlIGhleGFkZWNpbWFsIGNoYXJhY3RlcnMgKDAtOWEtZikuXG4gICAqXG4gICAqIEFkZHJlc3NlcyBhcmUgY2FsY3VsYXRlZCB1c2luZyBhIFNIQS0xIG9mIHRoZSBjb21wb25lbnRzIG9mIHRoZSBjb25zdHJ1Y3RcbiAgICogcGF0aC5cbiAgICpcbiAgICogVG8gZW5hYmxlIHJlZmFjdG9yaW5ncyBvZiBjb25zdHJ1Y3QgdHJlZXMsIGNvbnN0cnVjdHMgd2l0aCB0aGUgSUQgYERlZmF1bHRgXG4gICAqIHdpbGwgYmUgZXhjbHVkZWQgZnJvbSB0aGUgY2FsY3VsYXRpb24uIEluIHRob3NlIGNhc2VzIGNvbnN0cnVjdHMgaW4gdGhlXG4gICAqIHNhbWUgdHJlZSBtYXkgaGF2ZSB0aGUgc2FtZSBhZGRyZWVzcy5cbiAgICpcbiAgICogRXhhbXBsZSB2YWx1ZTogYGM4M2EyODQ2ZTUwNmJjYzVmMTA2ODJiNTY0MDg0YmNhMmQyNzU3MDllZWBcbiAgICovXG4gIHB1YmxpYyBnZXQgYWRkcigpOiBzdHJpbmcgeyByZXR1cm4gdGhpcy5fYWN0dWFsTm9kZS5hZGRyOyB9XG5cbiAgLyoqXG4gICAqIFJldHVybiBhIGRpcmVjdCBjaGlsZCBieSBpZCwgb3IgdW5kZWZpbmVkXG4gICAqXG4gICAqIEBwYXJhbSBpZCBJZGVudGlmaWVyIG9mIGRpcmVjdCBjaGlsZFxuICAgKiBAcmV0dXJucyB0aGUgY2hpbGQgaWYgZm91bmQsIG9yIHVuZGVmaW5lZFxuICAgKi9cbiAgcHVibGljIHRyeUZpbmRDaGlsZChpZDogc3RyaW5nKTogSUNvbnN0cnVjdCB8IHVuZGVmaW5lZCB7IHJldHVybiB0aGlzLl9hY3R1YWxOb2RlLnRyeUZpbmRDaGlsZChpZCkgYXMgSUNvbnN0cnVjdDsgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gYSBkaXJlY3QgY2hpbGQgYnkgaWRcbiAgICpcbiAgICogVGhyb3dzIGFuIGVycm9yIGlmIHRoZSBjaGlsZCBpcyBub3QgZm91bmQuXG4gICAqXG4gICAqIEBwYXJhbSBpZCBJZGVudGlmaWVyIG9mIGRpcmVjdCBjaGlsZFxuICAgKiBAcmV0dXJucyBDaGlsZCB3aXRoIHRoZSBnaXZlbiBpZC5cbiAgICovXG4gIHB1YmxpYyBmaW5kQ2hpbGQoaWQ6IHN0cmluZyk6IElDb25zdHJ1Y3QgeyByZXR1cm4gdGhpcy5fYWN0dWFsTm9kZS5maW5kQ2hpbGQoaWQpIGFzIElDb25zdHJ1Y3Q7IH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgY2hpbGQgY29uc3RydWN0IHRoYXQgaGFzIHRoZSBpZCBgRGVmYXVsdGAgb3IgYFJlc291cmNlXCJgLlxuICAgKiBUaGlzIGlzIHVzdWFsbHkgdGhlIGNvbnN0cnVjdCB0aGF0IHByb3ZpZGVzIHRoZSBidWxrIG9mIHRoZSB1bmRlcmx5aW5nIGZ1bmN0aW9uYWxpdHkuXG4gICAqIFVzZWZ1bCBmb3IgbW9kaWZpY2F0aW9ucyBvZiB0aGUgdW5kZXJseWluZyBjb25zdHJ1Y3QgdGhhdCBhcmUgbm90IGF2YWlsYWJsZSBhdCB0aGUgaGlnaGVyIGxldmVscy5cbiAgICpcbiAgICogQHRocm93cyBpZiB0aGVyZSBpcyBtb3JlIHRoYW4gb25lIGNoaWxkXG4gICAqIEByZXR1cm5zIGEgY29uc3RydWN0IG9yIHVuZGVmaW5lZCBpZiB0aGVyZSBpcyBubyBkZWZhdWx0IGNoaWxkXG4gICAqL1xuICBwdWJsaWMgZ2V0IGRlZmF1bHRDaGlsZCgpOiBJQ29uc3RydWN0IHwgdW5kZWZpbmVkIHsgcmV0dXJuIHRoaXMuX2FjdHVhbE5vZGUuZGVmYXVsdENoaWxkIGFzIElDb25zdHJ1Y3Q7IH1cblxuICAvKipcbiAgICogT3ZlcnJpZGUgdGhlIGRlZmF1bHRDaGlsZCBwcm9wZXJ0eS5cbiAgICpcbiAgICogVGhpcyBzaG91bGQgb25seSBiZSB1c2VkIGluIHRoZSBjYXNlcyB3aGVyZSB0aGUgY29ycmVjdFxuICAgKiBkZWZhdWx0IGNoaWxkIGlzIG5vdCBuYW1lZCAnUmVzb3VyY2UnIG9yICdEZWZhdWx0JyBhcyBpdFxuICAgKiBzaG91bGQgYmUuXG4gICAqXG4gICAqIElmIHlvdSBzZXQgdGhpcyB0byB1bmRlZmluZWQsIHRoZSBkZWZhdWx0IGJlaGF2aW9yIG9mIGZpbmRpbmdcbiAgICogdGhlIGNoaWxkIG5hbWVkICdSZXNvdXJjZScgb3IgJ0RlZmF1bHQnIHdpbGwgYmUgdXNlZC5cbiAgICovXG4gIHB1YmxpYyBzZXQgZGVmYXVsdENoaWxkKHZhbHVlOiBJQ29uc3RydWN0IHwgdW5kZWZpbmVkKSB7IHRoaXMuX2FjdHVhbE5vZGUuZGVmYXVsdENoaWxkID0gdmFsdWU7IH1cblxuICAvKipcbiAgICogQWxsIGRpcmVjdCBjaGlsZHJlbiBvZiB0aGlzIGNvbnN0cnVjdC5cbiAgICovXG4gIHB1YmxpYyBnZXQgY2hpbGRyZW4oKTogSUNvbnN0cnVjdFtdIHsgcmV0dXJuIHRoaXMuX2FjdHVhbE5vZGUuY2hpbGRyZW4gYXMgSUNvbnN0cnVjdFtdOyB9XG5cbiAgLyoqXG4gICAqIFJldHVybiB0aGlzIGNvbnN0cnVjdCBhbmQgYWxsIG9mIGl0cyBjaGlsZHJlbiBpbiB0aGUgZ2l2ZW4gb3JkZXJcbiAgICovXG4gIHB1YmxpYyBmaW5kQWxsKG9yZGVyOiBDb25zdHJ1Y3RPcmRlciA9IENvbnN0cnVjdE9yZGVyLlBSRU9SREVSKTogSUNvbnN0cnVjdFtdIHsgcmV0dXJuIHRoaXMuX2FjdHVhbE5vZGUuZmluZEFsbChvcmRlcikgYXMgSUNvbnN0cnVjdFtdOyB9XG5cbiAgLyoqXG4gICAqIFRoaXMgY2FuIGJlIHVzZWQgdG8gc2V0IGNvbnRleHR1YWwgdmFsdWVzLlxuICAgKiBDb250ZXh0IG11c3QgYmUgc2V0IGJlZm9yZSBhbnkgY2hpbGRyZW4gYXJlIGFkZGVkLCBzaW5jZSBjaGlsZHJlbiBtYXkgY29uc3VsdCBjb250ZXh0IGluZm8gZHVyaW5nIGNvbnN0cnVjdGlvbi5cbiAgICogSWYgdGhlIGtleSBhbHJlYWR5IGV4aXN0cywgaXQgd2lsbCBiZSBvdmVycmlkZGVuLlxuICAgKiBAcGFyYW0ga2V5IFRoZSBjb250ZXh0IGtleVxuICAgKiBAcGFyYW0gdmFsdWUgVGhlIGNvbnRleHQgdmFsdWVcbiAgICovXG4gIHB1YmxpYyBzZXRDb250ZXh0KGtleTogc3RyaW5nLCB2YWx1ZTogYW55KSB7XG4gICAgaWYgKFRva2VuLmlzVW5yZXNvbHZlZChrZXkpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgY29udGV4dCBrZXk6IGNvbnRleHQga2V5cyBjYW5cXCd0IGluY2x1ZGUgdG9rZW5zJyk7XG4gICAgfVxuICAgIHRoaXMuX2FjdHVhbE5vZGUuc2V0Q29udGV4dChrZXksIHZhbHVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgYSB2YWx1ZSBmcm9tIHRyZWUgY29udGV4dC5cbiAgICpcbiAgICogQ29udGV4dCBpcyB1c3VhbGx5IGluaXRpYWxpemVkIGF0IHRoZSByb290LCBidXQgY2FuIGJlIG92ZXJyaWRkZW4gYXQgYW55IHBvaW50IGluIHRoZSB0cmVlLlxuICAgKlxuICAgKiBAcGFyYW0ga2V5IFRoZSBjb250ZXh0IGtleVxuICAgKiBAcmV0dXJucyBUaGUgY29udGV4dCB2YWx1ZSBvciBgdW5kZWZpbmVkYCBpZiB0aGVyZSBpcyBubyBjb250ZXh0IHZhbHVlIGZvciB0aGUga2V5LlxuICAgKi9cbiAgcHVibGljIHRyeUdldENvbnRleHQoa2V5OiBzdHJpbmcpOiBhbnkge1xuICAgIGlmIChUb2tlbi5pc1VucmVzb2x2ZWQoa2V5KSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGNvbnRleHQga2V5OiBjb250ZXh0IGtleXMgY2FuXFwndCBpbmNsdWRlIHRva2VucycpO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fYWN0dWFsTm9kZS50cnlHZXRDb250ZXh0KGtleSk7XG4gIH1cblxuICAvKipcbiAgICogREVQUkVDQVRFRFxuICAgKiBAZGVwcmVjYXRlZCB1c2UgYG1ldGFkYXRhRW50cnlgXG4gICAqL1xuICBwdWJsaWMgZ2V0IG1ldGFkYXRhKCkgeyByZXR1cm4gdGhpcy5fYWN0dWFsTm9kZS5tZXRhZGF0YSBhcyBjeGFwaS5NZXRhZGF0YUVudHJ5W107IH1cblxuICAvKipcbiAgICogQW4gaW1tdXRhYmxlIGFycmF5IG9mIG1ldGFkYXRhIG9iamVjdHMgYXNzb2NpYXRlZCB3aXRoIHRoaXMgY29uc3RydWN0LlxuICAgKiBUaGlzIGNhbiBiZSB1c2VkLCBmb3IgZXhhbXBsZSwgdG8gaW1wbGVtZW50IHN1cHBvcnQgZm9yIGRlcHJlY2F0aW9uIG5vdGljZXMsIHNvdXJjZSBtYXBwaW5nLCBldGMuXG4gICAqL1xuICBwdWJsaWMgZ2V0IG1ldGFkYXRhRW50cnkoKSB7IHJldHVybiB0aGlzLl9hY3R1YWxOb2RlLm1ldGFkYXRhOyB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYSBtZXRhZGF0YSBlbnRyeSB0byB0aGlzIGNvbnN0cnVjdC5cbiAgICogRW50cmllcyBhcmUgYXJiaXRyYXJ5IHZhbHVlcyBhbmQgd2lsbCBhbHNvIGluY2x1ZGUgYSBzdGFjayB0cmFjZSB0byBhbGxvdyB0cmFjaW5nIGJhY2sgdG9cbiAgICogdGhlIGNvZGUgbG9jYXRpb24gZm9yIHdoZW4gdGhlIGVudHJ5IHdhcyBhZGRlZC4gSXQgY2FuIGJlIHVzZWQsIGZvciBleGFtcGxlLCB0byBpbmNsdWRlIHNvdXJjZVxuICAgKiBtYXBwaW5nIGluIENsb3VkRm9ybWF0aW9uIHRlbXBsYXRlcyB0byBpbXByb3ZlIGRpYWdub3N0aWNzLlxuICAgKlxuICAgKiBAcGFyYW0gdHlwZSBhIHN0cmluZyBkZW5vdGluZyB0aGUgdHlwZSBvZiBtZXRhZGF0YVxuICAgKiBAcGFyYW0gZGF0YSB0aGUgdmFsdWUgb2YgdGhlIG1ldGFkYXRhIChjYW4gYmUgYSBUb2tlbikuIElmIG51bGwvdW5kZWZpbmVkLCBtZXRhZGF0YSB3aWxsIG5vdCBiZSBhZGRlZC5cbiAgICogQHBhcmFtIGZyb21GdW5jdGlvbiBhIGZ1bmN0aW9uIHVuZGVyIHdoaWNoIHRvIHJlc3RyaWN0IHRoZSBtZXRhZGF0YSBlbnRyeSdzIHN0YWNrIHRyYWNlIChkZWZhdWx0cyB0byB0aGlzLmFkZE1ldGFkYXRhKVxuICAgKi9cbiAgcHVibGljIGFkZE1ldGFkYXRhKHR5cGU6IHN0cmluZywgZGF0YTogYW55LCBmcm9tRnVuY3Rpb24/OiBhbnkpOiB2b2lkIHsgdGhpcy5fYWN0dWFsTm9kZS5hZGRNZXRhZGF0YSh0eXBlLCBkYXRhLCBmcm9tRnVuY3Rpb24pOyB9XG5cbiAgLyoqXG4gICAqIERFUFJFQ0FURUQ6IEFkZHMgYSB7IFwiaW5m