UNPKG

181 kBJavaScriptView Raw
1"use strict";
2var _a;
3Object.defineProperty(exports, "__esModule", { value: true });
4exports.TableClass = exports.StreamViewType = exports.ProjectionType = exports.BillingMode = exports.AttributeType = exports.Table = exports.TableEncryption = exports.Operation = void 0;
5const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
6const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
7const appscaling = require("@aws-cdk/aws-applicationautoscaling");
8const cloudwatch = require("@aws-cdk/aws-cloudwatch");
9const iam = require("@aws-cdk/aws-iam");
10const kms = require("@aws-cdk/aws-kms");
11const core_1 = require("@aws-cdk/core");
12const dynamodb_canned_metrics_generated_1 = require("./dynamodb-canned-metrics.generated");
13const dynamodb_generated_1 = require("./dynamodb.generated");
14const perms = require("./perms");
15const replica_provider_1 = require("./replica-provider");
16const scalable_table_attribute_1 = require("./scalable-table-attribute");
17// keep this import separate from other imports to reduce chance for merge conflicts with v2-main
18// eslint-disable-next-line no-duplicate-imports, import/order
19const core_2 = require("@aws-cdk/core");
20const HASH_KEY_TYPE = 'HASH';
21const RANGE_KEY_TYPE = 'RANGE';
22// https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Limits.html#limits-secondary-indexes
23const MAX_LOCAL_SECONDARY_INDEX_COUNT = 5;
24/**
25 * Supported DynamoDB table operations.
26 */
27var Operation;
28(function (Operation) {
29 /** GetItem */
30 Operation["GET_ITEM"] = "GetItem";
31 /** BatchGetItem */
32 Operation["BATCH_GET_ITEM"] = "BatchGetItem";
33 /** Scan */
34 Operation["SCAN"] = "Scan";
35 /** Query */
36 Operation["QUERY"] = "Query";
37 /** GetRecords */
38 Operation["GET_RECORDS"] = "GetRecords";
39 /** PutItem */
40 Operation["PUT_ITEM"] = "PutItem";
41 /** DeleteItem */
42 Operation["DELETE_ITEM"] = "DeleteItem";
43 /** UpdateItem */
44 Operation["UPDATE_ITEM"] = "UpdateItem";
45 /** BatchWriteItem */
46 Operation["BATCH_WRITE_ITEM"] = "BatchWriteItem";
47 /** TransactWriteItems */
48 Operation["TRANSACT_WRITE_ITEMS"] = "TransactWriteItems";
49 /** TransactGetItems */
50 Operation["TRANSACT_GET_ITEMS"] = "TransactGetItems";
51 /** ExecuteTransaction */
52 Operation["EXECUTE_TRANSACTION"] = "ExecuteTransaction";
53 /** BatchExecuteStatement */
54 Operation["BATCH_EXECUTE_STATEMENT"] = "BatchExecuteStatement";
55 /** ExecuteStatement */
56 Operation["EXECUTE_STATEMENT"] = "ExecuteStatement";
57})(Operation = exports.Operation || (exports.Operation = {}));
58/**
59 * What kind of server-side encryption to apply to this table.
60 */
61var TableEncryption;
62(function (TableEncryption) {
63 /**
64 * Server-side KMS encryption with a master key owned by AWS.
65 */
66 TableEncryption["DEFAULT"] = "AWS_OWNED";
67 /**
68 * Server-side KMS encryption with a customer master key managed by customer.
69 * If `encryptionKey` is specified, this key will be used, otherwise, one will be defined.
70 *
71 * > **NOTE**: if `encryptionKey` is not specified and the `Table` construct creates
72 * > a KMS key for you, the key will be created with default permissions. If you are using
73 * > CDKv2, these permissions will be sufficient to enable the key for use with DynamoDB tables.
74 * > If you are using CDKv1, make sure the feature flag `@aws-cdk/aws-kms:defaultKeyPolicies`
75 * > is set to `true` in your `cdk.json`.
76 */
77 TableEncryption["CUSTOMER_MANAGED"] = "CUSTOMER_MANAGED";
78 /**
79 * Server-side KMS encryption with a master key managed by AWS.
80 */
81 TableEncryption["AWS_MANAGED"] = "AWS_MANAGED";
82})(TableEncryption = exports.TableEncryption || (exports.TableEncryption = {}));
83class TableBase extends core_1.Resource {
84 constructor() {
85 super(...arguments);
86 this.regionalArns = new Array();
87 }
88 /**
89 * Adds an IAM policy statement associated with this table to an IAM
90 * principal's policy.
91 *
92 * If `encryptionKey` is present, appropriate grants to the key needs to be added
93 * separately using the `table.encryptionKey.grant*` methods.
94 *
95 * @param grantee The principal (no-op if undefined)
96 * @param actions The set of actions to allow (i.e. "dynamodb:PutItem", "dynamodb:GetItem", ...)
97 */
98 grant(grantee, ...actions) {
99 return iam.Grant.addToPrincipal({
100 grantee,
101 actions,
102 resourceArns: [
103 this.tableArn,
104 core_1.Lazy.string({ produce: () => this.hasIndex ? `${this.tableArn}/index/*` : core_1.Aws.NO_VALUE }),
105 ...this.regionalArns,
106 ...this.regionalArns.map(arn => core_1.Lazy.string({
107 produce: () => this.hasIndex ? `${arn}/index/*` : core_1.Aws.NO_VALUE,
108 })),
109 ],
110 scope: this,
111 });
112 }
113 /**
114 * Adds an IAM policy statement associated with this table's stream to an
115 * IAM principal's policy.
116 *
117 * If `encryptionKey` is present, appropriate grants to the key needs to be added
118 * separately using the `table.encryptionKey.grant*` methods.
119 *
120 * @param grantee The principal (no-op if undefined)
121 * @param actions The set of actions to allow (i.e. "dynamodb:DescribeStream", "dynamodb:GetRecords", ...)
122 */
123 grantStream(grantee, ...actions) {
124 if (!this.tableStreamArn) {
125 throw new Error(`DynamoDB Streams must be enabled on the table ${this.node.path}`);
126 }
127 return iam.Grant.addToPrincipal({
128 grantee,
129 actions,
130 resourceArns: [this.tableStreamArn],
131 scope: this,
132 });
133 }
134 /**
135 * Permits an IAM principal all data read operations from this table:
136 * BatchGetItem, GetRecords, GetShardIterator, Query, GetItem, Scan, DescribeTable.
137 *
138 * Appropriate grants will also be added to the customer-managed KMS key
139 * if one was configured.
140 *
141 * @param grantee The principal to grant access to
142 */
143 grantReadData(grantee) {
144 const tableActions = perms.READ_DATA_ACTIONS.concat(perms.DESCRIBE_TABLE);
145 return this.combinedGrant(grantee, { keyActions: perms.KEY_READ_ACTIONS, tableActions });
146 }
147 /**
148 * Permits an IAM Principal to list streams attached to current dynamodb table.
149 *
150 * @param grantee The principal (no-op if undefined)
151 */
152 grantTableListStreams(grantee) {
153 if (!this.tableStreamArn) {
154 throw new Error(`DynamoDB Streams must be enabled on the table ${this.node.path}`);
155 }
156 return iam.Grant.addToPrincipal({
157 grantee,
158 actions: ['dynamodb:ListStreams'],
159 resourceArns: ['*'],
160 });
161 }
162 /**
163 * Permits an IAM principal all stream data read operations for this
164 * table's stream:
165 * DescribeStream, GetRecords, GetShardIterator, ListStreams.
166 *
167 * Appropriate grants will also be added to the customer-managed KMS key
168 * if one was configured.
169 *
170 * @param grantee The principal to grant access to
171 */
172 grantStreamRead(grantee) {
173 this.grantTableListStreams(grantee);
174 return this.combinedGrant(grantee, { keyActions: perms.KEY_READ_ACTIONS, streamActions: perms.READ_STREAM_DATA_ACTIONS });
175 }
176 /**
177 * Permits an IAM principal all data write operations to this table:
178 * BatchWriteItem, PutItem, UpdateItem, DeleteItem, DescribeTable.
179 *
180 * Appropriate grants will also be added to the customer-managed KMS key
181 * if one was configured.
182 *
183 * @param grantee The principal to grant access to
184 */
185 grantWriteData(grantee) {
186 const tableActions = perms.WRITE_DATA_ACTIONS.concat(perms.DESCRIBE_TABLE);
187 const keyActions = perms.KEY_READ_ACTIONS.concat(perms.KEY_WRITE_ACTIONS);
188 return this.combinedGrant(grantee, { keyActions, tableActions });
189 }
190 /**
191 * Permits an IAM principal to all data read/write operations to this table.
192 * BatchGetItem, GetRecords, GetShardIterator, Query, GetItem, Scan,
193 * BatchWriteItem, PutItem, UpdateItem, DeleteItem, DescribeTable
194 *
195 * Appropriate grants will also be added to the customer-managed KMS key
196 * if one was configured.
197 *
198 * @param grantee The principal to grant access to
199 */
200 grantReadWriteData(grantee) {
201 const tableActions = perms.READ_DATA_ACTIONS.concat(perms.WRITE_DATA_ACTIONS).concat(perms.DESCRIBE_TABLE);
202 const keyActions = perms.KEY_READ_ACTIONS.concat(perms.KEY_WRITE_ACTIONS);
203 return this.combinedGrant(grantee, { keyActions, tableActions });
204 }
205 /**
206 * Permits all DynamoDB operations ("dynamodb:*") to an IAM principal.
207 *
208 * Appropriate grants will also be added to the customer-managed KMS key
209 * if one was configured.
210 *
211 * @param grantee The principal to grant access to
212 */
213 grantFullAccess(grantee) {
214 const keyActions = perms.KEY_READ_ACTIONS.concat(perms.KEY_WRITE_ACTIONS);
215 return this.combinedGrant(grantee, { keyActions, tableActions: ['dynamodb:*'] });
216 }
217 /**
218 * Return the given named metric for this Table
219 *
220 * By default, the metric will be calculated as a sum over a period of 5 minutes.
221 * You can customize this by using the `statistic` and `period` properties.
222 */
223 metric(metricName, props) {
224 return new cloudwatch.Metric({
225 namespace: 'AWS/DynamoDB',
226 metricName,
227 dimensionsMap: {
228 TableName: this.tableName,
229 },
230 ...props,
231 }).attachTo(this);
232 }
233 /**
234 * Metric for the consumed read capacity units this table
235 *
236 * By default, the metric will be calculated as a sum over a period of 5 minutes.
237 * You can customize this by using the `statistic` and `period` properties.
238 */
239 metricConsumedReadCapacityUnits(props) {
240 return this.cannedMetric(dynamodb_canned_metrics_generated_1.DynamoDBMetrics.consumedReadCapacityUnitsSum, props);
241 }
242 /**
243 * Metric for the consumed write capacity units this table
244 *
245 * By default, the metric will be calculated as a sum over a period of 5 minutes.
246 * You can customize this by using the `statistic` and `period` properties.
247 */
248 metricConsumedWriteCapacityUnits(props) {
249 return this.cannedMetric(dynamodb_canned_metrics_generated_1.DynamoDBMetrics.consumedWriteCapacityUnitsSum, props);
250 }
251 /**
252 * Metric for the system errors this table
253 *
254 * @deprecated use `metricSystemErrorsForOperations`.
255 */
256 metricSystemErrors(props) {
257 if (!props?.dimensions?.Operation && !props?.dimensionsMap?.Operation) {
258 // 'Operation' must be passed because its an operational metric.
259 throw new Error("'Operation' dimension must be passed for the 'SystemErrors' metric.");
260 }
261 const dimensionsMap = {
262 TableName: this.tableName,
263 ...props?.dimensions ?? {},
264 ...props?.dimensionsMap ?? {},
265 };
266 return this.metric('SystemErrors', { statistic: 'sum', ...props, dimensionsMap });
267 }
268 /**
269 * Metric for the user errors. Note that this metric reports user errors across all
270 * the tables in the account and region the table resides in.
271 *
272 * By default, the metric will be calculated as a sum over a period of 5 minutes.
273 * You can customize this by using the `statistic` and `period` properties.
274 */
275 metricUserErrors(props) {
276 if (props?.dimensions) {
277 throw new Error("'dimensions' is not supported for the 'UserErrors' metric");
278 }
279 // overriding 'dimensions' here because this metric is an account metric.
280 // see 'UserErrors' in https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/metrics-dimensions.html
281 return this.metric('UserErrors', { statistic: 'sum', ...props, dimensionsMap: {} });
282 }
283 /**
284 * Metric for the conditional check failed requests this table
285 *
286 * By default, the metric will be calculated as a sum over a period of 5 minutes.
287 * You can customize this by using the `statistic` and `period` properties.
288 */
289 metricConditionalCheckFailedRequests(props) {
290 return this.metric('ConditionalCheckFailedRequests', { statistic: 'sum', ...props });
291 }
292 /**
293 * How many requests are throttled on this table
294 *
295 * Default: sum over 5 minutes
296 *
297 * @deprecated Do not use this function. It returns an invalid metric. Use `metricThrottledRequestsForOperation` instead.
298 */
299 metricThrottledRequests(props) {
300 return this.metric('ThrottledRequests', { statistic: 'sum', ...props });
301 }
302 /**
303 * How many requests are throttled on this table, for the given operation
304 *
305 * Default: sum over 5 minutes
306 */
307 metricThrottledRequestsForOperation(operation, props) {
308 return new cloudwatch.Metric({
309 ...dynamodb_canned_metrics_generated_1.DynamoDBMetrics.throttledRequestsSum({ Operation: operation, TableName: this.tableName }),
310 ...props,
311 }).attachTo(this);
312 }
313 /**
314 * Metric for the successful request latency this table.
315 *
316 * By default, the metric will be calculated as an average over a period of 5 minutes.
317 * You can customize this by using the `statistic` and `period` properties.
318 */
319 metricSuccessfulRequestLatency(props) {
320 if (!props?.dimensions?.Operation && !props?.dimensionsMap?.Operation) {
321 throw new Error("'Operation' dimension must be passed for the 'SuccessfulRequestLatency' metric.");
322 }
323 const dimensionsMap = {
324 TableName: this.tableName,
325 Operation: props.dimensionsMap?.Operation ?? props.dimensions?.Operation,
326 };
327 return new cloudwatch.Metric({
328 ...dynamodb_canned_metrics_generated_1.DynamoDBMetrics.successfulRequestLatencyAverage(dimensionsMap),
329 ...props,
330 dimensionsMap,
331 }).attachTo(this);
332 }
333 /**
334 * Metric for the system errors this table.
335 *
336 * This will sum errors across all possible operations.
337 * Note that by default, each individual metric will be calculated as a sum over a period of 5 minutes.
338 * You can customize this by using the `statistic` and `period` properties.
339 */
340 metricSystemErrorsForOperations(props) {
341 if (props?.dimensions?.Operation) {
342 throw new Error("The Operation dimension is not supported. Use the 'operations' property.");
343 }
344 const operations = props?.operations ?? Object.values(Operation);
345 const values = this.createMetricsForOperations('SystemErrors', operations, { statistic: 'sum', ...props });
346 const sum = new cloudwatch.MathExpression({
347 expression: `${Object.keys(values).join(' + ')}`,
348 usingMetrics: { ...values },
349 color: props?.color,
350 label: 'Sum of errors across all operations',
351 period: props?.period,
352 });
353 return sum;
354 }
355 /**
356 * Create a map of metrics that can be used in a math expression.
357 *
358 * Using the return value of this function as the `usingMetrics` property in `cloudwatch.MathExpression` allows you to
359 * use the keys of this map as metric names inside you expression.
360 *
361 * @param metricName The metric name.
362 * @param operations The list of operations to create metrics for.
363 * @param props Properties for the individual metrics.
364 * @param metricNameMapper Mapper function to allow controlling the individual metric name per operation.
365 */
366 createMetricsForOperations(metricName, operations, props, metricNameMapper) {
367 const metrics = {};
368 const mapper = metricNameMapper ?? (op => op.toLowerCase());
369 if (props?.dimensions?.Operation) {
370 throw new Error('Invalid properties. Operation dimension is not supported when calculating operational metrics');
371 }
372 for (const operation of operations) {
373 const metric = this.metric(metricName, {
374 ...props,
375 dimensionsMap: {
376 TableName: this.tableName,
377 Operation: operation,
378 ...props?.dimensions,
379 },
380 });
381 const operationMetricName = mapper(operation);
382 const firstChar = operationMetricName.charAt(0);
383 if (firstChar === firstChar.toUpperCase()) {
384 // https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/using-metric-math.html#metric-math-syntax
385 throw new Error(`Mapper generated an illegal operation metric name: ${operationMetricName}. Must start with a lowercase letter`);
386 }
387 metrics[operationMetricName] = metric;
388 }
389 return metrics;
390 }
391 /**
392 * Adds an IAM policy statement associated with this table to an IAM
393 * principal's policy.
394 * @param grantee The principal (no-op if undefined)
395 * @param opts Options for keyActions, tableActions and streamActions
396 */
397 combinedGrant(grantee, opts) {
398 if (opts.tableActions) {
399 const resources = [this.tableArn,
400 core_1.Lazy.string({ produce: () => this.hasIndex ? `${this.tableArn}/index/*` : core_1.Aws.NO_VALUE }),
401 ...this.regionalArns,
402 ...this.regionalArns.map(arn => core_1.Lazy.string({
403 produce: () => this.hasIndex ? `${arn}/index/*` : core_1.Aws.NO_VALUE,
404 }))];
405 const ret = iam.Grant.addToPrincipal({
406 grantee,
407 actions: opts.tableActions,
408 resourceArns: resources,
409 scope: this,
410 });
411 if (this.encryptionKey && opts.keyActions) {
412 this.encryptionKey.grant(grantee, ...opts.keyActions);
413 }
414 return ret;
415 }
416 if (opts.streamActions) {
417 if (!this.tableStreamArn) {
418 throw new Error(`DynamoDB Streams must be enabled on the table ${this.node.path}`);
419 }
420 const resources = [this.tableStreamArn];
421 const ret = iam.Grant.addToPrincipal({
422 grantee,
423 actions: opts.streamActions,
424 resourceArns: resources,
425 scope: this,
426 });
427 return ret;
428 }
429 throw new Error(`Unexpected 'action', ${opts.tableActions || opts.streamActions}`);
430 }
431 cannedMetric(fn, props) {
432 return new cloudwatch.Metric({
433 ...fn({ TableName: this.tableName }),
434 ...props,
435 }).attachTo(this);
436 }
437}
438/**
439 * Provides a DynamoDB table.
440 */
441class Table extends TableBase {
442 constructor(scope, id, props) {
443 super(scope, id, {
444 physicalName: props.tableName,
445 });
446 this.keySchema = new Array();
447 this.attributeDefinitions = new Array();
448 this.globalSecondaryIndexes = new Array();
449 this.localSecondaryIndexes = new Array();
450 this.secondaryIndexSchemas = new Map();
451 this.nonKeyAttributes = new Set();
452 this.tableScaling = {};
453 this.indexScaling = new Map();
454 this.globalReplicaCustomResources = new Array();
455 try {
456 jsiiDeprecationWarnings._aws_cdk_aws_dynamodb_TableProps(props);
457 }
458 catch (error) {
459 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
460 Error.captureStackTrace(error, Table);
461 }
462 throw error;
463 }
464 const { sseSpecification, encryptionKey } = this.parseEncryption(props);
465 let streamSpecification;
466 if (props.replicationRegions) {
467 if (props.stream && props.stream !== StreamViewType.NEW_AND_OLD_IMAGES) {
468 throw new Error('`stream` must be set to `NEW_AND_OLD_IMAGES` when specifying `replicationRegions`');
469 }
470 streamSpecification = { streamViewType: StreamViewType.NEW_AND_OLD_IMAGES };
471 this.billingMode = props.billingMode ?? BillingMode.PAY_PER_REQUEST;
472 }
473 else {
474 this.billingMode = props.billingMode ?? BillingMode.PROVISIONED;
475 if (props.stream) {
476 streamSpecification = { streamViewType: props.stream };
477 }
478 }
479 this.validateProvisioning(props);
480 this.table = new dynamodb_generated_1.CfnTable(this, 'Resource', {
481 tableName: this.physicalName,
482 keySchema: this.keySchema,
483 attributeDefinitions: this.attributeDefinitions,
484 globalSecondaryIndexes: core_1.Lazy.any({ produce: () => this.globalSecondaryIndexes }, { omitEmptyArray: true }),
485 localSecondaryIndexes: core_1.Lazy.any({ produce: () => this.localSecondaryIndexes }, { omitEmptyArray: true }),
486 pointInTimeRecoverySpecification: props.pointInTimeRecovery != null ? { pointInTimeRecoveryEnabled: props.pointInTimeRecovery } : undefined,
487 billingMode: this.billingMode === BillingMode.PAY_PER_REQUEST ? this.billingMode : undefined,
488 provisionedThroughput: this.billingMode === BillingMode.PAY_PER_REQUEST ? undefined : {
489 readCapacityUnits: props.readCapacity || 5,
490 writeCapacityUnits: props.writeCapacity || 5,
491 },
492 sseSpecification,
493 streamSpecification,
494 tableClass: props.tableClass,
495 timeToLiveSpecification: props.timeToLiveAttribute ? { attributeName: props.timeToLiveAttribute, enabled: true } : undefined,
496 contributorInsightsSpecification: props.contributorInsightsEnabled !== undefined ? { enabled: props.contributorInsightsEnabled } : undefined,
497 kinesisStreamSpecification: props.kinesisStream ? { streamArn: props.kinesisStream.streamArn } : undefined,
498 });
499 this.table.applyRemovalPolicy(props.removalPolicy);
500 this.encryptionKey = encryptionKey;
501 this.tableArn = this.getResourceArnAttribute(this.table.attrArn, {
502 service: 'dynamodb',
503 resource: 'table',
504 resourceName: this.physicalName,
505 });
506 this.tableName = this.getResourceNameAttribute(this.table.ref);
507 if (props.tableName) {
508 this.node.addMetadata('aws:cdk:hasPhysicalName', this.tableName);
509 }
510 this.tableStreamArn = streamSpecification ? this.table.attrStreamArn : undefined;
511 this.scalingRole = this.makeScalingRole();
512 this.addKey(props.partitionKey, HASH_KEY_TYPE);
513 this.tablePartitionKey = props.partitionKey;
514 if (props.sortKey) {
515 this.addKey(props.sortKey, RANGE_KEY_TYPE);
516 this.tableSortKey = props.sortKey;
517 }
518 if (props.replicationRegions && props.replicationRegions.length > 0) {
519 this.createReplicaTables(props.replicationRegions, props.replicationTimeout, props.waitForReplicationToFinish);
520 }
521 }
522 /**
523 * Permits an IAM Principal to list all DynamoDB Streams.
524 * @deprecated Use {@link #grantTableListStreams} for more granular permission
525 * @param grantee The principal (no-op if undefined)
526 */
527 static grantListStreams(grantee) {
528 try {
529 jsiiDeprecationWarnings.print("@aws-cdk/aws-dynamodb.Table#grantListStreams", "Use {@link #grantTableListStreams} for more granular permission");
530 }
531 catch (error) {
532 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
533 Error.captureStackTrace(error, this.grantListStreams);
534 }
535 throw error;
536 }
537 return iam.Grant.addToPrincipal({
538 grantee,
539 actions: ['dynamodb:ListStreams'],
540 resourceArns: ['*'],
541 });
542 }
543 /**
544 * Creates a Table construct that represents an external table via table name.
545 *
546 * @param scope The parent creating construct (usually `this`).
547 * @param id The construct's name.
548 * @param tableName The table's name.
549 */
550 static fromTableName(scope, id, tableName) {
551 return Table.fromTableAttributes(scope, id, { tableName });
552 }
553 /**
554 * Creates a Table construct that represents an external table via table arn.
555 *
556 * @param scope The parent creating construct (usually `this`).
557 * @param id The construct's name.
558 * @param tableArn The table's ARN.
559 */
560 static fromTableArn(scope, id, tableArn) {
561 return Table.fromTableAttributes(scope, id, { tableArn });
562 }
563 /**
564 * Creates a Table construct that represents an external table.
565 *
566 * @param scope The parent creating construct (usually `this`).
567 * @param id The construct's name.
568 * @param attrs A `TableAttributes` object.
569 */
570 static fromTableAttributes(scope, id, attrs) {
571 try {
572 jsiiDeprecationWarnings._aws_cdk_aws_dynamodb_TableAttributes(attrs);
573 }
574 catch (error) {
575 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
576 Error.captureStackTrace(error, this.fromTableAttributes);
577 }
578 throw error;
579 }
580 class Import extends TableBase {
581 constructor(_tableArn, tableName, tableStreamArn) {
582 super(scope, id);
583 this.hasIndex = (attrs.globalIndexes ?? []).length > 0 ||
584 (attrs.localIndexes ?? []).length > 0;
585 this.tableArn = _tableArn;
586 this.tableName = tableName;
587 this.tableStreamArn = tableStreamArn;
588 this.encryptionKey = attrs.encryptionKey;
589 }
590 }
591 let name;
592 let arn;
593 const stack = core_1.Stack.of(scope);
594 if (!attrs.tableName) {
595 if (!attrs.tableArn) {
596 throw new Error('One of tableName or tableArn is required!');
597 }
598 arn = attrs.tableArn;
599 const maybeTableName = stack.splitArn(attrs.tableArn, core_1.ArnFormat.SLASH_RESOURCE_NAME).resourceName;
600 if (!maybeTableName) {
601 throw new Error('ARN for DynamoDB table must be in the form: ...');
602 }
603 name = maybeTableName;
604 }
605 else {
606 if (attrs.tableArn) {
607 throw new Error('Only one of tableArn or tableName can be provided');
608 }
609 name = attrs.tableName;
610 arn = stack.formatArn({
611 service: 'dynamodb',
612 resource: 'table',
613 resourceName: attrs.tableName,
614 });
615 }
616 return new Import(arn, name, attrs.tableStreamArn);
617 }
618 /**
619 * Add a global secondary index of table.
620 *
621 * @param props the property of global secondary index
622 */
623 addGlobalSecondaryIndex(props) {
624 try {
625 jsiiDeprecationWarnings._aws_cdk_aws_dynamodb_GlobalSecondaryIndexProps(props);
626 }
627 catch (error) {
628 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
629 Error.captureStackTrace(error, this.addGlobalSecondaryIndex);
630 }
631 throw error;
632 }
633 this.validateProvisioning(props);
634 this.validateIndexName(props.indexName);
635 // build key schema and projection for index
636 const gsiKeySchema = this.buildIndexKeySchema(props.partitionKey, props.sortKey);
637 const gsiProjection = this.buildIndexProjection(props);
638 this.globalSecondaryIndexes.push({
639 indexName: props.indexName,
640 keySchema: gsiKeySchema,
641 projection: gsiProjection,
642 provisionedThroughput: this.billingMode === BillingMode.PAY_PER_REQUEST ? undefined : {
643 readCapacityUnits: props.readCapacity || 5,
644 writeCapacityUnits: props.writeCapacity || 5,
645 },
646 });
647 this.secondaryIndexSchemas.set(props.indexName, {
648 partitionKey: props.partitionKey,
649 sortKey: props.sortKey,
650 });
651 this.indexScaling.set(props.indexName, {});
652 }
653 /**
654 * Add a local secondary index of table.
655 *
656 * @param props the property of local secondary index
657 */
658 addLocalSecondaryIndex(props) {
659 try {
660 jsiiDeprecationWarnings._aws_cdk_aws_dynamodb_LocalSecondaryIndexProps(props);
661 }
662 catch (error) {
663 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
664 Error.captureStackTrace(error, this.addLocalSecondaryIndex);
665 }
666 throw error;
667 }
668 // https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Limits.html#limits-secondary-indexes
669 if (this.localSecondaryIndexes.length >= MAX_LOCAL_SECONDARY_INDEX_COUNT) {
670 throw new RangeError(`a maximum number of local secondary index per table is ${MAX_LOCAL_SECONDARY_INDEX_COUNT}`);
671 }
672 this.validateIndexName(props.indexName);
673 // build key schema and projection for index
674 const lsiKeySchema = this.buildIndexKeySchema(this.tablePartitionKey, props.sortKey);
675 const lsiProjection = this.buildIndexProjection(props);
676 this.localSecondaryIndexes.push({
677 indexName: props.indexName,
678 keySchema: lsiKeySchema,
679 projection: lsiProjection,
680 });
681 this.secondaryIndexSchemas.set(props.indexName, {
682 partitionKey: this.tablePartitionKey,
683 sortKey: props.sortKey,
684 });
685 }
686 /**
687 * Enable read capacity scaling for this table
688 *
689 * @returns An object to configure additional AutoScaling settings
690 */
691 autoScaleReadCapacity(props) {
692 try {
693 jsiiDeprecationWarnings._aws_cdk_aws_dynamodb_EnableScalingProps(props);
694 }
695 catch (error) {
696 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
697 Error.captureStackTrace(error, this.autoScaleReadCapacity);
698 }
699 throw error;
700 }
701 if (this.tableScaling.scalableReadAttribute) {
702 throw new Error('Read AutoScaling already enabled for this table');
703 }
704 if (this.billingMode === BillingMode.PAY_PER_REQUEST) {
705 throw new Error('AutoScaling is not available for tables with PAY_PER_REQUEST billing mode');
706 }
707 return this.tableScaling.scalableReadAttribute = new scalable_table_attribute_1.ScalableTableAttribute(this, 'ReadScaling', {
708 serviceNamespace: appscaling.ServiceNamespace.DYNAMODB,
709 resourceId: `table/${this.tableName}`,
710 dimension: 'dynamodb:table:ReadCapacityUnits',
711 role: this.scalingRole,
712 ...props,
713 });
714 }
715 /**
716 * Enable write capacity scaling for this table
717 *
718 * @returns An object to configure additional AutoScaling settings for this attribute
719 */
720 autoScaleWriteCapacity(props) {
721 try {
722 jsiiDeprecationWarnings._aws_cdk_aws_dynamodb_EnableScalingProps(props);
723 }
724 catch (error) {
725 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
726 Error.captureStackTrace(error, this.autoScaleWriteCapacity);
727 }
728 throw error;
729 }
730 if (this.tableScaling.scalableWriteAttribute) {
731 throw new Error('Write AutoScaling already enabled for this table');
732 }
733 if (this.billingMode === BillingMode.PAY_PER_REQUEST) {
734 throw new Error('AutoScaling is not available for tables with PAY_PER_REQUEST billing mode');
735 }
736 this.tableScaling.scalableWriteAttribute = new scalable_table_attribute_1.ScalableTableAttribute(this, 'WriteScaling', {
737 serviceNamespace: appscaling.ServiceNamespace.DYNAMODB,
738 resourceId: `table/${this.tableName}`,
739 dimension: 'dynamodb:table:WriteCapacityUnits',
740 role: this.scalingRole,
741 ...props,
742 });
743 for (const globalReplicaCustomResource of this.globalReplicaCustomResources) {
744 globalReplicaCustomResource.node.addDependency(this.tableScaling.scalableWriteAttribute);
745 }
746 return this.tableScaling.scalableWriteAttribute;
747 }
748 /**
749 * Enable read capacity scaling for the given GSI
750 *
751 * @returns An object to configure additional AutoScaling settings for this attribute
752 */
753 autoScaleGlobalSecondaryIndexReadCapacity(indexName, props) {
754 try {
755 jsiiDeprecationWarnings._aws_cdk_aws_dynamodb_EnableScalingProps(props);
756 }
757 catch (error) {
758 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
759 Error.captureStackTrace(error, this.autoScaleGlobalSecondaryIndexReadCapacity);
760 }
761 throw error;
762 }
763 if (this.billingMode === BillingMode.PAY_PER_REQUEST) {
764 throw new Error('AutoScaling is not available for tables with PAY_PER_REQUEST billing mode');
765 }
766 const attributePair = this.indexScaling.get(indexName);
767 if (!attributePair) {
768 throw new Error(`No global secondary index with name ${indexName}`);
769 }
770 if (attributePair.scalableReadAttribute) {
771 throw new Error('Read AutoScaling already enabled for this index');
772 }
773 return attributePair.scalableReadAttribute = new scalable_table_attribute_1.ScalableTableAttribute(this, `${indexName}ReadScaling`, {
774 serviceNamespace: appscaling.ServiceNamespace.DYNAMODB,
775 resourceId: `table/${this.tableName}/index/${indexName}`,
776 dimension: 'dynamodb:index:ReadCapacityUnits',
777 role: this.scalingRole,
778 ...props,
779 });
780 }
781 /**
782 * Enable write capacity scaling for the given GSI
783 *
784 * @returns An object to configure additional AutoScaling settings for this attribute
785 */
786 autoScaleGlobalSecondaryIndexWriteCapacity(indexName, props) {
787 try {
788 jsiiDeprecationWarnings._aws_cdk_aws_dynamodb_EnableScalingProps(props);
789 }
790 catch (error) {
791 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
792 Error.captureStackTrace(error, this.autoScaleGlobalSecondaryIndexWriteCapacity);
793 }
794 throw error;
795 }
796 if (this.billingMode === BillingMode.PAY_PER_REQUEST) {
797 throw new Error('AutoScaling is not available for tables with PAY_PER_REQUEST billing mode');
798 }
799 const attributePair = this.indexScaling.get(indexName);
800 if (!attributePair) {
801 throw new Error(`No global secondary index with name ${indexName}`);
802 }
803 if (attributePair.scalableWriteAttribute) {
804 throw new Error('Write AutoScaling already enabled for this index');
805 }
806 return attributePair.scalableWriteAttribute = new scalable_table_attribute_1.ScalableTableAttribute(this, `${indexName}WriteScaling`, {
807 serviceNamespace: appscaling.ServiceNamespace.DYNAMODB,
808 resourceId: `table/${this.tableName}/index/${indexName}`,
809 dimension: 'dynamodb:index:WriteCapacityUnits',
810 role: this.scalingRole,
811 ...props,
812 });
813 }
814 /**
815 * Get schema attributes of table or index.
816 *
817 * @returns Schema of table or index.
818 */
819 schema(indexName) {
820 if (!indexName) {
821 return {
822 partitionKey: this.tablePartitionKey,
823 sortKey: this.tableSortKey,
824 };
825 }
826 let schema = this.secondaryIndexSchemas.get(indexName);
827 if (!schema) {
828 throw new Error(`Cannot find schema for index: ${indexName}. Use 'addGlobalSecondaryIndex' or 'addLocalSecondaryIndex' to add index`);
829 }
830 return schema;
831 }
832 /**
833 * Validate the table construct.
834 *
835 * @returns an array of validation error message
836 */
837 validate() {
838 const errors = new Array();
839 if (!this.tablePartitionKey) {
840 errors.push('a partition key must be specified');
841 }
842 if (this.localSecondaryIndexes.length > 0 && !this.tableSortKey) {
843 errors.push('a sort key of the table must be specified to add local secondary indexes');
844 }
845 if (this.globalReplicaCustomResources.length > 0 && this.billingMode === BillingMode.PROVISIONED) {
846 const writeAutoScaleAttribute = this.tableScaling.scalableWriteAttribute;
847 if (!writeAutoScaleAttribute) {
848 errors.push('A global Table that uses PROVISIONED as the billing mode needs auto-scaled write capacity. ' +
849 'Use the autoScaleWriteCapacity() method to enable it.');
850 }
851 else if (!writeAutoScaleAttribute._scalingPolicyCreated) {
852 errors.push('A global Table that uses PROVISIONED as the billing mode needs auto-scaled write capacity with a policy. ' +
853 'Call one of the scaleOn*() methods of the object returned from autoScaleWriteCapacity()');
854 }
855 }
856 return errors;
857 }
858 /**
859 * Validate read and write capacity are not specified for on-demand tables (billing mode PAY_PER_REQUEST).
860 *
861 * @param props read and write capacity properties
862 */
863 validateProvisioning(props) {
864 if (this.billingMode === BillingMode.PAY_PER_REQUEST) {
865 if (props.readCapacity !== undefined || props.writeCapacity !== undefined) {
866 throw new Error('you cannot provision read and write capacity for a table with PAY_PER_REQUEST billing mode');
867 }
868 }
869 }
870 /**
871 * Validate index name to check if a duplicate name already exists.
872 *
873 * @param indexName a name of global or local secondary index
874 */
875 validateIndexName(indexName) {
876 if (this.secondaryIndexSchemas.has(indexName)) {
877 // a duplicate index name causes validation exception, status code 400, while trying to create CFN stack
878 throw new Error(`a duplicate index name, ${indexName}, is not allowed`);
879 }
880 }
881 /**
882 * Validate non-key attributes by checking limits within secondary index, which may vary in future.
883 *
884 * @param nonKeyAttributes a list of non-key attribute names
885 */
886 validateNonKeyAttributes(nonKeyAttributes) {
887 if (this.nonKeyAttributes.size + nonKeyAttributes.length > 100) {
888 // https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Limits.html#limits-secondary-indexes
889 throw new RangeError('a maximum number of nonKeyAttributes across all of secondary indexes is 100');
890 }
891 // store all non-key attributes
892 nonKeyAttributes.forEach(att => this.nonKeyAttributes.add(att));
893 }
894 buildIndexKeySchema(partitionKey, sortKey) {
895 this.registerAttribute(partitionKey);
896 const indexKeySchema = [
897 { attributeName: partitionKey.name, keyType: HASH_KEY_TYPE },
898 ];
899 if (sortKey) {
900 this.registerAttribute(sortKey);
901 indexKeySchema.push({ attributeName: sortKey.name, keyType: RANGE_KEY_TYPE });
902 }
903 return indexKeySchema;
904 }
905 buildIndexProjection(props) {
906 if (props.projectionType === ProjectionType.INCLUDE && !props.nonKeyAttributes) {
907 // https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-projectionobject.html
908 throw new Error(`non-key attributes should be specified when using ${ProjectionType.INCLUDE} projection type`);
909 }
910 if (props.projectionType !== ProjectionType.INCLUDE && props.nonKeyAttributes) {
911 // this combination causes validation exception, status code 400, while trying to create CFN stack
912 throw new Error(`non-key attributes should not be specified when not using ${ProjectionType.INCLUDE} projection type`);
913 }
914 if (props.nonKeyAttributes) {
915 this.validateNonKeyAttributes(props.nonKeyAttributes);
916 }
917 return {
918 projectionType: props.projectionType ?? ProjectionType.ALL,
919 nonKeyAttributes: props.nonKeyAttributes ?? undefined,
920 };
921 }
922 findKey(keyType) {
923 return this.keySchema.find(prop => prop.keyType === keyType);
924 }
925 addKey(attribute, keyType) {
926 const existingProp = this.findKey(keyType);
927 if (existingProp) {
928 throw new Error(`Unable to set ${attribute.name} as a ${keyType} key, because ${existingProp.attributeName} is a ${keyType} key`);
929 }
930 this.registerAttribute(attribute);
931 this.keySchema.push({
932 attributeName: attribute.name,
933 keyType,
934 });
935 return this;
936 }
937 /**
938 * Register the key attribute of table or secondary index to assemble attribute definitions of TableResourceProps.
939 *
940 * @param attribute the key attribute of table or secondary index
941 */
942 registerAttribute(attribute) {
943 const { name, type } = attribute;
944 const existingDef = this.attributeDefinitions.find(def => def.attributeName === name);
945 if (existingDef && existingDef.attributeType !== type) {
946 throw new Error(`Unable to specify ${name} as ${type} because it was already defined as ${existingDef.attributeType}`);
947 }
948 if (!existingDef) {
949 this.attributeDefinitions.push({
950 attributeName: name,
951 attributeType: type,
952 });
953 }
954 }
955 /**
956 * Return the role that will be used for AutoScaling
957 */
958 makeScalingRole() {
959 // Use a Service Linked Role.
960 // https://docs.aws.amazon.com/autoscaling/application/userguide/application-auto-scaling-service-linked-roles.html
961 return iam.Role.fromRoleArn(this, 'ScalingRole', core_1.Stack.of(this).formatArn({
962 service: 'iam',
963 region: '',
964 resource: 'role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com',
965 resourceName: 'AWSServiceRoleForApplicationAutoScaling_DynamoDBTable',
966 }));
967 }
968 /**
969 * Creates replica tables
970 *
971 * @param regions regions where to create tables
972 */
973 createReplicaTables(regions, timeout, waitForReplicationToFinish) {
974 const stack = core_1.Stack.of(this);
975 if (!core_1.Token.isUnresolved(stack.region) && regions.includes(stack.region)) {
976 throw new Error('`replicationRegions` cannot include the region where this stack is deployed.');
977 }
978 const provider = replica_provider_1.ReplicaProvider.getOrCreate(this, { timeout });
979 // Documentation at https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/V2gt_IAM.html
980 // is currently incorrect. AWS Support recommends `dynamodb:*` in both source and destination regions
981 const onEventHandlerPolicy = new SourceTableAttachedPolicy(this, provider.onEventHandler.role);
982 const isCompleteHandlerPolicy = new SourceTableAttachedPolicy(this, provider.isCompleteHandler.role);
983 // Permissions in the source region
984 this.grant(onEventHandlerPolicy, 'dynamodb:*');
985 this.grant(isCompleteHandlerPolicy, 'dynamodb:DescribeTable');
986 let previousRegion;
987 let previousRegionCondition;
988 for (const region of new Set(regions)) { // Remove duplicates
989 // Use multiple custom resources because multiple create/delete
990 // updates cannot be combined in a single API call.
991 const currentRegion = new core_1.CustomResource(this, `Replica${region}`, {
992 serviceToken: provider.provider.serviceToken,
993 resourceType: 'Custom::DynamoDBReplica',
994 properties: {
995 TableName: this.tableName,
996 Region: region,
997 SkipReplicationCompletedWait: waitForReplicationToFinish == null
998 ? undefined
999 // CFN changes Custom Resource properties to strings anyways,
1000 // so let's do that ourselves to make it clear in the handler this is a string, not a boolean
1001 : (!waitForReplicationToFinish).toString(),
1002 },
1003 });
1004 currentRegion.node.addDependency(onEventHandlerPolicy.policy, isCompleteHandlerPolicy.policy);
1005 this.globalReplicaCustomResources.push(currentRegion);
1006 // Deploy time check to prevent from creating a replica in the region
1007 // where this stack is deployed. Only needed for environment agnostic
1008 // stacks.
1009 let createReplica;
1010 if (core_1.Token.isUnresolved(stack.region)) {
1011 createReplica = new core_1.CfnCondition(this, `StackRegionNotEquals${region}`, {
1012 expression: core_1.Fn.conditionNot(core_1.Fn.conditionEquals(region, core_1.Aws.REGION)),
1013 });
1014 const cfnCustomResource = currentRegion.node.defaultChild;
1015 cfnCustomResource.cfnOptions.condition = createReplica;
1016 }
1017 // Save regional arns for grantXxx() methods
1018 this.regionalArns.push(stack.formatArn({
1019 region,
1020 service: 'dynamodb',
1021 resource: 'table',
1022 resourceName: this.tableName,
1023 }));
1024 // We need to create/delete regions sequentially because we cannot
1025 // have multiple table updates at the same time. The `isCompleteHandler`
1026 // of the provider waits until the replica is in an ACTIVE state.
1027 if (previousRegion) {
1028 if (previousRegionCondition) {
1029 // we can't simply use a Dependency,
1030 // because the previousRegion is protected by the "different region" Condition,
1031 // and you can't have Fn::If in DependsOn.
1032 // Instead, rely on Ref adding a dependency implicitly!
1033 const previousRegionCfnResource = previousRegion.node.defaultChild;
1034 const currentRegionCfnResource = currentRegion.node.defaultChild;
1035 currentRegionCfnResource.addMetadata('DynamoDbReplicationDependency', core_1.Fn.conditionIf(previousRegionCondition.logicalId, previousRegionCfnResource.ref, core_1.Aws.NO_VALUE));
1036 }
1037 else {
1038 currentRegion.node.addDependency(previousRegion);
1039 }
1040 }
1041 previousRegion = currentRegion;
1042 previousRegionCondition = createReplica;
1043 }
1044 // Permissions in the destination regions (outside of the loop to
1045 // minimize statements in the policy)
1046 onEventHandlerPolicy.grantPrincipal.addToPrincipalPolicy(new iam.PolicyStatement({
1047 actions: ['dynamodb:*'],
1048 resources: this.regionalArns,
1049 }));
1050 }
1051 /**
1052 * Whether this table has indexes
1053 */
1054 get hasIndex() {
1055 return this.globalSecondaryIndexes.length + this.localSecondaryIndexes.length > 0;
1056 }
1057 /**
1058 * Set up key properties and return the Table encryption property from the
1059 * user's configuration.
1060 */
1061 parseEncryption(props) {
1062 let encryptionType = props.encryption;
1063 if (encryptionType != null && props.serverSideEncryption != null) {
1064 throw new Error('Only one of encryption and serverSideEncryption can be specified, but both were provided');
1065 }
1066 if (props.serverSideEncryption && props.encryptionKey) {
1067 throw new Error('encryptionKey cannot be specified when serverSideEncryption is specified. Use encryption instead');
1068 }
1069 if (encryptionType === undefined) {
1070 encryptionType = props.encryptionKey != null
1071 // If there is a configured encryptionKey, the encryption is implicitly CUSTOMER_MANAGED
1072 ? TableEncryption.CUSTOMER_MANAGED
1073 // Otherwise, if severSideEncryption is enabled, it's AWS_MANAGED; else undefined (do not set anything)
1074 : props.serverSideEncryption ? TableEncryption.AWS_MANAGED : undefined;
1075 }
1076 if (encryptionType !== TableEncryption.CUSTOMER_MANAGED && props.encryptionKey) {
1077 throw new Error('`encryptionKey cannot be specified unless encryption is set to TableEncryption.CUSTOMER_MANAGED (it was set to ${encryptionType})`');
1078 }
1079 if (encryptionType === TableEncryption.CUSTOMER_MANAGED && props.replicationRegions) {
1080 throw new Error('TableEncryption.CUSTOMER_MANAGED is not supported by DynamoDB Global Tables (where replicationRegions was set)');
1081 }
1082 switch (encryptionType) {
1083 case TableEncryption.CUSTOMER_MANAGED:
1084 const encryptionKey = props.encryptionKey ?? new kms.Key(this, 'Key', {
1085 description: `Customer-managed key auto-created for encrypting DynamoDB table at ${this.node.path}`,
1086 enableKeyRotation: true,
1087 });
1088 return {
1089 sseSpecification: { sseEnabled: true, kmsMasterKeyId: encryptionKey.keyArn, sseType: 'KMS' },
1090 encryptionKey,
1091 };
1092 case TableEncryption.AWS_MANAGED:
1093 // Not specifying "sseType: 'KMS'" here because it would cause phony changes to existing stacks.
1094 return { sseSpecification: { sseEnabled: true } };
1095 case TableEncryption.DEFAULT:
1096 return { sseSpecification: { sseEnabled: false } };
1097 case undefined:
1098 // Not specifying "sseEnabled: false" here because it would cause phony changes to existing stacks.
1099 return { sseSpecification: undefined };
1100 default:
1101 throw new Error(`Unexpected 'encryptionType': ${encryptionType}`);
1102 }
1103 }
1104}
1105exports.Table = Table;
1106_a = JSII_RTTI_SYMBOL_1;
1107Table[_a] = { fqn: "@aws-cdk/aws-dynamodb.Table", version: "1.191.0" };
1108/**
1109 * Data types for attributes within a table
1110 *
1111 * @see https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html#HowItWorks.DataTypes
1112 */
1113var AttributeType;
1114(function (AttributeType) {
1115 /** Up to 400KiB of binary data (which must be encoded as base64 before sending to DynamoDB) */
1116 AttributeType["BINARY"] = "B";
1117 /** Numeric values made of up to 38 digits (positive, negative or zero) */
1118 AttributeType["NUMBER"] = "N";
1119 /** Up to 400KiB of UTF-8 encoded text */
1120 AttributeType["STRING"] = "S";
1121})(AttributeType = exports.AttributeType || (exports.AttributeType = {}));
1122/**
1123 * DynamoDB's Read/Write capacity modes.
1124 */
1125var BillingMode;
1126(function (BillingMode) {
1127 /**
1128 * Pay only for what you use. You don't configure Read/Write capacity units.
1129 */
1130 BillingMode["PAY_PER_REQUEST"] = "PAY_PER_REQUEST";
1131 /**
1132 * Explicitly specified Read/Write capacity units.
1133 */
1134 BillingMode["PROVISIONED"] = "PROVISIONED";
1135})(BillingMode = exports.BillingMode || (exports.BillingMode = {}));
1136/**
1137 * The set of attributes that are projected into the index
1138 *
1139 * @see https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Projection.html
1140 */
1141var ProjectionType;
1142(function (ProjectionType) {
1143 /** Only the index and primary keys are projected into the index. */
1144 ProjectionType["KEYS_ONLY"] = "KEYS_ONLY";
1145 /** Only the specified table attributes are projected into the index. The list of projected attributes is in `nonKeyAttributes`. */
1146 ProjectionType["INCLUDE"] = "INCLUDE";
1147 /** All of the table attributes are projected into the index. */
1148 ProjectionType["ALL"] = "ALL";
1149})(ProjectionType = exports.ProjectionType || (exports.ProjectionType = {}));
1150/**
1151 * When an item in the table is modified, StreamViewType determines what information
1152 * is written to the stream for this table.
1153 *
1154 * @see https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_StreamSpecification.html
1155 */
1156var StreamViewType;
1157(function (StreamViewType) {
1158 /** The entire item, as it appears after it was modified, is written to the stream. */
1159 StreamViewType["NEW_IMAGE"] = "NEW_IMAGE";
1160 /** The entire item, as it appeared before it was modified, is written to the stream. */
1161 StreamViewType["OLD_IMAGE"] = "OLD_IMAGE";
1162 /** Both the new and the old item images of the item are written to the stream. */
1163 StreamViewType["NEW_AND_OLD_IMAGES"] = "NEW_AND_OLD_IMAGES";
1164 /** Only the key attributes of the modified item are written to the stream. */
1165 StreamViewType["KEYS_ONLY"] = "KEYS_ONLY";
1166})(StreamViewType = exports.StreamViewType || (exports.StreamViewType = {}));
1167/**
1168 * DynamoDB's table class.
1169 *
1170 * @see https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.TableClasses.html
1171 */
1172var TableClass;
1173(function (TableClass) {
1174 /** Default table class for DynamoDB. */
1175 TableClass["STANDARD"] = "STANDARD";
1176 /** Table class for DynamoDB that reduces storage costs compared to existing DynamoDB Standard tables. */
1177 TableClass["STANDARD_INFREQUENT_ACCESS"] = "STANDARD_INFREQUENT_ACCESS";
1178})(TableClass = exports.TableClass || (exports.TableClass = {}));
1179/**
1180 * An inline policy that is logically bound to the source table of a DynamoDB Global Tables
1181 * "cluster". This is here to ensure permissions are removed as part of (and not before) the
1182 * CleanUp phase of a stack update, when a replica is removed (or the entire "cluster" gets
1183 * replaced).
1184 *
1185 * If statements are added directly to the handler roles (as opposed to in a separate inline
1186 * policy resource), new permissions are in effect before clean up happens, and so replicas that
1187 * need to be dropped can no longer be due to lack of permissions.
1188 */
1189class SourceTableAttachedPolicy extends core_2.Construct {
1190 constructor(sourceTable, role) {
1191 super(sourceTable, `SourceTableAttachedManagedPolicy-${core_1.Names.nodeUniqueId(role.node)}`);
1192 const policy = new iam.ManagedPolicy(this, 'Resource', {
1193 // A CF update of the description property of a managed policy requires
1194 // a replacement. Use the table name in the description to force a managed
1195 // policy replacement when the table name changes. This way we preserve permissions
1196 // to delete old replicas in case of a table replacement.
1197 description: `DynamoDB replication managed policy for table ${sourceTable.tableName}`,
1198 roles: [role],
1199 });
1200 this.policy = policy;
1201 this.grantPrincipal = new SourceTableAttachedPrincipal(role, policy);
1202 }
1203}
1204/**
1205 * An `IPrincipal` entity that can be used as the target of `grant` calls, used by the
1206 * `SourceTableAttachedPolicy` class so it can act as an `IGrantable`.
1207 */
1208class SourceTableAttachedPrincipal extends iam.PrincipalBase {
1209 constructor(role, policy) {
1210 super();
1211 this.role = role;
1212 this.policy = policy;
1213 }
1214 get policyFragment() {
1215 return this.role.policyFragment;
1216 }
1217 addToPrincipalPolicy(statement) {
1218 this.policy.addStatements(statement);
1219 return {
1220 policyDependable: this.policy,
1221 statementAdded: true,
1222 };
1223 }
1224 dedupeString() {
1225 return undefined;
1226 }
1227}
1228//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFibGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJ0YWJsZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSxrRUFBa0U7QUFDbEUsc0RBQXNEO0FBQ3RELHdDQUF3QztBQUV4Qyx3Q0FBd0M7QUFDeEMsd0NBSXVCO0FBRXZCLDJGQUFzRTtBQUN0RSw2REFBK0Q7QUFDL0QsaUNBQWlDO0FBQ2pDLHlEQUFxRDtBQUVyRCx5RUFBb0U7QUFFcEUsaUdBQWlHO0FBQ2pHLDhEQUE4RDtBQUM5RCx3Q0FBMkQ7QUFFM0QsTUFBTSxhQUFhLEdBQUcsTUFBTSxDQUFDO0FBQzdCLE1BQU0sY0FBYyxHQUFHLE9BQU8sQ0FBQztBQUUvQix3R0FBd0c7QUFDeEcsTUFBTSwrQkFBK0IsR0FBRyxDQUFDLENBQUM7QUFnQjFDOztHQUVHO0FBQ0gsSUFBWSxTQTRDWDtBQTVDRCxXQUFZLFNBQVM7SUFFbkIsY0FBYztJQUNkLGlDQUFvQixDQUFBO0lBRXBCLG1CQUFtQjtJQUNuQiw0Q0FBK0IsQ0FBQTtJQUUvQixXQUFXO0lBQ1gsMEJBQWEsQ0FBQTtJQUViLFlBQVk7SUFDWiw0QkFBZSxDQUFBO0lBRWYsaUJBQWlCO0lBQ2pCLHVDQUEwQixDQUFBO0lBRTFCLGNBQWM7SUFDZCxpQ0FBb0IsQ0FBQTtJQUVwQixpQkFBaUI7SUFDakIsdUNBQTBCLENBQUE7SUFFMUIsaUJBQWlCO0lBQ2pCLHVDQUEwQixDQUFBO0lBRTFCLHFCQUFxQjtJQUNyQixnREFBbUMsQ0FBQTtJQUVuQyx5QkFBeUI7SUFDekIsd0RBQTJDLENBQUE7SUFFM0MsdUJBQXVCO0lBQ3ZCLG9EQUF1QyxDQUFBO0lBRXZDLHlCQUF5QjtJQUN6Qix1REFBMEMsQ0FBQTtJQUUxQyw0QkFBNEI7SUFDNUIsOERBQWlELENBQUE7SUFFakQsdUJBQXVCO0lBQ3ZCLG1EQUFzQyxDQUFBO0FBRXhDLENBQUMsRUE1Q1csU0FBUyxHQUFULGlCQUFTLEtBQVQsaUJBQVMsUUE0Q3BCO0FBa0JEOztHQUVH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QUVEOzs7R0FHRztBQUNILE1BQU0sNEJBQTZCLFNBQVEsR0FBRyxDQUFDLGFBQWE7SUFDMUQsWUFBb0MsSUFBZSxFQUFtQixNQUF5QjtRQUM3RixLQUFLLEVBQUUsQ0FBQztRQUQwQixTQUFJLEdBQUosSUFBSSxDQUFXO1FBQW1CLFdBQU0sR0FBTixNQUFNLENBQW1CO0tBRTlGO0lBRUQsSUFBVyxjQUFjO1FBQ3ZCLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUM7S0FDakM7SUFFTSxvQkFBb0IsQ0FBQyxTQUE4QjtRQUN4RCxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUNyQyxPQUFPO1lBQ0wsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLE1BQU07WUFDN0IsY0FBYyxFQUFFLElBQUk7U0FDckIsQ0FBQztLQUNIO0lBRU0sWUFBWTtRQUNqQixPQUFPLFNBQVMsQ0FBQztLQUNsQjtDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgYXBwc2NhbGluZyBmcm9tICdAYXdzLWNkay9hd3MtYXBwbGljYXRpb25hdXRvc2NhbGluZyc7XG5pbXBvcnQgKiBhcyBjbG91ZHdhdGNoIGZyb20gJ0Bhd3MtY2RrL2F3cy1jbG91ZHdhdGNoJztcbmltcG9ydCAqIGFzIGlhbSBmcm9tICdAYXdzLWNkay9hd3MtaWFtJztcbmltcG9ydCAqIGFzIGtpbmVzaXMgZnJvbSAnQGF3cy1jZGsvYXdzLWtpbmVzaXMnO1xuaW1wb3J0ICogYXMga21zIGZyb20gJ0Bhd3MtY2RrL2F3cy1rbXMnO1xuaW1wb3J0IHtcbiAgQXJuRm9ybWF0LFxuICBBd3MsIENmbkNvbmRpdGlvbiwgQ2ZuQ3VzdG9tUmVzb3VyY2UsIENmblJlc291cmNlLCBDdXN0b21SZXNvdXJjZSwgRHVyYXRpb24sXG4gIEZuLCBJUmVzb3VyY2UsIExhenksIE5hbWVzLCBSZW1vdmFsUG9saWN5LCBSZXNvdXJjZSwgU3RhY2ssIFRva2VuLFxufSBmcm9tICdAYXdzLWNkay9jb3JlJztcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0IHsgRHluYW1vREJNZXRyaWNzIH0gZnJvbSAnLi9keW5hbW9kYi1jYW5uZWQtbWV0cmljcy5nZW5lcmF0ZWQnO1xuaW1wb3J0IHsgQ2ZuVGFibGUsIENmblRhYmxlUHJvcHMgfSBmcm9tICcuL2R5bmFtb2RiLmdlbmVyYXRlZCc7XG5pbXBvcnQgKiBhcyBwZXJtcyBmcm9tICcuL3Blcm1zJztcbmltcG9ydCB7IFJlcGxpY2FQcm92aWRlciB9IGZyb20gJy4vcmVwbGljYS1wcm92aWRlcic7XG5pbXBvcnQgeyBFbmFibGVTY2FsaW5nUHJvcHMsIElTY2FsYWJsZVRhYmxlQXR0cmlidXRlIH0gZnJvbSAnLi9zY2FsYWJsZS1hdHRyaWJ1dGUtYXBpJztcbmltcG9ydCB7IFNjYWxhYmxlVGFibGVBdHRyaWJ1dGUgfSBmcm9tICcuL3NjYWxhYmxlLXRhYmxlLWF0dHJpYnV0ZSc7XG5cbi8vIGtlZXAgdGhpcyBpbXBvcnQgc2VwYXJhdGUgZnJvbSBvdGhlciBpbXBvcnRzIHRvIHJlZHVjZSBjaGFuY2UgZm9yIG1lcmdlIGNvbmZsaWN0cyB3aXRoIHYyLW1haW5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1kdXBsaWNhdGUtaW1wb3J0cywgaW1wb3J0L29yZGVyXG5pbXBvcnQgeyBDb25zdHJ1Y3QgYXMgQ29yZUNvbnN0cnVjdCB9IGZyb20gJ0Bhd3MtY2RrL2NvcmUnO1xuXG5jb25zdCBIQVNIX0tFWV9UWVBFID0gJ0hBU0gnO1xuY29uc3QgUkFOR0VfS0VZX1RZUEUgPSAnUkFOR0UnO1xuXG4vLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vYW1hem9uZHluYW1vZGIvbGF0ZXN0L2RldmVsb3Blcmd1aWRlL0xpbWl0cy5odG1sI2xpbWl0cy1zZWNvbmRhcnktaW5kZXhlc1xuY29uc3QgTUFYX0xPQ0FMX1NFQ09OREFSWV9JTkRFWF9DT1VOVCA9IDU7XG5cbi8qKlxuICogT3B0aW9ucyBmb3IgY29uZmlndXJpbmcgYSBzeXN0ZW0gZXJyb3JzIG1ldHJpYyB0aGF0IGNvbnNpZGVycyBtdWx0aXBsZSBvcGVyYXRpb25zLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFN5c3RlbUVycm9yc0Zvck9wZXJhdGlvbnNNZXRyaWNPcHRpb25zIGV4dGVuZHMgY2xvdWR3YXRjaC5NZXRyaWNPcHRpb25zIHtcblxuICAvKipcbiAgICogVGhlIG9wZXJhdGlvbnMgdG8gYXBwbHkgdGhlIG1ldHJpYyB0by5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBBbGwgb3BlcmF0aW9ucyBhdmFpbGFibGUgYnkgRHluYW1vREIgdGFibGVzIHdpbGwgYmUgY29uc2lkZXJlZC5cbiAgICovXG4gIHJlYWRvbmx5IG9wZXJhdGlvbnM/OiBPcGVyYXRpb25bXTtcblxufVxuXG4vKipcbiAqIFN1cHBvcnRlZCBEeW5hbW9EQiB0YWJsZSBvcGVyYXRpb25zLlxuICovXG5leHBvcnQgZW51bSBPcGVyYXRpb24ge1xuXG4gIC8qKiBHZXRJdGVtICovXG4gIEdFVF9JVEVNID0gJ0dldEl0ZW0nLFxuXG4gIC8qKiBCYXRjaEdldEl0ZW0gKi9cbiAgQkFUQ0hfR0VUX0lURU0gPSAnQmF0Y2hHZXRJdGVtJyxcblxuICAvKiogU2NhbiAqL1xuICBTQ0FOID0gJ1NjYW4nLFxuXG4gIC8qKiBRdWVyeSAqL1xuICBRVUVSWSA9ICdRdWVyeScsXG5cbiAgLyoqIEdldFJlY29yZHMgKi9cbiAgR0VUX1JFQ09SRFMgPSAnR2V0UmVjb3JkcycsXG5cbiAgLyoqIFB1dEl0ZW0gKi9cbiAgUFVUX0lURU0gPSAnUHV0SXRlbScsXG5cbiAgLyoqIERlbGV0ZUl0ZW0gKi9cbiAgREVMRVRFX0lURU0gPSAnRGVsZXRlSXRlbScsXG5cbiAgLyoqIFVwZGF0ZUl0ZW0gKi9cbiAgVVBEQVRFX0lURU0gPSAnVXBkYXRlSXRlbScsXG5cbiAgLyoqIEJhdGNoV3JpdGVJdGVtICovXG4gIEJBVENIX1dSSVRFX0lURU0gPSAnQmF0Y2hXcml0ZUl0ZW0nLFxuXG4gIC8qKiBUcmFuc2FjdFdyaXRlSXRlbXMgKi9cbiAgVFJBTlNBQ1RfV1JJVEVfSVRFTVMgPSAnVHJhbnNhY3RXcml0ZUl0ZW1zJyxcblxuICAvKiogVHJhbnNhY3RHZXRJdGVtcyAqL1xuICBUUkFOU0FDVF9HRVRfSVRFTVMgPSAnVHJhbnNhY3RHZXRJdGVtcycsXG5cbiAgLyoqIEV4ZWN1dGVUcmFuc2FjdGlvbiAqL1xuICBFWEVDVVRFX1RSQU5TQUNUSU9OID0gJ0V4ZWN1dGVUcmFuc2FjdGlvbicsXG5cbiAgLyoqIEJhdGNoRXhlY3V0ZVN0YXRlbWVudCAqL1xuICBCQVRDSF9FWEVDVVRFX1NUQVRFTUVOVCA9ICdCYXRjaEV4ZWN1dGVTdGF0ZW1lbnQnLFxuXG4gIC8qKiBFeGVjdXRlU3RhdGVtZW50ICovXG4gIEVYRUNVVEVfU1RBVEVNRU5UID0gJ0V4ZWN1dGVTdGF0ZW1lbnQnLFxuXG59XG5cbi8qKlxuICogUmVwcmVzZW50cyBhbiBhdHRyaWJ1dGUgZm9yIGRlc2NyaWJpbmcgdGhlIGtleSBzY2hlbWEgZm9yIHRoZSB0YWJsZVxuICogYW5kIGluZGV4ZXMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQXR0cmlidXRlIHtcbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIGFuIGF0dHJpYnV0ZS5cbiAgICovXG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIGRhdGEgdHlwZSBvZiBhbiBhdHRyaWJ1dGUuXG4gICAqL1xuICByZWFkb25seSB0eXBlOiBBdHRyaWJ1dGVUeXBlO1xufVxuXG4vKipcbiAqIFdoYXQga2luZCBvZiBzZXJ2ZXItc2lkZSBlbmNyeXB0aW9uIHRvIGFwcGx5IHRvIHRoaXMgdGFibGUuXG4gKi9cbmV4cG9ydCBlbnVtIFRhYmxlRW5jcnlwdGlvbiB7XG4gIC8qKlxuICAgKiBTZXJ2ZXItc2lkZSBLTVMgZW5jcnlwdGlvbiB3aXRoIGEgbWFzdGVyIGtleSBvd25lZCBieSBBV1MuXG4gICAqL1xuICBERUZBVUxUID0gJ0FXU19PV05FRCcsXG5cbiAgLyoqXG4gICAqIFNlcnZlci1zaWRlIEtNUyBlbmNyeXB0aW9uIHdpdGggYSBjdXN0b21lciBtYXN0ZXIga2V5IG1hbmFnZWQgYnkgY3VzdG9tZXIuXG4gICAqIElmIGBlbmNyeXB0aW9uS2V5YCBpcyBzcGVjaWZpZWQsIHRoaXMga2V5IHdpbGwgYmUgdXNlZCwgb3RoZXJ3aXNlLCBvbmUgd2lsbCBiZSBkZWZpbmVkLlxuICAgKlxuICAgKiA+ICoqTk9URSoqOiBpZiBgZW5jcnlwdGlvbktleWAgaXMgbm90IHNwZWNpZmllZCBhbmQgdGhlIGBUYWJsZWAgY29uc3RydWN0IGNyZWF0ZXNcbiAgICogPiBhIEtNUyBrZXkgZm9yIHlvdSwgdGhlIGtleSB3aWxsIGJlIGNyZWF0ZWQgd2l0aCBkZWZhdWx0IHBlcm1pc3Npb25zLiBJZiB5b3UgYXJlIHVzaW5nXG4gICAqID4gQ0RLdjIsIHRoZXNlIHBlcm1pc3Npb25zIHdpbGwgYmUgc3VmZmljaWVudCB0byBlbmFibGUgdGhlIGtleSBmb3IgdXNlIHdpdGggRHluYW1vREIgdGFibGVzLlxuICAgKiA+IElmIHlvdSBhcmUgdXNpbmcgQ0RLdjEsIG1ha2Ugc3VyZSB0aGUgZmVhdHVyZSBmbGFnIGBAYXdzLWNkay9hd3Mta21zOmRlZmF1bHRLZXlQb2xpY2llc2BcbiAgICogPiBpcyBzZXQgdG8gYHRydWVgIGluIHlvdXIgYGNkay5qc29uYC5cbiAgICovXG4gIENVU1RPTUVSX01BTkFHRUQgPSAnQ1VTVE9NRVJfTUFOQUdFRCcsXG5cbiAgLyoqXG4gICAqIFNlcnZlci1zaWRlIEtNUyBlbmNyeXB0aW9uIHdpdGggYSBtYXN0ZXIga2V5IG1hbmFnZWQgYnkgQVdTLlxuICAgKi9cbiAgQVdTX01BTkFHRUQgPSAnQVdTX01BTkFHRUQnLFxufVxuXG4vKipcbiAqIFJlcHJlc2VudHMgdGhlIHRhYmxlIHNjaGVtYSBhdHRyaWJ1dGVzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNjaGVtYU9wdGlvbnMge1xuICAvKipcbiAgICogUGFydGl0aW9uIGtleSBhdHRyaWJ1dGUgZGVmaW5pdGlvbi5cbiAgICovXG4gIHJlYWRvbmx5IHBhcnRpdGlvbktleTogQXR0cmlidXRlO1xuXG4gIC8qKlxuICAgKiBTb3J0IGtleSBhdHRyaWJ1dGUgZGVmaW5pdGlvbi5cbiAgICpcbiAgICogQGRlZmF1bHQgbm8gc29ydCBrZXlcbiAgICovXG4gIHJlYWRvbmx5IHNvcnRLZXk/OiBBdHRyaWJ1dGU7XG59XG5cbi8qKlxuICogUHJvcGVydGllcyBvZiBhIER5bmFtb0RCIFRhYmxlXG4gKlxuICogVXNlIHtAbGluayBUYWJsZVByb3BzfSBmb3IgYWxsIHRhYmxlIHByb3BlcnRpZXNcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBUYWJsZU9wdGlvbnMgZXh0ZW5kcyBTY2hlbWFPcHRpb25zIHtcbiAgLyoqXG4gICAqIFRoZSByZWFkIGNhcGFjaXR5IGZvciB0aGUgdGFibGUuIENhcmVmdWwgaWYgeW91IGFkZCBHbG9iYWwgU2Vjb25kYXJ5IEluZGV4ZXMsIGFzXG4gICAqIHRob3NlIHdpbGwgc2hhcmUgdGhlIHRhYmxlJ3MgcHJvdmlzaW9uZWQgdGhyb3VnaHB1dC5cbiAgICpcbiAgICogQ2FuIG9ubHkgYmUgcHJvdmlkZWQgaWYgYmlsbGluZ01vZGUgaXMgUHJvdmlzaW9uZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IDVcbiAgICovXG4gIHJlYWRvbmx5IHJlYWRDYXBhY2l0eT86IG51bWJlcjtcbiAgLyoqXG4gICAqIFRoZSB3cml0ZSBjYXBhY2l0eSBmb3IgdGhlIHRhYmxlLiBDYXJlZnVsIGlmIHlvdSBhZGQgR2xvYmFsIFNlY29uZGFyeSBJbmRleGVzLCBhc1xuICAgKiB0aG9zZSB3aWxsIHNoYXJlIHRoZSB0YWJsZSdzIHByb3Zpc2lvbmVkIHRocm91Z2hwdXQuXG4gICAqXG4gICAqIENhbiBvbmx5IGJlIHByb3ZpZGVkIGlmIGJpbGxpbmdNb2RlIGlzIFByb3Zpc2lvbmVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCA1XG4gICAqL1xuICByZWFkb25seSB3cml0ZUNhcGFjaXR5PzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBTcGVjaWZ5IGhvdyB5b3UgYXJlIGNoYXJnZWQgZm9yIHJlYWQgYW5kIHdyaXRlIHRocm91Z2hwdXQgYW5kIGhvdyB5b3UgbWFuYWdlIGNhcGFjaXR5LlxuICAgKlxuICAgKiBAZGVmYXVsdCBQUk9WSVNJT05FRCBpZiBgcmVwbGljYXRpb25SZWdpb25zYCBpcyBub3Qgc3BlY2lmaWVkLCBQQVlfUEVSX1JFUVVFU1Qgb3RoZXJ3aXNlXG4gICAqL1xuICByZWFkb25seSBiaWxsaW5nTW9kZT86IEJpbGxpbmdNb2RlO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHBvaW50LWluLXRpbWUgcmVjb3ZlcnkgaXMgZW5hYmxlZC5cbiAgICogQGRlZmF1bHQgLSBwb2ludC1pbi10aW1lIHJlY292ZXJ5IGlzIGRpc2FibGVkXG4gICAqL1xuICByZWFkb25seSBwb2ludEluVGltZVJlY292ZXJ5PzogYm9vbGVhbjtcblxuICAvKipcbiAgICogV2hldGhlciBzZXJ2ZXItc2lkZSBlbmNyeXB0aW9uIHdpdGggYW4gQVdTIG1hbmFnZWQgY3VzdG9tZXIgbWFzdGVyIGtleSBpcyBlbmFibGVkLlxuICAgKlxuICAgKiBUaGlzIHByb3BlcnR5IGNhbm5vdCBiZSBzZXQgaWYgYGVuY3J5cHRpb25gIGFuZC9vciBgZW5jcnlwdGlvbktleWAgaXMgc2V0LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIHNlcnZlci1zaWRlIGVuY3J5cHRpb24gaXMgZW5hYmxlZCB3aXRoIGFuIEFXUyBvd25lZCBjdXN0b21lciBtYXN0ZXIga2V5XG4gICAqXG4gICAqIEBkZXByZWNhdGVkIFRoaXMgcHJvcGVydHkgaXMgZGVwcmVjYXRlZC4gSW4gb3JkZXIgdG8gb2J0YWluIHRoZSBzYW1lIGJlaGF2aW9yIGFzXG4gICAqIGVuYWJsaW5nIHRoaXMsIHNldCB0aGUgYGVuY3J5cHRpb25gIHByb3BlcnR5IHRvIGBUYWJsZUVuY3J5cHRpb24uQVdTX01BTkFHRURgIGluc3RlYWQuXG4gICAqL1xuICByZWFkb25seSBzZXJ2ZXJTaWRlRW5jcnlwdGlvbj86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFNwZWNpZnkgdGhlIHRhYmxlIGNsYXNzLlxuICAgKiBAZGVmYXVsdCBTVEFOREFSRFxuICAgKi9cbiAgcmVhZG9ubHkgdGFibGVDbGFzcz86IFRhYmxlQ2xhc3M7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgc2VydmVyLXNpZGUgZW5jcnlwdGlvbiB3aXRoIGFuIEFXUyBtYW5hZ2VkIGN1c3RvbWVyIG1hc3RlciBrZXkgaXMgZW5hYmxlZC5cbiAgICpcbiAgICogVGhpcyBwcm9wZXJ0eSBjYW5ub3QgYmUgc2V0IGlmIGBzZXJ2ZXJTaWRlRW5jcnlwdGlvbmAgaXMgc2V0LlxuICAgKlxuICAgKiA+ICoqTk9URSoqOiBpZiB5b3Ugc2V0IHRoaXMgdG8gYENVU1RPTUVSX01BTkFHRURgIGFuZCBgZW5jcnlwdGlvbktleWAgaXMgbm90XG4gICAqID4gc3BlY2lmaWVkLCB0aGUga2V5IHRoYXQgdGhlIFRhYmxldCBnZW5lcmF0ZXMgZm9yIHlvdSB3aWxsIGJlIGNyZWF0ZWQgd2l0aFxuICAgKiA+IGRlZmF1bHQgcGVybWlzc2lvbnMuIElmIHlvdSBhcmUgdXNpbmcgQ0RLdjIsIHRoZXNlIHBlcm1pc3Npb25zIHdpbGwgYmVcbiAgICogPiBzdWZmaWNpZW50IHRvIGVuYWJsZSB0aGUga2V5IGZvciB1c2Ugd2l0aCBEeW5hbW9EQiB0YWJsZXMuICBJZiB5b3UgYXJlXG4gICAqID4gdXNpbmcgQ0RLdjEsIG1ha2Ugc3VyZSB0aGUgZmVhdHVyZSBmbGFnXG4gICAqID4gYEBhd3MtY2RrL2F3cy1rbXM6ZGVmYXVsdEtleVBvbGljaWVzYCBpcyBzZXQgdG8gYHRydWVgIGluIHlvdXIgYGNkay5qc29uYC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBzZXJ2ZXItc2lkZSBlbmNyeXB0aW9uIGlzIGVuYWJsZWQgd2l0aCBhbiBBV1Mgb3duZWQgY3VzdG9tZXIgbWFzdGVyIGtleVxuICAgKi9cbiAgcmVhZG9ubHkgZW5jcnlwdGlvbj86IFRhYmxlRW5jcnlwdGlvbjtcblxuICAvKipcbiAgICogRXh0ZXJuYWwgS01TIGtleSB0byB1c2UgZm9yIHRhYmxlIGVuY3J5cHRpb24uXG4gICAqXG4gICAqIFRoaXMgcHJvcGVydHkgY2FuIG9ubHkgYmUgc2V0IGlmIGBlbmNyeXB0aW9uYCBpcyBzZXQgdG8gYFRhYmxlRW5jcnlwdGlvbi5DVVNUT01FUl9NQU5BR0VEYC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBJZiBgZW5jcnlwdGlvbmAgaXMgc2V0IHRvIGBUYWJsZUVuY3J5cHRpb24uQ1VTVE9NRVJfTUFOQUdFRGAgYW5kIHRoaXNcbiAgICogcHJvcGVydHkgaXMgdW5kZWZpbmVkLCBhIG5ldyBLTVMga2V5IHdpbGwgYmUgY3JlYXRlZCBhbmQgYXNzb2NpYXRlZCB3aXRoIHRoaXMgdGFibGUuXG4gICAqL1xuICByZWFkb25seSBlbmNyeXB0aW9uS2V5Pzoga21zLklLZXk7XG5cbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIFRUTCBhdHRyaWJ1dGUuXG4gICAqIEBkZWZhdWx0IC0gVFRMIGlzIGRpc2FibGVkXG4gICAqL1xuICByZWFkb25seSB0aW1lVG9MaXZlQXR0cmlidXRlPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBXaGVuIGFuIGl0ZW0gaW4gdGhlIHRhYmxlIGlzIG1vZGlmaWVkLCBTdHJlYW1WaWV3VHlwZSBkZXRlcm1pbmVzIHdoYXQgaW5mb3JtYXRpb25cbiAgICogaXMgd3JpdHRlbiB0byB0aGUgc3RyZWFtIGZvciB0aGlzIHRhYmxlLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIHN0cmVhbXMgYXJlIGRpc2FibGVkIHVubGVzcyBgcmVwbGljYXRpb25SZWdpb25zYCBpcyBzcGVjaWZpZWRcbiAgICovXG4gIHJlYWRvbmx5IHN0cmVhbT86IFN0cmVhbVZpZXdUeXBlO1xuXG4gIC8qKlxuICAgKiBUaGUgcmVtb3ZhbCBwb2xpY3kgdG8gYXBwbHkgdG8gdGhlIER5bmFtb0RCIFRhYmxlLlxuICAgKlxuICAgKiBAZGVmYXVsdCBSZW1vdmFsUG9saWN5LlJFVEFJTlxuICAgKi9cbiAgcmVhZG9ubHkgcmVtb3ZhbFBvbGljeT86IFJlbW92YWxQb2xpY3k7XG5cbiAgLyoqXG4gICAqIFJlZ2lvbnMgd2hlcmUgcmVwbGljYSB0YWJsZXMgd2lsbCBiZSBjcmVhdGVkXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm8gcmVwbGljYSB0YWJsZXMgYXJlIGNyZWF0ZWRcbiAgICovXG4gIHJlYWRvbmx5IHJlcGxpY2F0aW9uUmVnaW9ucz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBUaGUgdGltZW91dCBmb3IgYSB0YWJsZSByZXBsaWNhdGlvbiBvcGVyYXRpb24gaW4gYSBzaW5nbGUgcmVnaW9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCBEdXJhdGlvbi5taW51dGVzKDMwKVxuICAgKi9cbiAgcmVhZG9ubHkgcmVwbGljYXRpb25UaW1lb3V0PzogRHVyYXRpb247XG5cbiAgLyoqXG4gICAqIEluZGljYXRlcyB3aGV0aGVyIENsb3VkRm9ybWF0aW9uIHN0YWNrIHdhaXRzIGZvciByZXBsaWNhdGlvbiB0byBmaW5pc2guXG4gICAqIElmIHNldCB0byBmYWxzZSwgdGhlIENsb3VkRm9ybWF0aW9uIHJlc291cmNlIHdpbGwgbWFyayB0aGUgcmVzb3VyY2UgYXNcbiAgICogY3JlYXRlZCBhbmQgcmVwbGljYXRpb24gd2lsbCBiZSBjb21wbGV0ZWQgYXN5bmNocm9ub3VzbHkuIFRoaXMgcHJvcGVydHkgaXNcbiAgICogaWdub3JlZCBpZiByZXBsaWNhdGlvblJlZ2lvbnMgcHJvcGVydHkgaXMgbm90IHNldC5cbiAgICpcbiAgICogRE8gTk9UIFVOU0VUIHRoaXMgcHJvcGVydHkgaWYgYWRkaW5nL3JlbW92aW5nIG11bHRpcGxlIHJlcGxpY2F0aW9uUmVnaW9uc1xuICAgKiBpbiBvbmUgZGVwbG95bWVudCwgYXMgQ2xvdWRGb3JtYXRpb24gb25seSBzdXBwb3J0cyBvbmUgcmVnaW9uIHJlcGxpY2F0aW9uXG4gICAqIGF0IGEgdGltZS4gQ0RLIG92ZXJjb21lcyB0aGlzIGxpbWl0YXRpb24gYnkgd2FpdGluZyBmb3IgcmVwbGljYXRpb24gdG9cbiAgICogZmluaXNoIGJlZm9yZSBzdGFydGluZyBuZXcgcmVwbGljYXRpb25SZWdpb24uXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0Nsb3VkRm9ybWF0aW9uL2xhdGVzdC9Vc2VyR3VpZGUvYXdzLXJlc291cmNlLWR5bmFtb2RiLWdsb2JhbHRhYmxlLmh0bWwjY2ZuLWR5bmFtb2RiLWdsb2JhbHRhYmxlLXJlcGxpY2FzXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIHJlYWRvbmx5IHdhaXRGb3JSZXBsaWNhdGlvblRvRmluaXNoPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogV2hldGhlciBDbG91ZFdhdGNoIGNvbnRyaWJ1dG9yIGluc2lnaHRzIGlzIGVuYWJsZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBjb250cmlidXRvckluc2lnaHRzRW5hYmxlZD86IGJvb2xlYW47XG59XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgYSBEeW5hbW9EQiBUYWJsZVxuICovXG5leHBvcnQgaW50ZXJmYWNlIFRhYmxlUHJvcHMgZXh0ZW5kcyBUYWJsZU9wdGlvbnMge1xuICAvKipcbiAgICogRW5mb3JjZXMgYSBwYXJ0aWN1bGFyIHBoeXNpY2FsIHRhYmxlIG5hbWUuXG4gICAqIEBkZWZhdWx0IDxnZW5lcmF0ZWQ+XG4gICAqL1xuICByZWFkb25seSB0YWJsZU5hbWU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEtpbmVzaXMgRGF0YSBTdHJlYW0gdG8gY2FwdHVyZSBpdGVtLWxldmVsIGNoYW5nZXMgZm9yIHRoZSB0YWJsZS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBLaW5lc2lzIERhdGEgU3RyZWFtXG4gICAqL1xuICByZWFkb25seSBraW5lc2lzU3RyZWFtPzoga2luZXNpcy5JU3RyZWFtO1xufVxuXG4vKipcbiAqIFByb3BlcnRpZXMgZm9yIGEgc2Vjb25kYXJ5IGluZGV4XG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2Vjb25kYXJ5SW5kZXhQcm9wcyB7XG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgc2Vjb25kYXJ5IGluZGV4LlxuICAgKi9cbiAgcmVhZG9ubHkgaW5kZXhOYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBzZXQgb2YgYXR0cmlidXRlcyB0aGF0IGFyZSBwcm9qZWN0ZWQgaW50byB0aGUgc2Vjb25kYXJ5IGluZGV4LlxuICAgKiBAZGVmYXVsdCBBTExcbiAgICovXG4gIHJlYWRvbmx5IHByb2plY3Rpb25UeXBlPzogUHJvamVjdGlvblR5cGU7XG5cbiAgLyoqXG4gICAqIFRoZSBub24ta2V5IGF0dHJpYnV0ZXMgdGhhdCBhcmUgcHJvamVjdGVkIGludG8gdGhlIHNlY29uZGFyeSBpbmRleC5cbiAgICogQGRlZmF1bHQgLSBObyBhZGRpdGlvbmFsIGF0dHJpYnV0ZXNcbiAgICovXG4gIHJlYWRvbmx5IG5vbktleUF0dHJpYnV0ZXM/OiBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBQcm9wZXJ0aWVzIGZvciBhIGdsb2JhbCBzZWNvbmRhcnkgaW5kZXhcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBHbG9iYWxTZWNvbmRhcnlJbmRleFByb3BzIGV4dGVuZHMgU2Vjb25kYXJ5SW5kZXhQcm9wcywgU2NoZW1hT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBUaGUgcmVhZCBjYXBhY2l0eSBmb3IgdGhlIGdsb2JhbCBzZWNvbmRhcnkgaW5kZXguXG4gICAqXG4gICAqIENhbiBvbmx5IGJlIHByb3ZpZGVkIGlmIHRhYmxlIGJpbGxpbmdNb2RlIGlzIFByb3Zpc2lvbmVkIG9yIHVuZGVmaW5lZC5cbiAgICpcbiAgICogQGRlZmF1bHQgNVxuICAgKi9cbiAgcmVhZG9ubHkgcmVhZENhcGFjaXR5PzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBUaGUgd3JpdGUgY2FwYWNpdHkgZm9yIHRoZSBnbG9iYWwgc2Vjb25kYXJ5IGluZGV4LlxuICAgKlxuICAgKiBDYW4gb25seSBiZSBwcm92aWRlZCBpZiB0YWJsZSBiaWxsaW5nTW9kZSBpcyBQcm92aXNpb25lZCBvciB1bmRlZmluZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IDVcbiAgICovXG4gIHJlYWRvbmx5IHdyaXRlQ2FwYWNpdHk/OiBudW1iZXI7XG59XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgYSBsb2NhbCBzZWNvbmRhcnkgaW5kZXhcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBMb2NhbFNlY29uZGFyeUluZGV4UHJvcHMgZXh0ZW5kcyBTZWNvbmRhcnlJbmRleFByb3BzIHtcbiAgLyoqXG4gICAqIFRoZSBhdHRyaWJ1dGUgb2YgYSBzb3J0IGtleSBmb3IgdGhlIGxvY2FsIHNlY29uZGFyeSBpbmRleC5cbiAgICovXG4gIHJlYWRvbmx5IHNvcnRLZXk6IEF0dHJpYnV0ZTtcbn1cblxuLyoqXG4gKiBBbiBpbnRlcmZhY2UgdGhhdCByZXByZXNlbnRzIGEgRHluYW1vREIgVGFibGUgLSBlaXRoZXIgY3JlYXRlZCB3aXRoIHRoZSBDREssIG9yIGFuIGV4aXN0aW5nIG9uZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJVGFibGUgZXh0ZW5kcyBJUmVzb3VyY2Uge1xuICAvKipcbiAgICogQXJuIG9mIHRoZSBkeW5hbW9kYiB0YWJsZS5cbiAgICpcbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcmVhZG9ubHkgdGFibGVBcm46IHN0cmluZztcblxuICAvKipcbiAgICogVGFibGUgbmFtZSBvZiB0aGUgZHluYW1vZGIgdGFibGUuXG4gICAqXG4gICAqIEBhdHRyaWJ1dGVcbiAgICovXG4gIHJlYWRvbmx5IHRhYmxlTmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBUk4gb2YgdGhlIHRhYmxlJ3Mgc3RyZWFtLCBpZiB0aGVyZSBpcyBvbmUuXG4gICAqXG4gICAqIEBhdHRyaWJ1dGVcbiAgICovXG4gIHJlYWRvbmx5IHRhYmxlU3RyZWFtQXJuPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKlxuICAgKiBPcHRpb25hbCBLTVMgZW5jcnlwdGlvbiBrZXkgYXNzb2NpYXRlZCB3aXRoIHRoaXMgdGFibGUuXG4gICAqL1xuICByZWFkb25seSBlbmNyeXB0aW9uS2V5Pzoga21zLklLZXk7XG5cbiAgLyoqXG4gICAqIEFkZHMgYW4gSUFNIHBvbGljeSBzdGF0ZW1lbnQgYXNzb2NpYXRlZCB3aXRoIHRoaXMgdGFibGUgdG8gYW4gSUFNXG4gICAqIHByaW5jaXBhbCdzIHBvbGljeS5cbiAgICpcbiAgICogSWYgYGVuY3J5cHRpb25LZXlgIGlzIHByZXNlbnQsIGFwcHJvcHJpYXRlIGdyYW50cyB0byB0aGUga2V5IG5lZWRzIHRvIGJlIGFkZGVkXG4gICAqIHNlcGFyYXRlbHkgdXNpbmcgdGhlIGB0YWJsZS5lbmNyeXB0aW9uS2V5LmdyYW50KmAgbWV0aG9kcy5cbiAgICpcbiAgICogQHBhcmFtIGdyYW50ZWUgVGhlIHByaW5jaXBhbCAobm8tb3AgaWYgdW5kZWZpbmVkKVxuICAgKiBAcGFyYW0gYWN0aW9ucyBUaGUgc2V0IG9mIGFjdGlvbnMgdG8gYWxsb3cgKGkuZS4gXCJkeW5hbW9kYjpQdXRJdGVtXCIsIFwiZHluYW1vZGI6R2V0SXRlbVwiLCAuLi4pXG4gICAqL1xuICBncmFudChncmFudGVlOiBpYW0uSUdyYW50YWJsZSwgLi4uYWN0aW9uczogc3RyaW5nW10pOiBpYW0uR3JhbnQ7XG5cbiAgLyoqXG4gICAqIEFkZHMgYW4gSUFNIHBvbGljeSBzdGF0ZW1lbnQgYXNzb2NpYXRlZCB3aXRoIHRoaXMgdGFibGUncyBzdHJlYW0gdG8gYW5cbiAgICogSUFNIHByaW5jaXBhbCdzIHBvbGljeS5cbiAgICpcbiAgICogSWYgYGVuY3J5cHRpb25LZXlgIGlzIHByZXNlbnQsIGFwcHJvcHJpYXRlIGdyYW50cyB0byB0aGUga2V5IG5lZWRzIHRvIGJlIGFkZGVkXG4gICAqIHNlcGFyYXRlbHkgdXNpbmcgdGhlIGB0YWJsZS5lbmNyeXB0aW9uS2V5LmdyYW50KmAgbWV0aG9kcy5cbiAgICpcbiAgICogQHBhcmFtIGdyYW50ZWUgVGhlIHByaW5jaXBhbCAobm8tb3AgaWYgdW5kZWZpbmVkKVxuICAgKiBAcGFyYW0gYWN0aW9ucyBUaGUgc2V0IG9mIGFjdGlvbnMgdG8gYWxsb3cgKGkuZS4gXCJkeW5hbW9kYjpEZXNjcmliZVN0cmVhbVwiLCBcImR5bmFtb2RiOkdldFJlY29yZHNcIiwgLi4uKVxuICAgKi9cbiAgZ3JhbnRTdHJlYW0oZ3JhbnRlZTogaWFtLklHcmFudGFibGUsIC4uLmFjdGlvbnM6IHN0cmluZ1tdKTogaWFtLkdyYW50O1xuXG4gIC8qKlxuICAgKiBQZXJtaXRzIGFuIElBTSBwcmluY2lwYWwgYWxsIGRhdGEgcmVhZCBvcGVyYXRpb25zIGZyb20gdGhpcyB0YWJsZTpcbiAgICogQmF0Y2hHZXRJdGVtLCBHZXRSZWNvcmRzLCBHZXRTaGFyZEl0ZXJhdG9yLCBRdWVyeSwgR2V0SXRlbSwgU2Nhbi5cbiAgICpcbiAgICogQXBwcm9wcmlhdGUgZ3JhbnRzIHdpbGwgYWxzbyBiZSBhZGRlZCB0byB0aGUgY3VzdG9tZXItbWFuYWdlZCBLTVMga2V5XG4gICAqIGlmIG9uZSB3YXMgY29uZmlndXJlZC5cbiAgICpcbiAgICogQHBhcmFtIGdyYW50ZWUgVGhlIHByaW5jaXBhbCB0byBncmFudCBhY2Nlc3MgdG9cbiAgICovXG4gIGdyYW50UmVhZERhdGEoZ3JhbnRlZTogaWFtLklHcmFudGFibGUpOiBpYW0uR3JhbnQ7XG5cbiAgLyoqXG4gICAqIFBlcm1pdHMgYW4gSUFNIFByaW5jaXBhbCB0byBsaXN0IHN0cmVhbXMgYXR0YWNoZWQgdG8gY3VycmVudCBkeW5hbW9kYiB0YWJsZS5cbiAgICpcbiAgICogQHBhcmFtIGdyYW50ZWUgVGhlIHByaW5jaXBhbCAobm8tb3AgaWYgdW5kZWZpbmVkKVxuICAgKi9cbiAgZ3JhbnRUYWJsZUxpc3RTdHJlYW1zKGdyYW50ZWU6IGlhbS5JR3JhbnRhYmxlKTogaWFtLkdyYW50O1xuXG4gIC8qKlxuICAgKiBQZXJtaXRzIGFuIElBTSBwcmluY2lwYWwgYWxsIHN0cmVhbSBkYXRhIHJlYWQgb3BlcmF0aW9ucyBmb3IgdGhpc1xuICAgKiB0YWJsZSdzIHN0cmVhbTpcbiAgICogRGVzY3JpYmVTdHJlYW0sIEdldFJlY29yZHMsIEdldFNoYXJkSXRlcmF0b3IsIExpc3RTdHJlYW1zLlxuICAgKlxuICAgKiBBcHByb3ByaWF0ZSBncmFudHMgd2lsbCBhbHNvIGJlIGFkZGVkIHRvIHRoZSBjdXN0b21lci1tYW5hZ2VkIEtNUyBrZXlcbiAgICogaWYgb25lIHdhcyBjb25maWd1cmVkLlxuICAgKlxuICAgKiBAcGFyYW0gZ3JhbnRlZSBUaGUgcHJpbmNpcGFsIHRvIGdyYW50IGFjY2VzcyB0b1xuICAgKi9cbiAgZ3JhbnRTdHJlYW1SZWFkKGdyYW50ZWU6IGlhbS5JR3JhbnRhYmxlKTogaWFtLkdyYW50O1xuXG4gIC8qKlxuICAgKiBQZXJtaXRzIGFuIElBTSBwcmluY2lwYWwgYWxsIGRhdGEgd3JpdGUgb3BlcmF0aW9ucyB0byB0aGlzIHRhYmxlOlxuICAgKiBCYXRjaFdyaXRlSXRlbSwgUHV0SXRlbSwgVXBkYXRlSXRlbSwgRGVsZXRlSXRlbS5cbiAgICpcbiAgICogQXBwcm9wcmlhdGUgZ3JhbnRzIHdpbGwgYWxzbyBiZSBhZGRlZCB0byB0aGUgY3VzdG9tZXItbWFuYWdlZCBLTVMga2V5XG4gICAqIGlmIG9uZSB3YXMgY29uZmlndXJlZC5cbiAgICpcbiAgICogQHBhcmFtIGdyYW50ZWUgVGhlIHByaW5jaXBhbCB0byBncmFudCBhY2Nlc3MgdG9cbiAgICovXG4gIGdyYW50V3JpdGVEYXRhKGdyYW50ZWU6IGlhbS5JR3JhbnRhYmxlKTogaWFtLkdyYW50O1xuXG4gIC8qKlxuICAgKiBQZXJtaXRzIGFuIElBTSBwcmluY2lwYWwgdG8gYWxsIGRhdGEgcmVhZC93cml0ZSBvcGVyYXRpb25zIHRvIHRoaXMgdGFibGUuXG4gICAqIEJhdGNoR2V0SXRlbSwgR2V0UmVjb3JkcywgR2V0U2hhcmRJdGVyYXRvciwgUXVlcnksIEdldEl0ZW0sIFNjYW4sXG4gICAqIEJhdGNoV3JpdGVJdGVtLCBQdXRJdGVtLCBVcGRhdGVJdGVtLCBEZWxldGVJdGVtXG4gICAqXG4gICAqIEFwcHJvcHJpYXRlIGdyYW50cyB3aWxsIGFsc28gYmUgYWRkZWQgdG8gdGhlIGN1c3RvbWVyLW1hbmFnZWQgS01TIGtleVxuICAgKiBpZiBvbmUgd2FzIGNvbmZpZ3VyZWQuXG4gICAqXG4gICAqIEBwYXJhbSBncmFudGVlIFRoZSBwcmluY2lwYWwgdG8gZ3JhbnQgYWNjZXNzIHRvXG4gICAqL1xuICBncmFudFJlYWRXcml0ZURhdGEoZ3JhbnRlZTogaWFtLklHcmFudGFibGUpOiBpYW0uR3JhbnQ7XG5cbiAgLyoqXG4gICAqIFBlcm1pdHMgYWxsIER5bmFtb0RCIG9wZXJhdGlvbnMgKFwiZHluYW1vZGI6KlwiKSB0byBhbiBJQU0gcHJpbmNpcGFsLlxuICAgKlxuICAgKiBBcHByb3ByaWF0ZSBncmFudHMgd2lsbCBhbHNvIGJlIGFkZGVkIHRvIHRoZSBjdXN0b21lci1tYW5hZ2VkIEtNUyBrZXlcbiAgICogaWYgb25lIHdhcyBjb25maWd1cmVkLlxuICAgKlxuICAgKiBAcGFyYW0gZ3JhbnRlZSBUaGUgcHJpbmNpcGFsIHRvIGdyYW50IGFjY2VzcyB0b1xuICAgKi9cbiAgZ3JhbnRGdWxsQWNjZXNzKGdyYW50ZWU6IGlhbS5JR3JhbnRhYmxlKTogaWFtLkdyYW50O1xuXG4gIC8qKlxuICAgKiBNZXRyaWMgZm9yIHRoZSBudW1iZXIgb2YgRXJyb3JzIGV4ZWN1dGluZyBhbGwgTGFtYmRhc1xuICAgKi9cbiAgbWV0cmljKG1ldHJpY05hbWU6IHN0cmluZywgcHJvcHM/OiBjbG91ZHdhdGNoLk1ldHJpY09wdGlvbnMpOiBjbG91ZHdhdGNoLk1ldHJpYztcblxuICAvKipcbiAgICogTWV0cmljIGZvciB0aGUgY29uc3VtZWQgcmVhZCBjYXBhY2l0eSB1bml0c1xuICAgKlxuICAgKiBAcGFyYW0gcHJvcHMgcHJvcGVydGllcyBvZiBhIG1ldHJpY1xuICAgKi9cbiAgbWV0cmljQ29uc3VtZWRSZWFkQ2FwYWNpdHlVbml0cyhwcm9wcz86IGNsb3Vkd2F0Y2guTWV0cmljT3B0aW9ucyk6IGNsb3Vkd2F0Y2guTWV0cmljO1xuXG4gIC8qKlxuICAgKiBNZXRyaWMgZm9yIHRoZSBjb25zdW1lZCB3cml0ZSBjYXBhY2l0eSB1bml0c1xuICAgKlxuICAgKiBAcGFyYW0gcHJvcHMgcHJvcGVydGllcyBvZiBhIG1ldHJpY1xuICAgKi9cbiAgbWV0cmljQ29uc3VtZWRXcml0ZUNhcGFjaXR5VW5pdHMocHJvcHM/OiBjbG91ZHdhdGNoLk1ldHJpY09wdGlvbnMpOiBjbG91ZHdhdGNoLk1ldHJpYztcblxuICAvKipcbiAgICogTWV0cmljIGZvciB0aGUgc3lzdGVtIGVycm9yc1xuICAgKlxuICAgKiBAcGFyYW0gcHJvcHMgcHJvcGVydGllcyBvZiBhIG1ldHJpY1xuICAgKlxuICAgKiBAZGVwcmVjYXRlZCB1c2UgYG1ldHJpY1N5c3RlbUVycm9yc0Zvck9wZXJhdGlvbnNgXG4gICAqL1xuICBtZXRyaWNTeXN0ZW1FcnJvcnMocHJvcHM/OiBjbG91ZHdhdGNoLk1ldHJpY09wdGlvbnMpOiBjbG91ZHdhdGNoLk1ldHJpYztcblxuICAvKipcbiAgICogTWV0cmljIGZvciB0aGUgc3lzdGVtIGVycm9ycyB0aGlzIHRhYmxlXG4gICAqXG4gICAqIEBwYXJhbSBwcm9wcyBwcm9wZXJ0aWVzIG9mIGEgbWV0cmljXG4gICAqXG4gICAqL1xuICBtZXRyaWNTeXN0ZW1FcnJvcnNGb3JPcGVyYXRpb25zKHByb3BzPzogU3lzdGVtRXJyb3JzRm9yT3BlcmF0aW9uc01ldHJpY09wdGlvbnMpOiBjbG91ZHdhdGNoLklNZXRyaWM7XG5cbiAgLyoqXG4gICAqIE1ldHJpYyBmb3IgdGhlIHVzZXIgZXJyb3JzXG4gICAqXG4gICAqIEBwYXJhbSBwcm9wcyBwcm9wZXJ0aWVzIG9mIGEgbWV0cmljXG4gICAqL1xuICBtZXRyaWNVc2VyRXJyb3JzKHByb3BzPzogY2xvdWR3YXRjaC5NZXRyaWNPcHRpb25zKTogY2xvdWR3YXRjaC5NZXRyaWM7XG5cbiAgLyoqXG4gICAqIE1ldHJpYyBmb3IgdGhlIGNvbmRpdGlvbmFsIGNoZWNrIGZhaWxlZCByZXF1ZXN0c1xuICAgKlxuICAgKiBAcGFyYW0gcHJvcHMgcHJvcGVydGllcyBvZiBhIG1ldHJpY1xuICAgKi9cbiAgbWV0cmljQ29uZGl0aW9uYWxDaGVja0ZhaWxlZFJlcXVlc3RzKHByb3BzPzogY2xvdWR3YXRjaC5NZXRyaWNPcHRpb25zKTogY2xvdWR3YXRjaC5NZXRyaWM7XG5cbiAgLyoqXG4gICAqIE1ldHJpYyBmb3IgdGhyb3R0bGVkIHJlcXVlc3RzXG4gICAqXG4gICAqIEBwYXJhbSBwcm9wcyBwcm9wZXJ0aWVzIG9mIGEgbWV0cmljXG4gICAqXG4gICAqL1xuICBtZXRyaWNUaHJvdHRsZWRSZXF1ZXN0cyhwcm9wcz86IGNsb3Vkd2F0Y2guTWV0cmljT3B0aW9ucyk6IGNsb3Vkd2F0Y2guTWV0cmljO1xuXG4gIC8qKlxuICAgKiBNZXRyaWMgZm9yIHRoZSBzdWNjZXNzZnVsIHJlcXVlc3QgbGF0ZW5jeVxuICAgKlxuICAgKiBAcGFyYW0gcHJvcHMgcHJvcGVydGllcyBvZiBhIG1ldHJpY1xuICAgKlxuICAgKi9cbiAgbWV0cmljU3VjY2Vzc2Z1bFJlcXVlc3RMYXRlbmN5KHByb3BzPzogY2xvdWR3YXRjaC5NZXRyaWNPcHRpb25zKTogY2xvdWR3YXRjaC5NZXRyaWM7XG59XG5cbi8qKlxuICogUmVmZXJlbmNlIHRvIGEgZHluYW1vZGIgdGFibGUuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVGFibGVBdHRyaWJ1dGVzIHtcbiAgLyoqXG4gICAqIFRoZSBBUk4gb2YgdGhlIGR5bmFtb2RiIHRhYmxlLlxuICAgKiBPbmUgb2YgdGhpcywgb3Ige0BsaW5rIHRhYmxlTmFtZX0sIGlzIHJlcXVpcmVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIHRhYmxlIGFyblxuICAgKi9cbiAgcmVhZG9ubHkgdGFibGVBcm4/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSB0YWJsZSBuYW1lIG9mIHRoZSBkeW5hbW9kYiB0YWJsZS5cbiAgICogT25lIG9mIHRoaXMsIG9yIHtAbGluayB0YWJsZUFybn0sIGlzIHJlcXVpcmVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIHRhYmxlIG5hbWVcbiAgICovXG4gIHJlYWRvbmx5IHRhYmxlTmFtZT86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIEFSTiBvZiB0aGUgdGFibGUncyBzdHJlYW0uXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm8gdGFibGUgc3RyZWFtXG4gICAqL1xuICByZWFkb25seSB0YWJsZVN0cmVhbUFybj86IHN0cmluZztcblxuICAvKipcbiAgICogS01TIGVuY3J5cHRpb24ga2V5LCBpZiB0aGlzIHRhYmxlIHVzZXMgYSBjdXN0b21lci1tYW5hZ2VkIGVuY3J5cHRpb24ga2V5LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIGtleVxuICAgKi9cbiAgcmVhZG9ubHkgZW5jcnlwdGlvbktleT86IGttcy5JS2V5O1xuXG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgZ2xvYmFsIGluZGV4ZXMgc2V0IGZvciB0aGlzIFRhYmxlLlxuICAgKiBOb3RlIHRoYXQgeW91IG5lZWQgdG8gc2V0IGVpdGhlciB0aGlzIHByb3BlcnR5LFxuICAgKiBvciB7QGxpbmsgbG9jYWxJbmRleGVzfSxcbiAgICogaWYgeW91IHdhbnQgbWV0aG9kcyBsaWtlIGdyYW50UmVhZERhdGEoKVxuICAgKiB0byBncmFudCBwZXJtaXNzaW9ucyBmb3IgaW5kZXhlcyBhcyB3ZWxsIGFzIHRoZSB0YWJsZSBpdHNlbGYuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm8gZ2xvYmFsIGluZGV4ZXNcbiAgICovXG4gIHJlYWRvbmx5IGdsb2JhbEluZGV4ZXM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIGxvY2FsIGluZGV4ZXMgc2V0IGZvciB0aGlzIFRhYmxlLlxuICAgKiBOb3RlIHRoYXQgeW91IG5lZWQgdG8gc2V0IGVpdGhlciB0aGlzIHByb3BlcnR5LFxuICAgKiBvciB7QGxpbmsgZ2xvYmFsSW5kZXhlc30sXG4gICAqIGlmIHlvdSB3YW50IG1ldGhvZHMgbGlrZSBncmFudFJlYWREYXRhKClcbiAgICogdG8gZ3JhbnQgcGVybWlzc2lvbnMgZm9yIGluZGV4ZXMgYXMgd2VsbCBhcyB0aGUgdGFibGUgaXRzZWxmLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIGxvY2FsIGluZGV4ZXNcbiAgICovXG4gIHJlYWRvbmx5IGxvY2FsSW5kZXhlcz86IHN0cmluZ1tdO1xufVxuXG5hYnN0cmFjdCBjbGFzcyBUYWJsZUJhc2UgZXh0ZW5kcyBSZXNvdXJjZSBpbXBsZW1lbnRzIElUYWJsZSB7XG4gIC8qKlxuICAgKiBAYXR0cmlidXRlXG4gICAqL1xuICBwdWJsaWMgYWJzdHJhY3QgcmVhZG9ubHkgdGFibGVBcm46IHN0cmluZztcblxuICAvKipcbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcHVibGljIGFic3RyYWN0IHJlYWRvbmx5IHRhYmxlTmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlXG4gICAqL1xuICBwdWJsaWMgYWJzdHJhY3QgcmVhZG9ubHkgdGFibGVTdHJlYW1Bcm4/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEtNUyBlbmNyeXB0aW9uIGtleSwgaWYgdGhpcyB0YWJsZSB1c2VzIGEgY3VzdG9tZXItbWFuYWdlZCBlbmNyeXB0aW9uIGtleS5cbiAgICovXG4gIHB1YmxpYyBhYnN0cmFjdCByZWFkb25seSBlbmNyeXB0aW9uS2V5Pzoga21zLklLZXk7XG5cbiAgcHJvdGVjdGVkIHJlYWRvbmx5IHJlZ2lvbmFsQXJucyA9IG5ldyBBcnJheTxzdHJpbmc+KCk7XG5cbiAgLyoqXG4gICAqIEFkZHMgYW4gSUFNIHBvbGljeSBzdGF0ZW1lbnQgYXNzb2NpYXRlZCB3aXRoIHRoaXMgdGFibGUgdG8gYW4gSUFNXG4gICAqIHByaW5jaXBhbCdzIHBvbGljeS5cbiAgICpcbiAgICogSWYgYGVuY3J5cHRpb25LZXlgIGlzIHByZXNlbnQsIGFwcHJvcHJpYXRlIGdyYW50cyB0byB0aGUga2V5IG5lZWRzIHRvIGJlIGFkZGVkXG4gICAqIHNlcGFyYXRlbHkgdXNpbmcgdGhlIGB0YWJsZS5lbmNyeXB0aW9uS2V5LmdyYW50KmAgbWV0aG9kcy5cbiAgICpcbiAgICogQHBhcmFtIGdyYW50ZWUgVGhlIHByaW5jaXBhbCAobm8tb3AgaWYgdW5kZWZpbmVkKVxuICAgKiBAcGFyYW0gYWN0aW9ucyBUaGUgc2V0IG9mIGFjdGlvbnMgdG8gYWxsb3cgKGkuZS4gXCJkeW5hbW9kYjpQdXRJdGVtXCIsIFwiZHluYW1vZGI6R2V0SXRlbVwiLCAuLi4pXG4gICAqL1xuICBwdWJsaWMgZ3JhbnQoZ3JhbnRlZTogaWFtLklHcmFudGFibGUsIC4uLmFjdGlvbnM6IHN0cmluZ1tdKTogaWFtLkdyYW50IHtcbiAgICByZXR1cm4gaWFtLkdyYW50LmFkZFRvUHJpbmNpcGFsKHtcbiAgICAgIGdyYW50ZWUsXG4gICAgICBhY3Rpb25zLFxuICAgICAgcmVzb3VyY2VBcm5zOiBbXG4gICAgICAgIHRoaXMudGFibGVBcm4sXG4gICAgICAgIExhenkuc3RyaW5nKHsgcHJvZHVjZTogKCkgPT4gdGhpcy5oYXNJbmRleCA/IGAke3RoaXMudGFibGVBcm59L2luZGV4LypgIDogQXdzLk5PX1ZBTFVFIH0pLFxuICAgICAgICAuLi50aGlzLnJlZ2lvbmFsQXJucyxcbiAgICAgICAgLi4udGhpcy5yZWdpb25hbEFybnMubWFwKGFybiA9PiBMYXp5LnN0cmluZyh7XG4gICAgICAgICAgcHJvZHVjZTogKCkgPT4gdGhpcy5oYXNJbmRleCA/IGAke2Fybn0vaW5kZXgvKmAgOiBBd3MuTk9fVkFMVUUsXG4gICAgICAgIH0pKSxcbiAgICAgIF0sXG4gICAgICBzY29wZTogdGhpcyxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGFuIElBTSBwb2xpY3kgc3RhdGVtZW50IGFzc29jaWF0ZWQgd2l0aCB0aGlzIHRhYmxlJ3Mgc3RyZWFtIHRvIGFuXG4gICAqIElBTSBwcmluY2lwYWwncyBwb2xpY3kuXG4gICAqXG4gICAqIElmIGBlbmNyeXB0aW9uS2V5YCBpcyBwcmVzZW50LCBhcHByb3ByaWF0ZSBncmFudHMgdG8gdGhlIGtleSBuZWVkcyB0byBiZSBhZGRlZFxuICAgKiBzZXBhcmF0ZWx5IHVzaW5nIHRoZSBgdGFibGUuZW5jcnlwdGlvbktleS5ncmFudCpgIG1ldGhvZHMuXG4gICAqXG4gICAqIEBwYXJhbSBncmFudGVlIFRoZSBwcmluY2lwYWwgKG5vLW9wIGlmIHVuZGVmaW5lZClcbiAgICogQHBhcmFtIGFjdGlvbnMgVGhlIHNldCBvZiBhY3Rpb25zIHRvIGFsbG93IChpLmUuIFwiZHluYW1vZGI6RGVzY3JpYmVTdHJlYW1cIiwgXCJkeW5hbW9kYjpHZXRSZWNvcmRzXCIsIC4uLilcbiAgICovXG4gIHB1YmxpYyBncmFudFN0cmVhbShncmFudGVlOiBpYW0uSUdyYW50YWJsZSwgLi4uYWN0aW9uczogc3RyaW5nW10pOiBpYW0uR3JhbnQge1xuICAgIGlmICghdGhpcy50YWJsZVN0cmVhbUFybikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBEeW5hbW9EQiBTdHJlYW1zIG11c3QgYmUgZW5hYmxlZCBvbiB0aGUgdGFibGUgJHt0aGlzLm5vZGUucGF0aH1gKTtcbiAgICB9XG5cbiAgICByZXR1cm4gaWFtLkdyYW50LmFkZFRvUHJpbmNpcGFsKHtcbiAgICAgIGdyYW50ZWUsXG4gICAgICBhY3Rpb25zLFxuICAgICAgcmVzb3VyY2VBcm5zOiBbdGhpcy50YWJsZVN0cmVhbUFybl0sXG4gICAgICBzY29wZTogdGhpcyxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJtaXRzIGFuIElBTSBwcmluY2lwYWwgYWxsIGRhdGEgcmVhZCBvcGVyYXRpb25zIGZyb20gdGhpcyB0YWJsZTpcbiAgICogQmF0Y2hHZXRJdGVtLCBHZXRSZWNvcmRzLCBHZXRTaGFyZEl0ZXJhdG9yLCBRdWVyeSwgR2V0SXRlbSwgU2NhbiwgRGVzY3JpYmVUYWJsZS5cbiAgICpcbiAgICogQXBwcm9wcmlhdGUgZ3JhbnRzIHdpbGwgYWxzbyBiZSBhZGRlZCB0byB0aGUgY3VzdG9tZXItbWFuYWdlZCBLTVMga2V5XG4gICAqIGlmIG9uZSB3YXMgY29uZmlndXJlZC5cbiAgICpcbiAgICogQHBhcmFtIGdyYW50ZWUgVGhlIHByaW5jaXBhbCB0byBncmFudCBhY2Nlc3MgdG9cbiAgICovXG4gIHB1YmxpYyBncmFudFJlYWREYXRhKGdyYW50ZWU6IGlhbS5JR3JhbnRhYmxlKTogaWFtLkdyYW50IHtcbiAgICBjb25zdCB0YWJsZUFjdGlvbnMgPSBwZXJtcy5SRUFEX0RBVEFfQUNUSU9OUy5jb25jYXQocGVybXMuREVTQ1JJQkVfVEFCTEUpO1xuICAgIHJldHVybiB0aGlzLmNvbWJpbmVkR3JhbnQoZ3JhbnRlZSwgeyBrZXlBY3Rpb25zOiBwZXJtcy5LRVlfUkVBRF9BQ1RJT05TLCB0YWJsZUFjdGlvbnMgfSk7XG4gIH1cblxuICAvKipcbiAgICogUGVybWl0cyBhbiBJQU0gUHJpbmNpcGFsIHRvIGxpc3Qgc3RyZWFtcyBhdHRhY2hlZCB0byBjdXJyZW50IGR5bmFtb2RiIHRhYmxlLlxuICAgKlxuICAgKiBAcGFyYW0gZ3JhbnRlZSBUaGUgcHJpbmNpcGFsIChuby1vcCBpZiB1bmRlZmluZWQpXG4gICAqL1xuICBwdWJsaWMgZ3JhbnRUYWJsZUxpc3RTdHJlYW1zKGdyYW50ZWU6IGlhbS5JR3JhbnRhYmxlKTogaWFtLkdyYW50IHtcbiAgICBpZiAoIXRoaXMudGFibGVTdHJlYW1Bcm4pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgRHluYW1vREIgU3RyZWFtcyBtdXN0IGJlIGVuYWJsZWQgb24gdGhlIHRhYmxlICR7dGhpcy5ub2RlLnBhdGh9YCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGlhbS5HcmFudC5hZGRUb1ByaW5jaXBhbCh7XG4gICAgICBncmFudGVlLFxuICAgICAgYWN0aW9uczogWydkeW5hbW9kYjpMaXN0U3RyZWFtcyddLFxuICAgICAgcmVzb3VyY2VBcm5zOiBbJyonXSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJtaXRzIGFuIElBTSBwcmluY2lwYWwgYWxsIHN0cmVhbSBkYXRhIHJlYWQgb3BlcmF0aW9ucyBmb3IgdGhpc1xuICAgKiB0YWJsZSdzIHN0cmVhbTpcbiAgICogRGVzY3JpYmVTdHJlYW0sIEdldFJlY29yZHMsIEdldFNoYXJkSXRlcmF0b3IsIExpc3RTdHJlYW1zLlxuICAgKlxuICAgKiBBcHByb3ByaWF0ZSBncmFudHMgd2lsbCBhbHNvIGJlIGFkZGVkIHRvIHRoZSBjdXN0b21lci1tYW5hZ2VkIEtNUyBrZXlcbiAgICogaWYgb25lIHdhcyBjb25maWd1cmVkLlxuICAgKlxuICAgKiBAcGFyYW0gZ3JhbnRlZSBUaGUgcHJpbmNpcGFsIHRvIGdyYW50IGFjY2VzcyB0b1xuICAgKi9cbiAgcHVibGljIGdyYW50U3RyZWFtUmVhZChncmFudGVlOiBpYW0uSUdyYW50YWJsZSk6IGlhbS5HcmFudCB7XG4gICAgdGhpcy5ncmFudFRhYmxlTGlzdFN0cmVhbXMoZ3JhbnRlZSk7XG4gICAgcmV0dXJuIHRoaXMuY29tYmluZWRHcmFudChncmFudGVlLCB7IGtleUFjdGlvbnM6IHBlcm1zLktFWV9SRUFEX0FDVElPTlMsIHN0cmVhbUFjdGlvbnM6IHBlcm1zLlJFQURfU1RSRUFNX0RBVEFfQUNUSU9OUyB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQZXJtaXRzIGFuIElBTSBwcmluY2lwYWwgYWxsIGRhdGEgd3JpdGUgb3BlcmF0aW9ucyB0byB0aGlzIHRhYmxlOlxuICAgKiBCYXRjaFdyaXRlSXRlbSwgUHV0SXRlbSwgVXBkYXRlSXRlbSwgRGVsZXRlSXRlbSwgRGVzY3JpYmVUYWJsZS5cbiAgICpcbiAgICogQXBwcm9wcmlhdGUgZ3JhbnRzIHdpbGwgYWxzbyBiZSBhZGRlZCB0byB0aGUgY3VzdG9tZXItbWFuYWdlZCBLTVMga2V5XG4gICAqIGlmIG9uZSB3YXMgY29uZmlndXJlZC5cbiAgICpcbiAgICogQHBhcmFtIGdyYW50ZWUgVGhlIHByaW5jaXBhbCB0byBncmFudCBhY2Nlc3MgdG9cbiAgICovXG4gIHB1YmxpYyBncmFudFdyaXRlRGF0YShncmFudGVlOiBpYW0uSUdyYW50YWJsZSk6IGlhbS5HcmFudCB7XG4gICAgY29uc3QgdGFibGVBY3Rpb25zID0gcGVybXMuV1JJVEVfREFUQV9BQ1RJT05TLmNvbmNhdChwZXJtcy5ERVNDUklCRV9UQUJMRSk7XG4gICAgY29uc3Qga2V5QWN0aW9ucyA9IHBlcm1zLktFWV9SRUFEX0FDVElPTlMuY29uY2F0KHBlcm1zLktFWV9XUklURV9BQ1RJT05TKTtcbiAgICByZXR1cm4gdGhpcy5jb21iaW5lZEdyYW50KGdyYW50ZWUsIHsga2V5QWN0aW9ucywgdGFibGVBY3Rpb25zIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFBlcm1pdHMgYW4gSUFNIHByaW5jaXBhbCB0byBhbGwgZGF0YSByZWFkL3dyaXRlIG9wZXJhdGlvbnMgdG8gdGhpcyB0YWJsZS5cbiAgICogQmF0Y2hHZXRJdGVtLCBHZXRSZWNvcmRzLCBHZXRTaGFyZEl0ZXJhdG9yLCBRdWVyeSwgR2V0SXRlbSwgU2NhbixcbiAgICogQmF0Y2hXcml0ZUl0ZW0sIFB1dEl0ZW0sIFVwZGF0ZUl0ZW0sIERlbGV0ZUl0ZW0sIERlc2NyaWJlVGFibGVcbiAgICpcbiAgICogQXBwcm9wcmlhdGUgZ3JhbnRzIHdpbGwgYWxzbyBiZSBhZGRlZCB0byB0aGUgY3VzdG9tZXItbWFuYWdlZCBLTVMga2V5XG4gICAqIGlmIG9uZSB3YXMgY29uZmlndXJlZC5cbiAgICpcbiAgICogQHBhcmFtIGdyYW50ZWUgVGhlIHByaW5jaXBhbCB0byBncmFudCBhY2Nlc3MgdG9cbiAgICovXG4gIHB1YmxpYyBncmFudFJlYWRXcml0ZURhdGEoZ3JhbnRlZTogaWFtLklHcmFudGFibGUpOiBpYW0uR3JhbnQge1xuICAgIGNvbnN0IHRhYmxlQWN0aW9ucyA9IHBlcm1zLlJFQURfREFUQV9BQ1RJT05TLmNvbmNhdChwZXJtcy5XUklURV9EQVRBX0FDVElPTlMpLmNvbmNhdChwZXJtcy5ERVNDUklCRV9UQUJMRSk7XG4gICAgY29uc3Qga2V5QWN0aW9ucyA9IHBlcm1zLktFWV9SRUFEX0FDVElPTlMuY29uY2F0KHBlcm1zLktFWV9XUklURV9BQ1RJT05TKTtcbiAgICByZXR1cm4gdGhpcy5jb21iaW5lZEdyYW50KGdyYW50ZWUsIHsga2V5QWN0aW9ucywgdGFibGVBY3Rpb25zIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFBlcm1pdHMgYWxsIER5bmFtb0RCIG9wZXJhdGlvbnMgKFwiZHluYW1vZGI6KlwiKSB0byBhbiBJQU0gcHJpbmNpcGFsLlxuICAgKlxuICAgKiBBcHByb3ByaWF0ZSBncmFudHMgd2lsbCBhbHNvIGJlIGFkZGVkIHRvIHRoZSBjdXN0b21lci1tYW5hZ2VkIEtNUyBrZXlcbiAgICogaWYgb25lIHdhcyBjb25maWd1cmVkLlxuICAgKlxuICAgKiBAcGFyYW0gZ3JhbnRlZSBUaGUgcHJpbmNpcGFsIHRvIGdyYW50IGFjY2VzcyB0b1xuICAgKi9cbiAgcHVibGljIGdyYW50RnVsbEFjY2VzcyhncmFudGVlOiBpYW0uSUdyYW50YWJsZSkge1xuICAgIGNvbnN0IGtleUFjdGlvbnMgPSBwZXJtcy5LRVlfUkVBRF9BQ1RJT05TLmNvbmNhdChwZXJtcy5LRVlfV1JJVEVfQUNUSU9OUyk7XG4gICAgcmV0dXJuIHRoaXMuY29tYmluZWRHcmFudChncmFudGVlLCB7IGtleUFjdGlvbnMsIHRhYmxlQWN0aW9uczogWydkeW5hbW9kYjoqJ10gfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIHRoZSBnaXZlbiBuYW1lZCBtZXRyaWMgZm9yIHRoaXMgVGFibGVcbiAgICpcbiAgICogQnkgZGVmYXVsdCwgdGhlIG1ldHJpYyB3aWxsIGJlIGNhbGN1bGF0ZWQgYXMgYSBzdW0gb3ZlciBhIHBlcmlvZCBvZiA1IG1pbnV0ZXMuXG4gICAqIFlvdSBjYW4gY3VzdG9taXplIHRoaXMgYnkgdXNpbmcgdGhlIGBzdGF0aXN0aWNgIGFuZCBgcGVyaW9kYCBwcm9wZXJ0aWVzLlxuICAgKi9cbiAgcHVibGljIG1ldHJpYyhtZXRyaWNOYW1lOiBzdHJpbmcsIHByb3BzPzogY2xvdWR3YXRjaC5NZXRyaWNPcHRpb25zKTogY2xvdWR3YXRjaC5NZXRyaWMge1xuICAgIHJldHVybiBuZXcgY2xvdWR3YXRjaC5NZXRyaWMoe1xuICAgICAgbmFtZXNwYWNlOiAnQVdTL0R5bmFtb0RCJyxcbiAgICAgIG1ldHJpY05hbWUsXG4gICAgICBkaW1lbnNpb25zTWFwOiB7XG4gICAgICAgIFRhYmxlTmFtZTogdGhpcy50YWJsZU5hbWUsXG4gICAgICB9LFxuICAgICAgLi4ucHJvcHMsXG4gICAgfSkuYXR0YWNoVG8odGhpcyk7XG4gIH1cblxuICAvKipcbiAgICogTWV0cmljIGZvciB0aGUgY29uc3VtZWQgcmVhZCBjYXBhY2l0eSB1bml0cyB0aGlzIHRhYmxlXG4gICAqXG4gICAqIEJ5IGRlZmF1bHQsIHRoZSBtZXRyaWMgd2lsbCBiZSBjYWxjdWxhdGVkIGFzIGEgc3VtIG92ZXIgYSBwZXJpb2Qgb2YgNSBtaW51dGVzLlxuICAgKiBZb3UgY2FuIGN1c3RvbWl6ZSB0aGlzIGJ5IHVzaW5nIHRoZSBgc3RhdGlzdGljYCBhbmQgYHBlcmlvZGAgcHJvcGVydGllcy5cbiAgICovXG4gIHB1YmxpYyBtZXRyaWNDb25zdW1lZFJlYWRDYXBhY2l0eVVuaXRzKHByb3BzPzogY2xvdWR3YXRjaC5NZXRyaWNPcHRpb25zKTogY2xvdWR3YXRjaC5NZXRyaWMge1xuICAgIHJldHVybiB0aGlzLmNhbm5lZE1ldHJpYyhEeW5hbW9EQk1ldHJpY3MuY29uc3VtZWRSZWFkQ2FwYWNpdHlVbml0c1N1bSwgcHJvcHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldHJpYyBmb3IgdGhlIGNvbnN1bWVkIHdyaXRlIGNhcGFjaXR5IHVuaXRzIHRoaXMgdGFibGVcbiAgICpcbiAgICogQnkgZGVmYXVsdCwgdGhlIG1ldHJpYyB3aWxsIGJlIGNhbGN1bGF0ZWQgYXMgYSBzdW0gb3ZlciBhIHBlcmlvZCBvZiA1IG1pbnV0ZXMuXG4gICAqIFlvdSBjYW4gY3VzdG9taXplIHRoaXMgYnkgdXNpbmcgdGhlIGBzdGF0aXN0aWNgIGFuZCBgcGVyaW9kYCBwcm9wZXJ0aWVzLlxuICAgKi9cbiAgcHVibGljIG1ldHJpY0NvbnN1bWVkV3JpdGVDYXBhY2l0eVVuaXRzKHByb3BzPzogY2xvdWR3YXRjaC5NZXRyaWNPcHRpb25zKTogY2xvdWR3YXRjaC5NZXRyaWMge1xuICAgIHJldHVybiB0aGlzLmNhbm5lZE1ldHJpYyhEeW5hbW9EQk1ldHJpY3MuY29uc3VtZWRXcml0ZUNhcGFjaXR5VW5pdHNTdW0sIHByb3BzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRyaWMgZm9yIHRoZSBzeXN0ZW0gZXJyb3JzIHRoaXMgdGFibGVcbiAgICpcbiAgICogQGRlcHJlY2F0ZWQgdXNlIGBtZXRyaWNTeXN0ZW1FcnJvcnNGb3JPcGVyYXRpb25zYC5cbiAgICovXG4gIHB1YmxpYyBtZXRyaWNTeXN0ZW1FcnJvcnMocHJvcHM/OiBjbG91ZHdhdGNoLk1ldHJpY09wdGlvbnMpOiBjbG91ZHdhdGNoLk1ldHJpYyB7XG4gICAgaWYgKCFwcm9wcz8uZGltZW5zaW9ucz8uT3BlcmF0aW9uICYmICFwcm9wcz8uZGltZW5zaW9uc01hcD8uT3BlcmF0aW9uKSB7XG4gICAgICAvLyAnT3BlcmF0aW9uJyBtdXN0IGJlIHBhc3NlZCBiZWNhdXNlIGl0cyBhbiBvcGVyYXRpb25hbCBtZXRyaWMuXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCInT3BlcmF0aW9uJyBkaW1lbnNpb24gbXVzdCBiZSBwYXNzZWQgZm9yIHRoZSAnU3lzdGVtRXJyb3JzJyBtZXRyaWMuXCIpO1xuICAgIH1cblxuICAgIGNvbnN0IGRpbWVuc2lvbnNNYXAgPSB7XG4gICAgICBUYWJsZU5hbWU6IHRoaXMudGFibGVOYW1lLFxuICAgICAgLi4ucHJvcHM/LmRpbWVuc2lvbnMgPz8ge30sXG4gICAgICAuLi5wcm9wcz8uZGltZW5zaW9uc01hcCA/PyB7fSxcbiAgICB9O1xuXG4gICAgcmV0dXJuIHRoaXMubWV0cmljKCdTeXN0ZW1FcnJvcnMnLCB7IHN0YXRpc3RpYzogJ3N1bScsIC4uLnByb3BzLCBkaW1lbnNpb25zTWFwIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldHJpYyBmb3IgdGhlIHVzZXIgZXJyb3JzLiBOb3RlIHRoYXQgdGhpcyBtZXRyaWMgcmVwb3J0cyB1c2VyIGVycm9ycyBhY3Jvc3MgYWxsXG4gICAqIHRoZSB0YWJsZXMgaW4gdGhlIGFjY291bnQgYW5kIHJlZ2lvbiB0aGUgdGFibGUgcmVzaWRlcyBpbi5cbiAgICpcbiAgICogQnkgZGVmYXVsdCwgdGhlIG1ldHJpYyB3aWxsIGJlIGNhbGN1bGF0ZWQgYXMgYSBzdW0gb3ZlciBhIHBlcmlvZCBvZiA1IG1pbnV0ZXMuXG4gICAqIFlvdSBjYW4gY3VzdG9taXplIHRoaXMgYnkgdXNpbmcgdGhlIGBzdGF0aXN0aWNgIGFuZCBgcGVyaW9kYCBwcm9wZXJ0aWVzLlxuICAgKi9cbiAgcHVibGljIG1ldHJpY1VzZXJFcnJvcnMocHJvcHM/OiBjbG91ZHdhdGNoLk1ldHJpY09wdGlvbnMpOiBjbG91ZHdhdGNoLk1ldHJpYyB7XG4gICAgaWYgKHByb3BzPy5kaW1lbnNpb25zKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCInZGltZW5zaW9ucycgaXMgbm90IHN1cHBvcnRlZCBmb3IgdGhlICdVc2VyRXJyb3JzJyBtZXRyaWNcIik7XG4gICAgfVxuXG4gICAgLy8gb3ZlcnJpZGluZyAnZGltZW5zaW9ucycgaGVyZSBiZWNhdXNlIHRoaXMgbWV0cmljIGlzIGFuIGFjY291bnQgbWV0cmljLlxuICAgIC8vIHNlZSAnVXNlckVycm9ycycgaW4gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2FtYXpvbmR5bmFtb2RiL2xhdGVzdC9kZXZlbG9wZXJndWlkZS9tZXRyaWNzLWRpbWVuc2lvbnMuaHRtbFxuICAgIHJldHVybiB0aGlzLm1ldHJpYygnVXNlckVycm9ycycsIHsgc3RhdGlzdGljOiAnc3VtJywgLi4ucHJvcHMsIGRpbWVuc2lvbnNNYXA6IHt9IH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldHJpYyBmb3IgdGhlIGNvbmRpdGlvbmFsIGNoZWNrIGZhaWxlZCByZXF1ZXN0cyB0aGlzIHRhYmxlXG4gICAqXG4gICAqIEJ5IGRlZmF1bHQsIHRoZSBtZXRyaWMgd2lsbCBiZSBjYWxjdWxhdGVkIGFzIGEgc3VtIG92ZXIgYSBwZXJpb2Qgb2YgNSBtaW51dGVzLlxuICAgKiBZb3UgY2FuIGN1c3RvbWl6ZSB0aGlzIGJ5IHVzaW5nIHRoZSBgc3RhdGlzdGljYCBhbmQgYHBlcmlvZGAgcHJvcGVydGllcy5cbiAgICovXG4gIHB1YmxpYyBtZXRyaWNDb25kaXRpb25hbENoZWNrRmFpbGVkUmVxdWVzdHMocHJvcHM/OiBjbG91ZHdhdGNoLk1ldHJpY09wdGlvbnMpOiBjbG91ZHdhdGNoLk1ldHJpYyB7XG4gICAgcmV0dXJuIHRoaXMubWV0cmljKCdDb25kaXRpb25hbENoZWNrRmFpbGVkUmVxdWVzdHMnLCB7IHN0YXRpc3RpYzogJ3N1bScsIC4uLnByb3BzIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEhvdyBtYW55IHJlcXVlc3RzIGFyZSB0aHJvdHRsZWQgb24gdGhpcyB0YWJsZVxuICAgKlxuICAgKiBEZWZhdWx0OiBzdW0gb3ZlciA1IG1pbnV0ZXNcbiAgICpcbiAgICogQGRlcHJlY2F0ZWQgRG8gbm90IHVzZSB0aGlzIGZ1bmN0aW9uLiBJdCByZXR1cm5zIGFuIGludmFsaWQgbWV0cmljLiBVc2UgYG1ldHJpY1Rocm90dGxlZFJlcXVlc3RzRm9yT3BlcmF0aW9uYCBpbnN0ZWFkLlxuICAgKi9cbiAgcHVibGljIG1ldHJpY1Rocm90dGxlZFJlcXVlc3RzKHByb3BzPzogY2xvdWR3YXRjaC5NZXRyaWNPcHRpb25zKTogY2xvdWR3YXRjaC5NZXRyaWMge1xuICAgIHJldHVybiB0aGlzLm1ldHJpYygnVGhyb3R0bGVkUmVxdWVzdHMnLCB7IHN0YXRpc3RpYzogJ3N1bScsIC4uLnByb3BzIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEhvdyBtYW55IHJlcXVlc3RzIGFyZSB0aHJvdHRsZWQgb24gdGhpcyB0YWJsZSwgZm9yIHRoZSBnaXZlbiBvcGVyYXRpb25cbiAgICpcbiAgICogRGVmYXVsdDogc3VtIG92ZXIgNSBtaW51dGVzXG4gICAqL1xuICBwdWJsaWMgbWV0cmljVGhyb3R0bGVkUmVxdWVzdHNGb3JPcGVyYXRpb24ob3BlcmF0aW9uOiBzdHJpbmcsIHByb3BzPzogY2xvdWR3YXRjaC5NZXRyaWNPcHRpb25zKTogY2xvdWR3YXRjaC5NZXRyaWMge1xuICAgIHJldHVybiBuZXcgY2xvdWR3YXRjaC5NZXRyaWMoe1xuICAgICAgLi4uRHluYW1vREJNZXRyaWNzLnRocm90dGxlZFJlcXVlc3RzU3VtKHsgT3BlcmF0aW9uOiBvcGVyYXRpb24sIFRhYmxlTmFtZTogdGhpcy50YWJsZU5hbWUgfSksXG4gICAgICAuLi5wcm9wcyxcbiAgICB9KS5hdHRhY2hUbyh0aGlzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRyaWMgZm9yIHRoZSBzdWNjZXNzZnVsIHJlcXVlc3QgbGF0ZW5jeSB0aGlzIHRhYmxlLlxuICAgKlxuICAgKiBCeSBkZWZhdWx0LCB0aGUgbWV0cmljIHdpbGwgYmUgY2FsY3VsYXRlZCBhcyBhbiBhdmVyYWdlIG92ZXIgYSBwZXJpb2Qgb2YgNSBtaW51dGVzLlxuICAgKiBZb3UgY2FuIGN1c3RvbWl6ZSB0aGlzIGJ5IHVzaW5nIHRoZSBgc3RhdGlzdGljYCBhbmQgYHBlcmlvZGAgcHJvcGVydGllcy5cbiAgICovXG4gIHB1YmxpYyBtZXRyaWNTdWNjZXNzZnVsUmVxdWVzdExhdGVuY3kocHJvcHM/OiBjbG91ZHdhdGNoLk1ldHJpY09wdGlvbnMpOiBjbG91ZHdhdGNoLk1ldHJpYyB7XG4gICAgaWYgKCFwcm9wcz8uZGltZW5zaW9ucz8uT3BlcmF0aW9uICYmICFwcm9wcz8uZGltZW5zaW9uc01hcD8uT3BlcmF0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCInT3BlcmF0aW9uJyBkaW1lbnNpb24gbXVzdCBiZSBwYXNzZWQgZm9yIHRoZSAnU3VjY2Vzc2Z1bFJlcXVlc3RMYXRlbmN5JyBtZXRyaWMuXCIpO1xuICAgIH1cblxuICAgIGNvbnN0IGRpbWVuc2lvbnNNYXAgPSB7XG4gICAgICBUYWJsZU5hbWU6IHRoaXMudGFibGVOYW1lLFxuICAgICAgT3BlcmF0aW9uOiBwcm9wcy5kaW1lbnNpb25zTWFwPy5PcGVyYXRpb24gPz8gcHJvcHMuZGltZW5zaW9ucz8uT3BlcmF0aW9uLFxuICAgIH07XG5cbiAgICByZXR1cm4gbmV3IGNsb3Vkd2F0Y2guTWV0cmljKHtcbiAgICAgIC4uLkR5bmFtb0RCTWV0cmljcy5zdWNjZXNzZnVsUmVxdWVzdExhdGVuY3lBdmVyYWdlKGRpbWVuc2lvbnNNYXApLFxuICAgICAgLi4ucHJvcHMsXG4gICAgICBkaW1lbnNpb25zTWFwLFxuICAgIH0pLmF0dGFjaFRvKHRoaXMpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldHJpYyBmb3IgdGhlIHN5c3RlbSBlcnJvcnMgdGhpcyB0YWJsZS5cbiAgICpcbiAgICogVGhpcyB3aWxsIHN1bSBlcnJvcnMgYWNyb3NzIGFsbCBwb3NzaWJsZSBvcGVyYXRpb25zLlxuICAgKiBOb3RlIHRoYXQgYnkgZGVmYXVsdCwgZWFjaCBpbmRpdmlkdWFsIG1ldHJpYyB3aWxsIGJlIGNhbGN1bGF0ZWQgYXMgYSBzdW0gb3ZlciBhIHBlcmlvZCBvZiA1IG1pbnV0ZXMuXG4gICAqIFlvdSBjYW4gY3VzdG9taXplIHRoaXMgYnkgdXNpbmcgdGhlIGBzdGF0aXN0aWNgIGFuZCBgcGVyaW9kYCBwcm9wZXJ0aWVzLlxuICAgKi9cbiAgcHVibGljIG1ldHJpY1N5c3RlbUVycm9yc0Zvck9wZXJhdGlvbnMocHJvcHM/OiBTeXN0ZW1FcnJvcnNGb3JPcGVyYXRpb25zTWV0cmljT3B0aW9ucyk6IGNsb3Vkd2F0Y2guSU1ldHJpYyB7XG5cbiAgICBpZiAocHJvcHM/LmRpbWVuc2lvbnM/Lk9wZXJhdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiVGhlIE9wZXJhdGlvbiBkaW1lbnNpb24gaXMgbm90IHN1cHBvcnRlZC4gVXNlIHRoZSAnb3BlcmF0aW9ucycgcHJvcGVydHkuXCIpO1xuICAgIH1cblxuICAgIGNvbnN0IG9wZXJhdGlvbnMgPSBwcm9wcz8ub3BlcmF0aW9ucyA/PyBPYmplY3QudmFsdWVzKE9wZXJhdGlvbik7XG5cbiAgICBjb25zdCB2YWx1ZXMgPSB0aGlzLmNyZWF0ZU1ldHJpY3NGb3JPcGVyYXRpb25zKCdTeXN0ZW1FcnJvcnMnLCBvcGVyYXRpb25zLCB7IHN0YXRpc3RpYzogJ3N1bScsIC4uLnByb3BzIH0pO1xuXG4gICAgY29uc3Qgc3VtID0gbmV3IGNsb3Vkd2F0Y2guTWF0aEV4cHJlc3Npb24oe1xuICAgICAgZXhwcmVzc2lvbjogYCR7T2JqZWN0LmtleXModmFsdWVzKS5qb2luKCcgKyAnKX1gLFxuICAgICAgdXNpbmdNZXRyaWNzOiB7IC4uLnZhbHVlcyB9LFxuICAgICAgY29sb3I6IHByb3BzPy5jb2xvcixcbiAgICAgIGxhYmVsOiAnU3VtIG9mIGVycm9ycyBhY3Jvc3MgYWxsIG9wZXJhdGlvbnMnLFxuICAgICAgcGVyaW9kOiBwcm9wcz8ucGVyaW9kLFxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHN1bTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBtYXAgb2YgbWV0cmljcyB0aGF0IGNhbiBiZSB1c2VkIGluIGEgbWF0aCBleHByZXNzaW9uLlxuICAgKlxuICAgKiBVc2luZyB0aGUgcmV0dXJuIHZhbHVlIG9mIHRoaXMgZnVuY3Rpb24gYXMgdGhlIGB1c2luZ01ldHJpY3NgIHByb3BlcnR5IGluIGBjbG91ZHdhdGNoLk1hdGhFeHByZXNzaW9uYCBhbGxvd3MgeW91IHRvXG4gICAqIHVzZSB0aGUga2V5cyBvZiB0aGlzIG1hcCBhcyBtZXRyaWMgbmFtZXMgaW5zaWRlIHlvdSBleHByZXNzaW9uLlxuICAgKlxuICAgKiBAcGFyYW0gbWV0cmljTmFtZSBUaGUgbWV0cmljIG5hbWUuXG4gICAqIEBwYXJhbSBvcGVyYXRpb25zIFRoZSBsaXN0IG9mIG9wZXJhdGlvbnMgdG8gY3JlYXRlIG1ldHJpY3MgZm9yLlxuICAgKiBAcGFyYW0gcHJvcHMgUHJvcGVydGllcyBmb3IgdGhlIGluZGl2aWR1YWwgbWV0cmljcy5cbiAgICogQHBhcmFtIG1ldHJpY05hbWVNYXBwZXIgTWFwcGVyIGZ1bmN0aW9uIHRvIGFsbG93IGNvbnRyb2xsaW5nIHRoZSBpbmRpdmlkdWFsIG1ldHJpYyBuYW1lIHBlciBvcGVyYXRpb24uXG4gICAqL1xuICBwcml2YXRlIGNyZWF0ZU1ldHJpY3NGb3JPcGVyYXRpb25zKG1ldHJpY05hbWU6IHN0cmluZywgb3BlcmF0aW9uczogT3BlcmF0aW9uW10sXG4gICAgcHJvcHM/OiBjbG91ZHdhdGNoLk1ldHJpY09wdGlvbnMsIG1ldHJpY05hbWVNYXBwZXI/OiAob3A6IE9wZXJhdGlvbikgPT4gc3RyaW5nKTogUmVjb3JkPHN0cmluZywgY2xvdWR3YXRjaC5JTWV0cmljPiB7XG5cbiAgICBjb25zdCBtZXRyaWNzOiBSZWNvcmQ8c3RyaW5nLCBjbG91ZHdhdGNoLklNZXRyaWM+ID0ge307XG5cbiAgICBjb25zdCBtYXBwZXIgPSBtZXRyaWNOYW1lTWFwcGVyID8/IChvcCA9PiBvcC50b0xvd2VyQ2FzZSgpKTtcblxuICAgIGlmIChwcm9wcz8uZGltZW5zaW9ucz8uT3BlcmF0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgcHJvcGVydGllcy4gT3BlcmF0aW9uIGRpbWVuc2lvbiBpcyBub3Qgc3VwcG9ydGVkIHdoZW4gY2FsY3VsYXRpbmcgb3BlcmF0aW9uYWwgbWV0cmljcycpO1xuICAgIH1cblxuICAgIGZvciAoY29uc3Qgb3BlcmF0aW9uIG9mIG9wZXJhdGlvbnMpIHtcblxuICAgICAgY29uc3QgbWV0cmljID0gdGhpcy5tZXRyaWMobWV0cmljTmFtZSwge1xuICAgICAgICAuLi5wcm9wcyxcbiAgICAgICAgZGltZW5zaW9uc01hcDoge1xuICAgICAgICAgIFRhYmxlTmFtZTogdGhpcy50YWJsZU5hbWUsXG4gICAgICAgICAgT3BlcmF0aW9uOiBvcGVyYXRpb24sXG4gICAgICAgICAgLi4ucHJvcHM/LmRpbWVuc2lvbnMsXG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgY29uc3Qgb3BlcmF0aW9uTWV0cmljTmFtZSA9IG1hcHBlcihvcGVyYXRpb24pO1xuICAgICAgY29uc3QgZmlyc3RDaGFyID0gb3BlcmF0aW9uTWV0cmljTmFtZS5jaGFyQXQoMCk7XG5cbiAgICAgIGlmIChmaXJzdENoYXIgPT09IGZpcnN0Q2hhci50b1VwcGVyQ2FzZSgpKSB7XG4gICAgICAgIC8vIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BbWF6b25DbG91ZFdhdGNoL2xhdGVzdC9tb25pdG9yaW5nL3VzaW5nLW1ldHJpYy1tYXRoLmh0bWwjbWV0cmljLW1hdGgtc3ludGF4XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgTWFwcGVyIGdlbmVyYXRlZCBhbiBpbGxlZ2FsIG9wZXJhdGlvbiBtZXRyaWMgbmFtZTogJHtvcGVyYXRpb25NZXRyaWNOYW1lfS4gTXVzdCBzdGFydCB3aXRoIGEgbG93ZXJjYXNlIGxldHRlcmApO1xuICAgICAgfVxuXG4gICAgICBtZXRyaWNzW29wZXJhdGlvbk1ldHJpY05hbWVdID0gbWV0cmljO1xuICAgIH1cblxuICAgIHJldHVybiBtZXRyaWNzO1xuICB9XG5cbiAgcHJvdGVjdGVkIGFic3RyYWN0IGdldCBoYXNJbmRleCgpOiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBBZGRzIGFuIElBTSBwb2xpY3kgc3RhdGVtZW50IGFzc29jaWF0ZWQgd2l0aCB0aGlzIHRhYmxlIHRvIGFuIElBTVxuICAgKiBwcmluY2lwYWwncyBwb2xpY3kuXG4gICAqIEBwYXJhbSBncmFudGVlIFRoZSBwcmluY2lwYWwgKG5vLW9wIGlmIHVuZGVmaW5lZClcbiAgICogQHBhcmFtIG9wdHMgT3B0aW9ucyBmb3Iga2V5QWN0aW9ucywgdGFibGVBY3Rpb25zIGFuZCBzdHJlYW1BY3Rpb25zXG4gICAqL1xuICBwcml2YXRlIGNvbWJpbmVkR3JhbnQoXG4gICAgZ3JhbnRlZTogaWFtLklHcmFudGFibGUsXG4gICAgb3B0czogeyBrZXlBY3Rpb25zPzogc3RyaW5nW10sIHRhYmxlQWN0aW9ucz86IHN0cmluZ1tdLCBzdHJlYW1BY3Rpb25zPzogc3RyaW5nW10gfSxcbiAgKTogaWFtLkdyYW50IHtcbiAgICBpZiAob3B0cy50YWJsZUFjdGlvbnMpIHtcbiAgICAgIGNvbnN0IHJlc291cmNlcyA9IFt0aGlzLnRhYmxlQXJuLFxuICAgICAgICBMYXp5LnN0cmluZyh7IHByb2R1Y2U6ICgpID0+IHRoaXMuaGFzSW5kZXggPyBgJHt0aGlzLnRhYmxlQXJufS9pbmRleC8qYCA6IEF3cy5OT19WQUxVRSB9KSxcbiAgICAgICAgLi4udGhpcy5yZWdpb25hbEFybnMsXG4gICAgICAgIC4uLnRoaXMucmVnaW9uYWxBcm5zLm1hcChhcm4gPT4gTGF6eS5zdHJpbmcoe1xuICAgICAgICAgIHByb2R1Y2U6ICgpID0+IHRoaXMuaGFzSW5kZXggPyBgJHthcm59L2luZGV4LypgIDogQXdzLk5PX1ZBTFVFLFxuICAgICAgICB9KSldO1xuICAgICAgY29uc3QgcmV0ID0gaWFtLkdyYW50LmFkZFRvUHJpbmNpcGFsKHtcbiAgICAgICAgZ3JhbnRlZSxcbiAgICAgICAgYWN0aW9uczogb3B0cy50YWJsZUFjdGlvbnMsXG4gICAgICAgIHJlc291cmNlQXJuczogcmVzb3VyY2VzLFxuICAgICAgICBzY29wZTogdGhpcyxcbiAgICAgIH0pO1xuICAgICAgaWYgKHRoaXMuZW5jcnlwdGlvbktleSAmJiBvcHRzLmtleUFjdGlvbnMpIHtcbiAgICAgICAgdGhpcy5lbmNyeXB0aW9uS2V5LmdyYW50KGdyYW50ZWUsIC4uLm9wdHMua2V5QWN0aW9ucyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmV0O1xuICAgIH1cbiAgICBpZiAob3B0cy5zdHJlYW1BY3Rpb25zKSB7XG4gICAgICBpZiAoIXRoaXMudGFibGVTdHJlYW1Bcm4pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBEeW5hbW9EQiBTdHJlYW1zIG11c3QgYmUgZW5hYmxlZCBvbiB0aGUgdGFibGUgJHt0aGlzLm5vZGUucGF0aH1gKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHJlc291cmNlcyA9IFt0aGlzLnRhYmxlU3RyZWFtQXJuXTtcbiAgICAgIGNvbnN0IHJldCA9IGlhbS5HcmFudC5hZGRUb1ByaW5jaXBhbCh7XG4gICAgICAgIGdyYW50ZWUsXG4gICAgICAgIGFjdGlvbnM6IG9wdHMuc3RyZWFtQWN0aW9ucyxcbiAgICAgICAgcmVzb3VyY2VBcm5zOiByZXNvdXJjZXMsXG4gICAgICAgIHNjb3BlOiB0aGlzLFxuICAgICAgfSk7XG4gICAgICByZXR1cm4gcmV0O1xuICAgIH1cbiAgICB0aHJvdyBuZXcgRXJyb3IoYFVuZXhwZWN0ZWQgJ2FjdGlvbicsICR7b3B0cy50YWJsZUFjdGlvbnMgfHwgb3B0cy5zdHJlYW1BY3Rpb25zfWApO1xuICB9XG5cbiAgcHJpdmF0ZSBjYW5uZWRNZXRyaWMoXG4gICAgZm46IChkaW1zOiB7IFRhYmxlTmFtZTogc3RyaW5nIH0pID0+IGNsb3Vkd2F0Y2guTWV0cmljUHJvcHMsXG4gICAgcHJvcHM/OiBjbG91ZHdhdGNoLk1ldHJpY09wdGlvbnMpOiBjbG91ZHdhdGNoLk1ldHJpYyB7XG4gICAgcmV0dXJuIG5ldyBjbG91ZHdhdGNoLk1ldHJpYyh7XG4gICAgICAuLi5mbih7IFRhYmxlTmFtZTogdGhpcy50YWJsZU5hbWUgfSksXG4gICAgICAuLi5wcm9wcyxcbiAgICB9KS5hdHRhY2hUbyh0aGlzKTtcbiAgfVxufVxuXG4vKipcbiAqIFByb3ZpZGVzIGEgRHluYW1vREIgdGFibGUuXG4gKi9cbmV4cG9ydCBjbGFzcyBUYWJsZSBleHRlbmRzIFRhYmxlQmFzZSB7XG4gIC8qKlxuICAgKiBQZXJtaXRzIGFuIElBTSBQcmluY2lwYWwgdG8gbGlzdCBhbGwgRHluYW1vREIgU3RyZWFtcy5cbiAgICogQGRlcHJlY2F0ZWQgVXNlIHtAbGluayAjZ3JhbnRUYWJsZUxpc3RTdHJlYW1zfSBmb3IgbW9yZSBncmFudWxhciBwZXJtaXNzaW9uXG4gICAqIEBwYXJhbSBncmFudGVlIFRoZSBwcmluY2lwYWwgKG5vLW9wIGlmIHVuZGVmaW5lZClcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZ3JhbnRMaXN0U3RyZWFtcyhncmFudGVlOiBpYW0uSUdyYW50YWJsZSk6IGlhbS5HcmFudCB7XG4gICAgcmV0dXJuIGlhbS5HcmFudC5hZGRUb1ByaW5jaXBhbCh7XG4gICAgICBncmFudGVlLFxuICAgICAgYWN0aW9uczogWydkeW5hbW9kYjpMaXN0U3RyZWFtcyddLFxuICAgICAgcmVzb3VyY2VBcm5zOiBbJyonXSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgVGFibGUgY29uc3RydWN0IHRoYXQgcmVwcmVzZW50cyBhbiBleHRlcm5hbCB0YWJsZSB2aWEgdGFibGUgbmFtZS5cbiAgICpcbiAgICogQHBhcmFtIHNjb3BlIFRoZSBwYXJlbnQgY3JlYXRpbmcgY29uc3RydWN0ICh1c3VhbGx5IGB0aGlzYCkuXG4gICAqIEBwYXJhbSBpZCBUaGUgY29uc3RydWN0J3MgbmFtZS5cbiAgICogQHBhcmFtIHRhYmxlTmFtZSBUaGUgdGFibGUncyBuYW1lLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBmcm9tVGFibGVOYW1lKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHRhYmxlTmFtZTogc3RyaW5nKTogSVRhYmxlIHtcbiAgICByZXR1cm4gVGFibGUuZnJvbVRhYmxlQXR0cmlidXRlcyhzY29wZSwgaWQsIHsgdGFibGVOYW1lIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBUYWJsZSBjb25zdHJ1Y3QgdGhhdCByZXByZXNlbnRzIGFuIGV4dGVybmFsIHRhYmxlIHZpYSB0YWJsZSBhcm4uXG4gICAqXG4gICAqIEBwYXJhbSBzY29wZSBUaGUgcGFyZW50IGNyZWF0aW5nIGNvbnN0cnVjdCAodXN1YWxseSBgdGhpc2ApLlxuICAgKiBAcGFyYW0gaWQgVGhlIGNvbnN0cnVjdCdzIG5hbWUuXG4gICAqIEBwYXJhbSB0YWJsZUFybiBUaGUgdGFibGUncyBBUk4uXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGZyb21UYWJsZUFybihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCB0YWJsZUFybjogc3RyaW5nKTogSVRhYmxlIHtcbiAgICByZXR1cm4gVGFibGUuZnJvbVRhYmxlQXR0cmlidXRlcyhzY29wZSwgaWQsIHsgdGFibGVBcm4gfSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIFRhYmxlIGNvbnN0cnVjdCB0aGF0IHJlcHJlc2VudHMgYW4gZXh0ZXJuYWwgdGFibGUuXG4gICAqXG4gICAqIEBwYXJhbSBzY29wZSBUaGUgcGFyZW50IGNyZWF0aW5nIGNvbnN0cnVjdCAodXN1YWxseSBgdGhpc2ApLlxuICAgKiBAcGFyYW0gaWQgVGhlIGNvbnN0cnVjdCdzIG5hbWUuXG4gICAqIEBwYXJhbSBhdHRycyBBIGBUYWJsZUF0dHJpYnV0ZXNgIG9iamVjdC5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZnJvbVRhYmxlQXR0cmlidXRlcyhzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBhdHRyczogVGFibGVBdHRyaWJ1dGVzKTogSVRhYmxlIHtcblxuICAgIGNsYXNzIEltcG9ydCBleHRlbmRzIFRhYmxlQmFzZSB7XG5cbiAgICAgIHB1YmxpYyByZWFkb25seSB0YWJsZU5hbWU6IHN0cmluZztcbiAgICAgIHB1YmxpYyByZWFkb25seSB0YWJsZUFybjogc3RyaW5nO1xuICAgICAgcHVibGljIHJlYWRvbmx5IHRhYmxlU3RyZWFtQXJuPzogc3RyaW5nO1xuICAgICAgcHVibGljIHJlYWRvbmx5IGVuY3J5cHRpb25LZXk/OiBrbXMuSUtleTtcbiAgICAgIHByb3RlY3RlZCByZWFkb25seSBoYXNJbmRleCA9IChhdHRycy5nbG9iYWxJbmRleGVzID8/IFtdKS5sZW5ndGggPiAwIHx8XG4gICAgICAgIChhdHRycy5sb2NhbEluZGV4ZXMgPz8gW10pLmxlbmd0aCA+IDA7XG5cbiAgICAgIGNvbnN0cnVjdG9yKF90YWJsZUFybjogc3RyaW5nLCB0YWJsZU5hbWU6IHN0cmluZywgdGFibGVTdHJlYW1Bcm4/OiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoc2NvcGUsIGlkKTtcbiAgICAgICAgdGhpcy50YWJsZUFybiA9IF90YWJsZUFybjtcbiAgICAgICAgdGhpcy50YWJsZU5hbWUgPSB0YWJsZU5hbWU7XG4gICAgICAgIHRoaXMudGFibGVTdHJlYW1Bcm4gPSB0YWJsZVN0cmVhbUFybjtcbiAgICAgICAgdGhpcy5lbmNyeXB0aW9uS2V5ID0gYXR0cnMuZW5jcnlwdGlvbktleTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBsZXQgbmFtZTogc3RyaW5nO1xuICAgIGxldCBhcm46IHN0cmluZztcbiAgICBjb25zdCBzdGFjayA9IFN0YWNrLm9mKHNjb3BlKTtcbiAgICBpZiAoIWF0dHJzLnRhYmxlTmFtZSkge1xuICAgICAgaWYgKCFhdHRycy50YWJsZUFybikgeyB0aHJvdyBuZXcgRXJyb3IoJ09uZSBvZiB0YWJsZU5hbWUgb3IgdGFibGVBcm4gaXMgcmVxdWlyZWQhJyk7IH1cblxuICAgICAgYXJuID0gYXR0cnMudGFibGVBcm47XG4gICAgICBjb25zdCBtYXliZVRhYmxlTmFtZSA9IHN0YWNrLnNwbGl0QXJuKGF0dHJzLnRhYmxlQXJuLCBBcm5Gb3JtYXQuU0xBU0hfUkVTT1VSQ0VfTkFNRSkucmVzb3VyY2VOYW1lO1xuICAgICAgaWYgKCFtYXliZVRhYmxlTmFtZSkgeyB0aHJvdyBuZXcgRXJyb3IoJ0FSTiBmb3IgRHluYW1vREIgdGFibGUgbXVzdCBiZSBpbiB0aGUgZm9ybTogLi4uJyk7IH1cbiAgICAgIG5hbWUgPSBtYXliZVRhYmxlTmFtZTtcbiAgICB9IGVsc2Uge1xuICAgICAgaWYgKGF0dHJzLnRhYmxlQXJuKSB7IHRocm93IG5ldyBFcnJvcignT25seSBvbmUgb2YgdGFibGVBcm4gb3IgdGFibGVOYW1lIGNhbiBiZSBwcm92aWRlZCcpOyB9XG4gICAgICBuYW1lID0gYXR0cnMudGFibGVOYW1lO1xuICAgICAgYXJuID0gc3RhY2suZm9ybWF0QXJuKHtcbiAgICAgICAgc2VydmljZTogJ2R5bmFtb2RiJyxcbiAgICAgICAgcmVzb3VyY2U6ICd0YWJsZScsXG4gICAgICAgIHJlc291cmNlTmFtZTogYXR0cnMudGFibGVOYW1lLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBJbXBvcnQoYXJuLCBuYW1lLCBhdHRycy50YWJsZVN0cmVhbUFybik7XG4gIH1cblxuICBwdWJsaWMgcmVhZG9ubHkgZW5jcnlwdGlvbktleT86IGttcy5JS2V5O1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgdGFibGVBcm46IHN0cmluZztcblxuICAvKipcbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHRhYmxlTmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBAYXR0cmlidXRlXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgdGFibGVTdHJlYW1Bcm46IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICBwcml2YXRlIHJlYWRvbmx5IHRhYmxlOiBDZm5UYWJsZTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGtleVNjaGVtYSA9IG5ldyBBcnJheTxDZm5UYWJsZS5LZXlTY2hlbWFQcm9wZXJ0eT4oKTtcbiAgcHJpdmF0ZSByZWFkb25seSBhdHRyaWJ1dGVEZWZpbml0aW9ucyA9IG5ldyBBcnJheTxDZm5UYWJsZS5BdHRyaWJ1dGVEZWZpbml0aW9uUHJvcGVydHk+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgZ2xvYmFsU2Vjb25kYXJ5SW5kZXhlcyA9IG5ldyBBcnJheTxDZm5UYWJsZS5HbG9iYWxTZWNvbmRhcnlJbmRleFByb3BlcnR5PigpO1xuICBwcml2YXRlIHJlYWRvbmx5IGxvY2FsU2Vjb25kYXJ5SW5kZXhlcyA9IG5ldyBBcnJheTxDZm5UYWJsZS5Mb2NhbFNlY29uZGFyeUluZGV4UHJvcGVydHk+KCk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBzZWNvbmRhcnlJbmRleFNjaGVtYXMgPSBuZXcgTWFwPHN0cmluZywgU2NoZW1hT3B0aW9ucz4oKTtcbiAgcHJpdmF0ZSByZWFkb25seSBub25LZXlBdHRyaWJ1dGVzID0gbmV3IFNldDxzdHJpbmc+KCk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSB0YWJsZVBhcnRpdGlvbktleTogQXR0cmlidXRlO1xuICBwcml2YXRlIHJlYWRvbmx5IHRhYmxlU29ydEtleT86IEF0dHJpYnV0ZTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGJpbGxpbmdNb2RlOiBCaWxsaW5nTW9kZTtcbiAgcHJpdmF0ZSByZWFkb25seSB0YWJsZVNjYWxpbmc6IFNjYWxhYmxlQXR0cmlidXRlUGFpciA9IHt9O1xuICBwcml2YXRlIHJlYWRvbmx5IGluZGV4U2NhbGluZyA9IG5ldyBNYXA8c3RyaW5nLCBTY2FsYWJsZUF0dHJpYnV0ZVBhaXI+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgc2NhbGluZ1JvbGU6IGlhbS5JUm9sZTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGdsb2JhbFJlcGxpY2FDdXN0b21SZXNvdXJjZXMgPSBuZXcgQXJyYXk8Q3VzdG9tUmVzb3VyY2U+KCk7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IFRhYmxlUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQsIHtcbiAgICAgIHBoeXNpY2FsTmFtZTogcHJvcHMudGFibGVOYW1lLFxuICAgIH0pO1xuXG4gICAgY29uc3QgeyBzc2VTcGVjaWZpY2F0aW9uLCBlbmNyeXB0aW9uS2V5IH0gPSB0aGlzLnBhcnNlRW5jcnlwdGlvbihwcm9wcyk7XG5cbiAgICBsZXQgc3RyZWFtU3BlY2lmaWNhdGlvbjogQ2ZuVGFibGUuU3RyZWFtU3BlY2lmaWNhdGlvblByb3BlcnR5IHwgdW5kZWZpbmVkO1xuICAgIGlmIChwcm9wcy5yZXBsaWNhdGlvblJlZ2lvbnMpIHtcbiAgICAgIGlmIChwcm9wcy5zdHJlYW0gJiYgcHJvcHMuc3RyZWFtICE9PSBTdHJlYW1WaWV3VHlwZS5ORVdfQU5EX09MRF9JTUFHRVMpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdgc3RyZWFtYCBtdXN0IGJlIHNldCB0byBgTkVXX0FORF9PTERfSU1BR0VTYCB3aGVuIHNwZWNpZnlpbmcgYHJlcGxpY2F0aW9uUmVnaW9uc2AnKTtcbiAgICAgIH1cbiAgICAgIHN0cmVhbVNwZWNpZmljYXRpb24gPSB7IHN0cmVhbVZpZXdUeXBlOiBTdHJlYW1WaWV3VHlwZS5ORVdfQU5EX09MRF9JTUFHRVMgfTtcblxuICAgICAgdGhpcy5iaWxsaW5nTW9kZSA9IHByb3BzLmJpbGxpbmdNb2RlID8/IEJpbGxpbmdNb2RlLlBBWV9QRVJfUkVRVUVTVDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5iaWxsaW5nTW9kZSA9IHByb3BzLmJpbGxpbmdNb2RlID8/IEJpbGxpbmdNb2RlLlBST1ZJU0lPTkVEO1xuICAgICAgaWYgKHByb3BzLnN0cmVhbSkge1xuICAgICAgICBzdHJlYW1TcGVjaWZpY2F0aW9uID0geyBzdHJlYW1WaWV3VHlwZTogcHJvcHMuc3RyZWFtIH07XG4gICAgICB9XG4gICAgfVxuICAgIHRoaXMudmFsaWRhdGVQcm92aXNpb25pbmcocHJvcHMpO1xuXG4gICAgdGhpcy50YWJsZSA9IG5ldyBDZm5UYWJsZSh0aGlzLCAnUmVzb3VyY2UnLCB7XG4gICAgICB0YWJsZU5hbWU6IHRoaXMucGh5c2ljYWxOYW1lLFxuICAgICAga2V5U2NoZW1hOiB0aGlzLmtleVNjaGVtYSxcbiAgICAgIGF0dHJpYnV0ZURlZmluaXRpb25zOiB0aGlzLmF0dHJpYnV0ZURlZmluaXRpb25zLFxuICAgICAgZ2xvYmFsU2Vjb25kYXJ5SW5kZXhlczogTGF6eS5hbnkoeyBwcm9kdWNlOiAoKSA9PiB0aGlzLmdsb2JhbFNlY29uZGFyeUluZGV4ZXMgfSwgeyBvbWl0RW1wdHlBcnJheTogdHJ1ZSB9KSxcbiAgICAgIGxvY2FsU2Vjb25kYXJ5SW5kZXhlczogTGF6eS5hbnkoeyBwcm9kdWNlOiAoKSA9PiB0aGlzLmxvY2FsU2Vjb25kYXJ5SW5kZXhlcyB9LCB7IG9taXRFbXB0eUFycmF5OiB0cnVlIH0pLFxuICAgICAgcG9pbnRJblRpbWVSZWNvdmVyeVNwZWNpZmljYXRpb246IHByb3BzLnBvaW50SW5UaW1lUmVjb3ZlcnkgIT0gbnVsbCA/IHsgcG9pbnRJblRpbWVSZWNvdmVyeUVuYWJsZWQ6IHByb3BzLnBvaW50SW5UaW1lUmVjb3ZlcnkgfSA6IHVuZGVmaW5lZCxcbiAgICAgIGJpbGxpbmdNb2RlOiB0aGlzLmJpbGxpbmdNb2RlID09PSBCaWxsaW5nTW9kZS5QQVlfUEVSX1JFUVVFU1QgPyB0aGlzLmJpbGxpbmdNb2RlIDogdW5kZWZpbmVkLFxuICAgICAgcHJvdmlzaW9uZWRUaHJvdWdocHV0OiB0aGlzLmJpbGxpbmdNb2RlID09PSBCaWxsaW5nTW9kZS5QQVlfUEVSX1JFUVVFU1QgPyB1bmRlZmluZWQgOiB7XG4gICAgICAgIHJlYWRDYXBhY2l0eVVuaXRzOiBwcm9wcy5yZWFkQ2FwYWNpdHkgfHwgNSxcbiAgICAgICAgd3JpdGVDYXBhY2l0eVVuaXRzOiBwcm9wcy53cml0ZUNhcGFjaXR5IHx8IDUsXG4gICAgICB9LFxuICAgICAgc3NlU3BlY2lmaWNhdGlvbixcbiAgICAgIHN0cmVhbVNwZWNpZmljYXRpb24sXG4gICAgICB0YWJsZUNsYXNzOiBwcm9wcy50YWJsZUNsYXNzLFxuICAgICAgdGltZVRvTGl2ZVNwZWNpZmljYXRpb246IHByb3BzLnRpbWVUb0xpdmVBdHRyaWJ1dGUgPyB7IGF0dHJpYnV0ZU5hbWU6IHByb3BzLnRpbWVUb0xpdmVBdHRyaWJ1dGUsIGVuYWJsZWQ6IHRydWUgfSA6IHVuZGVmaW5lZCxcbiAgICAgIGNvbnRyaWJ1dG9ySW5zaWdodHNTcGVjaWZpY2F0aW9uOiBwcm9wcy5jb250cmlidXRvckluc2lnaHRzRW5hYmxlZCAhPT0gdW5kZWZpbmVkID8geyBlbmFibGVkOiBwcm9wcy5jb250cmlidXRvckluc2lnaHRzRW5hYmxlZCB9IDogdW5kZWZpbmVkLFxuICAgICAga2luZXNpc1N0cmVhbVNwZWNpZmljYXRpb246IHByb3BzLmtpbmVzaXNTdHJlYW0gPyB7IHN0cmVhbUFybjogcHJvcHMua2luZXNpc1N0cmVhbS5zdHJlYW1Bcm4gfSA6IHVuZGVmaW5lZCxcbiAgICB9KTtcbiAgICB0aGlzLnRhYmxlLmFwcGx5UmVtb3ZhbFBvbGljeShwcm9wcy5yZW1vdmFsUG9saWN5KTtcblxuICAgIHRoaXMuZW5jcnlwdGlvbktleSA9IGVuY3J5cHRpb25LZXk7XG5cbiAgICB0aGlzLnRhYmxlQXJuID0gdGhpcy5nZXRSZXNvdXJjZUFybkF0dHJpYnV0ZSh0aGlzLnRhYmxlLmF0dHJBcm4sIHtcbiAgICAgIHNlcnZpY2U6ICdkeW5hbW9kYicsXG4gICAgICByZXNvdXJjZTogJ3RhYmxlJyxcbiAgICAgIHJlc291cmNlTmFtZTogdGhpcy5waHlzaWNhbE5hbWUsXG4gICAgfSk7XG4gICAgdGhpcy50YWJsZU5hbWUgPSB0aGlzLmdldFJlc291cmNlTmFtZUF0dHJpYnV0ZSh0aGlzLnRhYmxlLnJlZik7XG5cbiAgICBpZiAocHJvcHMudGFibGVOYW1lKSB7IHRoaXMubm9kZS5hZGRNZXRhZGF0YSgnYXdzOmNkazpoYXNQaHlzaWNhbE5hbWUnLCB0aGlzLnRhYmxlTmFtZSk7IH1cblxuICAgIHRoaXMudGFibGVTdHJlYW1Bcm4gPSBzdHJlYW1TcGVjaWZpY2F0aW9uID8gdGhpcy50YWJsZS5hdHRyU3RyZWFtQXJuIDogdW5kZWZpbmVkO1xuXG4gICAgdGhpcy5zY2FsaW5nUm9sZSA9IHRoaXMubWFrZVNjYWxpbmdSb2xlKCk7XG5cbiAgICB0aGlzLmFkZEtleShwcm9wcy5wYXJ0aXRpb25LZXksIEhBU0hfS0VZX1RZUEUpO1xuICAgIHRoaXMudGFibGVQYXJ0aXRpb25LZXkgPSBwcm9wcy5wYXJ0aXRpb25LZXk7XG5cbiAgICBpZiAocHJvcHMuc29ydEtleSkge1xuICAgICAgdGhpcy5hZGRLZXkocHJvcHMuc29ydEtleSwgUkFOR0VfS0VZX1RZUEUpO1xuICAgICAgdGhpcy50YWJsZVNvcnRLZXkgPSBwcm9wcy5zb3J0S2V5O1xuICAgIH1cblxuICAgIGlmIChwcm9wcy5yZXBsaWNhdGlvblJlZ2lvbnMgJiYgcHJvcHMucmVwbGljYXRpb25SZWdpb25zLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMuY3JlYXRlUmVwbGljYVRhYmxlcyhwcm9wcy5yZXBsaWNhdGlvblJlZ2lvbnMsIHByb3BzLnJlcGxpY2F0aW9uVGltZW91dCwgcHJvcHMud2FpdEZvclJlcGxpY2F0aW9uVG9GaW5pc2gpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgYSBnbG9iYWwgc2Vjb25kYXJ5IGluZGV4IG9mIHRhYmxlLlxuICAgKlxuICAgKiBAcGFyYW0gcHJvcHMgdGhlIHByb3BlcnR5IG9mIGdsb2JhbCBzZWNvbmRhcnkgaW5kZXhcbiAgICovXG4gIHB1YmxpYyBhZGRHbG9iYWxTZWNvbmRhcnlJbmRleChwcm9wczogR2xvYmFsU2Vjb25kYXJ5SW5kZXhQcm9wcykge1xuICAgIHRoaXMudmFsaWRhdGVQcm92aXNpb25pbmcocHJvcHMpO1xuICAgIHRoaXMudmFsaWRhdGVJbmRleE5hbWUocHJvcHMuaW5kZXhOYW1lKTtcblxuICAgIC8vIGJ1aWxkIGtleSBzY2hlbWEgYW5kIHByb2plY3Rpb24gZm9yIGluZGV4XG4gICAgY29uc3QgZ3NpS2V5U2NoZW1hID0gdGhpcy5idWlsZEluZGV4S2V5U2NoZW1hKHByb3BzLnBhcnRpdGlvbktleSwgcHJvcHMuc29ydEtleSk7XG4gICAgY29uc3QgZ3NpUHJvamVjdGlvbiA9IHRoaXMuYnVpbGRJbmRleFByb2plY3Rpb24ocHJvcHMpO1xuXG4gICAgdGhpcy5nbG9iYWxTZWNvbmRhcnlJbmRleGVzLnB1c2goe1xuICAgICAgaW5kZXhOYW1lOiBwcm9wcy5pbmRleE5hbWUsXG4gICAgICBrZXlTY2hlbWE6IGdzaUtleVNjaGVtYSxcbiAgICAgIHByb2plY3Rpb246IGdzaVByb2plY3Rpb24sXG4gICAgICBwcm92aXNpb25lZFRocm91Z2hwdXQ6IHRoaXMuYmlsbGluZ01vZGUgPT09IEJpbGxpbmdNb2RlLlBBWV9QRVJfUkVRVUVTVCA/IHVuZGVmaW5lZCA6IHtcbiAgICAgICAgcmVhZENhcGFjaXR5VW5pdHM6IHByb3BzLnJlYWRDYXBhY2l0eSB8fCA1LFxuICAgICAgICB3cml0ZUNhcGFjaXR5VW5pdHM6IHByb3BzLndyaXRlQ2FwYWNpdHkgfHwgNSxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICB0aGlzLnNlY29uZGFyeUluZGV4U2NoZW1hcy5zZXQocHJvcHMuaW5kZXhOYW1lLCB7XG4gICAgICBwYXJ0aXRpb25LZXk6IHByb3BzLnBhcnRpdGlvbktleSxcbiAgICAgIHNvcnRLZXk6IHByb3BzLnNvcnRLZXksXG4gICAgfSk7XG5cbiAgICB0aGlzLmluZGV4U2NhbGluZy5zZXQocHJvcHMuaW5kZXhOYW1lLCB7fSk7XG4gIH1cblxuICAvKipcbiAgICogQWRkIGEgbG9jYWwgc2Vjb25kYXJ5IGluZGV4IG9mIHRhYmxlLlxuICAgKlxuICAgKiBAcGFyYW0gcHJvcHMgdGhlIHByb3BlcnR5IG9mIGxvY2FsIHNlY29uZGFyeSBpbmRleFxuICAgKi9cbiAgcHVibGljIGFkZExvY2FsU2Vjb25kYXJ5SW5kZXgocHJvcHM6IExvY2FsU2Vjb25kYXJ5SW5kZXhQcm9wcykge1xuICAgIC8vIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9hbWF6b25keW5hbW9kYi9sYXRlc3QvZGV2ZWxvcGVyZ3VpZGUvTGltaXRzLmh0bWwjbGltaXRzLXNlY29uZGFyeS1pbmRleGVzXG4gICAgaWYgKHRoaXMubG9jYWxTZWNvbmRhcnlJbmRleGVzLmxlbmd0aCA+PSBNQVhfTE9DQUxfU0VDT05EQVJZX0lOREVYX0NPVU5UKSB7XG4gICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcihgYSBtYXhpbXVtIG51bWJlciBvZiBsb2NhbCBzZWNvbmRhcnkgaW5kZXggcGVyIHRhYmxlIGlzICR7TUFYX0xPQ0FMX1NFQ09OREFSWV9JTkRFWF9DT1VOVH1gKTtcbiAgICB9XG5cbiAgICB0aGlzLnZhbGlkYXRlSW5kZXhOYW1lKHByb3BzLmluZGV4TmFtZSk7XG5cbiAgICAvLyBidWlsZCBrZXkgc2NoZW1hIGFuZCBwcm9qZWN0aW9uIGZvciBpbmRleFxuICAgIGNvbnN0IGxzaUtleVNjaGVtYSA9IHRoaXMuYnVpbGRJbmRleEtleVNjaGVtYSh0aGlzLnRhYmxlUGFydGl0aW9uS2V5LCBwcm9wcy5zb3J0S2V5KTtcbiAgICBjb25zdCBsc2lQcm9qZWN0aW9uID0gdGhpcy5idWlsZEluZGV4UHJvamVjdGlvbihwcm9wcyk7XG5cbiAgICB0aGlzLmxvY2FsU2Vjb25kYXJ5SW5kZXhlcy5wdXNoKHtcbiAgICAgIGluZGV4TmFtZTogcHJvcHMuaW5kZXhOYW1lLFxuICAgICAga2V5U2NoZW1hOiBsc2lLZXlTY2hlbWEsXG4gICAgICBwcm9qZWN0aW9uOiBsc2lQcm9qZWN0aW9uLFxuICAgIH0pO1xuXG4gICAgdGhpcy5zZWNvbmRhcnlJbmRleFNjaGVtYXMuc2V0KHByb3BzLmluZGV4TmFtZSwge1xuICAgICAgcGFydGl0aW9uS2V5OiB0aGlzLnRhYmxlUGFydGl0aW9uS2V5LFxuICAgICAgc29ydEtleTogcHJvcHMuc29ydEtleSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFbmFibGUgcmVhZCBjYXBhY2l0eSBzY2FsaW5nIGZvciB0aGlzIHRhYmxlXG4gICAqXG4gICAqIEByZXR1cm5zIEFuIG9iamVjdCB0byBjb25maWd1cmUgYWRkaXRpb25hbCBBdXRvU2NhbGluZyBzZXR0aW5nc1xuICAgKi9cbiAgcHVibGljIGF1dG9TY2FsZVJlYWRDYXBhY2l0eShwcm9wczogRW5hYmxlU2NhbGluZ1Byb3BzKTogSVNjYWxhYmxlVGFibGVBdHRyaWJ1dGUge1xuICAgIGlmICh0aGlzLnRhYmxlU2NhbGluZy5zY2FsYWJsZVJlYWRBdHRyaWJ1dGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignUmVhZCBBdXRvU2NhbGluZyBhbHJlYWR5IGVuYWJsZWQgZm9yIHRoaXMgdGFibGUnKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuYmlsbGluZ01vZGUgPT09IEJpbGxpbmdNb2RlLlBBWV9QRVJfUkVRVUVTVCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdBdXRvU2NhbGluZyBpcyBub3QgYXZhaWxhYmxlIGZvciB0YWJsZXMgd2l0aCBQQVlfUEVSX1JFUVVFU1QgYmlsbGluZyBtb2RlJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMudGFibGVTY2FsaW5nLnNjYWxhYmxlUmVhZEF0dHJpYnV0ZSA9IG5ldyBTY2FsYWJsZVRhYmxlQXR0cmlidXRlKHRoaXMsICdSZWFkU2NhbGluZycsIHtcbiAgICAgIHNlcnZpY2VOYW1lc3BhY2U6IGFwcHNjYWxpbmcuU2VydmljZU5hbWVzcGFjZS5EWU5BTU9EQixcbiAgICAgIHJlc291cmNlSWQ6IGB0YWJsZS8ke3RoaXMudGFibGVOYW1lfWAsXG4gICAgICBkaW1lbnNpb246ICdkeW5hbW9kYjp0YWJsZTpSZWFkQ2FwYWNpdHlVbml0cycsXG4gICAgICByb2xlOiB0aGlzLnNjYWxpbmdSb2xlLFxuICAgICAgLi4ucHJvcHMsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogRW5hYmxlIHdyaXRlIGNhcGFjaXR5IHNjYWxpbmcgZm9yIHRoaXMgdGFibGVcbiAgICpcbiAgICogQHJldHVybnMgQW4gb2JqZWN0IHRvIGNvbmZpZ3VyZSBhZGRpdGlvbmFsIEF1dG9TY2FsaW5nIHNldHRpbmdzIGZvciB0aGlzIGF0dHJpYnV0ZVxuICAgKi9cbiAgcHVibGljIGF1dG9TY2FsZVdyaXRlQ2FwYWNpdHkocHJvcHM6IEVuYWJsZVNjYWxpbmdQcm9wcyk6IElTY2FsYWJsZVRhYmxlQXR0cmlidXRlIHtcbiAgICBpZiAodGhpcy50YWJsZVNjYWxpbmcuc2NhbGFibGVXcml0ZUF0dHJpYnV0ZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdXcml0ZSBBdXRvU2NhbGluZyBhbHJlYWR5IGVuYWJsZWQgZm9yIHRoaXMgdGFibGUnKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuYmlsbGluZ01vZGUgPT09IEJpbGxpbmdNb2RlLlBBWV9QRVJfUkVRVUVTVCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdBdXRvU2NhbGluZyBpcyBub3QgYXZhaWxhYmxlIGZvciB0YWJsZXMgd2l0aCBQQVlfUEVSX1JFUVVFU1QgYmlsbGluZyBtb2RlJyk7XG4gICAgfVxuXG4gICAgdGhpcy50YWJsZVNjYWxpbmcuc2NhbGFibGVXcml0ZUF0dHJpYnV0ZSA9IG5ldyBTY2FsYWJsZVRhYmxlQXR0cmlidXRlKHRoaXMsICdXcml0ZVNjYWxpbmcnLCB7XG4gICAgICBzZXJ2aWNlTmFtZXNwYWNlOiBhcHBzY2FsaW5nLlNlcnZpY2VOYW1lc3BhY2UuRFlOQU1PREIsXG4gICAgICByZXNvdXJjZUlkOiBgdGFibGUvJHt0aGlzLnRhYmxlTmFtZX1gLFxuICAgICAgZGltZW5zaW9uOiAnZHluYW1vZGI6dGFibGU6V3JpdGVDYXBhY2l0eVVuaXRzJyxcbiAgICAgIHJvbGU6IHRoaXMuc2NhbGluZ1JvbGUsXG4gICAgICAuLi5wcm9wcyxcbiAgICB9KTtcbiAgICBmb3IgKGNvbnN0IGdsb2JhbFJlcGxpY2FDdXN0b21SZXNvdXJjZSBvZiB0aGlzLmdsb2JhbFJlcGxpY2FDdXN0b21SZXNvdXJjZXMpIHtcbiAgICAgIGdsb2JhbFJlcGxpY2FDdXN0b21SZXNvdXJjZS5ub2RlLmFkZERlcGVuZGVuY3kodGhpcy50YWJsZVNjYWxpbmcuc2NhbGFibGVXcml0ZUF0dHJpYnV0ZSk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnRhYmxlU2NhbGluZy5zY2FsYWJsZVdyaXRlQXR0cmlidXRlO1xuICB9XG5cbiAgLyoqXG4gICAqIEVuYWJsZSByZWFkIGNhcGFjaXR5IHNjYWxpbmcgZm9yIHRoZSBnaXZlbiBHU0lcbiAgICpcbiAgICogQHJldHVybnMgQW4gb2JqZWN0IHRvIGNvbmZpZ3VyZSBhZGRpdGlvbmFsIEF1dG9TY2FsaW5nIHNldHRpbmdzIGZvciB0aGlzIGF0dHJpYnV0ZVxuICAgKi9cbiAgcHVibGljIGF1dG9TY2FsZUdsb2JhbFNlY29uZGFyeUluZGV4UmVhZENhcGFjaXR5KGluZGV4TmFtZTogc3RyaW5nLCBwcm9wczogRW5hYmxlU2NhbGluZ1Byb3BzKTogSVNjYWxhYmxlVGFibGVBdHRyaWJ1dGUge1xuICAgIGlmICh0aGlzLmJpbGxpbmdNb2RlID09PSBCaWxsaW5nTW9kZS5QQVlfUEVSX1JFUVVFU1QpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQXV0b1NjYWxpbmcgaXMgbm90IGF2YWlsYWJsZSBmb3IgdGFibGVzIHdpdGggUEFZX1BFUl9SRVFVRVNUIGJpbGxpbmcgbW9kZScpO1xuICAgIH1cbiAgICBjb25zdCBhdHRyaWJ1dGVQYWlyID0gdGhpcy5pbmRleFNjYWxpbmcuZ2V0KGluZGV4TmFtZSk7XG4gICAgaWYgKCFhdHRyaWJ1dGVQYWlyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIGdsb2JhbCBzZWNvbmRhcnkgaW5kZXggd2l0aCBuYW1lICR7aW5kZXhOYW1lfWApO1xuICAgIH1cbiAgICBpZiAoYXR0cmlidXRlUGFpci5zY2FsYWJsZVJlYWRBdHRyaWJ1dGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignUmVhZCBBdXRvU2NhbGluZyBhbHJlYWR5IGVuYWJsZWQgZm9yIHRoaXMgaW5kZXgnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gYXR0cmlidXRlUGFpci5zY2FsYWJsZVJlYWRBdHRyaWJ1dGUgPSBuZXcgU2NhbGFibGVUYWJsZUF0dHJpYnV0ZSh0aGlzLCBgJHtpbmRleE5hbWV9UmVhZFNjYWxpbmdgLCB7XG4gICAgICBzZXJ2aWNlTmFtZXNwYWNlOiBhcHBzY2FsaW5nLlNlcnZpY2VOYW1lc3BhY2UuRFlOQU1PREIsXG4gICAgICByZXNvdXJjZUlkOiBgdGFibGUvJHt0aGlzLnRhYmxlTmFtZX0vaW5kZXgvJHtpbmRleE5hbWV9YCxcbiAgICAgIGRpbWVuc2lvbjogJ2R5bmFtb2RiOmluZGV4OlJlYWRDYXBhY2l0eVVuaXRzJyxcbiAgICAgIHJvbGU6IHRoaXMuc2NhbGluZ1JvbGUsXG4gICAgICAuLi5wcm9wcyxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFbmFibGUgd3JpdGUgY2FwYWNpdHkgc2NhbGluZyBmb3IgdGhlIGdpdmVuIEdTSVxuICAgKlxuICAgKiBAcmV0dXJucyBBbiBvYmplY3QgdG8gY29uZmlndXJlIGFkZGl0aW9uYWwgQXV0b1NjYWxpbmcgc2V0dGluZ3MgZm9yIHRoaXMgYXR0cmlidXRlXG4gICAqL1xuICBwdWJsaWMgYXV0b1NjYWxlR2xvYmFsU2Vjb25kYXJ5SW5kZXhXcml0ZUNhcGFjaXR5KGluZGV4TmFtZTogc3RyaW5nLCBwcm9wczogRW5hYmxlU2NhbGluZ1Byb3BzKTogSVNjYWxhYmxlVGFibGVBdHRyaWJ1dGUge1xuICAgIGlmICh0aGlzLmJpbGxpbmdNb2RlID09PSBCaWxsaW5nTW9kZS5QQVlfUEVSX1JFUVVFU1QpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQXV0b1NjYWxpbmcgaXMgbm90IGF2YWlsYWJsZSBmb3IgdGFibGVzIHdpdGggUEFZX1BFUl9SRVFVRVNUIGJpbGxpbmcgbW9kZScpO1xuICAgIH1cbiAgICBjb25zdCBhdHRyaWJ1dGVQYWlyID0gdGhpcy5pbmRleFNjYWxpbmcuZ2V0KGluZGV4TmFtZSk7XG4gICAgaWYgKCFhdHRyaWJ1dGVQYWlyKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYE5vIGdsb2JhbCBzZWNvbmRhcnkgaW5kZXggd2l0aCBuYW1lICR7aW5kZXhOYW1lfWApO1xuICAgIH1cbiAgICBpZiAoYXR0cmlidXRlUGFpci5zY2FsYWJsZVdyaXRlQXR0cmlidXRlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1dyaXRlIEF1dG9TY2FsaW5nIGFscmVhZHkgZW5hYmxlZCBmb3IgdGhpcyBpbmRleCcpO1xuICAgIH1cblxuICAgIHJldHVybiBhdHRyaWJ1dGVQYWlyLnNjYWxhYmxlV3JpdGVBdHRyaWJ1dGUgPSBuZXcgU2NhbGFibGVUYWJsZUF0dHJpYnV0ZSh0aGlzLCBgJHtpbmRleE5hbWV9V3JpdGVTY2FsaW5nYCwge1xuICAgICAgc2VydmljZU5hbWVzcGFjZTogYXBwc2NhbGluZy5TZXJ2aWNlTmFtZXNwYWNlLkRZTkFNT0RCLFxuICAgICAgcmVzb3VyY2VJZDogYHRhYmxlLyR7dGhpcy50YWJsZU5hbWV9L2luZGV4LyR7aW5kZXhOYW1lfWAsXG4gICAgICBkaW1lbnNpb246ICdkeW5hbW9kYjppbmRleDpXcml0ZUNhcGFjaXR5VW5pdHMnLFxuICAgICAgcm9sZTogdGhpcy5zY2FsaW5nUm9sZSxcbiAgICAgIC4uLnByb3BzLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBzY2hlbWEgYXR0cmlidXRlcyBvZiB0YWJsZSBvciBpbmRleC5cbiAgICpcbiAgICogQHJldHVybnMgU2NoZW1hIG9mIHRhYmxlIG9yIGluZGV4LlxuICAgKi9cbiAgcHVibGljIHNjaGVtYShpbmRleE5hbWU/OiBzdHJpbmcpOiBTY2hlbWFPcHRpb25zIHtcbiAgICBpZiAoIWluZGV4TmFtZSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgcGFydGl0aW9uS2V5OiB0aGlzLnRhYmxlUGFydGl0aW9uS2V5LFxuICAgICAgICBzb3J0S2V5OiB0aGlzLnRhYmxlU29ydEtleSxcbiAgICAgIH07XG4gICAgfVxuICAgIGxldCBzY2hlbWEgPSB0aGlzLnNlY29uZGFyeUluZGV4U2NoZW1hcy5nZXQoaW5kZXhOYW1lKTtcbiAgICBpZiAoIXNjaGVtYSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgZmluZCBzY2hlbWEgZm9yIGluZGV4OiAke2luZGV4TmFtZX0uIFVzZSAnYWRkR2xvYmFsU2Vjb25kYXJ5SW5kZXgnIG9yICdhZGRMb2NhbFNlY29uZGFyeUluZGV4JyB0byBhZGQgaW5kZXhgKTtcbiAgICB9XG4gICAgcmV0dXJuIHNjaGVtYTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZSB0aGUgdGFibGUgY29uc3RydWN0LlxuICAgKlxuICAgKiBAcmV0dXJucyBhbiBhcnJheSBvZiB2YWxpZGF0aW9uIGVycm9yIG1lc3NhZ2VcbiAgICovXG4gIHByb3RlY3RlZCB2YWxpZGF0ZSgpOiBzdHJpbmdbXSB7XG4gICAgY29uc3QgZXJyb3JzID0gbmV3IEFycmF5PHN0cmluZz4oKTtcblxuICAgIGlmICghdGhpcy50YWJsZVBhcnRpdGlvbktleSkge1xuICAgICAgZXJyb3JzLnB1c2goJ2EgcGFydGl0aW9uIGtleSBtdXN0IGJlIHNwZWNpZmllZCcpO1xuICAgIH1cbiAgICBpZiAodGhpcy5sb2NhbFNlY29uZGFyeUluZGV4ZXMubGVuZ3RoID4gMCAmJiAhdGhpcy50YWJsZVNvcnRLZXkpIHtcbiAgICAgIGVycm9ycy5wdXNoKCdhIHNvcnQga2V5IG9mIHRoZSB0YWJsZSBtdXN0IGJlIHNwZWNpZmllZCB0byBhZGQgbG9jYWwgc2Vjb25kYXJ5IGluZGV4ZXMnKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5nbG9iYWxSZXBsaWNhQ3VzdG9tUmVzb3VyY2VzLmxlbmd0aCA+IDAgJiYgdGhpcy5iaWxsaW5nTW9kZSA9PT0gQmlsbGluZ01vZGUuUFJPVklTSU9ORUQpIHtcbiAgICAgIGNvbnN0IHdyaXRlQXV0b1NjYWxlQXR0cmlidXRlID0gdGhpcy50YWJsZVNjYWxpbmcuc2NhbGFibGVXcml0ZUF0dHJpYnV0ZTtcbiAgICAgIGlmICghd3JpdGVBdXRvU2NhbGVBdHRyaWJ1dGUpIHtcbiAgICAgICAgZXJyb3JzLnB1c2goJ0EgZ2xvYmFsIFRhYmxlIHRoYXQgdXNlcyBQUk9WSVNJT05FRCBhcyB0aGUgYmlsbGluZyBtb2RlIG5lZWRzIGF1dG8tc2NhbGVkIHdyaXRlIGNhcGFjaXR5LiAnICtcbiAgICAgICAgICAnVXNlIHRoZSBhdXRvU2NhbGVXcml0ZUNhcGFjaXR5KCkgbWV0aG9kIHRvIGVuYWJsZSBpdC4nKTtcbiAgICAgIH0gZWxzZSBpZiAoIXdyaXRlQXV0b1NjYWxlQXR0cmlidXRlLl9zY2FsaW5nUG9saWN5Q3JlYXRlZCkge1xuICAgICAgICBlcnJvcnMucHVzaCgnQSBnbG9iYWwgVGFibGUgdGhhdCB1c2VzIFBST1ZJU0lPTkVEIGFzIHRoZSBiaWxsaW5nIG1vZGUgbmVlZHMgYXV0by1zY2FsZWQgd3JpdGUgY2FwYWNpdHkgd2l0aCBhIHBvbGljeS4gJyArXG4gICAgICAgICAgJ0NhbGwgb25lIG9mIHRoZSBzY2FsZU9uKigpIG1ldGhvZHMgb2YgdGhlIG9iamVjdCByZXR1cm5lZCBmcm9tIGF1dG9TY2FsZVdyaXRlQ2FwYWNpdHkoKScpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBlcnJvcnM7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgcmVhZCBhbmQgd3JpdGUgY2FwYWNpdHkgYXJlIG5vdCBzcGVjaWZpZWQgZm9yIG9uLWRlbWFuZCB0YWJsZXMgKGJpbGxpbmcgbW9kZSBQQVlfUEVSX1JFUVVFU1QpLlxuICAgKlxuICAgKiBAcGFyYW0gcHJvcHMgcmVhZCBhbmQgd3JpdGUgY2FwYWNpdHkgcHJvcGVydGllc1xuICAgKi9cbiAgcHJpdmF0ZSB2YWxpZGF0ZVByb3Zpc2lvbmluZyhwcm9wczogeyByZWFkQ2FwYWNpdHk/OiBudW1iZXIsIHdyaXRlQ2FwYWNpdHk/OiBudW1iZXIgfSk6IHZvaWQge1xuICAgIGlmICh0aGlzLmJpbGxpbmdNb2RlID09PSBCaWxsaW5nTW9kZS5QQVlfUEVSX1JFUVVFU1QpIHtcbiAgICAgIGlmIChwcm9wcy5yZWFkQ2FwYWNpdHkgIT09IHVuZGVmaW5lZCB8fCBwcm9wcy53cml0ZUNhcGFjaXR5ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd5b3UgY2Fubm90IHByb3Zpc2lvbiByZWFkIGFuZCB3cml0ZSBjYXBhY2l0eSBmb3IgYSB0YWJsZSB3aXRoIFBBWV9QRVJfUkVRVUVTVCBiaWxsaW5nIG1vZGUnKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgaW5kZXggbmFtZSB0byBjaGVjayBpZiBhIGR1cGxpY2F0ZSBuYW1lIGFscmVhZHkgZXhpc3RzLlxuICAgKlxuICAgKiBAcGFyYW0gaW5kZXhOYW1lIGEgbmFtZSBvZiBnbG9iYWwgb3IgbG9jYWwgc2Vjb25kYXJ5IGluZGV4XG4gICAqL1xuICBwcml2YXRlIHZhbGlkYXRlSW5kZXhOYW1lKGluZGV4TmFtZTogc3RyaW5nKSB7XG4gICAgaWYgKHRoaXMuc2Vjb25kYXJ5SW5kZXhTY2hlbWFzLmhhcyhpbmRleE5hbWUpKSB7XG4gICAgICAvLyBhIGR1cGxpY2F0ZSBpbmRleCBuYW1lIGNhdXNlcyB2YWxpZGF0aW9uIGV4Y2VwdGlvbiwgc3RhdHVzIGNvZGUgNDAwLCB3aGlsZSB0cnlpbmcgdG8gY3JlYXRlIENGTiBzdGFja1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBhIGR1cGxpY2F0ZSBpbmRleCBuYW1lLCAke2luZGV4TmFtZX0sIGlzIG5vdCBhbGxvd2VkYCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlIG5vbi1rZXkgYXR0cmlidXRlcyBieSBjaGVja2luZyBsaW1pdHMgd2l0aGluIHNlY29uZGFyeSBpbmRleCwgd2hpY2ggbWF5IHZhcnkgaW4gZnV0dXJlLlxuICAgKlxuICAgKiBAcGFyYW0gbm9uS2V5QXR0cmlidXRlcyBhIGxpc3Qgb2Ygbm9uLWtleSBhdHRyaWJ1dGUgbmFtZXNcbiAgICovXG4gIHByaXZhdGUgdmFsaWRhdGVOb25LZXlBdHRyaWJ1dGVzKG5vbktleUF0dHJpYnV0ZXM6IHN0cmluZ1tdKSB7XG4gICAgaWYgKHRoaXMubm9uS2V5QXR0cmlidXRlcy5zaXplICsgbm9uS2V5QXR0cmlidXRlcy5sZW5ndGggPiAxMDApIHtcbiAgICAgIC8vIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9hbWF6b25keW5hbW9kYi9sYXRlc3QvZGV2ZWxvcGVyZ3VpZGUvTGltaXRzLmh0bWwjbGltaXRzLXNlY29uZGFyeS1pbmRleGVzXG4gICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignYSBtYXhpbXVtIG51bWJlciBvZiBub25LZXlBdHRyaWJ1dGVzIGFjcm9zcyBhbGwgb2Ygc2Vjb25kYXJ5IGluZGV4ZXMgaXMgMTAwJyk7XG4gICAgfVxuXG4gICAgLy8gc3RvcmUgYWxsIG5vbi1rZXkgYXR0cmlidXRlc1xuICAgIG5vbktleUF0dHJpYnV0ZXMuZm9yRWFjaChhdHQgPT4gdGhpcy5ub25LZXlBdHRyaWJ1dGVzLmFkZChhdHQpKTtcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRJbmRleEtleVNjaGVtYShwYXJ0aXRpb25LZXk6IEF0dHJpYnV0ZSwgc29ydEtleT86IEF0dHJpYnV0ZSk6IENmblRhYmxlLktleVNjaGVtYVByb3BlcnR5W10ge1xuICAgIHRoaXMucmVnaXN0ZXJBdHRyaWJ1dGUocGFydGl0aW9uS2V5KTtcbiAgICBjb25zdCBpbmRleEtleVNjaGVtYTogQ2ZuVGFibGUuS2V5U2NoZW1hUHJvcGVydHlbXSA9IFtcbiAgICAgIHsgYXR0cmlidXRlTmFtZTogcGFydGl0aW9uS2V5Lm5hbWUsIGtleVR5cGU6IEhBU0hfS0VZX1RZUEUgfSxcbiAgICBdO1xuXG4gICAgaWYgKHNvcnRLZXkpIHtcbiAgICAgIHRoaXMucmVnaXN0ZXJBdHRyaWJ1dGUoc29ydEtleSk7XG4gICAgICBpbmRleEtleVNjaGVtYS5wdXNoKHsgYXR0cmlidXRlTmFtZTogc29ydEtleS5uYW1lLCBrZXlUeXBlOiBSQU5HRV9LRVlfVFlQRSB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gaW5kZXhLZXlTY2hlbWE7XG4gIH1cblxuICBwcml2YXRlIGJ1aWxkSW5kZXhQcm9qZWN0aW9uKHByb3BzOiBTZWNvbmRhcnlJbmRleFByb3BzKTogQ2ZuVGFibGUuUHJvamVjdGlvblByb3BlcnR5IHtcbiAgICBpZiAocHJvcHMucHJvamVjdGlvblR5cGUgPT09IFByb2plY3Rpb25UeXBlLklOQ0xVREUgJiYgIXByb3BzLm5vbktleUF0dHJpYnV0ZXMpIHtcbiAgICAgIC8vIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NDbG91ZEZvcm1hdGlvbi9sYXRlc3QvVXNlckd1aWRlL2F3cy1wcm9wZXJ0aWVzLWR5bmFtb2RiLXByb2plY3Rpb25vYmplY3QuaHRtbFxuICAgICAgdGhyb3cgbmV3IEVycm9yKGBub24ta2V5IGF0dHJpYnV0ZXMgc2hvdWxkIGJlIHNwZWNpZmllZCB3aGVuIHVzaW5nICR7UHJvamVjdGlvblR5cGUuSU5DTFVERX0gcHJvamVjdGlvbiB0eXBlYCk7XG4gICAgfVxuXG4gICAgaWYgKHByb3BzLnByb2plY3Rpb25UeXBlICE9PSBQcm9qZWN0aW9uVHlwZS5JTkNMVURFICYmIHByb3BzLm5vbktleUF0dHJpYnV0ZXMpIHtcbiAgICAgIC8vIHRoaXMgY29tYmluYXRpb24gY2F1c2VzIHZhbGlkYXRpb24gZXhjZXB0aW9uLCBzdGF0dXMgY29kZSA0MDAsIHdoaWxlIHRyeWluZyB0byBjcmVhdGUgQ0ZOIHN0YWNrXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYG5vbi1rZXkgYXR0cmlidXRlcyBzaG91bGQgbm90IGJlIHNwZWNpZmllZCB3aGVuIG5vdCB1c2luZyAke1Byb2plY3Rpb25UeXBlLklOQ0xVREV9IHByb2plY3Rpb24gdHlwZWApO1xuICAgIH1cblxuICAgIGlmIChwcm9wcy5ub25LZXlBdHRyaWJ1dGVzKSB7XG4gICAgICB0aGlzLnZhbGlkYXRlTm9uS2V5QXR0cmlidXRlcyhwcm9wcy5ub25LZXlBdHRyaWJ1dGVzKTtcbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgcHJvamVjdGlvblR5cGU6IHByb3BzLnByb2plY3Rpb25UeXBlID8/IFByb2plY3Rpb25UeXBlLkFMTCxcbiAgICAgIG5vbktleUF0dHJpYnV0ZXM6IHByb3BzLm5vbktleUF0dHJpYnV0ZXMgPz8gdW5kZWZpbmVkLFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIGZpbmRLZXkoa2V5VHlwZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMua2V5U2NoZW1hLmZpbmQocHJvcCA9PiBwcm9wLmtleVR5cGUgPT09IGtleVR5cGUpO1xuICB9XG5cbiAgcHJpdmF0ZSBhZGRLZXkoYXR0cmlidXRlOiBBdHRyaWJ1dGUsIGtleVR5cGU6IHN0cmluZykge1xuICAgIGNvbnN0IGV4aXN0aW5nUHJvcCA9IHRoaXMuZmluZEtleShrZXlUeXBlKTtcbiAgICBpZiAoZXhpc3RpbmdQcm9wKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuYWJsZSB0byBzZXQgJHthdHRyaWJ1dGUubmFtZX0gYXMgYSAke2tleVR5cGV9IGtleSwgYmVjYXVzZSAke2V4aXN0aW5nUHJvcC5hdHRyaWJ1dGVOYW1lfSBpcyBhICR7a2V5VHlwZX0ga2V5YCk7XG4gICAgfVxuICAgIHRoaXMucmVnaXN0ZXJBdHRyaWJ1dGUoYXR0cmlidXRlKTtcbiAgICB0aGlzLmtleVNjaGVtYS5wdXNoKHtcbiAgICAgIGF0dHJpYnV0ZU5hbWU6IGF0dHJpYnV0ZS5uYW1lLFxuICAgICAga2V5VHlwZSxcbiAgICB9KTtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlciB0aGUga2V5IGF0dHJpYnV0ZSBvZiB0YWJsZSBvciBzZWNvbmRhcnkgaW5kZXggdG8gYXNzZW1ibGUgYXR0cmlidXRlIGRlZmluaXRpb25zIG9mIFRhYmxlUmVzb3VyY2VQcm9wcy5cbiAgICpcbiAgICogQHBhcmFtIGF0dHJpYnV0ZSB0aGUga2V5IGF0dHJpYnV0ZSBvZiB0YWJsZSBvciBzZWNvbmRhcnkgaW5kZXhcbiAgICovXG4gIHByaXZhdGUgcmVnaXN0ZXJBdHRyaWJ1dGUoYXR0cmlidXRlOiBBdHRyaWJ1dGUpIHtcbiAgICBjb25zdCB7IG5hbWUsIHR5cGUgfSA9IGF0dHJpYnV0ZTtcbiAgICBjb25zdCBleGlzdGluZ0RlZiA9IHRoaXMuYXR0cmlidXRlRGVmaW5pdGlvbnMuZmluZChkZWYgPT4gZGVmLmF0dHJpYnV0ZU5hbWUgPT09IG5hbWUpO1xuICAgIGlmIChleGlzdGluZ0RlZiAmJiBleGlzdGluZ0RlZi5hdHRyaWJ1dGVUeXBlICE9PSB0eXBlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuYWJsZSB0byBzcGVjaWZ5ICR7bmFtZX0gYXMgJHt0eXBlfSBiZWNhdXNlIGl0IHdhcyBhbHJlYWR5IGRlZmluZWQgYXMgJHtleGlzdGluZ0RlZi5hdHRyaWJ1dGVUeXBlfWApO1xuICAgIH1cbiAgICBpZiAoIWV4aXN0aW5nRGVmKSB7XG4gICAgICB0aGlzLmF0dHJpYnV0ZURlZmluaXRpb25zLnB1c2goe1xuICAgICAgICBhdHRyaWJ1dGVOYW1lOiBuYW1lLFxuICAgICAgICBhdHRyaWJ1dGVUeXBlOiB0eXBlLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiB0aGUgcm9sZSB0aGF0IHdpbGwgYmUgdXNlZCBmb3IgQXV0b1NjYWxpbmdcbiAgICovXG4gIHByaXZhdGUgbWFrZVNjYWxpbmdSb2xlKCk6IGlhbS5JUm9sZSB7XG4gICAgLy8gVXNlIGEgU2VydmljZSBMaW5rZWQgUm9sZS5cbiAgICAvLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vYXV0b3NjYWxpbmcvYXBwbGljYXRpb24vdXNlcmd1aWRlL2FwcGxpY2F0aW9uLWF1dG8tc2NhbGluZy1zZXJ2aWNlLWxpbmtlZC1yb2xlcy5odG1sXG4gICAgcmV0dXJuIGlhbS5Sb2xlLmZyb21Sb2xlQXJuKHRoaXMsICdTY2FsaW5nUm9sZScsIFN0YWNrLm9mKHRoaXMpLmZvcm1hdEFybih7XG4gICAgICBzZXJ2aWNlOiAnaWFtJyxcbiAgICAgIHJlZ2lvbjogJycsXG4gICAgICByZXNvdXJjZTogJ3JvbGUvYXdzLXNlcnZpY2Utcm9sZS9keW5hbW9kYi5hcHBsaWNhdGlvbi1hdXRvc2NhbGluZy5hbWF6b25hd3MuY29tJyxcbiAgICAgIHJlc291cmNlTmFtZTogJ0FXU1NlcnZpY2VSb2xlRm9yQXBwbGljYXRpb25BdXRvU2NhbGluZ19EeW5hbW9EQlRhYmxlJyxcbiAgICB9KSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyByZXBsaWNhIHRhYmxlc1xuICAgKlxuICAgKiBAcGFyYW0gcmVnaW9ucyByZWdpb25zIHdoZXJlIHRvIGNyZWF0ZSB0YWJsZXNcbiAgICovXG4gIHByaXZhdGUgY3JlYXRlUmVwbGljYVRhYmxlcyhyZWdpb25zOiBzdHJpbmdbXSwgdGltZW91dD86IER1cmF0aW9uLCB3YWl0Rm9yUmVwbGljYXRpb25Ub0ZpbmlzaD86IGJvb2xlYW4pIHtcbiAgICBjb25zdCBzdGFjayA9IFN0YWNrLm9mKHRoaXMpO1xuXG4gICAgaWYgKCFUb2tlbi5pc1VucmVzb2x2ZWQoc3RhY2sucmVnaW9uKSAmJiByZWdpb25zLmluY2x1ZGVzKHN0YWNrLnJlZ2lvbikpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignYHJlcGxpY2F0aW9uUmVnaW9uc2AgY2Fubm90IGluY2x1ZGUgdGhlIHJlZ2lvbiB3aGVyZSB0aGlzIHN0YWNrIGlzIGRlcGxveWVkLicpO1xuICAgIH1cblxuICAgIGNvbnN0IHByb3ZpZGVyID0gUmVwbGljYVByb3ZpZGVyLmdldE9yQ3JlYXRlKHRoaXMsIHsgdGltZW91dCB9KTtcblxuICAgIC8vIERvY3VtZW50YXRpb24gYXQgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2FtYXpvbmR5bmFtb2RiL2xhdGVzdC9kZXZlbG9wZXJndWlkZS9WMmd0X0lBTS5odG1sXG4gICAgLy8gaXMgY3VycmVudGx5IGluY29ycmVjdC4gQVdTIFN1cHBvcnQgcmVjb21tZW5kcyBgZHluYW1vZGI6KmAgaW4gYm90aCBzb3VyY2UgYW5kIGRlc3RpbmF0aW9uIHJlZ2lvbnNcblxuICAgIGNvbnN0IG9uRXZlbnRIYW5kbGVyUG9saWN5ID0gbmV3IFNvdXJjZVRhYmxlQXR0YWNoZWRQb2xpY3kodGhpcywgcHJvdmlkZXIub25FdmVudEhhbmRsZXIucm9sZSEpO1xuICAgIGNvbnN0IGlzQ29tcGxldGVIYW5kbGVyUG9saWN5ID0gbmV3IFNvdXJjZVRhYmxlQXR0YWNoZWRQb2xpY3kodGhpcywgcHJvdmlkZXIuaXNDb21wbGV0ZUhhbmRsZXIucm9sZSEpO1xuXG4gICAgLy8gUGVybWlzc2lvbnMgaW4gdGhlIHNvdXJjZSByZWdpb25cbiAgICB0aGlzLmdyYW50KG9uRXZlbnRIYW5kbGVyUG9saWN5LCAnZHluYW1vZGI6KicpO1xuICAgIHRoaXMuZ3JhbnQoaXNDb21wbGV0ZUhhbmRsZXJQb2xpY3ksICdkeW5hbW9kYjpEZXNjcmliZVRhYmxlJyk7XG5cbiAgICBsZXQgcHJldmlvdXNSZWdpb246IEN1c3RvbVJlc291cmNlIHwgdW5kZWZpbmVkO1xuICAgIGxldCBwcmV2aW91c1JlZ2lvbkNvbmRpdGlvbjogQ2ZuQ29uZGl0aW9uIHwgdW5kZWZpbmVkO1xuICAgIGZvciAoY29uc3QgcmVnaW9uIG9mIG5ldyBTZXQocmVnaW9ucykpIHsgLy8gUmVtb3ZlIGR1cGxpY2F0ZXNcbiAgICAgIC8vIFVzZSBtdWx0aXBsZSBjdXN0b20gcmVzb3VyY2VzIGJlY2F1c2UgbXVsdGlwbGUgY3JlYXRlL2RlbGV0ZVxuICAgICAgLy8gdXBkYXRlcyBjYW5ub3QgYmUgY29tYmluZWQgaW4gYSBzaW5nbGUgQVBJIGNhbGwuXG4gICAgICBjb25zdCBjdXJyZW50UmVnaW9uID0gbmV3IEN1c3RvbVJlc291cmNlKHRoaXMsIGBSZXBsaWNhJHtyZWdpb259YCwge1xuICAgICAgICBzZXJ2aWNlVG9rZW46IHByb3ZpZGVyLnByb3ZpZGVyLnNlcnZpY2VUb2tlbixcbiAgICAgICAgcmVzb3VyY2VUeXBlOiAnQ3VzdG9tOjpEeW5hbW9EQlJlcGxpY2EnLFxuICAgICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgVGFibGVOYW1lOiB0aGlzLnRhYmxlTmFtZSxcbiAgICAgICAgICBSZWdpb246IHJlZ2lvbixcbiAgICAgICAgICBTa2lwUmVwbGljYXRpb25Db21wbGV0ZWRXYWl0OiB3YWl0Rm9yUmVwbGljYXRpb25Ub0ZpbmlzaCA9PSBudWxsXG4gICAgICAgICAgICA/IHVuZGVmaW5lZFxuICAgICAgICAgICAgLy8gQ0ZOIGNoYW5nZXMgQ3VzdG9tIFJlc291cmNlIHByb3BlcnRpZXMgdG8gc3RyaW5ncyBhbnl3YXlzLFxuICAgICAgICAgICAgLy8gc28gbGV0J3MgZG8gdGhhdCBvdXJzZWx2ZXMgdG8gbWFrZSBpdCBjbGVhciBpbiB0aGUgaGFuZGxlciB0aGlzIGlzIGEgc3RyaW5nLCBub3QgYSBib29sZWFuXG4gICAgICAgICAgICA6ICghd2FpdEZvclJlcGxpY2F0aW9uVG9GaW5pc2gpLnRvU3RyaW5nKCksXG4gICAgICAgIH0sXG4gICAgICB9KTtcbiAgICAgIGN1cnJlbnRSZWdpb24ubm9kZS5hZGREZXBlbmRlbmN5KFxuICAgICAgICBvbkV2ZW50SGFuZGxlclBvbGljeS5wb2xpY3ksXG4gICAgICAgIGlzQ29tcGxldGVIYW5kbGVyUG9saWN5LnBvbGljeSxcbiAgICAgICk7XG4gICAgICB0aGlzLmdsb2JhbFJlcGxpY2FDdXN0b21SZXNvdXJjZXMucHVzaChjdXJyZW50UmVnaW9uKTtcblxuICAgICAgLy8gRGVwbG95IHRpbWUgY2hlY2sgdG8gcHJldmVudCBmcm9tIGNyZWF0aW5nIGEgcmVwbGljYSBpbiB0aGUgcmVnaW9uXG4gICAgICAvLyB3aGVyZSB0aGlzIHN0YWNrIGlzIGRlcGxveWVkLiBPbmx5IG5lZWRlZCBmb3IgZW52aXJvbm1lbnQgYWdub3N0aWNcbiAgICAgIC8vIHN0YWNrcy5cbiAgICAgIGxldCBjcmVhdGVSZXBsaWNhOiBDZm5Db25kaXRpb24gfCB1bmRlZmluZWQ7XG4gICAgICBpZiAoVG9rZW4uaXNVbnJlc29sdmVkKHN0YWNrLnJlZ2lvbikpIHtcbiAgICAgICAgY3JlYXRlUmVwbGljYSA9IG5ldyBDZm5Db25kaXRpb24odGhpcywgYFN0YWNrUmVnaW9uTm90RXF1YWxzJHtyZWdpb259YCwge1xuICAgICAgICAgIGV4cHJlc3Npb246IEZuLmNvbmRpdGlvbk5vdChGbi5jb25kaXRpb25FcXVhbHMocmVnaW9uLCBBd3MuUkVHSU9OKSksXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCBjZm5DdXN0b21SZXNvdXJjZSA9IGN1cnJlbnRSZWdpb24ubm9kZS5kZWZhdWx0Q2hpbGQgYXMgQ2ZuQ3VzdG9tUmVzb3VyY2U7XG4gICAgICAgIGNmbkN1c3RvbVJlc291cmNlLmNmbk9wdGlvbnMuY29uZGl0aW9uID0gY3JlYXRlUmVwbGljYTtcbiAgICAgIH1cblxuICAgICAgLy8gU2F2ZSByZWdpb25hbCBhcm5zIGZvciBncmFudFh4eCgpIG1ldGhvZHNcbiAgICAgIHRoaXMucmVnaW9uYWxBcm5zLnB1c2goc3RhY2suZm9ybWF0QXJuKHtcbiAgICAgICAgcmVnaW9uLFxuICAgICAgICBzZXJ2aWNlOiAnZHluYW1vZGInLFxuICAgICAgICByZXNvdXJjZTogJ3RhYmxlJyxcbiAgICAgICAgcmVzb3VyY2VOYW1lOiB0aGlzLnRhYmxlTmFtZSxcbiAgICAgIH0pKTtcblxuICAgICAgLy8gV2UgbmVlZCB0byBjcmVhdGUvZGVsZXRlIHJlZ2lvbnMgc2VxdWVudGlhbGx5IGJlY2F1c2Ugd2UgY2Fubm90XG4gICAgICAvLyBoYXZlIG11bHRpcGxlIHRhYmxlIHVwZGF0ZXMgYXQgdGhlIHNhbWUgdGltZS4gVGhlIGBpc0NvbXBsZXRlSGFuZGxlcmBcbiAgICAgIC8vIG9mIHRoZSBwcm92aWRlciB3YWl0cyB1bnRpbCB0aGUgcmVwbGljYSBpcyBpbiBhbiBBQ1RJVkUgc3RhdGUuXG4gICAgICBpZiAocHJldmlvdXNSZWdpb24pIHtcbiAgICAgICAgaWYgKHByZXZpb3VzUmVnaW9uQ29uZGl0aW9uKSB7XG4gICAgICAgICAgLy8gd2UgY2FuJ3Qgc2ltcGx5IHVzZSBhIERlcGVuZGVuY3ksXG4gICAgICAgICAgLy8gYmVjYXVzZSB0aGUgcHJldmlvdXNSZWdpb24gaXMgcHJvdGVjdGVkIGJ5IHRoZSBcImRpZmZlcmVudCByZWdpb25cIiBDb25kaXRpb24sXG4gICAgICAgICAgLy8gYW5kIHlvdSBjYW4ndCBoYXZlIEZuOjpJZiBpbiBEZXBlbmRzT24uXG4gICAgICAgICAgLy8gSW5zdGVhZCwgcmVseSBvbiBSZWYgYWRkaW5nIGEgZGVwZW5kZW5jeSBpbXBsaWNpdGx5IVxuICAgICAgICAgIGNvbnN0IHByZXZpb3VzUmVnaW9uQ2ZuUmVzb3VyY2UgPSBwcmV2aW91c1JlZ2lvbi5ub2RlLmRlZmF1bHRDaGlsZCBhcyBDZm5SZXNvdXJjZTtcbiAgICAgICAgICBjb25zdCBjdXJyZW50UmVnaW9uQ2ZuUmVzb3VyY2UgPSBjdXJyZW50UmVnaW9uLm5vZGUuZGVmYXVsdENoaWxkIGFzIENmblJlc291cmNlO1xuICAgICAgICAgIGN1cnJlbnRSZWdpb25DZm5SZXNvdXJjZS5hZGRNZXRhZGF0YSgnRHluYW1vRGJSZXBsaWNhdGlvbkRlcGVuZGVuY3knLFxuICAgICAgICAgICAgRm4uY29uZGl0aW9uSWYocHJldmlvdXNSZWdpb25Db25kaXRpb24ubG9naWNhbElkLCBwcmV2aW91c1JlZ2lvbkNmblJlc291cmNlLnJlZiwgQXdzLk5PX1ZBTFVFKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY3VycmVudFJlZ2lvbi5ub2RlLmFkZERlcGVuZGVuY3kocHJldmlvdXNSZWdpb24pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHByZXZpb3VzUmVnaW9uID0gY3VycmVudFJlZ2lvbjtcbiAgICAgIHByZXZpb3VzUmVnaW9uQ29uZGl0aW9uID0gY3JlYXRlUmVwbGljYTtcbiAgICB9XG5cbiAgICAvLyBQZXJtaXNzaW9ucyBpbiB0aGUgZGVzdGluYXRpb24gcmVnaW9ucyAob3V0c2lkZSBvZiB0aGUgbG9vcCB0b1xuICAgIC8vIG1pbmltaXplIHN0YXRlbWVudHMgaW4gdGhlIHBvbGljeSlcbiAgICBvbkV2ZW50SGFuZGxlclBvbGljeS5ncmFudFByaW5jaXBhbC5hZGRUb1ByaW5jaXBhbFBvbGljeShuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICBhY3Rpb25zOiBbJ2R5bmFtb2RiOionXSxcbiAgICAgIHJlc291cmNlczogdGhpcy5yZWdpb25hbEFybnMsXG4gICAgfSkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhpcyB0YWJsZSBoYXMgaW5kZXhlc1xuICAgKi9cbiAgcHJvdGVjdGVkIGdldCBoYXNJbmRleCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5nbG9iYWxTZWNvbmRhcnlJbmRleGVzLmxlbmd0aCArIHRoaXMubG9jYWxTZWNvbmRhcnlJbmRleGVzLmxlbmd0aCA+IDA7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHVwIGtleSBwcm9wZXJ0aWVzIGFuZCByZXR1cm4gdGhlIFRhYmxlIGVuY3J5cHRpb24gcHJvcGVydHkgZnJvbSB0aGVcbiAgICogdXNlcidzIGNvbmZpZ3VyYXRpb24uXG4gICAqL1xuICBwcml2YXRlIHBhcnNlRW5jcnlwdGlvbihwcm9wczogVGFibGVQcm9wcyk6IHsgc3NlU3BlY2lmaWNhdGlvbjogQ2ZuVGFibGVQcm9wc1snc3NlU3BlY2lmaWNhdGlvbiddLCBlbmNyeXB0aW9uS2V5Pzoga21zLklLZXkgfSB7XG4gICAgbGV0IGVuY3J5cHRpb25UeXBlID0gcHJvcHMuZW5jcnlwdGlvbjtcblxuICAgIGlmIChlbmNyeXB0aW9uVHlwZSAhPSBudWxsICYmIHByb3BzLnNlcnZlclNpZGVFbmNyeXB0aW9uICE9IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignT25seSBvbmUgb2YgZW5jcnlwdGlvbiBhbmQgc2VydmVyU2lkZUVuY3J5cHRpb24gY2FuIGJlIHNwZWNpZmllZCwgYnV0IGJvdGggd2VyZSBwcm92aWRlZCcpO1xuICAgIH1cblxuICAgIGlmIChwcm9wcy5zZXJ2ZXJTaWRlRW5jcnlwdGlvbiAmJiBwcm9wcy5lbmNyeXB0aW9uS2V5KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2VuY3J5cHRpb25LZXkgY2Fubm90IGJlIHNwZWNpZmllZCB3aGVuIHNlcnZlclNpZGVFbmNyeXB0aW9uIGlzIHNwZWNpZmllZC4gVXNlIGVuY3J5cHRpb24gaW5zdGVhZCcpO1xuICAgIH1cblxuICAgIGlmIChlbmNyeXB0aW9uVHlwZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBlbmNyeXB0aW9uVHlwZSA9IHByb3BzLmVuY3J5cHRpb25LZXkgIT0gbnVsbFxuICAgICAgICAvLyBJZiB0aGVyZSBpcyBhIGNvbmZpZ3VyZWQgZW5jcnlwdGlvbktleSwgdGhlIGVuY3J5cHRpb24gaXMgaW1wbGljaXRseSBDVVNUT01FUl9NQU5BR0VEXG4gICAgICAgID8gVGFibGVFbmNyeXB0aW9uLkNVU1RPTUVSX01BTkFHRURcbiAgICAgICAgLy8gT3RoZXJ3aXNlLCBpZiBzZXZlclNpZGVFbmNyeXB0aW9uIGlzIGVuYWJsZWQsIGl0J3MgQVdTX01BTkFHRUQ7IGVsc2UgdW5kZWZpbmVkIChkbyBub3Qgc2V0IGFueXRoaW5nKVxuICAgICAgICA6IHByb3BzLnNlcnZlclNpZGVFbmNyeXB0aW9uID8gVGFibGVFbmNyeXB0aW9uLkFXU19NQU5BR0VEIDogdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGlmIChlbmNyeXB0aW9uVHlwZSAhPT0gVGFibGVFbmNyeXB0aW9uLkNVU1RPTUVSX01BTkFHRUQgJiYgcHJvcHMuZW5jcnlwdGlvbktleSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdgZW5jcnlwdGlvbktleSBjYW5ub3QgYmUgc3BlY2lmaWVkIHVubGVzcyBlbmNyeXB0aW9uIGlzIHNldCB0byBUYWJsZUVuY3J5cHRpb24uQ1VTVE9NRVJfTUFOQUdFRCAoaXQgd2FzIHNldCB0byAke2VuY3J5cHRpb25UeXBlfSlgJyk7XG4gICAgfVxuXG4gICAgaWYgKGVuY3J5cHRpb25UeXBlID09PSBUYWJsZUVuY3J5cHRpb24uQ1VTVE9NRVJfTUFOQUdFRCAmJiBwcm9wcy5yZXBsaWNhdGlvblJlZ2lvbnMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVGFibGVFbmNyeXB0aW9uLkNVU1RPTUVSX01BTkFHRUQgaXMgbm90IHN1cHBvcnRlZCBieSBEeW5hbW9EQiBHbG9iYWwgVGFibGVzICh3aGVyZSByZXBsaWNhdGlvblJlZ2lvbnMgd2FzIHNldCknKTtcbiAgICB9XG5cbiAgICBzd2l0Y2ggKGVuY3J5cHRpb25UeXBlKSB7XG4gICAgICBjYXNlIFRhYmxlRW5jcnlwdGlvbi5DVVNUT01FUl9NQU5BR0VEOlxuICAgICAgICBjb25zdCBlbmNyeXB0aW9uS2V5ID0gcHJvcHMuZW5jcnlwdGlvbktleSA/PyBuZXcga21zLktleSh0aGlzLCAnS2V5Jywge1xuICAgICAgICAgIGRlc2NyaXB0aW9uOiBgQ3VzdG9tZXItbWFuYWdlZCBrZXkgYXV0by1jcmVhdGVkIGZvciBlbmNyeXB0aW5nIER5bmFtb0RCIHRhYmxlIGF0ICR7dGhpcy5ub2RlLnBhdGh9YCxcbiAgICAgICAgICBlbmFibGVLZXlSb3RhdGlvbjogdHJ1ZSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBzc2VTcGVjaWZpY2F0aW9uOiB7IHNzZUVuYWJsZWQ6IHRydWUsIGttc01hc3RlcktleUlkOiBlbmNyeXB0aW9uS2V5LmtleUFybiwgc3NlVHlwZTogJ0tNUycgfSxcbiAgICAgICAgICBlbmNyeXB0aW9uS2V5LFxuICAgICAgICB9O1xuXG4gICAgICBjYXNlIFRhYmxlRW5jcnlwdGlvbi5BV1NfTUFOQUdFRDpcbiAgICAgICAgLy8gTm90IHNwZWNpZnlpbmcgXCJzc2VUeXBlOiAnS01TJ1wiIGhlcmUgYmVjYXVzZSBpdCB3b3VsZCBjYXVzZSBwaG9ueSBjaGFuZ2VzIHRvIGV4aXN0aW5nIHN0YWNrcy5cbiAgICAgICAgcmV0dXJuIHsgc3NlU3BlY2lmaWNhdGlvbjogeyBzc2VFbmFibGVkOiB0cnVlIH0gfTtcblxuICAgICAgY2FzZSBUYWJsZUVuY3J5cHRpb24uREVGQVVMVDpcbiAgICAgICAgcmV0dXJuIHsgc3NlU3BlY2lmaWNhdGlvbjogeyBzc2VFbmFibGVkOiBmYWxzZSB9IH07XG5cbiAgICAgIGNhc2UgdW5kZWZpbmVkOlxuICAgICAgICAvLyBOb3Qgc3BlY2lmeWluZyBcInNzZUVuYWJsZWQ6IGZhbHNlXCIgaGVyZSBiZWNhdXNlIGl0IHdvdWxkIGNhdXNlIHBob255IGNoYW5nZXMgdG8gZXhpc3Rpbmcgc3RhY2tzLlxuICAgICAgICByZXR1cm4geyBzc2VTcGVjaWZpY2F0aW9uOiB1bmRlZmluZWQgfTtcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbmV4cGVjdGVkICdlbmNyeXB0aW9uVHlwZSc6ICR7ZW5jcnlwdGlvblR5cGV9YCk7XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogRGF0YSB0eXBlcyBmb3IgYXR0cmlidXRlcyB3aXRoaW4gYSB0YWJsZVxuICpcbiAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2FtYXpvbmR5bmFtb2RiL2xhdGVzdC9kZXZlbG9wZXJndWlkZS9Ib3dJdFdvcmtzLk5hbWluZ1J1bGVzRGF0YVR5cGVzLmh0bWwjSG93SXRXb3Jrcy5EYXRhVHlwZXNcbiAqL1xuZXhwb3J0IGVudW0gQXR0cmlidXRlVHlwZSB7XG4gIC8qKiBVcCB0byA0MDBLaUIgb2YgYmluYXJ5IGRhdGEgKHdoaWNoIG11c3QgYmUgZW5jb2RlZCBhcyBiYXNlNjQgYmVmb3JlIHNlbmRpbmcgdG8gRHluYW1vREIpICovXG4gIEJJTkFSWSA9ICdCJyxcbiAgLyoqIE51bWVyaWMgdmFsdWVzIG1hZGUgb2YgdXAgdG8gMzggZGlnaXRzIChwb3NpdGl2ZSwgbmVnYXRpdmUgb3IgemVybykgKi9cbiAgTlVNQkVSID0gJ04nLFxuICAvKiogVXAgdG8gNDAwS2lCIG9mIFVURi04IGVuY29kZWQgdGV4dCAqL1xuICBTVFJJTkcgPSAnUycsXG59XG5cbi8qKlxuICogRHluYW1vREIncyBSZWFkL1dyaXRlIGNhcGFjaXR5IG1vZGVzLlxuICovXG5leHBvcnQgZW51bSBCaWxsaW5nTW9kZSB7XG4gIC8qKlxuICAgKiBQYXkgb25seSBmb3Igd2hhdCB5b3UgdXNlLiBZb3UgZG9uJ3QgY29uZmlndXJlIFJlYWQvV3JpdGUgY2FwYWNpdHkgdW5pdHMuXG4gICAqL1xuICBQQVlfUEVSX1JFUVVFU1QgPSAnUEFZX1BFUl9SRVFVRVNUJyxcbiAgLyoqXG4gICAqIEV4cGxpY2l0bHkgc3BlY2lmaWVkIFJlYWQvV3JpdGUgY2FwYWNpdHkgdW5pdHMuXG4gICAqL1xuICBQUk9WSVNJT05FRCA9ICdQUk9WSVNJT05FRCcsXG59XG5cbi8qKlxuICogVGhlIHNldCBvZiBhdHRyaWJ1dGVzIHRoYXQgYXJlIHByb2plY3RlZCBpbnRvIHRoZSBpbmRleFxuICpcbiAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2FtYXpvbmR5bmFtb2RiL2xhdGVzdC9BUElSZWZlcmVuY2UvQVBJX1Byb2plY3Rpb24uaHRtbFxuICovXG5leHBvcnQgZW51bSBQcm9qZWN0aW9uVHlwZSB7XG4gIC8qKiBPbmx5IHRoZSBpbmRleCBhbmQgcHJpbWFyeSBrZXlzIGFyZSBwcm9qZWN0ZWQgaW50byB0aGUgaW5kZXguICovXG4gIEtFWVNfT05MWSA9ICdLRVlTX09OTFknLFxuICAvKiogT25seSB0aGUgc3BlY2lmaWVkIHRhYmxlIGF0dHJpYnV0ZXMgYXJlIHByb2plY3RlZCBpbnRvIHRoZSBpbmRleC4gVGhlIGxpc3Qgb2YgcHJvamVjdGVkIGF0dHJpYnV0ZXMgaXMgaW4gYG5vbktleUF0dHJpYnV0ZXNgLiAqL1xuICBJTkNMVURFID0gJ0lOQ0xVREUnLFxuICAvKiogQWxsIG9mIHRoZSB0YWJsZSBhdHRyaWJ1dGVzIGFyZSBwcm9qZWN0ZWQgaW50byB0aGUgaW5kZXguICovXG4gIEFMTCA9ICdBTEwnXG59XG5cbi8qKlxuICogV2hlbiBhbiBpdGVtIGluIHRoZSB0YWJsZSBpcyBtb2RpZmllZCwgU3RyZWFtVmlld1R5cGUgZGV0ZXJtaW5lcyB3aGF0IGluZm9ybWF0aW9uXG4gKiBpcyB3cml0dGVuIHRvIHRoZSBzdHJlYW0gZm9yIHRoaXMgdGFibGUuXG4gKlxuICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vYW1hem9uZHluYW1vZGIvbGF0ZXN0L0FQSVJlZmVyZW5jZS9BUElfU3RyZWFtU3BlY2lmaWNhdGlvbi5odG1sXG4gKi9cbmV4cG9ydCBlbnVtIFN0cmVhbVZpZXdUeXBlIHtcbiAgLyoqIFRoZSBlbnRpcmUgaXRlbSwgYXMgaXQgYXBwZWFycyBhZnRlciBpdCB3YXMgbW9kaWZpZWQsIGlzIHdyaXR0ZW4gdG8gdGhlIHN0cmVhbS4gKi9cbiAgTkVXX0lNQUdFID0gJ05FV19JTUFHRScsXG4gIC8qKiBUaGUgZW50aXJlIGl0ZW0sIGFzIGl0IGFwcGVhcmVkIGJlZm9yZSBpdCB3YXMgbW9kaWZpZWQsIGlzIHdyaXR0ZW4gdG8gdGhlIHN0cmVhbS4gKi9cbiAgT0xEX0lNQUdFID0gJ09MRF9JTUFHRScsXG4gIC8qKiBCb3RoIHRoZSBuZXcgYW5kIHRoZSBvbGQgaXRlbSBpbWFnZXMgb2YgdGhlIGl0ZW0gYXJlIHdyaXR0ZW4gdG8gdGhlIHN0cmVhbS4gKi9cbiAgTkVXX0FORF9PTERfSU1BR0VTID0gJ05FV19BTkRfT0xEX0lNQUdFUycsXG4gIC8qKiBPbmx5IHRoZSBrZXkgYXR0cmlidXRlcyBvZiB0aGUgbW9kaWZpZWQgaXRlbSBhcmUgd3JpdHRlbiB0byB0aGUgc3RyZWFtLiAqL1xuICBLRVlTX09OTFkgPSAnS0VZU19PTkxZJ1xufVxuXG4vKipcbiAqIER5bmFtb0RCJ3MgdGFibGUgY2xhc3MuXG4gKlxuICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vYW1hem9uZHluYW1vZGIvbGF0ZXN0L2RldmVsb3Blcmd1aWRlL0hvd0l0V29ya3MuVGFibGVDbGFzc2VzLmh0bWxcbiAqL1xuZXhwb3J0IGVudW0gVGFibGVDbGFzcyB7XG4gIC8qKiBEZWZhdWx0IHRhYmxlIGNsYXNzIGZvciBEeW5hbW9EQi4gKi9cbiAgU1RBTkRBUkQgPSAnU1RBTkRBUkQnLFxuXG4gIC8qKiBUYWJsZSBjbGFzcyBmb3IgRHluYW1vREIgdGhhdCByZWR1Y2VzIHN0b3JhZ2UgY29zdHMgY29tcGFyZWQgdG8gZXhpc3RpbmcgRHluYW1vREIgU3RhbmRhcmQgdGFibGVzLiAqL1xuICBTVEFOREFSRF9JTkZSRVFVRU5UX0FDQ0VTUyA9ICdTVEFOREFSRF9JTkZSRVFVRU5UX0FDQ0VTUycsXG59XG5cbi8qKlxuICogSnVzdCBhIGNvbnZlbmllbnQgd2F5IHRvIGtlZXAgdHJhY2sgb2YgYm90aCBhdHRyaWJ1dGVzXG4gKi9cbmludGVyZmFjZSBTY2FsYWJsZUF0dHJpYnV0ZVBhaXIge1xuICBzY2FsYWJsZVJlYWRBdHRyaWJ1dGU/OiBTY2FsYWJsZVRhYmxlQXR0cmlidXRlO1xuICBzY2FsYWJsZVdyaXRlQXR0cmlidXRlPzogU2NhbGFibGVUYWJsZUF0dHJpYnV0ZTtcbn1cblxuLyoqXG4gKiBBbiBpbmxpbmUgcG9saWN5IHRoYXQgaXMgbG9naWNhbGx5IGJvdW5kIHRvIHRoZSBzb3VyY2UgdGFibGUgb2YgYSBEeW5hbW9EQiBHbG9iYWwgVGFibGVzXG4gKiBcImNsdXN0ZXJcIi4gVGhpcyBpcyBoZXJlIHRvIGVuc3VyZSBwZXJtaXNzaW9ucyBhcmUgcmVtb3ZlZCBhcyBwYXJ0IG9mIChhbmQgbm90IGJlZm9yZSkgdGhlXG4gKiBDbGVhblVwIHBoYXNlIG9mIGEgc3RhY2sgdXBkYXRlLCB3aGVuIGEgcmVwbGljYSBpcyByZW1vdmVkIChvciB0aGUgZW50aXJlIFwiY2x1c3RlclwiIGdldHNcbiAqIHJlcGxhY2VkKS5cbiAqXG4gKiBJZiBzdGF0ZW1lbnRzIGFyZSBhZGRlZCBkaXJlY3RseSB0byB0aGUgaGFuZGxlciByb2xlcyAoYXMgb3Bwb3NlZCB0byBpbiBhIHNlcGFyYXRlIGlubGluZVxuICogcG9saWN5IHJlc291cmNlKSwgbmV3IHBlcm1pc3Npb25zIGFyZSBpbiBlZmZlY3QgYmVmb3JlIGNsZWFuIHVwIGhhcHBlbnMsIGFuZCBzbyByZXBsaWNhcyB0aGF0XG4gKiBuZWVkIHRvIGJlIGRyb3BwZWQgY2FuIG5vIGxvbmdlciBiZSBkdWUgdG8gbGFjayBvZiBwZXJtaXNzaW9ucy5cbiAqL1xuY2xhc3MgU291cmNlVGFibGVBdHRhY2hlZFBvbGljeSBleHRlbmRzIENvcmVDb25zdHJ1Y3QgaW1wbGVtZW50cyBpYW0uSUdyYW50YWJsZSB7XG4gIHB1YmxpYyByZWFkb25seSBncmFudFByaW5jaXBhbDogaWFtLklQcmluY2lwYWw7XG4gIHB1YmxpYyByZWFkb25seSBwb2xpY3k6IGlhbS5JTWFuYWdlZFBvbGljeTtcblxuICBwdWJsaWMgY29uc3RydWN0b3Ioc291cmNlVGFibGU6IFRhYmxlLCByb2xlOiBpYW0uSVJvbGUpIHtcbiAgICBzdXBlcihzb3VyY2VUYWJsZSwgYFNvdXJjZVRhYmxlQXR0YWNoZWRNYW5hZ2VkUG9saWN5LSR7TmFtZXMubm9kZVVuaXF1ZUlkKHJvbGUubm9kZSl9YCk7XG5cbiAgICBjb25zdCBwb2xpY3kgPSBuZXcgaWFtLk1hbmFnZWRQb2xpY3kodGhpcywgJ1Jlc291cmNlJywge1xuICAgICAgLy8gQSBDRiB1cGRhdGUgb2YgdGhlIGRlc2NyaXB0aW9uIHByb3BlcnR5IG9mIGEgbWFuYWdlZCBwb2xpY3kgcmVxdWlyZXNcbiAgICAgIC8vIGEgcmVwbGFjZW1lbnQuIFVzZSB0aGUgdGFibGUgbmFtZSBpbiB0aGUgZGVzY3JpcHRpb24gdG8gZm9yY2UgYSBtYW5hZ2VkXG4gICAgICAvLyBwb2xpY3kgcmVwbGFjZW1lbnQgd2hlbiB0aGUgdGFibGUgbmFtZSBjaGFuZ2VzLiBUaGlzIHdheSB3ZSBwcmVzZXJ2ZSBwZXJtaXNzaW9uc1xuICAgICAgLy8gdG8gZGVsZXRlIG9sZCByZXBsaWNhcyBpbiBjYXNlIG9mIGEgdGFibGUgcmVwbGFjZW1lbnQuXG4gICAgICBkZXNjcmlwdGlvbjogYER5bmFtb0RCIHJlcGxpY2F0aW9uIG1hbmFnZWQgcG9saWN5IGZvciB0YWJsZSAke3NvdXJjZVRhYmxlLnRhYmxlTmFtZX1gLFxuICAgICAgcm9sZXM6IFtyb2xlXSxcbiAgICB9KTtcbiAgICB0aGlzLnBvbGljeSA9IHBvbGljeTtcbiAgICB0aGlzLmdyYW50UHJpbmNpcGFsID0gbmV3IFNvdXJjZVRhYmxlQXR0YWNoZWRQcmluY2lwYWwocm9sZSwgcG9saWN5KTtcbiAgfVxufVxuXG4vKipcbiAqIEFuIGBJUHJpbmNpcGFsYCBlbnRpdHkgdGhhdCBjYW4gYmUgdXNlZCBhcyB0aGUgdGFyZ2V0IG9mIGBncmFudGAgY2FsbHMsIHVzZWQgYnkgdGhlXG4gKiBgU291cmNlVGFibGVBdHRhY2hlZFBvbGljeWAgY2xhc3Mgc28gaXQgY2FuIGFjdCBhcyBhbiBgSUdyYW50YWJsZWAuXG4gKi9cbmNsYXNzIFNvdXJjZVRhYmxlQXR0YWNoZWRQcmluY2lwYWwgZXh0ZW5kcyBpYW0uUHJpbmNpcGFsQmFzZSB7XG4gIHB1YmxpYyBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IHJvbGU6IGlhbS5JUm9sZSwgcHJpdmF0ZSByZWFkb25seSBwb2xpY3k6IGlhbS5NYW5hZ2VkUG9saWN5KSB7XG4gICAgc3VwZXIoKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgcG9saWN5RnJhZ21lbnQoKTogaWFtLlByaW5jaXBhbFBvbGljeUZyYWdtZW50IHtcbiAgICByZXR1cm4gdGhpcy5yb2xlLnBvbGljeUZyYWdtZW50O1xuICB9XG5cbiAgcHVibGljIGFkZFRvUHJpbmNpcGFsUG9saWN5KHN0YXRlbWVudDogaWFtLlBvbGljeVN0YXRlbWVudCk6IGlhbS5BZGRUb1ByaW5jaXBhbFBvbGljeVJlc3VsdCB7XG4gICAgdGhpcy5wb2xpY3kuYWRkU3RhdGVtZW50cyhzdGF0ZW1lbnQpO1xuICAgIHJldHVybiB7XG4gICAgICBwb2xpY3lEZXBlbmRhYmxlOiB0aGlzLnBvbGljeSxcbiAgICAgIHN0YXRlbWVudEFkZGVkOiB0cnVlLFxuICAgIH07XG4gIH1cblxuICBwdWJsaWMgZGVkdXBlU3RyaW5nKCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxufVxuIl19
\No newline at end of file