cdk-monitoring-constructs
Version:
[](https://badge.fury.io/js/cdk-monitoring-constructs) [](https://m
448 lines • 59.2 kB
JavaScript
"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.MonitoringAspect = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const aws_cdk_lib_1 = require("aws-cdk-lib");
const apigw = require("aws-cdk-lib/aws-apigateway");
const apigwv2 = require("aws-cdk-lib/aws-apigatewayv2");
const appsync = require("aws-cdk-lib/aws-appsync");
const autoscaling = require("aws-cdk-lib/aws-autoscaling");
const acm = require("aws-cdk-lib/aws-certificatemanager");
const cloudfront = require("aws-cdk-lib/aws-cloudfront");
const codebuild = require("aws-cdk-lib/aws-codebuild");
const docdb = require("aws-cdk-lib/aws-docdb");
const dynamodb = require("aws-cdk-lib/aws-dynamodb");
const ecs = require("aws-cdk-lib/aws-ecs");
const ecsPatterns = require("aws-cdk-lib/aws-ecs-patterns");
const elasticsearch = require("aws-cdk-lib/aws-elasticsearch");
const glue = require("aws-cdk-lib/aws-glue");
const kinesis = require("aws-cdk-lib/aws-kinesis");
const kinesisanalytics = require("aws-cdk-lib/aws-kinesisanalytics");
const kinesisfirehose = require("aws-cdk-lib/aws-kinesisfirehose");
const lambda = require("aws-cdk-lib/aws-lambda");
const opensearch = require("aws-cdk-lib/aws-opensearchservice");
const rds = require("aws-cdk-lib/aws-rds");
const redshift = require("aws-cdk-lib/aws-redshift");
const s3 = require("aws-cdk-lib/aws-s3");
const secretsmanager = require("aws-cdk-lib/aws-secretsmanager");
const sns = require("aws-cdk-lib/aws-sns");
const sqs = require("aws-cdk-lib/aws-sqs");
const stepfunctions = require("aws-cdk-lib/aws-stepfunctions");
const synthetics = require("aws-cdk-lib/aws-synthetics");
const wafv2 = require("aws-cdk-lib/aws-wafv2");
const monitoring_1 = require("../monitoring");
/**
* A CDK aspect that adds support for monitoring all resources within scope.
*/
class MonitoringAspect {
constructor(monitoringFacade, props = {}) {
this.monitoringFacade = monitoringFacade;
this.props = props;
/**
* Whether or not we've added a monitoring to the scope for node independent monitorings.
*/
this.addedNodeIndependentMonitoringToScope = false;
}
visit(node) {
this.monitorAcm(node);
this.monitorApiGateway(node);
this.monitorApiGatewayV2(node);
this.monitorAppSync(node);
this.monitorAuroraCluster(node);
this.monitorAutoScalingGroup(node);
this.monitorCloudFront(node);
this.monitorCodeBuild(node);
this.monitorDocumentDb(node);
this.monitorDynamoDb(node);
this.monitorFargateService(node);
this.monitorFargateLoadBalancedService(node);
this.monitorQueueProcessingFargateService(node);
this.monitorGlue(node);
this.monitorKinesisAnalytics(node);
this.monitorKinesisDataStream(node);
this.monitorKinesisDataStreamConsumer(node);
this.monitorKinesisFirehose(node);
this.monitorLambda(node);
this.monitorOpenSearch(node);
this.monitorRdsCluster(node);
this.monitorRdsInstance(node);
this.monitorRedshift(node);
this.monitorS3(node);
this.monitorSecretsManager(node);
this.monitorSns(node);
this.monitorSqs(node);
this.monitorStepFunctions(node);
this.monitorSyntheticsCanaries(node);
this.monitorWebApplicationFirewallV2Acls(node);
if (!this.addedNodeIndependentMonitoringToScope) {
this.addedNodeIndependentMonitoringToScope = true;
this.monitorEc2();
this.monitorBilling();
this.monitorElasticCache();
}
}
getMonitoringDetails(aspectOptions) {
const isEnabled = aspectOptions?.enabled ?? true;
const props = aspectOptions?.props;
return [isEnabled, props];
}
monitorAcm(node) {
const [isEnabled, props] = this.getMonitoringDetails(this.props.acm);
if (isEnabled && node instanceof acm.Certificate) {
this.monitoringFacade.monitorCertificate({
certificate: node,
alarmFriendlyName: node.node.path,
...props,
});
}
}
monitorApiGateway(node) {
const [isEnabled, props] = this.getMonitoringDetails(this.props.apiGateway);
if (isEnabled && node instanceof apigw.RestApi) {
this.monitoringFacade.monitorApiGateway({
api: node,
apiStage: node.deploymentStage.stageName,
...props,
});
}
}
monitorApiGatewayV2(node) {
const [isEnabled, props] = this.getMonitoringDetails(this.props.apiGatewayV2);
if (isEnabled && node instanceof apigwv2.HttpApi) {
this.monitoringFacade.monitorApiGatewayV2HttpApi({
api: node,
...props,
});
}
}
monitorAppSync(node) {
const [isEnabled, props] = this.getMonitoringDetails(this.props.appSync);
if (isEnabled && node instanceof appsync.GraphqlApi) {
this.monitoringFacade.monitorAppSyncApi({
api: node,
alarmFriendlyName: node.node.path,
...props,
});
}
}
monitorAuroraCluster(node) {
const [isEnabled, props] = this.getMonitoringDetails(this.props.auroraCluster);
if (isEnabled && node instanceof rds.ServerlessCluster) {
this.monitoringFacade.monitorAuroraCluster({
cluster: node,
alarmFriendlyName: node.node.path,
...props,
});
}
}
monitorAutoScalingGroup(node) {
const [isEnabled, props] = this.getMonitoringDetails(this.props.autoScalingGroup);
if (isEnabled && node instanceof autoscaling.AutoScalingGroup) {
this.monitoringFacade.monitorAutoScalingGroup({
autoScalingGroup: node,
...props,
});
}
}
monitorBilling() {
const [isEnabled, props] = this.getMonitoringDetails(this.props.billing);
if (isEnabled) {
this.monitoringFacade.monitorBilling({
...props,
alarmFriendlyName: "Billing",
});
}
}
monitorCloudFront(node) {
const [isEnabled, props] = this.getMonitoringDetails(this.props.cloudFront);
if (isEnabled && node instanceof cloudfront.Distribution) {
this.monitoringFacade.monitorCloudFrontDistribution({
distribution: node,
...props,
});
}
}
monitorCodeBuild(node) {
const [isEnabled, props] = this.getMonitoringDetails(this.props.codeBuild);
if (isEnabled && node instanceof codebuild.Project) {
this.monitoringFacade.monitorCodeBuildProject({
project: node,
...props,
});
}
}
monitorDocumentDb(node) {
const [isEnabled, props] = this.getMonitoringDetails(this.props.documentDb);
if (isEnabled && node instanceof docdb.DatabaseCluster) {
this.monitoringFacade.monitorDocumentDbCluster({
cluster: node,
alarmFriendlyName: node.node.path,
...props,
});
}
}
monitorDynamoDb(node) {
const [isEnabled, props] = this.getMonitoringDetails(this.props.dynamoDB);
if (isEnabled && node instanceof dynamodb.Table) {
this.monitoringFacade.monitorDynamoTable({
table: node,
...props,
});
}
}
monitorEc2() {
const [isEnabled, props] = this.getMonitoringDetails(this.props.ec2);
if (isEnabled) {
this.monitoringFacade.monitorEC2Instances({
...props,
});
}
}
monitorElasticCache() {
const [isEnabled, props] = this.getMonitoringDetails(this.props.elasticCache);
if (isEnabled) {
this.monitoringFacade.monitorElastiCacheCluster({
clusterType: monitoring_1.ElastiCacheClusterType.MEMCACHED,
...props,
});
this.monitoringFacade.monitorElastiCacheCluster({
clusterType: monitoring_1.ElastiCacheClusterType.REDIS,
...props,
});
}
}
monitorFargateService(node) {
const [isEnabled, props] = this.getMonitoringDetails(this.props.fargateService);
if (isEnabled &&
node instanceof ecs.FargateService &&
!this.isInsideFargatePattern(node)) {
this.monitoringFacade.monitorSimpleFargateService({
fargateService: node,
...props,
});
}
}
monitorFargateLoadBalancedService(node) {
const [isEnabled, props] = this.getMonitoringDetails(this.props.fargateLoadBalancedService);
if (isEnabled &&
(node instanceof ecsPatterns.ApplicationLoadBalancedFargateService ||
node instanceof ecsPatterns.NetworkLoadBalancedFargateService)) {
this.monitoringFacade.monitorFargateService({
fargateService: node,
...props,
});
}
}
monitorQueueProcessingFargateService(node) {
const [isEnabled, props] = this.getMonitoringDetails(this.props.queueProcessingFargateService);
if (isEnabled &&
node instanceof ecsPatterns.QueueProcessingFargateService) {
this.monitoringFacade.monitorQueueProcessingFargateService({
fargateService: node,
...props,
});
}
}
/**
* Returns true if the FargateService is owned by an L3 ecs-patterns
* construct (ApplicationLoadBalancedFargateService,
* NetworkLoadBalancedFargateService, QueueProcessingFargateService).
* The L3 pattern has its own aspect hook, so monitoring the inner
* service separately would duplicate alarms.
*/
isInsideFargatePattern(service) {
const MAX_ANCESTOR_DEPTH = 3;
let current = service.node.scope;
for (let i = 0; i < MAX_ANCESTOR_DEPTH && current; i++) {
if (current instanceof ecsPatterns.ApplicationLoadBalancedFargateService ||
current instanceof ecsPatterns.NetworkLoadBalancedFargateService ||
current instanceof ecsPatterns.QueueProcessingFargateService) {
return true;
}
current = current.node.scope;
}
return false;
}
monitorGlue(node) {
const [isEnabled, props] = this.getMonitoringDetails(this.props.glue);
if (isEnabled && node instanceof glue.CfnJob) {
this.monitoringFacade.monitorGlueJob({
jobName: node.name,
...props,
});
}
}
monitorKinesisAnalytics(node) {
const [isEnabled, props] = this.getMonitoringDetails(this.props.kinesisDataAnalytics);
if (isEnabled && node instanceof kinesisanalytics.CfnApplication) {
this.monitoringFacade.monitorKinesisDataAnalytics({
application: node.applicationName,
alarmFriendlyName: node.node.path,
...props,
});
}
}
monitorKinesisDataStream(node) {
const [isEnabled, props] = this.getMonitoringDetails(this.props.kinesisDataStream);
if (isEnabled && node instanceof kinesis.CfnStream) {
this.monitoringFacade.monitorKinesisDataStream({
streamName: node.name,
alarmFriendlyName: node.node.path,
...props,
});
}
}
monitorKinesisDataStreamConsumer(node) {
const [isEnabled, props] = this.getMonitoringDetails(this.props.kinesisDataStreamConsumer);
if (isEnabled && node instanceof kinesis.CfnStreamConsumer) {
const streamName = aws_cdk_lib_1.Arn.split(node.streamArn, aws_cdk_lib_1.ArnFormat.SLASH_RESOURCE_NAME).resourceName;
this.monitoringFacade.monitorKinesisDataStreamConsumer({
streamName,
consumerName: node.consumerName,
alarmFriendlyName: node.node.path,
...props,
});
}
}
monitorKinesisFirehose(node) {
const [isEnabled, props] = this.getMonitoringDetails(this.props.kinesisFirehose);
if (isEnabled && node instanceof kinesisfirehose.CfnDeliveryStream) {
this.monitoringFacade.monitorKinesisFirehose({
deliveryStreamName: node.deliveryStreamName,
alarmFriendlyName: node.node.path,
...props,
});
}
}
monitorLambda(node) {
const [isEnabled, props] = this.getMonitoringDetails(this.props.lambda);
if (isEnabled && node instanceof lambda.Function) {
this.monitoringFacade.monitorLambdaFunction({
lambdaFunction: node,
...props,
});
}
}
monitorOpenSearch(node) {
const [isEnabled, props] = this.getMonitoringDetails(this.props.openSearch);
if (isEnabled &&
(node instanceof elasticsearch.Domain ||
node instanceof elasticsearch.CfnDomain ||
node instanceof opensearch.Domain ||
node instanceof opensearch.CfnDomain)) {
this.monitoringFacade.monitorOpenSearchCluster({
domain: node,
...props,
});
}
}
monitorRdsCluster(node) {
const [isEnabled, props] = this.getMonitoringDetails(this.props.rdsCluster ?? this.props.rds);
if (isEnabled && node instanceof rds.DatabaseCluster) {
this.monitoringFacade.monitorRdsCluster({
cluster: node,
alarmFriendlyName: node.node.path,
...props,
});
}
}
monitorRdsInstance(node) {
const [isEnabled, props] = this.getMonitoringDetails(this.props.rdsInstance);
if (isEnabled && node instanceof rds.DatabaseInstance) {
this.monitoringFacade.monitorRdsInstance({
instance: node,
alarmFriendlyName: node.node.path,
...props,
});
}
}
monitorRedshift(node) {
const [isEnabled, props] = this.getMonitoringDetails(this.props.redshift);
if (isEnabled && this.isProbablyL2RedshiftCluster(node)) {
const cfnCluster = node.cluster;
this.monitoringFacade.monitorRedshiftCluster({
clusterIdentifier: cfnCluster.ref,
alarmFriendlyName: cfnCluster.node.path,
...props,
});
}
}
isProbablyL2RedshiftCluster(node) {
return (node.cluster instanceof redshift.CfnCluster &&
!!node.clusterName &&
!!node.node?.path);
}
monitorS3(node) {
const [isEnabled, props] = this.getMonitoringDetails(this.props.s3);
if (isEnabled && node instanceof s3.Bucket) {
this.monitoringFacade.monitorS3Bucket({
bucket: node,
...props,
});
}
}
monitorSecretsManager(node) {
const [isEnabled, props] = this.getMonitoringDetails(this.props.secretsManager);
if (isEnabled && node instanceof secretsmanager.Secret) {
this.monitoringFacade.monitorSecretsManagerSecret({
secret: node,
...props,
});
}
}
monitorSns(node) {
const [isEnabled, props] = this.getMonitoringDetails(this.props.sns);
if (isEnabled && node instanceof sns.Topic) {
this.monitoringFacade.monitorSnsTopic({
topic: node,
...props,
});
}
}
monitorSqs(node) {
const [isEnabled, props] = this.getMonitoringDetails(this.props.sqs);
if (isEnabled && node instanceof sqs.Queue) {
this.monitoringFacade.monitorSqsQueue({
queue: node,
...props,
});
}
}
monitorStepFunctions(node) {
const [isEnabled, props] = this.getMonitoringDetails(this.props.stepFunctions);
if (isEnabled && node instanceof stepfunctions.StateMachine) {
this.monitoringFacade.monitorStepFunction({
stateMachine: node,
...props,
});
}
}
monitorSyntheticsCanaries(node) {
const [isEnabled, props] = this.getMonitoringDetails(this.props.syntheticsCanaries);
if (isEnabled && node instanceof synthetics.Canary) {
this.monitoringFacade.monitorSyntheticsCanary({
canary: node,
...props,
});
}
}
monitorWebApplicationFirewallV2Acls(node) {
const [isEnabled, props] = this.getMonitoringDetails(this.props.webApplicationFirewallAclV2);
if (isEnabled && node instanceof wafv2.CfnWebACL) {
const regionProps = {};
if (node.scope === "REGIONAL") {
regionProps.region = aws_cdk_lib_1.Stack.of(node).region;
}
this.monitoringFacade.monitorWebApplicationFirewallAclV2({
acl: node,
...regionProps,
...props,
});
}
}
}
exports.MonitoringAspect = MonitoringAspect;
_a = JSII_RTTI_SYMBOL_1;
MonitoringAspect[_a] = { fqn: "cdk-monitoring-constructs.MonitoringAspect", version: "10.0.0" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTW9uaXRvcmluZ0FzcGVjdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIk1vbml0b3JpbmdBc3BlY3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSw2Q0FBNkQ7QUFDN0Qsb0RBQW9EO0FBQ3BELHdEQUF3RDtBQUN4RCxtREFBbUQ7QUFDbkQsMkRBQTJEO0FBQzNELDBEQUEwRDtBQUMxRCx5REFBeUQ7QUFDekQsdURBQXVEO0FBQ3ZELCtDQUErQztBQUMvQyxxREFBcUQ7QUFDckQsMkNBQTJDO0FBQzNDLDREQUE0RDtBQUM1RCwrREFBK0Q7QUFDL0QsNkNBQTZDO0FBQzdDLG1EQUFtRDtBQUNuRCxxRUFBcUU7QUFDckUsbUVBQW1FO0FBQ25FLGlEQUFpRDtBQUNqRCxnRUFBZ0U7QUFDaEUsMkNBQTJDO0FBQzNDLHFEQUFxRDtBQUNyRCx5Q0FBeUM7QUFDekMsaUVBQWlFO0FBQ2pFLDJDQUEyQztBQUMzQywyQ0FBMkM7QUFDM0MsK0RBQStEO0FBQy9ELHlEQUF5RDtBQUN6RCwrQ0FBK0M7QUFRL0MsOENBQXVEO0FBRXZEOztHQUVHO0FBQ0gsTUFBYSxnQkFBZ0I7SUFNM0IsWUFDbUIsZ0JBQWtDLEVBQ2xDLFFBQStCLEVBQUU7UUFEakMscUJBQWdCLEdBQWhCLGdCQUFnQixDQUFrQjtRQUNsQyxVQUFLLEdBQUwsS0FBSyxDQUE0QjtRQVBwRDs7V0FFRztRQUNLLDBDQUFxQyxHQUFHLEtBQUssQ0FBQztJQUtuRCxDQUFDO0lBRUcsS0FBSyxDQUFDLElBQWdCO1FBQzNCLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDdEIsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzdCLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUMvQixJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQzFCLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsQ0FB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QUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUFNLENBQUM7WUFDN0MsQ0FBQztZQUVELElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxrQ0FBa0MsQ0FBQztnQkFDdkQsR0FBRyxFQUFFLElBQUk7Z0JBQ1QsR0FBRyxXQUFXO2dCQUNkLEdBQUcsS0FBSzthQUNULENBQUMsQ0FBQztRQUNMLENBQUM7SUFDSCxDQUFDOztBQWpmSCw0Q0FrZkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJQXNwZWN0LCBTdGFjaywgQXJuLCBBcm5Gb3JtYXQgfSBmcm9tIFwiYXdzLWNkay1saWJcIjtcbmltcG9ydCAqIGFzIGFwaWd3IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtYXBpZ2F0ZXdheVwiO1xuaW1wb3J0ICogYXMgYXBpZ3d2MiBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWFwaWdhdGV3YXl2MlwiO1xuaW1wb3J0ICogYXMgYXBwc3luYyBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWFwcHN5bmNcIjtcbmltcG9ydCAqIGFzIGF1dG9zY2FsaW5nIGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtYXV0b3NjYWxpbmdcIjtcbmltcG9ydCAqIGFzIGFjbSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWNlcnRpZmljYXRlbWFuYWdlclwiO1xuaW1wb3J0ICogYXMgY2xvdWRmcm9udCBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWNsb3VkZnJvbnRcIjtcbmltcG9ydCAqIGFzIGNvZGVidWlsZCBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWNvZGVidWlsZFwiO1xuaW1wb3J0ICogYXMgZG9jZGIgZnJvbSBcImF3cy1jZGstbGliL2F3cy1kb2NkYlwiO1xuaW1wb3J0ICogYXMgZHluYW1vZGIgZnJvbSBcImF3cy1jZGstbGliL2F3cy1keW5hbW9kYlwiO1xuaW1wb3J0ICogYXMgZWNzIGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtZWNzXCI7XG5pbXBvcnQgKiBhcyBlY3NQYXR0ZXJucyBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWVjcy1wYXR0ZXJuc1wiO1xuaW1wb3J0ICogYXMgZWxhc3RpY3NlYXJjaCBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWVsYXN0aWNzZWFyY2hcIjtcbmltcG9ydCAqIGFzIGdsdWUgZnJvbSBcImF3cy1jZGstbGliL2F3cy1nbHVlXCI7XG5pbXBvcnQgKiBhcyBraW5lc2lzIGZyb20gXCJhd3MtY2RrLWxpYi9hd3Mta2luZXNpc1wiO1xuaW1wb3J0ICogYXMga2luZXNpc2FuYWx5dGljcyBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWtpbmVzaXNhbmFseXRpY3NcIjtcbmltcG9ydCAqIGFzIGtpbmVzaXNmaXJlaG9zZSBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWtpbmVzaXNmaXJlaG9zZVwiO1xuaW1wb3J0ICogYXMgbGFtYmRhIGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtbGFtYmRhXCI7XG5pbXBvcnQgKiBhcyBvcGVuc2VhcmNoIGZyb20gXCJhd3MtY2RrLWxpYi9hd3Mtb3BlbnNlYXJjaHNlcnZpY2VcIjtcbmltcG9ydCAqIGFzIHJkcyBmcm9tIFwiYXdzLWNkay1saWIvYXdzLXJkc1wiO1xuaW1wb3J0ICogYXMgcmVkc2hpZnQgZnJvbSBcImF3cy1jZGstbGliL2F3cy1yZWRzaGlmdFwiO1xuaW1wb3J0ICogYXMgczMgZnJvbSBcImF3cy1jZGstbGliL2F3cy1zM1wiO1xuaW1wb3J0ICogYXMgc2VjcmV0c21hbmFnZXIgZnJvbSBcImF3cy1jZGstbGliL2F3cy1zZWNyZXRzbWFuYWdlclwiO1xuaW1wb3J0ICogYXMgc25zIGZyb20gXCJhd3MtY2RrLWxpYi9hd3Mtc25zXCI7XG5pbXBvcnQgKiBhcyBzcXMgZnJvbSBcImF3cy1jZGstbGliL2F3cy1zcXNcIjtcbmltcG9ydCAqIGFzIHN0ZXBmdW5jdGlvbnMgZnJvbSBcImF3cy1jZGstbGliL2F3cy1zdGVwZnVuY3Rpb25zXCI7XG5pbXBvcnQgKiBhcyBzeW50aGV0aWNzIGZyb20gXCJhd3MtY2RrLWxpYi9hd3Mtc3ludGhldGljc1wiO1xuaW1wb3J0ICogYXMgd2FmdjIgZnJvbSBcImF3cy1jZGstbGliL2F3cy13YWZ2MlwiO1xuaW1wb3J0IHsgSUNvbnN0cnVjdCB9IGZyb20gXCJjb25zdHJ1Y3RzXCI7XG5cbmltcG9ydCB7XG4gIE1vbml0b3JpbmdBc3BlY3RQcm9wcyxcbiAgQmFzZU1vbml0b3JpbmdBc3BlY3RUeXBlLFxufSBmcm9tIFwiLi9JTW9uaXRvcmluZ0FzcGVjdFwiO1xuaW1wb3J0IHsgTW9uaXRvcmluZ0ZhY2FkZSB9IGZyb20gXCIuL01vbml0b3JpbmdGYWNhZGVcIjtcbmltcG9ydCB7IEVsYXN0aUNhY2hlQ2x1c3RlclR5cGUgfSBmcm9tIFwiLi4vbW9uaXRvcmluZ1wiO1xuXG4vKipcbiAqIEEgQ0RLIGFzcGVjdCB0aGF0IGFkZHMgc3VwcG9ydCBmb3IgbW9uaXRvcmluZyBhbGwgcmVzb3VyY2VzIHdpdGhpbiBzY29wZS5cbiAqL1xuZXhwb3J0IGNsYXNzIE1vbml0b3JpbmdBc3BlY3QgaW1wbGVtZW50cyBJQXNwZWN0IHtcbiAgLyoqXG4gICAqIFdoZXRoZXIgb3Igbm90IHdlJ3ZlIGFkZGVkIGEgbW9uaXRvcmluZyB0byB0aGUgc2NvcGUgZm9yIG5vZGUgaW5kZXBlbmRlbnQgbW9uaXRvcmluZ3MuXG4gICAqL1xuICBwcml2YXRlIGFkZGVkTm9kZUluZGVwZW5kZW50TW9uaXRvcmluZ1RvU2NvcGUgPSBmYWxzZTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHJlYWRvbmx5IG1vbml0b3JpbmdGYWNhZGU6IE1vbml0b3JpbmdGYWNhZGUsXG4gICAgcHJpdmF0ZSByZWFkb25seSBwcm9wczogTW9uaXRvcmluZ0FzcGVjdFByb3BzID0ge30sXG4gICkge31cblxuICBwdWJsaWMgdmlzaXQobm9kZTogSUNvbnN0cnVjdCk6IHZvaWQge1xuICAgIHRoaXMubW9uaXRvckFjbShub2RlKTtcbiAgICB0aGlzLm1vbml0b3JBcGlHYXRld2F5KG5vZGUpO1xuICAgIHRoaXMubW9uaXRvckFwaUdhdGV3YXlWMihub2RlKTtcbiAgICB0aGlzLm1vbml0b3JBcHBTeW5jKG5vZGUpO1xuICAgIHRoaXMubW9uaXRvckF1cm9yYUNsdXN0ZXIobm9kZSk7XG4gICAgdGhpcy5tb25pdG9yQXV0b1NjYWxpbmdHcm91cChub2RlKTtcbiAgICB0aGlzLm1vbml0b3JDbG91ZEZyb250KG5vZGUpO1xuICAgIHRoaXMubW9uaXRvckNvZGVCdWlsZChub2RlKTtcbiAgICB0aGlzLm1vbml0b3JEb2N1bWVudERiKG5vZGUpO1xuICAgIHRoaXMubW9uaXRvckR5bmFtb0RiKG5vZGUpO1xuICAgIHRoaXMubW9uaXRvckZhcmdhdGVTZXJ2aWNlKG5vZGUpO1xuICAgIHRoaXMubW9uaXRvckZhcmdhdGVMb2FkQmFsYW5jZWRTZXJ2aWNlKG5vZGUpO1xuICAgIHRoaXMubW9uaXRvclF1ZXVlUHJvY2Vzc2luZ0ZhcmdhdGVTZXJ2aWNlKG5vZGUpO1xuICAgIHRoaXMubW9uaXRvckdsdWUobm9kZSk7XG4gICAgdGhpcy5tb25pdG9yS2luZXNpc0FuYWx5dGljcyhub2RlKTtcbiAgICB0aGlzLm1vbml0b3JLaW5lc2lzRGF0YVN0cmVhbShub2RlKTtcbiAgICB0aGlzLm1vbml0b3JLaW5lc2lzRGF0YVN0cmVhbUNvbnN1bWVyKG5vZGUpO1xuICAgIHRoaXMubW9uaXRvcktpbmVzaXNGaXJlaG9zZShub2RlKTtcbiAgICB0aGlzLm1vbml0b3JMYW1iZGEobm9kZSk7XG4gICAgdGhpcy5tb25pdG9yT3BlblNlYXJjaChub2RlKTtcbiAgICB0aGlzLm1vbml0b3JSZHNDbHVzdGVyKG5vZGUpO1xuICAgIHRoaXMubW9uaXRvclJkc0luc3RhbmNlKG5vZGUpO1xuICAgIHRoaXMubW9uaXRvclJlZHNoaWZ0KG5vZGUpO1xuICAgIHRoaXMubW9uaXRvclMzKG5vZGUpO1xuICAgIHRoaXMubW9uaXRvclNlY3JldHNNYW5hZ2VyKG5vZGUpO1xuICAgIHRoaXMubW9uaXRvclNucyhub2RlKTtcbiAgICB0aGlzLm1vbml0b3JTcXMobm9kZSk7XG4gICAgdGhpcy5tb25pdG9yU3RlcEZ1bmN0aW9ucyhub2RlKTtcbiAgICB0aGlzLm1vbml0b3JTeW50aGV0aWNzQ2FuYXJpZXMobm9kZSk7XG4gICAgdGhpcy5tb25pdG9yV2ViQXBwbGljYXRpb25GaXJld2FsbFYyQWNscyhub2RlKTtcblxuICAgIGlmICghdGhpcy5hZGRlZE5vZGVJbmRlcGVuZGVudE1vbml0b3JpbmdUb1Njb3BlKSB7XG4gICAgICB0aGlzLmFkZGVkTm9kZUluZGVwZW5kZW50TW9uaXRvcmluZ1RvU2NvcGUgPSB0cnVlO1xuXG4gICAgICB0aGlzLm1vbml0b3JFYzIoKTtcbiAgICAgIHRoaXMubW9uaXRvckJpbGxpbmcoKTtcbiAgICAgIHRoaXMubW9uaXRvckVsYXN0aWNDYWNoZSgpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZ2V0TW9uaXRvcmluZ0RldGFpbHM8VCBleHRlbmRzIFJlY29yZDxzdHJpbmcsIGFueT4+KFxuICAgIGFzcGVjdE9wdGlvbnM/OiBCYXNlTW9uaXRvcmluZ0FzcGVjdFR5cGUgJiB7IHByb3BzPzogVCB9LFxuICApOiBbYm9vbGVhbiwgVD9dIHtcbiAgICBjb25zdCBpc0VuYWJsZWQgPSBhc3BlY3RPcHRpb25zPy5lbmFibGVkID8/IHRydWU7XG4gICAgY29uc3QgcHJvcHMgPSBhc3BlY3RPcHRpb25zPy5wcm9wcztcbiAgICByZXR1cm4gW2lzRW5hYmxlZCwgcHJvcHNdO1xuICB9XG5cbiAgcHJpdmF0ZSBtb25pdG9yQWNtKG5vZGU6IElDb25zdHJ1Y3QpIHtcbiAgICBjb25zdCBbaXNFbmFibGVkLCBwcm9wc10gPSB0aGlzLmdldE1vbml0b3JpbmdEZXRhaWxzKHRoaXMucHJvcHMuYWNtKTtcbiAgICBpZiAoaXNFbmFibGVkICYmIG5vZGUgaW5zdGFuY2VvZiBhY20uQ2VydGlmaWNhdGUpIHtcbiAgICAgIHRoaXMubW9uaXRvcmluZ0ZhY2FkZS5tb25pdG9yQ2VydGlmaWNhdGUoe1xuICAgICAgICBjZXJ0aWZpY2F0ZTogbm9kZSxcbiAgICAgICAgYWxhcm1GcmllbmRseU5hbWU6IG5vZGUubm9kZS5wYXRoLFxuICAgICAgICAuLi5wcm9wcyxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgbW9uaXRvckFwaUdhdGV3YXkobm9kZTogSUNvbnN0cnVjdCkge1xuICAgIGNvbnN0IFtpc0VuYWJsZWQsIHByb3BzXSA9IHRoaXMuZ2V0TW9uaXRvcmluZ0RldGFpbHModGhpcy5wcm9wcy5hcGlHYXRld2F5KTtcbiAgICBpZiAoaXNFbmFibGVkICYmIG5vZGUgaW5zdGFuY2VvZiBhcGlndy5SZXN0QXBpKSB7XG4gICAgICB0aGlzLm1vbml0b3JpbmdGYWNhZGUubW9uaXRvckFwaUdhdGV3YXkoe1xuICAgICAgICBhcGk6IG5vZGUsXG4gICAgICAgIGFwaVN0YWdlOiBub2RlLmRlcGxveW1lbnRTdGFnZS5zdGFnZU5hbWUsXG4gICAgICAgIC4uLnByb3BzLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBtb25pdG9yQXBpR2F0ZXdheVYyKG5vZGU6IElDb25zdHJ1Y3QpIHtcbiAgICBjb25zdCBbaXNFbmFibGVkLCBwcm9wc10gPSB0aGlzLmdldE1vbml0b3JpbmdEZXRhaWxzKFxuICAgICAgdGhpcy5wcm9wcy5hcGlHYXRld2F5VjIsXG4gICAgKTtcbiAgICBpZiAoaXNFbmFibGVkICYmIG5vZGUgaW5zdGFuY2VvZiBhcGlnd3YyLkh0dHBBcGkpIHtcbiAgICAgIHRoaXMubW9uaXRvcmluZ0ZhY2FkZS5tb25pdG9yQXBpR2F0ZXdheVYySHR0cEFwaSh7XG4gICAgICAgIGFwaTogbm9kZSxcbiAgICAgICAgLi4ucHJvcHMsXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIG1vbml0b3JBcHBTeW5jKG5vZGU6IElDb25zdHJ1Y3QpIHtcbiAgICBjb25zdCBbaXNFbmFibGVkLCBwcm9wc10gPSB0aGlzLmdldE1vbml0b3JpbmdEZXRhaWxzKHRoaXMucHJvcHMuYXBwU3luYyk7XG4gICAgaWYgKGlzRW5hYmxlZCAmJiBub2RlIGluc3RhbmNlb2YgYXBwc3luYy5HcmFwaHFsQXBpKSB7XG4gICAgICB0aGlzLm1vbml0b3JpbmdGYWNhZGUubW9uaXRvckFwcFN5bmNBcGkoe1xuICAgICAgICBhcGk6IG5vZGUsXG4gICAgICAgIGFsYXJtRnJpZW5kbHlOYW1lOiBub2RlLm5vZGUucGF0aCxcbiAgICAgICAgLi4ucHJvcHMsXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIG1vbml0b3JBdXJvcmFDbHVzdGVyKG5vZGU6IElDb25zdHJ1Y3QpIHtcbiAgICBjb25zdCBbaXNFbmFibGVkLCBwcm9wc10gPSB0aGlzLmdldE1vbml0b3JpbmdEZXRhaWxzKFxuICAgICAgdGhpcy5wcm9wcy5hdXJvcmFDbHVzdGVyLFxuICAgICk7XG4gICAgaWYgKGlzRW5hYmxlZCAmJiBub2RlIGluc3RhbmNlb2YgcmRzLlNlcnZlcmxlc3NDbHVzdGVyKSB7XG4gICAgICB0aGlzLm1vbml0b3JpbmdGYWNhZGUubW9uaXRvckF1cm9yYUNsdXN0ZXIoe1xuICAgICAgICBjbHVzdGVyOiBub2RlLFxuICAgICAgICBhbGFybUZyaWVuZGx5TmFtZTogbm9kZS5ub2RlLnBhdGgsXG4gICAgICAgIC4uLnByb3BzLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBtb25pdG9yQXV0b1NjYWxpbmdHcm91cChub2RlOiBJQ29uc3RydWN0KSB7XG4gICAgY29uc3QgW2lzRW5hYmxlZCwgcHJvcHNdID0gdGhpcy5nZXRNb25pdG9yaW5nRGV0YWlscyhcbiAgICAgIHRoaXMucHJvcHMuYXV0b1NjYWxpbmdHcm91cCxcbiAgICApO1xuICAgIGlmIChpc0VuYWJsZWQgJiYgbm9kZSBpbnN0YW5jZW9mIGF1dG9zY2FsaW5nLkF1dG9TY2FsaW5nR3JvdXApIHtcbiAgICAgIHRoaXMubW9uaXRvcmluZ0ZhY2FkZS5tb25pdG9yQXV0b1NjYWxpbmdHcm91cCh7XG4gICAgICAgIGF1dG9TY2FsaW5nR3JvdXA6IG5vZGUsXG4gICAgICAgIC4uLnByb3BzLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBtb25pdG9yQmlsbGluZygpIHtcbiAgICBjb25zdCBbaXNFbmFibGVkLCBwcm9wc10gPSB0aGlzLmdldE1vbml0b3JpbmdEZXRhaWxzKHRoaXMucHJvcHMuYmlsbGluZyk7XG4gICAgaWYgKGlzRW5hYmxlZCkge1xuICAgICAgdGhpcy5tb25pdG9yaW5nRmFjYWRlLm1vbml0b3JCaWxsaW5nKHtcbiAgICAgICAgLi4ucHJvcHMsXG4gICAgICAgIGFsYXJtRnJpZW5kbHlOYW1lOiBcIkJpbGxpbmdcIixcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgbW9uaXRvckNsb3VkRnJvbnQobm9kZTogSUNvbnN0cnVjdCkge1xuICAgIGNvbnN0IFtpc0VuYWJsZWQsIHByb3BzXSA9IHRoaXMuZ2V0TW9uaXRvcmluZ0RldGFpbHModGhpcy5wcm9wcy5jbG91ZEZyb250KTtcbiAgICBpZiAoaXNFbmFibGVkICYmIG5vZGUgaW5zdGFuY2VvZiBjbG91ZGZyb250LkRpc3RyaWJ1dGlvbikge1xuICAgICAgdGhpcy5tb25pdG9yaW5nRmFjYWRlLm1vbml0b3JDbG91ZEZyb250RGlzdHJpYnV0aW9uKHtcbiAgICAgICAgZGlzdHJpYnV0aW9uOiBub2RlLFxuICAgICAgICAuLi5wcm9wcyxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgbW9uaXRvckNvZGVCdWlsZChub2RlOiBJQ29uc3RydWN0KSB7XG4gICAgY29uc3QgW2lzRW5hYmxlZCwgcHJvcHNdID0gdGhpcy5nZXRNb25pdG9yaW5nRGV0YWlscyh0aGlzLnByb3BzLmNvZGVCdWlsZCk7XG4gICAgaWYgKGlzRW5hYmxlZCAmJiBub2RlIGluc3RhbmNlb2YgY29kZWJ1aWxkLlByb2plY3QpIHtcbiAgICAgIHRoaXMubW9uaXRvcmluZ0ZhY2FkZS5tb25pdG9yQ29kZUJ1aWxkUHJvamVjdCh7XG4gICAgICAgIHByb2plY3Q6IG5vZGUsXG4gICAgICAgIC4uLnByb3BzLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBtb25pdG9yRG9jdW1lbnREYihub2RlOiBJQ29uc3RydWN0KSB7XG4gICAgY29uc3QgW2lzRW5hYmxlZCwgcHJvcHNdID0gdGhpcy5nZXRNb25pdG9yaW5nRGV0YWlscyh0aGlzLnByb3BzLmRvY3VtZW50RGIpO1xuICAgIGlmIChpc0VuYWJsZWQgJiYgbm9kZSBpbnN0YW5jZW9mIGRvY2RiLkRhdGFiYXNlQ2x1c3Rlcikge1xuICAgICAgdGhpcy5tb25pdG9yaW5nRmFjYWRlLm1vbml0b3JEb2N1bWVudERiQ2x1c3Rlcih7XG4gICAgICAgIGNsdXN0ZXI6IG5vZGUsXG4gICAgICAgIGFsYXJtRnJpZW5kbHlOYW1lOiBub2RlLm5vZGUucGF0aCxcbiAgICAgICAgLi4ucHJvcHMsXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIG1vbml0b3JEeW5hbW9EYihub2RlOiBJQ29uc3RydWN0KSB7XG4gICAgY29uc3QgW2lzRW5hYmxlZCwgcHJvcHNdID0gdGhpcy5nZXRNb25pdG9yaW5nRGV0YWlscyh0aGlzLnByb3BzLmR5bmFtb0RCKTtcbiAgICBpZiAoaXNFbmFibGVkICYmIG5vZGUgaW5zdGFuY2VvZiBkeW5hbW9kYi5UYWJsZSkge1xuICAgICAgdGhpcy5tb25pdG9yaW5nRmFjYWRlLm1vbml0b3JEeW5hbW9UYWJsZSh7XG4gICAgICAgIHRhYmxlOiBub2RlLFxuICAgICAgICAuLi5wcm9wcyxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgbW9uaXRvckVjMigpIHtcbiAgICBjb25zdCBbaXNFbmFibGVkLCBwcm9wc10gPSB0aGlzLmdldE1vbml0b3JpbmdEZXRhaWxzKHRoaXMucHJvcHMuZWMyKTtcbiAgICBpZiAoaXNFbmFibGVkKSB7XG4gICAgICB0aGlzLm1vbml0b3JpbmdGYWNhZGUubW9uaXRvckVDMkluc3RhbmNlcyh7XG4gICAgICAgIC4uLnByb3BzLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBtb25pdG9yRWxhc3RpY0NhY2hlKCkge1xuICAgIGNvbnN0IFtpc0VuYWJsZWQsIHByb3BzXSA9IHRoaXMuZ2V0TW9uaXRvcmluZ0RldGFpbHMoXG4gICAgICB0aGlzLnByb3BzLmVsYXN0aWNDYWNoZSxcbiAgICApO1xuICAgIGlmIChpc0VuYWJsZWQpIHtcbiAgICAgIHRoaXMubW9uaXRvcmluZ0ZhY2FkZS5tb25pdG9yRWxhc3RpQ2FjaGVDbHVzdGVyKHtcbiAgICAgICAgY2x1c3RlclR5cGU6IEVsYXN0aUNhY2hlQ2x1c3RlclR5cGUuTUVNQ0FDSEVELFxuICAgICAgICAuLi5wcm9wcyxcbiAgICAgIH0pO1xuICAgICAgdGhpcy5tb25pdG9yaW5nRmFjYWRlLm1vbml0b3JFbGFzdGlDYWNoZUNsdXN0ZXIoe1xuICAgICAgICBjbHVzdGVyVHlwZTogRWxhc3RpQ2FjaGVDbHVzdGVyVHlwZS5SRURJUyxcbiAgICAgICAgLi4ucHJvcHMsXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIG1vbml0b3JGYXJnYXRlU2VydmljZShub2RlOiBJQ29uc3RydWN0KSB7XG4gICAgY29uc3QgW2lzRW5hYmxlZCwgcHJvcHNdID0gdGhpcy5nZXRNb25pdG9yaW5nRGV0YWlscyhcbiAgICAgIHRoaXMucHJvcHMuZmFyZ2F0ZVNlcnZpY2UsXG4gICAgKTtcbiAgICBpZiAoXG4gICAgICBpc0VuYWJsZWQgJiZcbiAgICAgIG5vZGUgaW5zdGFuY2VvZiBlY3MuRmFyZ2F0ZVNlcnZpY2UgJiZcbiAgICAgICF0aGlzLmlzSW5zaWRlRmFyZ2F0ZVBhdHRlcm4obm9kZSlcbiAgICApIHtcbiAgICAgIHRoaXMubW9uaXRvcmluZ0ZhY2FkZS5tb25pdG9yU2ltcGxlRmFyZ2F0ZVNlcnZpY2Uoe1xuICAgICAgICBmYXJnYXRlU2VydmljZTogbm9kZSxcbiAgICAgICAgLi4ucHJvcHMsXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIG1vbml0b3JGYXJnYXRlTG9hZEJhbGFuY2VkU2VydmljZShub2RlOiBJQ29uc3RydWN0KSB7XG4gICAgY29uc3QgW2lzRW5hYmxlZCwgcHJvcHNdID0gdGhpcy5nZXRNb25pdG9yaW5nRGV0YWlscyhcbiAgICAgIHRoaXMucHJvcHMuZmFyZ2F0ZUxvYWRCYWxhbmNlZFNlcnZpY2UsXG4gICAgKTtcbiAgICBpZiAoXG4gICAgICBpc0VuYWJsZWQgJiZcbiAgICAgIChub2RlIGluc3RhbmNlb2YgZWNzUGF0dGVybnMuQXBwbGljYXRpb25Mb2FkQmFsYW5jZWRGYXJnYXRlU2VydmljZSB8fFxuICAgICAgICBub2RlIGluc3RhbmNlb2YgZWNzUGF0dGVybnMuTmV0d29ya0xvYWRCYWxhbmNlZEZhcmdhdGVTZXJ2aWNlKVxuICAgICkge1xuICAgICAgdGhpcy5tb25pdG9yaW5nRmFjYWRlLm1vbml0b3JGYXJnYXRlU2VydmljZSh7XG4gICAgICAgIGZhcmdhdGVTZXJ2aWNlOiBub2RlLFxuICAgICAgICAuLi5wcm9wcyxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgbW9uaXRvclF1ZXVlUHJvY2Vzc2luZ0ZhcmdhdGVTZXJ2aWNlKG5vZGU6IElDb25zdHJ1Y3QpIHtcbiAgICBjb25zdCBbaXNFbmFibGVkLCBwcm9wc10gPSB0aGlzLmdldE1vbml0b3JpbmdEZXRhaWxzKFxuICAgICAgdGhpcy5wcm9wcy5xdWV1ZVByb2Nlc3NpbmdGYXJnYXRlU2VydmljZSxcbiAgICApO1xuICAgIGlmIChcbiAgICAgIGlzRW5hYmxlZCAmJlxuICAgICAgbm9kZSBpbnN0YW5jZW9mIGVjc1BhdHRlcm5zLlF1ZXVlUHJvY2Vzc2luZ0ZhcmdhdGVTZXJ2aWNlXG4gICAgKSB7XG4gICAgICB0aGlzLm1vbml0b3JpbmdGYWNhZGUubW9uaXRvclF1ZXVlUHJvY2Vzc2luZ0ZhcmdhdGVTZXJ2aWNlKHtcbiAgICAgICAgZmFyZ2F0ZVNlcnZpY2U6IG5vZGUsXG4gICAgICAgIC4uLnByb3BzLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgRmFyZ2F0ZVNlcnZpY2UgaXMgb3duZWQgYnkgYW4gTDMgZWNzLXBhdHRlcm5zXG4gICAqIGNvbnN0cnVjdCAoQXBwbGljYXRpb25Mb2FkQmFsYW5jZWRGYXJnYXRlU2VydmljZSxcbiAgICogTmV0d29ya0xvYWRCYWxhbmNlZEZhcmdhdGVTZXJ2aWNlLCBRdWV1ZVByb2Nlc3NpbmdGYXJnYXRlU2VydmljZSkuXG4gICAqIFRoZSBMMyBwYXR0ZXJuIGhhcyBpdHMgb3duIGFzcGVjdCBob29rLCBzbyBtb25pdG9yaW5nIHRoZSBpbm5lclxuICAgKiBzZXJ2aWNlIHNlcGFyYXRlbHkgd291bGQgZHVwbGljYXRlIGFsYXJtcy5cbiAgICovXG4gIHByaXZhdGUgaXNJbnNpZGVGYXJnYXRlUGF0dGVybihzZXJ2aWNlOiBlY3MuRmFyZ2F0ZVNlcnZpY2UpOiBib29sZWFuIHtcbiAgICBjb25zdCBNQVhfQU5DRVNUT1JfREVQVEggPSAzO1xuICAgIGxldCBjdXJyZW50OiBJQ29uc3RydWN0IHwgdW5kZWZpbmVkID0gc2VydmljZS5ub2RlLnNjb3BlO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgTUFYX0FOQ0VTVE9SX0RFUFRIICYmIGN1cnJlbnQ7IGkrKykge1xuICAgICAgaWYgKFxuICAgICAgICBjdXJyZW50IGluc3RhbmNlb2YgZWNzUGF0dGVybnMuQXBwbGljYXRpb25Mb2FkQmFsYW5jZWRGYXJnYXRlU2VydmljZSB8fFxuICAgICAgICBjdXJyZW50IGluc3RhbmNlb2YgZWNzUGF0dGVybnMuTmV0d29ya0xvYWRCYWxhbmNlZEZhcmdhdGVTZXJ2aWNlIHx8XG4gICAgICAgIGN1cnJlbnQgaW5zdGFuY2VvZiBlY3NQYXR0ZXJucy5RdWV1ZVByb2Nlc3NpbmdGYXJnYXRlU2VydmljZVxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuIC