@aws-cdk/core
Version:
AWS Cloud Development Kit Core Library
464 lines • 57.8 kB
JavaScript
"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TagType = exports.CfnResource = void 0;
const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const cxapi = require("@aws-cdk/cx-api");
// import required to be here, otherwise causes a cycle when running the generated JavaScript
/* eslint-disable import/order */
const cfn_element_1 = require("./cfn-element");
const cfn_resource_policy_1 = require("./cfn-resource-policy");
const constructs_1 = require("constructs");
const deps_1 = require("./deps");
const cfn_reference_1 = require("./private/cfn-reference");
const cloudformation_lang_1 = require("./private/cloudformation-lang");
const removal_policy_1 = require("./removal-policy");
const tag_manager_1 = require("./tag-manager");
const token_1 = require("./token");
const util_1 = require("./util");
/**
* Represents a CloudFormation resource.
*/
class CfnResource extends cfn_element_1.CfnRefElement {
/**
* Creates a resource construct.
* @param cfnResourceType The CloudFormation type of this resource (e.g. AWS::DynamoDB::Table)
*/
constructor(scope, id, props) {
super(scope, id);
// MAINTAINERS NOTE: this class serves as the base class for the generated L1
// ("CFN") resources (such as `s3.CfnBucket`). These resources will have a
// property for each CloudFormation property of the resource. This means that
// if at some point in the future a property is introduced with a name similar
// to one of the properties here, it will be "masked" by the derived class. To
// that end, we prefix all properties in this class with `cfnXxx` with the
// hope to avoid those conflicts in the future.
/**
* Options for this resource, such as condition, update policy etc.
*/
this.cfnOptions = {};
/**
* An object to be merged on top of the entire resource definition.
*/
this.rawOverrides = {};
/**
* Logical IDs of dependencies.
*
* Is filled during prepare().
*/
this.dependsOn = new Set();
try {
jsiiDeprecationWarnings._aws_cdk_core_CfnResourceProps(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, CfnResource);
}
throw error;
}
if (!props.type) {
throw new Error('The `type` property is required');
}
this.cfnResourceType = props.type;
this._cfnProperties = props.properties || {};
// if aws:cdk:enable-path-metadata is set, embed the current construct's
// path in the CloudFormation template, so it will be possible to trace
// back to the actual construct path.
if (constructs_1.Node.of(this).tryGetContext(cxapi.PATH_METADATA_ENABLE_CONTEXT)) {
this.addMetadata(cxapi.PATH_METADATA_KEY, constructs_1.Node.of(this).path);
}
}
/**
* Check whether the given construct is a CfnResource
*/
static isCfnResource(construct) {
return construct.cfnResourceType !== undefined;
}
/**
* Sets the deletion policy of the resource based on the removal policy specified.
*
* The Removal Policy controls what happens to this resource when it stops
* being managed by CloudFormation, either because you've removed it from the
* CDK application or because you've made a change that requires the resource
* to be replaced.
*
* The resource can be deleted (`RemovalPolicy.DESTROY`), or left in your AWS
* account for data recovery and cleanup later (`RemovalPolicy.RETAIN`).
*/
applyRemovalPolicy(policy, options = {}) {
try {
jsiiDeprecationWarnings._aws_cdk_core_RemovalPolicy(policy);
jsiiDeprecationWarnings._aws_cdk_core_RemovalPolicyOptions(options);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.applyRemovalPolicy);
}
throw error;
}
policy = policy || options.default || removal_policy_1.RemovalPolicy.RETAIN;
let deletionPolicy;
switch (policy) {
case removal_policy_1.RemovalPolicy.DESTROY:
deletionPolicy = cfn_resource_policy_1.CfnDeletionPolicy.DELETE;
break;
case removal_policy_1.RemovalPolicy.RETAIN:
deletionPolicy = cfn_resource_policy_1.CfnDeletionPolicy.RETAIN;
break;
case removal_policy_1.RemovalPolicy.SNAPSHOT:
deletionPolicy = cfn_resource_policy_1.CfnDeletionPolicy.SNAPSHOT;
break;
default:
throw new Error(`Invalid removal policy: ${policy}`);
}
this.cfnOptions.deletionPolicy = deletionPolicy;
if (options.applyToUpdateReplacePolicy !== false) {
this.cfnOptions.updateReplacePolicy = deletionPolicy;
}
}
/**
* Returns a token for an runtime attribute of this resource.
* Ideally, use generated attribute accessors (e.g. `resource.arn`), but this can be used for future compatibility
* in case there is no generated attribute.
* @param attributeName The name of the attribute.
*/
getAtt(attributeName) {
return cfn_reference_1.CfnReference.for(this, attributeName);
}
/**
* Adds an override to the synthesized CloudFormation resource. To add a
* property override, either use `addPropertyOverride` or prefix `path` with
* "Properties." (i.e. `Properties.TopicName`).
*
* If the override is nested, separate each nested level using a dot (.) in the path parameter.
* If there is an array as part of the nesting, specify the index in the path.
*
* To include a literal `.` in the property name, prefix with a `\`. In most
* programming languages you will need to write this as `"\\."` because the
* `\` itself will need to be escaped.
*
* For example,
* ```typescript
* cfnResource.addOverride('Properties.GlobalSecondaryIndexes.0.Projection.NonKeyAttributes', ['myattribute']);
* cfnResource.addOverride('Properties.GlobalSecondaryIndexes.1.ProjectionType', 'INCLUDE');
* ```
* would add the overrides
* ```json
* "Properties": {
* "GlobalSecondaryIndexes": [
* {
* "Projection": {
* "NonKeyAttributes": [ "myattribute" ]
* ...
* }
* ...
* },
* {
* "ProjectionType": "INCLUDE"
* ...
* },
* ]
* ...
* }
* ```
*
* The `value` argument to `addOverride` will not be processed or translated
* in any way. Pass raw JSON values in here with the correct capitalization
* for CloudFormation. If you pass CDK classes or structs, they will be
* rendered with lowercased key names, and CloudFormation will reject the
* template.
*
* @param path - The path of the property, you can use dot notation to
* override values in complex types. Any intermdediate keys
* will be created as needed.
* @param value - The value. Could be primitive or complex.
*/
addOverride(path, value) {
const parts = splitOnPeriods(path);
let curr = this.rawOverrides;
while (parts.length > 1) {
const key = parts.shift();
// if we can't recurse further or the previous value is not an
// object overwrite it with an object.
const isObject = curr[key] != null && typeof (curr[key]) === 'object' && !Array.isArray(curr[key]);
if (!isObject) {
curr[key] = {};
}
curr = curr[key];
}
const lastKey = parts.shift();
curr[lastKey] = value;
}
/**
* Syntactic sugar for `addOverride(path, undefined)`.
* @param path The path of the value to delete
*/
addDeletionOverride(path) {
this.addOverride(path, undefined);
}
/**
* Adds an override to a resource property.
*
* Syntactic sugar for `addOverride("Properties.<...>", value)`.
*
* @param propertyPath The path of the property
* @param value The value
*/
addPropertyOverride(propertyPath, value) {
this.addOverride(`Properties.${propertyPath}`, value);
}
/**
* Adds an override that deletes the value of a property from the resource definition.
* @param propertyPath The path to the property.
*/
addPropertyDeletionOverride(propertyPath) {
this.addPropertyOverride(propertyPath, undefined);
}
/**
* Indicates that this resource depends on another resource and cannot be
* provisioned unless the other resource has been successfully provisioned.
*
* This can be used for resources across stacks (or nested stack) boundaries
* and the dependency will automatically be transferred to the relevant scope.
*/
addDependsOn(target) {
try {
jsiiDeprecationWarnings._aws_cdk_core_CfnResource(target);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.addDependsOn);
}
throw error;
}
// skip this dependency if the target is not part of the output
if (!target.shouldSynthesize()) {
return;
}
deps_1.addDependency(this, target, `"${constructs_1.Node.of(this).path}" depends on "${constructs_1.Node.of(target).path}"`);
}
/**
* Add a value to the CloudFormation Resource Metadata
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/metadata-section-structure.html
*
* Note that this is a different set of metadata from CDK node metadata; this
* metadata ends up in the stack template under the resource, whereas CDK
* node metadata ends up in the Cloud Assembly.
*/
addMetadata(key, value) {
if (!this.cfnOptions.metadata) {
this.cfnOptions.metadata = {};
}
this.cfnOptions.metadata[key] = value;
}
/**
* Retrieve a value value from the CloudFormation Resource Metadata
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/metadata-section-structure.html
*
* Note that this is a different set of metadata from CDK node metadata; this
* metadata ends up in the stack template under the resource, whereas CDK
* node metadata ends up in the Cloud Assembly.
*/
getMetadata(key) {
return this.cfnOptions.metadata?.[key];
}
/**
* @returns a string representation of this resource
*/
toString() {
return `${super.toString()} [${this.cfnResourceType}]`;
}
/**
* Called by the `addDependency` helper function in order to realize a direct
* dependency between two resources that are directly defined in the same
* stacks.
*
* Use `resource.addDependsOn` to define the dependency between two resources,
* which also takes stack boundaries into account.
*
* @internal
*/
_addResourceDependency(target) {
this.dependsOn.add(target);
}
/**
* Emits CloudFormation for this resource.
* @internal
*/
_toCloudFormation() {
if (!this.shouldSynthesize()) {
return {};
}
try {
const ret = {
Resources: {
// Post-Resolve operation since otherwise deepMerge is going to mix values into
// the Token objects returned by ignoreEmpty.
[this.logicalId]: new util_1.PostResolveToken({
Type: this.cfnResourceType,
Properties: util_1.ignoreEmpty(this.cfnProperties),
DependsOn: util_1.ignoreEmpty(renderDependsOn(this.dependsOn)),
CreationPolicy: util_1.capitalizePropertyNames(this, renderCreationPolicy(this.cfnOptions.creationPolicy)),
UpdatePolicy: util_1.capitalizePropertyNames(this, this.cfnOptions.updatePolicy),
UpdateReplacePolicy: util_1.capitalizePropertyNames(this, this.cfnOptions.updateReplacePolicy),
DeletionPolicy: util_1.capitalizePropertyNames(this, this.cfnOptions.deletionPolicy),
Version: this.cfnOptions.version,
Description: this.cfnOptions.description,
Metadata: util_1.ignoreEmpty(this.cfnOptions.metadata),
Condition: this.cfnOptions.condition && this.cfnOptions.condition.logicalId,
}, resourceDef => {
const renderedProps = this.renderProperties(resourceDef.Properties || {});
if (renderedProps) {
const hasDefined = Object.values(renderedProps).find(v => v !== undefined);
resourceDef.Properties = hasDefined !== undefined ? renderedProps : undefined;
}
const resolvedRawOverrides = token_1.Tokenization.resolve(this.rawOverrides, {
scope: this,
resolver: cloudformation_lang_1.CLOUDFORMATION_TOKEN_RESOLVER,
// we need to preserve the empty elements here,
// as that's how removing overrides are represented as
removeEmpty: false,
});
return deepMerge(resourceDef, resolvedRawOverrides);
}),
},
};
return ret;
}
catch (e) {
// Change message
e.message = `While synthesizing ${this.node.path}: ${e.message}`;
// Adjust stack trace (make it look like node built it, too...)
const trace = this.creationStack;
if (trace) {
const creationStack = ['--- resource created at ---', ...trace].join('\n at ');
const problemTrace = e.stack.slice(e.stack.indexOf(e.message) + e.message.length);
e.stack = `${e.message}\n ${creationStack}\n --- problem discovered at ---${problemTrace}`;
}
// Re-throw
throw e;
}
// returns the set of logical ID (tokens) this resource depends on
// sorted by construct paths to ensure test determinism
function renderDependsOn(dependsOn) {
return Array
.from(dependsOn)
.sort((x, y) => x.node.path.localeCompare(y.node.path))
.map(r => r.logicalId);
}
function renderCreationPolicy(policy) {
if (!policy) {
return undefined;
}
const result = { ...policy };
if (policy.resourceSignal && policy.resourceSignal.timeout) {
result.resourceSignal = policy.resourceSignal;
}
return result;
}
}
get cfnProperties() {
const props = this._cfnProperties || {};
if (tag_manager_1.TagManager.isTaggable(this)) {
const tagsProp = {};
tagsProp[this.tags.tagPropertyName] = this.tags.renderTags();
return deepMerge(props, tagsProp);
}
return props;
}
renderProperties(props) {
return props;
}
/**
* Return properties modified after initiation
*
* Resources that expose mutable properties should override this function to
* collect and return the properties object for this resource.
*/
get updatedProperites() {
return this._cfnProperties;
}
validateProperties(_properties) {
}
/**
* Can be overridden by subclasses to determine if this resource will be rendered
* into the cloudformation template.
*
* @returns `true` if the resource should be included or `false` is the resource
* should be omitted.
*/
shouldSynthesize() {
return true;
}
}
exports.CfnResource = CfnResource;
_a = JSII_RTTI_SYMBOL_1;
CfnResource[_a] = { fqn: "@aws-cdk/core.CfnResource", version: "1.204.0" };
var TagType;
(function (TagType) {
TagType["STANDARD"] = "StandardTag";
TagType["AUTOSCALING_GROUP"] = "AutoScalingGroupTag";
TagType["MAP"] = "StringToStringMap";
TagType["KEY_VALUE"] = "KeyValue";
TagType["NOT_TAGGABLE"] = "NotTaggable";
})(TagType = exports.TagType || (exports.TagType = {}));
/**
* Merges `source` into `target`, overriding any existing values.
* `null`s will cause a value to be deleted.
*/
function deepMerge(target, ...sources) {
for (const source of sources) {
if (typeof (source) !== 'object' || typeof (target) !== 'object') {
throw new Error(`Invalid usage. Both source (${JSON.stringify(source)}) and target (${JSON.stringify(target)}) must be objects`);
}
for (const key of Object.keys(source)) {
const value = source[key];
if (typeof (value) === 'object' && value != null && !Array.isArray(value)) {
// if the value at the target is not an object, override it with an
// object so we can continue the recursion
if (typeof (target[key]) !== 'object') {
target[key] = {};
}
deepMerge(target[key], value);
// if the result of the merge is an empty object, it's because the
// eventual value we assigned is `undefined`, and there are no
// sibling concrete values alongside, so we can delete this tree.
const output = target[key];
if (typeof (output) === 'object' && Object.keys(output).length === 0) {
delete target[key];
}
}
else if (value === undefined) {
delete target[key];
}
else {
target[key] = value;
}
}
}
return target;
}
/**
* Split on periods while processing escape characters \
*/
function splitOnPeriods(x) {
// Build this list in reverse because it's more convenient to get the "current"
// item by doing ret[0] than by ret[ret.length - 1].
const ret = [''];
for (let i = 0; i < x.length; i++) {
if (x[i] === '\\' && i + 1 < x.length) {
ret[0] += x[i + 1];
i++;
}
else if (x[i] === '.') {
ret.unshift('');
}
else {
ret[0] += x[i];
}
}
ret.reverse();
return ret;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2ZuLXJlc291cmNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiY2ZuLXJlc291cmNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLHlDQUF5QztBQUV6Qyw2RkFBNkY7QUFDN0YsaUNBQWlDO0FBQ2pDLCtDQUE4QztBQUM5QywrREFBOEY7QUFDOUYsMkNBQXlEO0FBQ3pELGlDQUF1QztBQUN2QywyREFBdUQ7QUFDdkQsdUVBQThFO0FBRTlFLHFEQUF1RTtBQUN2RSwrQ0FBMkM7QUFDM0MsbUNBQXVDO0FBQ3ZDLGlDQUFnRjtBQWdCaEY7O0dBRUc7QUFDSCxNQUFhLFdBQVksU0FBUSwyQkFBYTtJQThDNUM7OztPQUdHO0lBQ0gsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUF1QjtRQUMvRCxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBM0NuQiw2RUFBNkU7UUFDN0UsMEVBQTBFO1FBQzFFLDZFQUE2RTtRQUM3RSw4RUFBOEU7UUFDOUUsOEVBQThFO1FBQzlFLDBFQUEwRTtRQUMxRSwrQ0FBK0M7UUFFL0M7O1dBRUc7UUFDYSxlQUFVLEdBQXdCLEVBQUUsQ0FBQztRQWVyRDs7V0FFRztRQUNjLGlCQUFZLEdBQVEsRUFBRSxDQUFDO1FBRXhDOzs7O1dBSUc7UUFDYyxjQUFTLEdBQUcsSUFBSSxHQUFHLEVBQWUsQ0FBQzs7Ozs7OytDQTVDekMsV0FBVzs7OztRQXFEcEIsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLEVBQUU7WUFDZixNQUFNLElBQUksS0FBSyxDQUFDLGlDQUFpQyxDQUFDLENBQUM7U0FDcEQ7UUFFRCxJQUFJLENBQUMsZUFBZSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUM7UUFDbEMsSUFBSSxDQUFDLGNBQWMsR0FBRyxLQUFLLENBQUMsVUFBVSxJQUFJLEVBQUUsQ0FBQztRQUU3Qyx3RUFBd0U7UUFDeEUsdUVBQXVFO1FBQ3ZFLHFDQUFxQztRQUNyQyxJQUFJLGlCQUFJLENBQUMsRUFB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QUMsRUFBRSxDQUFDLENBQUM7SUFDakIsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7UUFDakMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sRUFBRTtZQUNyQyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztZQUNuQixDQUFDLEVBQUUsQ0FBQztTQUNMO2FBQU0sSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssR0FBRyxFQUFFO1lBQ3ZCLEdBQUcsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLENBQUM7U0FDakI7YUFBTTtZQUNMLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7U0FDaEI7S0FDRjtJQUVELEdBQUcsQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUNkLE9BQU8sR0FBRyxDQUFDO0FBQ2IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGN4YXBpIGZyb20gJ0Bhd3MtY2RrL2N4LWFwaSc7XG5pbXBvcnQgeyBDZm5Db25kaXRpb24gfSBmcm9tICcuL2Nmbi1jb25kaXRpb24nO1xuLy8gaW1wb3J0IHJlcXVpcmVkIHRvIGJlIGhlcmUsIG90aGVyd2lzZSBjYXVzZXMgYSBjeWNsZSB3aGVuIHJ1bm5pbmcgdGhlIGdlbmVyYXRlZCBKYXZhU2NyaXB0XG4vKiBlc2xpbnQtZGlzYWJsZSBpbXBvcnQvb3JkZXIgKi9cbmltcG9ydCB7IENmblJlZkVsZW1lbnQgfSBmcm9tICcuL2Nmbi1lbGVtZW50JztcbmltcG9ydCB7IENmbkNyZWF0aW9uUG9saWN5LCBDZm5EZWxldGlvblBvbGljeSwgQ2ZuVXBkYXRlUG9saWN5IH0gZnJvbSAnLi9jZm4tcmVzb3VyY2UtcG9saWN5JztcbmltcG9ydCB7IENvbnN0cnVjdCwgSUNvbnN0cnVjdCwgTm9kZSB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0IHsgYWRkRGVwZW5kZW5jeSB9IGZyb20gJy4vZGVwcyc7XG5pbXBvcnQgeyBDZm5SZWZlcmVuY2UgfSBmcm9tICcuL3ByaXZhdGUvY2ZuLXJlZmVyZW5jZSc7XG5pbXBvcnQgeyBDTE9VREZPUk1BVElPTl9UT0tFTl9SRVNPTFZFUiB9IGZyb20gJy4vcHJpdmF0ZS9jbG91ZGZvcm1hdGlvbi1sYW5nJztcbmltcG9ydCB7IFJlZmVyZW5jZSB9IGZyb20gJy4vcmVmZXJlbmNlJztcbmltcG9ydCB7IFJlbW92YWxQb2xpY3ksIFJlbW92YWxQb2xpY3lPcHRpb25zIH0gZnJvbSAnLi9yZW1vdmFsLXBvbGljeSc7XG5pbXBvcnQgeyBUYWdNYW5hZ2VyIH0gZnJvbSAnLi90YWctbWFuYWdlcic7XG5pbXBvcnQgeyBUb2tlbml6YXRpb24gfSBmcm9tICcuL3Rva2VuJztcbmltcG9ydCB7IGNhcGl0YWxpemVQcm9wZXJ0eU5hbWVzLCBpZ25vcmVFbXB0eSwgUG9zdFJlc29sdmVUb2tlbiB9IGZyb20gJy4vdXRpbCc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2ZuUmVzb3VyY2VQcm9wcyB7XG4gIC8qKlxuICAgKiBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZSB0eXBlIChlLmcuIGBBV1M6OlMzOjpCdWNrZXRgKS5cbiAgICovXG4gIHJlYWRvbmx5IHR5cGU6IHN0cmluZztcblxuICAvKipcbiAgICogUmVzb3VyY2UgcHJvcGVydGllcy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBObyByZXNvdXJjZSBwcm9wZXJ0aWVzLlxuICAgKi9cbiAgcmVhZG9ubHkgcHJvcGVydGllcz86IHsgW25hbWU6IHN0cmluZ106IGFueSB9O1xufVxuXG4vKipcbiAqIFJlcHJlc2VudHMgYSBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZS5cbiAqL1xuZXhwb3J0IGNsYXNzIENmblJlc291cmNlIGV4dGVuZHMgQ2ZuUmVmRWxlbWVudCB7XG4gIC8qKlxuICAgKiBDaGVjayB3aGV0aGVyIHRoZSBnaXZlbiBjb25zdHJ1Y3QgaXMgYSBDZm5SZXNvdXJjZVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBpc0NmblJlc291cmNlKGNvbnN0cnVjdDogSUNvbnN0cnVjdCk6IGNvbnN0cnVjdCBpcyBDZm5SZXNvdXJjZSB7XG4gICAgcmV0dXJuIChjb25zdHJ1Y3QgYXMgYW55KS5jZm5SZXNvdXJjZVR5cGUgIT09IHVuZGVmaW5lZDtcbiAgfVxuXG4gIC8vIE1BSU5UQUlORVJTIE5PVEU6IHRoaXMgY2xhc3Mgc2VydmVzIGFzIHRoZSBiYXNlIGNsYXNzIGZvciB0aGUgZ2VuZXJhdGVkIEwxXG4gIC8vIChcIkNGTlwiKSByZXNvdXJjZXMgKHN1Y2ggYXMgYHMzLkNmbkJ1Y2tldGApLiBUaGVzZSByZXNvdXJjZXMgd2lsbCBoYXZlIGFcbiAgLy8gcHJvcGVydHkgZm9yIGVhY2ggQ2xvdWRGb3JtYXRpb24gcHJvcGVydHkgb2YgdGhlIHJlc291cmNlLiBUaGlzIG1lYW5zIHRoYXRcbiAgLy8gaWYgYXQgc29tZSBwb2ludCBpbiB0aGUgZnV0dXJlIGEgcHJvcGVydHkgaXMgaW50cm9kdWNlZCB3aXRoIGEgbmFtZSBzaW1pbGFyXG4gIC8vIHRvIG9uZSBvZiB0aGUgcHJvcGVydGllcyBoZXJlLCBpdCB3aWxsIGJlIFwibWFza2VkXCIgYnkgdGhlIGRlcml2ZWQgY2xhc3MuIFRvXG4gIC8vIHRoYXQgZW5kLCB3ZSBwcmVmaXggYWxsIHByb3BlcnRpZXMgaW4gdGhpcyBjbGFzcyB3aXRoIGBjZm5YeHhgIHdpdGggdGhlXG4gIC8vIGhvcGUgdG8gYXZvaWQgdGhvc2UgY29uZmxpY3RzIGluIHRoZSBmdXR1cmUuXG5cbiAgLyoqXG4gICAqIE9wdGlvbnMgZm9yIHRoaXMgcmVzb3VyY2UsIHN1Y2ggYXMgY29uZGl0aW9uLCB1cGRhdGUgcG9saWN5IGV0Yy5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBjZm5PcHRpb25zOiBJQ2ZuUmVzb3VyY2VPcHRpb25zID0ge307XG5cbiAgLyoqXG4gICAqIEFXUyByZXNvdXJjZSB0eXBlLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGNmblJlc291cmNlVHlwZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBV1MgQ2xvdWRGb3JtYXRpb24gcmVzb3VyY2UgcHJvcGVydGllcy5cbiAgICpcbiAgICogVGhpcyBvYmplY3QgaXMgcmV0dXJuZWQgdmlhIGNmblByb3BlcnRpZXNcbiAgICogQGludGVybmFsXG4gICAqL1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgX2NmblByb3BlcnRpZXM6IGFueTtcblxuICAvKipcbiAgICogQW4gb2JqZWN0IHRvIGJlIG1lcmdlZCBvbiB0b3Agb2YgdGhlIGVudGlyZSByZXNvdXJjZSBkZWZpbml0aW9uLlxuICAgKi9cbiAgcHJpdmF0ZSByZWFkb25seSByYXdPdmVycmlkZXM6IGFueSA9IHt9O1xuXG4gIC8qKlxuICAgKiBMb2dpY2FsIElEcyBvZiBkZXBlbmRlbmNpZXMuXG4gICAqXG4gICAqIElzIGZpbGxlZCBkdXJpbmcgcHJlcGFyZSgpLlxuICAgKi9cbiAgcHJpdmF0ZSByZWFkb25seSBkZXBlbmRzT24gPSBuZXcgU2V0PENmblJlc291cmNlPigpO1xuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgcmVzb3VyY2UgY29uc3RydWN0LlxuICAgKiBAcGFyYW0gY2ZuUmVzb3VyY2VUeXBlIFRoZSBDbG91ZEZvcm1hdGlvbiB0eXBlIG9mIHRoaXMgcmVzb3VyY2UgKGUuZy4gQVdTOjpEeW5hbW9EQjo6VGFibGUpXG4gICAqL1xuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogQ2ZuUmVzb3VyY2VQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICBpZiAoIXByb3BzLnR5cGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVGhlIGB0eXBlYCBwcm9wZXJ0eSBpcyByZXF1aXJlZCcpO1xuICAgIH1cblxuICAgIHRoaXMuY2ZuUmVzb3VyY2VUeXBlID0gcHJvcHMudHlwZTtcbiAgICB0aGlzLl9jZm5Qcm9wZXJ0aWVzID0gcHJvcHMucHJvcGVydGllcyB8fCB7fTtcblxuICAgIC8vIGlmIGF3czpjZGs6ZW5hYmxlLXBhdGgtbWV0YWRhdGEgaXMgc2V0LCBlbWJlZCB0aGUgY3VycmVudCBjb25zdHJ1Y3Qnc1xuICAgIC8vIHBhdGggaW4gdGhlIENsb3VkRm9ybWF0aW9uIHRlbXBsYXRlLCBzbyBpdCB3aWxsIGJlIHBvc3NpYmxlIHRvIHRyYWNlXG4gICAgLy8gYmFjayB0byB0aGUgYWN0dWFsIGNvbnN0cnVjdCBwYXRoLlxuICAgIGlmIChOb2RlLm9mKHRoaXMpLnRyeUdldENvbnRleHQoY3hhcGkuUEFUSF9NRVRBREFUQV9FTkFCTEVfQ09OVEVYVCkpIHtcbiAgICAgIHRoaXMuYWRkTWV0YWRhdGEoY3hhcGkuUEFUSF9NRVRBREFUQV9LRVksIE5vZGUub2YodGhpcykucGF0aCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdGhlIGRlbGV0aW9uIHBvbGljeSBvZiB0aGUgcmVzb3VyY2UgYmFzZWQgb24gdGhlIHJlbW92YWwgcG9saWN5IHNwZWNpZmllZC5cbiAgICpcbiAgICogVGhlIFJlbW92YWwgUG9saWN5IGNvbnRyb2xzIHdoYXQgaGFwcGVucyB0byB0aGlzIHJlc291cmNlIHdoZW4gaXQgc3RvcHNcbiAgICogYmVpbmcgbWFuYWdlZCBieSBDbG91ZEZvcm1hdGlvbiwgZWl0aGVyIGJlY2F1c2UgeW91J3ZlIHJlbW92ZWQgaXQgZnJvbSB0aGVcbiAgICogQ0RLIGFwcGxpY2F0aW9uIG9yIGJlY2F1c2UgeW91J3ZlIG1hZGUgYSBjaGFuZ2UgdGhhdCByZXF1aXJlcyB0aGUgcmVzb3VyY2VcbiAgICogdG8gYmUgcmVwbGFjZWQuXG4gICAqXG4gICAqIFRoZSByZXNvdXJjZSBjYW4gYmUgZGVsZXRlZCAoYFJlbW92YWxQb2xpY3kuREVTVFJPWWApLCBvciBsZWZ0IGluIHlvdXIgQVdTXG4gICAqIGFjY291bnQgZm9yIGRhdGEgcmVjb3ZlcnkgYW5kIGNsZWFudXAgbGF0ZXIgKGBSZW1vdmFsUG9saWN5LlJFVEFJTmApLlxuICAgKi9cbiAgcHVibGljIGFwcGx5UmVtb3ZhbFBvbGljeShwb2xpY3k6IFJlbW92YWxQb2xpY3kgfCB1bmRlZmluZWQsIG9wdGlvbnM6IFJlbW92YWxQb2xpY3lPcHRpb25zID0ge30pIHtcbiAgICBwb2xpY3kgPSBwb2xpY3kgfHwgb3B0aW9ucy5kZWZhdWx0IHx8IFJlbW92YWxQb2xpY3kuUkVUQUlOO1xuXG4gICAgbGV0IGRlbGV0aW9uUG9saWN5O1xuXG4gICAgc3dpdGNoIChwb2xpY3kpIHtcbiAgICAgIGNhc2UgUmVtb3ZhbFBvbGljeS5ERVNUUk9ZOlxuICAgICAgICBkZWxldGlvblBvbGljeSA9IENmbkRlbGV0aW9uUG9saWN5LkRFTEVURTtcbiAgICAgICAgYnJlYWs7XG5cbiAgICAgIGNhc2UgUmVtb3ZhbFBvbGljeS5SRVRBSU46XG4gICAgICAgIGRlbGV0aW9uUG9saWN5ID0gQ2ZuRGVsZXRpb25Qb2xpY3kuUkVUQUlOO1xuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSBSZW1vdmFsUG9saWN5LlNOQVBTSE9UOlxuICAgICAgICBkZWxldGlvblBvbGljeSA9IENmbkRlbGV0aW9uUG9saWN5LlNOQVBTSE9UO1xuICAgICAgICBicmVhaztcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIHJlbW92YWwgcG9saWN5OiAke3BvbGljeX1gKTtcbiAgICB9XG5cbiAgICB0aGlzLmNmbk9wdGlvbnMuZGVsZXRpb25Qb2xpY3kgPSBkZWxldGlvblBvbGljeTtcbiAgICBpZiAob3B0aW9ucy5hcHBseVRvVXBkYXRlUmVwbGFjZVBvbGljeSAhPT0gZmFsc2UpIHtcbiAgICAgIHRoaXMuY2ZuT3B0aW9ucy51cGRhdGVSZXBsYWNlUG9saWN5ID0gZGVsZXRpb25Qb2xpY3k7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSB0b2tlbiBmb3IgYW4gcnVudGltZSBhdHRyaWJ1dGUgb2YgdGhpcyByZXNvdXJjZS5cbiAgICogSWRlYWxseSwgdXNlIGdlbmVyYXRlZCBhdHRyaWJ1dGUgYWNjZXNzb3JzIChlLmcuIGByZXNvdXJjZS5hcm5gKSwgYnV0IHRoaXMgY2FuIGJlIHVzZWQgZm9yIGZ1dHVyZSBjb21wYXRpYmlsaXR5XG4gICAqIGluIGNhc2UgdGhlcmUgaXMgbm8gZ2VuZXJhdGVkIGF0dHJpYnV0ZS5cbiAgICogQHBhcmFtIGF0dHJpYnV0ZU5hbWUgVGhlIG5hbWUgb2YgdGhlIGF0dHJpYnV0ZS5cbiAgICovXG4gIHB1YmxpYyBnZXRBdHQoYXR0cmlidXRlTmFtZTogc3RyaW5nKTogUmVmZXJlbmNlIHtcbiAgICByZXR1cm4gQ2ZuUmVmZXJlbmNlLmZvcih0aGlzLCBhdHRyaWJ1dGVOYW1lKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGFuIG92ZXJyaWRlIHRvIHRoZSBzeW50aGVzaXplZCBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZS4gVG8gYWRkIGFcbiAgICogcHJvcGVydHkgb3ZlcnJpZGUsIGVpdGhlciB1c2UgYGFkZFByb3BlcnR5T3ZlcnJpZGVgIG9yIHByZWZpeCBgcGF0aGAgd2l0aFxuICAgKiBcIlByb3BlcnRpZXMuXCIgKGkuZS4gYFByb3BlcnRpZXMuVG9waWNOYW1lYCkuXG4gICAqXG4gICAqIElmIHRoZSBvdmVycmlkZSBpcyBuZXN0ZWQsIHNlcGFyYXRlIGVhY2ggbmVzdGVkIGxldmVsIHVzaW5nIGEgZG90ICguKSBpbiB0aGUgcGF0aCBwYXJhbWV0ZXIuXG4gICAqIElmIHRoZXJlIGlzIGFuIGFycmF5IGFzIHBhcnQgb2YgdGhlIG5lc3RpbmcsIHNwZWNpZnkgdGhlIGluZGV4IGluIHRoZSBwYXRoLlxuICAgKlxuICAgKiBUbyBpbmNsdWRlIGEgbGl0ZXJhbCBgLmAgaW4gdGhlIHByb3BlcnR5IG5hbWUsIHByZWZpeCB3aXRoIGEgYFxcYC4gSW4gbW9zdFxuICAgKiBwcm9ncmFtbWluZyBsYW5ndWFnZXMgeW91IHdpbGwgbmVlZCB0byB3cml0ZSB0aGlzIGFzIGBcIlxcXFwuXCJgIGJlY2F1c2UgdGhlXG4gICAqIGBcXGAgaXRzZWxmIHdpbGwgbmVlZCB0byBiZSBlc2NhcGVkLlxuICAgKlxuICAgKiBGb3IgZXhhbXBsZSxcbiAgICogYGBgdHlwZXNjcmlwdFxuICAgKiBjZm5SZXNvdXJjZS5hZGRPdmVycmlkZSgnUHJvcGVydGllcy5HbG9iYWxTZWNvbmRhcnlJbmRleGVzLjAuUHJvamVjdGlvbi5Ob25LZXlBdHRyaWJ1dGVzJywgWydteWF0dHJpYnV0ZSddKTtcbiAgICogY2ZuUmVzb3VyY2UuYWRkT3ZlcnJpZGUoJ1Byb3BlcnRpZXMuR2xvYmFsU2Vjb25kYXJ5SW5kZXhlcy4xLlByb2plY3Rpb25UeXBlJywgJ0lOQ0xVREUnKTtcbiAgICogYGBgXG4gICAqIHdvdWxkIGFkZCB0aGUgb3ZlcnJpZGVzXG4gICAqIGBgYGpzb25cbiAgICogXCJQcm9wZXJ0aWVzXCI6IHtcbiAgICogICBcIkdsb2JhbFNlY29uZGFyeUluZGV4ZXNcIjogW1xuICAgKiAgICAge1xuICAgKiAgICAgICBcIlByb2plY3Rpb25cIjoge1xuICAgKiAgICAgICAgIFwiTm9uS2V5QXR0cmlidXRlc1wiOiBbIFwibXlhdHRyaWJ1dGVcIiBdXG4gICAqICAgICAgICAgLi4uXG4gICAqICAgICAgIH1cbiAgICogICAgICAgLi4uXG4gICAqICAgICB9LFxuICAgKiAgICAge1xuICAgKiAgICAgICBcIlByb2plY3Rpb25UeXBlXCI6IFwiSU5DTFVERVwiXG4gICAqICAgICAgIC4uLlxuICAgKiAgICAgfSxcbiAgICogICBdXG4gICAqICAgLi4uXG4gICAqIH1cbiAgICogYGBgXG4gICAqXG4gICAqIFRoZSBgdmFsdWVgIGFyZ3VtZW50IHRvIGBhZGRPdmVycmlkZWAgd2lsbCBub3QgYmUgcHJvY2Vzc2VkIG9yIHRyYW5zbGF0ZWRcbiAgICogaW4gYW55IHdheS4gUGFzcyByYXcgSlNPTiB2YWx1ZXMgaW4gaGVyZSB3aXRoIHRoZSBjb3JyZWN0IGNhcGl0YWxpemF0aW9uXG4gICAqIGZvciBDbG91ZEZvcm1hdGlvbi4gSWYgeW91IHBhc3MgQ0RLIGNsYXNzZXMgb3Igc3RydWN0cywgdGhleSB3aWxsIGJlXG4gICAqIHJlbmRlcmVkIHdpdGggbG93ZXJjYXNlZCBrZXkgbmFtZXMsIGFuZCBDbG91ZEZvcm1hdGlvbiB3aWxsIHJlamVjdCB0aGVcbiAgICogdGVtcGxhdGUuXG4gICAqXG4gICAqIEBwYXJhbSBwYXRoIC0gVGhlIHBhdGggb2YgdGhlIHByb3BlcnR5LCB5b3UgY2FuIHVzZSBkb3Qgbm90YXRpb24gdG9cbiAgICogICAgICAgIG92ZXJyaWRlIHZhbHVlcyBpbiBjb21wbGV4IHR5cGVzLiBBbnkgaW50ZXJtZGVkaWF0ZSBrZXlzXG4gICAqICAgICAgICB3aWxsIGJlIGNyZWF0ZWQgYXMgbmVlZGVkLlxuICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgdmFsdWUuIENvdWxkIGJlIHByaW1pdGl2ZSBvciBjb21wbGV4LlxuICAgKi9cbiAgcHVibGljIGFkZE92ZXJyaWRlKHBhdGg6IHN0cmluZywgdmFsdWU6IGFueSkge1xuICAgIGNvbnN0IHBhcnRzID0gc3BsaXRPblBlcmlvZHMocGF0aCk7XG4gICAgbGV0IGN1cnI6IGFueSA9IHRoaXMucmF3T3ZlcnJpZGVzO1xuXG4gICAgd2hpbGUgKHBhcnRzLmxlbmd0aCA+IDEpIHtcbiAgICAgIGNvbnN0IGtleSA9IHBhcnRzLnNoaWZ0KCkhO1xuXG4gICAgICAvLyBpZiB3ZSBjYW4ndCByZWN1cnNlIGZ1cnRoZXIgb3IgdGhlIHByZXZpb3VzIHZhbHVlIGlzIG5vdCBhblxuICAgICAgLy8gb2JqZWN0IG92ZXJ3cml0ZSBpdCB3aXRoIGFuIG9iamVjdC5cbiAgICAgIGNvbnN0IGlzT2JqZWN0ID0gY3VycltrZXldICE9IG51bGwgJiYgdHlwZW9mKGN1cnJba2V5XSkgPT09ICdvYmplY3QnICYmICFBcnJheS5pc0FycmF5KGN1cnJba2V5XSk7XG4gICAgICBpZiAoIWlzT2JqZWN0KSB7XG4gICAgICAgIGN1cnJba2V5XSA9IHt9O1xuICAgICAgfVxuXG4gICAgICBjdXJyID0gY3VycltrZXldO1xuICAgIH1cblxuICAgIGNvbnN0IGxhc3RLZXkgPSBwYXJ0cy5zaGlmdCgpITtcbiAgICBjdXJyW2xhc3RLZXldID0gdmFsdWU7XG4gIH1cblxuICAvKipcbiAgICogU3ludGFjdGljIHN1Z2FyIGZvciBgYWRkT3ZlcnJpZGUocGF0aCwgdW5kZWZpbmVkKWAuXG4gICAqIEBwYXJhbSBwYXRoIFRoZSBwYXRoIG9mIHRoZSB2YWx1ZSB0byBkZWxldGVcbiAgICovXG4gIHB1YmxpYyBhZGREZWxldGlvbk92ZXJyaWRlKHBhdGg6IHN0cmluZykge1xuICAgIHRoaXMuYWRkT3ZlcnJpZGUocGF0aCwgdW5kZWZpbmVkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGFuIG92ZXJyaWRlIHRvIGEgcmVzb3VyY2UgcHJvcGVydHkuXG4gICAqXG4gICAqIFN5bnRhY3RpYyBzdWdhciBmb3IgYGFkZE92ZXJyaWRlKFwiUHJvcGVydGllcy48Li4uPlwiLCB2YWx1ZSlgLlxuICAgKlxuICAgKiBAcGFyYW0gcHJvcGVydHlQYXRoIFRoZSBwYXRoIG9mIHRoZSBwcm9wZXJ0eVxuICAgKiBAcGFyYW0gdmFsdWUgVGhlIHZhbHVlXG4gICAqL1xuICBwdWJsaWMgYWRkUHJvcGVydHlPdmVycmlkZShwcm9wZXJ0eVBhdGg6IHN0cmluZywgdmFsdWU6IGFueSkge1xuICAgIHRoaXMuYWRkT3ZlcnJpZGUoYFByb3BlcnRpZXMuJHtwcm9wZXJ0eVBhdGh9YCwgdmFsdWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYW4gb3ZlcnJpZGUgdGhhdCBkZWxldGVzIHRoZSB2YWx1ZSBvZiBhIHByb3BlcnR5IGZyb20gdGhlIHJlc291cmNlIGRlZmluaXRpb24uXG4gICAqIEBwYXJhbSBwcm9wZXJ0eVBhdGggVGhlIHBhdGggdG8gdGhlIHByb3BlcnR5LlxuICAgKi9cbiAgcHVibGljIGFkZFByb3BlcnR5RGVsZXRpb25PdmVycmlkZShwcm9wZXJ0eVBhdGg6IHN0cmluZykge1xuICAgIHRoaXMuYWRkUHJvcGVydHlPdmVycmlkZShwcm9wZXJ0eVBhdGgsIHVuZGVmaW5lZCk7XG4gIH1cblxuICAvKipcbiAgICogSW5kaWNhdGVzIHRoYXQgdGhpcyByZXNvdXJjZSBkZXBlbmRzIG9uIGFub3RoZXIgcmVzb3VyY2UgYW5kIGNhbm5vdCBiZVxuICAgKiBwcm92aXNpb25lZCB1bmxlc3MgdGhlIG90aGVyIHJlc291cmNlIGhhcyBiZWVuIHN1Y2Nlc3NmdWxseSBwcm92aXNpb25lZC5cbiAgICpcbiAgICogVGhpcyBjYW4gYmUgdXNlZCBmb3IgcmVzb3VyY2VzIGFjcm9zcyBzdGFja3MgKG9yIG5lc3RlZCBzdGFjaykgYm91bmRhcmllc1xuICAgKiBhbmQgdGhlIGRlcGVuZGVuY3kgd2lsbCBhdXRvbWF0aWNhbGx5IGJlIHRyYW5zZmVycmVkIHRvIHRoZSByZWxldmFudCBzY29wZS5cbiAgICovXG4gIHB1YmxpYyBhZGREZXBlbmRzT24odGFyZ2V0OiBDZm5SZXNvdXJjZSkge1xuICAgIC8vIHNraXAgdGhpcyBkZXBlbmRlbmN5IGlmIHRoZSB0YXJnZXQgaXMgbm90IHBhcnQgb2YgdGhlIG91dHB1dFxuICAgIGlmICghdGFyZ2V0LnNob3VsZFN5bnRoZXNpemUoKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGFkZERlcGVuZGVuY3kodGhpcywgdGFyZ2V0LCBgXCIke05vZGUub2YodGhpcykucGF0aH1cIiBkZXBlbmRzIG9uIFwiJHtOb2RlLm9mKHRhcmdldCkucGF0aH1cImApO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBhIHZhbHVlIHRvIHRoZSBDbG91ZEZvcm1hdGlvbiBSZXNvdXJjZSBNZXRhZGF0YVxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL21ldGFkYXRhLXNlY3Rpb24tc3RydWN0dXJlLmh0bWxcbiAgICpcbiAgICogTm90ZSB0aGF0IHRoaXMgaXMgYSBkaWZmZXJlbnQgc2V0IG9mIG1ldGFkYXRhIGZyb20gQ0RLIG5vZGUgbWV0YWRhdGE7IHRoaXNcbiAgICogbWV0YWRhdGEgZW5kcyB1cCBpbiB0aGUgc3RhY2sgdGVtcGxhdGUgdW5kZXIgdGhlIHJlc291cmNlLCB3aGVyZWFzIENES1xuICAgKiBub2RlIG1ldGFkYXRhIGVuZHMgdXAgaW4gdGhlIENsb3VkIEFzc2VtYmx5LlxuICAgKi9cbiAgcHVibGljIGFkZE1ldGFkYXRhKGtleTogc3RyaW5nLCB2YWx1ZTogYW55KSB7XG4gICAgaWYgKCF0aGlzLmNmbk9wdGlvbnMubWV0YWRhdGEpIHtcbiAgICAgIHRoaXMuY2ZuT3B0aW9ucy5tZXRhZGF0YSA9IHt9O1xuICAgIH1cblxuICAgIHRoaXMuY2ZuT3B0aW9ucy5tZXRhZGF0YVtrZXldID0gdmFsdWU7XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmUgYSB2YWx1ZSB2YWx1ZSBmcm9tIHRoZSBDbG91ZEZvcm1hdGlvbiBSZXNvdXJjZSBNZXRhZGF0YVxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL21ldGFkYXRhLXNlY3Rpb24tc3RydWN0dXJlLmh0bWxcbiAgICpcbiAgICogTm90ZSB0aGF0IHRoaXMgaXMgYSBkaWZmZXJlbnQgc2V0IG9mIG1ldGFkYXRhIGZyb20gQ0RLIG5vZGUgbWV0YWRhdGE7IHRoaXNcbiAgICogbWV0YWRhdGEgZW5kcyB1cCBpbiB0aGUgc3RhY2sgdGVtcGxhdGUgdW5kZXIgdGhlIHJlc291cmNlLCB3aGVyZWFzIENES1xuICAgKiBub2RlIG1ldGFkYXRhIGVuZHMgdXAgaW4gdGhlIENsb3VkIEFzc2VtYmx5LlxuICAgKi9cbiAgcHVibGljIGdldE1ldGFkYXRhKGtleTogc3RyaW5nKTogYW55IHtcbiAgICByZXR1cm4gdGhpcy5jZm5PcHRpb25zLm1ldGFkYXRhPy5ba2V5XTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJucyBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGlzIHJlc291cmNlXG4gICAqL1xuICBwdWJsaWMgdG9TdHJpbmcoKSB7XG4gICAgcmV0dXJuIGAke3N1cGVyLnRvU3RyaW5nKCl9IFske3RoaXMuY2ZuUmVzb3VyY2VUeXBlfV1gO1xuICB9XG5cbiAgLyoqXG4gICAqIENhbGxlZCBieSB0aGUgYGFkZERlcGVuZGVuY3lgIGhlbHBlciBmdW5jdGlvbiBpbiBvcmRlciB0byByZWFsaXplIGEgZGlyZWN0XG4gICAqIGRlcGVuZGVuY3kgYmV0d2VlbiB0d28gcmVzb3VyY2VzIHRoYXQgYXJlIGRpcmVjdGx5IGRlZmluZWQgaW4gdGhlIHNhbWVcbiAgICogc3RhY2tzLlxuICAgKlxuICAgKiBVc2UgYHJlc291cmNlLmFkZERlcGVuZHNPbmAgdG8gZGVmaW5lIHRoZSBkZXBlbmRlbmN5IGJldHdlZW4gdHdvIHJlc291cmNlcyxcbiAgICogd2hpY2ggYWxzbyB0YWtlcyBzdGFjayBib3VuZGFyaWVzIGludG8gYWNjb3VudC5cbiAgICpcbiAgICogQGludGVybmFsXG4gICAqL1xuICBwdWJsaWMgX2FkZFJlc291cmNlRGVwZW5kZW5jeSh0YXJnZXQ6IENmblJlc291cmNlKSB7XG4gICAgdGhpcy5kZXBlbmRzT24uYWRkKHRhcmdldCk7XG4gIH1cblxuICAvKipcbiAgICogRW1pdHMgQ2xvdWRGb3JtYXRpb24gZm9yIHRoaXMgcmVzb3VyY2UuXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHVibGljIF90b0Nsb3VkRm9ybWF0aW9uKCk6IG9iamVjdCB7XG4gICAgaWYgKCF0aGlzLnNob3VsZFN5bnRoZXNpemUoKSkge1xuICAgICAgcmV0dXJuIHsgfTtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcmV0ID0ge1xuICAgICAgICBSZXNvdXJjZXM6IHtcbiAgICAgICAgICAvLyBQb3N0LVJlc29sdmUgb3BlcmF0aW9uIHNpbmNlIG90aGVyd2lzZSBkZWVwTWVyZ2UgaXMgZ29pbmcgdG8gbWl4IHZhbHVlcyBpbnRvXG4gICAgICAgICAgLy8gdGhlIFRva2VuIG9iamVjdHMgcmV0dXJuZWQgYnkgaWdub3JlRW1wdHkuXG4gICAgICAgICAgW3RoaXMubG9naWNhbElkXTogbmV3IFBvc3RSZXNvbHZlVG9rZW4oe1xuICAgICAgICAgICAgVHlwZTogdGhpcy5jZm5SZXNvdXJjZVR5cGUsXG4gICAgICAgICAgICBQcm9wZXJ0aWVzOiBpZ25vcmVFbXB0eSh0aGlzLmNmblByb3BlcnRpZXMpLFxuICAgICAgICAgICAgRGVwZW5kc09uOiBpZ25vcmVFbXB0eShyZW5kZXJEZXBlbmRzT24odGhpcy5kZXBlbmRzT24pKSxcbiAgICAgICAgICAgIENyZWF0aW9uUG9saWN5OiBjYXBpdGFsaXplUHJvcGVydHlOYW1lcyh0aGlzLCByZW5kZXJDcmVhdGlvblBvbGljeSh0aGlzLmNmbk9wdGlvbnMuY3JlYXRpb25Qb2xpY3kpKSxcbiAgICAgICAgICAgIFVwZGF0ZVBvbGljeTogY2FwaXRhbGl6ZVByb3BlcnR5TmFtZXModGhpcywgdGhpcy5jZm5PcHRpb25zLnVwZGF0ZVBvbGljeSksXG4gICAgICAgICAgICBVcGRhdGVSZXBsYWNlUG9saWN5OiBjYXBpdGFsaXplUHJvcGVydHlOYW1lcyh0aGlzLCB0aGlzLmNmbk9wdGlvbnMudXBkYXRlUmVwbGFjZVBvbGljeSksXG4gICAgICAgICAgICBEZWxldGlvblBvbGljeTogY2FwaXRhbGl6ZVByb3BlcnR5TmFtZXModGhpcywgdGhpcy5jZm5PcHRpb25zLmRlbGV0aW9uUG9saWN5KSxcbiAgICAgICAgICAgIFZlcnNpb246IHRoaXMuY2ZuT3B0aW9ucy52ZXJzaW9uLFxuICAgICAgICAgICAgRGVzY3JpcHRpb246IHRoaXMuY2ZuT3B0aW9ucy5kZXNjcmlwdGlvbixcbiAgICAgICAgICAgIE1ldGFkYXRhOiBpZ25vcmVFbXB0eSh0aGlzLmNmbk9wdGlvbnMubWV0YWRhdGEpLFxuICAgICAgICAgICAgQ29uZGl0aW9uOiB0aGlzLmNmbk9wdGlvbnMuY29uZGl0aW9uICYmIHRoaXMuY2ZuT3B0aW9ucy5jb25kaXRpb24ubG9naWNhbElkLFxuICAgICAgICAgIH0sIHJlc291cmNlRGVmID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHJlbmRlcmVkUHJvcHMgPSB0aGlzLnJlbmRlclByb3BlcnRpZXMocmVzb3VyY2VEZWYuUHJvcGVydGllcyB8fCB7fSk7XG4gICAgICAgICAgICBpZiAocmVuZGVyZWRQcm9wcykge1xuICAgICAgICAgICAgICBjb25zdCBoYXNEZWZpbmVkID0gT2JqZWN0LnZhbHVlcyhyZW5kZXJlZFByb3BzKS5maW5kKHYgPT4gdiAhPT0gdW5kZWZpbmVkKTtcbiAgICAgICAgICAgICAgcmVzb3VyY2VEZWYuUHJvcGVydGllcyA9IGhhc0RlZmluZWQgIT09IHVuZGVmaW5lZCA/IHJlbmRlcmVkUHJvcHMgOiB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCByZXNvbHZlZFJhd092ZXJyaWRlcyA9IFRva2VuaXphdGlvbi5yZXNvbHZlKHRoaXMucmF3T3ZlcnJpZGVzLCB7XG4gICAgICAgICAgICAgIHNjb3BlOiB0aGlzLFxuICAgICAgICAgICAgICByZXNvbHZlcjogQ0xPVURGT1JNQVRJT05fVE9LRU5fUkVTT0xWRVIsXG4gICAgICAgICAgICAgIC8vIHdlIG5lZWQgdG8gcHJlc2VydmUgdGhlIGVtcHR5IGVsZW1lbnRzIGhlcmUsXG4gICAgICAgICAgICAgIC8vIGFzIHRoYXQncyBob3cgcmVtb3Zpbmcgb3ZlcnJpZGVzIGFyZSByZXByZXNlbnRlZCBhc1xuICAgICAgICAgICAgICByZW1vdmVFbXB0eTogZmFsc2UsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybiBkZWVwTWVyZ2UocmVzb3VyY2VEZWYsIHJlc29sdmVkUmF3T3ZlcnJpZGVzKTtcbiAgICAgICAgICB9KSxcbiAgICAgICAgfSxcbiAgICAgIH07XG4gICAgICByZXR1cm4gcmV0O1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIC8vIENoYW5nZSBtZXNzYWdlXG4gICAgICBlLm1lc3NhZ2UgPSBgV2hpbGUgc3ludGhlc2l6aW5nICR7dGhpcy5ub2RlLnBhdGh9OiAke2UubWVzc2FnZX1gO1xuICAgICAgLy8gQWRqdXN0IHN0YWNrIHRyYWNlIChtYWtlIGl0IGxvb2sgbGlrZSBub2RlIGJ1aWx0IGl0LCB0b28uLi4pXG4gICAgICBjb25zdCB0cmFjZSA9IHRoaXMuY3JlYXRpb25TdGFjaztcbiAgICAgIGlmICh0cmFjZSkge1xuICAgICAgICBjb25zdCBjcmVhdGlvblN0YWNrID0gWyctLS0gcmVzb3VyY2UgY3JlYXRlZCBhdCAtLS0nLCAuLi50cmFjZV0uam9pbignXFxuICBhdCAnKTtcbiAgICAgICAgY29uc3QgcHJvYmxlbVRyYWNlID0gZS5zdGFjay5zbGljZShlLnN0YWNrLmluZGV4T2YoZS5tZXNzYWdlKSArIGUubWVzc2FnZS5sZW5ndGgpO1xuICAgICAgICBlLnN0YWNrID0gYCR7ZS5tZXNzYWdlfVxcbiAgJHtjcmVhdGlvblN0YWNrfVxcbiAgLS0tIHByb2JsZW0gZGlzY292ZXJlZCBhdCAtLS0ke3Byb2JsZW1UcmFjZX1gO1xuICAgICAgfVxuXG4gICAgICAvLyBSZS10aHJvd1xuICAgICAgdGhyb3cgZTtcbiAgICB9XG5cbiAgICAvLyByZXR1cm5zIHRoZSBzZXQgb2YgbG9naWNhbCBJRCAodG9rZW5zKSB0aGlzIHJlc291cmNlIGRlcGVuZHMgb25cbiAgICAvLyBzb3J0ZWQgYnkgY29uc3RydWN0IHBhdGhzIHRvIGVuc3VyZSB0ZXN0IGRldGVybWluaXNtXG4gICAgZnVuY3Rpb24gcmVuZGVyRGVwZW5kc09uKGRlcGVuZHNPbjogU2V0PENmblJlc291cmNlPikge1xuICAgICAgcmV0dXJuIEFycmF5XG4gICAgICAgIC5mcm9tKGRlcGVuZHNPbilcbiAgICAgICAgLnNvcnQoKHgsIHkpID0+IHgubm9kZS5wYXRoLmxvY2FsZUNvbXBhcmUoeS5ub2RlLnBhdGgpKVxuICAgICAgICAubWFwKHIgPT4gci5sb2dpY2FsSWQpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJlbmRlckNyZWF0aW9uUG9saWN5KHBvbGljeTogQ2ZuQ3JlYXRpb25Qb2xpY3kgfCB1bmRlZmluZWQpOiBhbnkge1xuICAgICAgaWYgKCFwb2xpY3kpIHsgcmV0dXJuIHVuZGVmaW5lZDsgfVxuICAgICAgY29uc3QgcmVzdWx0OiBhbnkgPSB7IC4uLnBvbGljeSB9O1xuICAgICAgaWYgKHBvbGljeS5yZXNvdXJjZVNpZ25hbCAmJiBwb2xpY3kucmVzb3VyY2VTaWduYWwudGltZW91dCkge1xuICAgICAgICByZXN1bHQucmVzb3VyY2VTaWduYWwgPSBwb2xpY3kucmVzb3VyY2VTaWduYWw7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCBnZXQgY2ZuUHJvcGVydGllcygpOiB7IFtrZXk6IHN0cmluZ106IGFueSB9IHtcbiAgICBjb25zdCBwcm9wcyA9IHRoaXMuX2NmblByb3BlcnRpZXMgfHwge307XG4gICAgaWYgKFRhZ01hbmFnZXIuaXNUYWdnYWJsZSh0aGlzKSkge1xuICAgICAgY29uc3QgdGFnc1Byb3A6IHsgW2tleTogc3RyaW5nXTogYW55IH0gPSB7fTtcbiAgICAgIHRhZ3NQcm9wW3RoaXMudGFncy50YWdQcm9wZXJ0eU5hbWVdID0gdGhpcy50YWdzLnJlbmRlclRhZ3Mo