UNPKG

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