@aws-cdk/aws-elasticache-alpha 2.218.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,429 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var _a;
9
+ var ServerlessCache_1;
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.ServerlessCache = void 0;
12
+ const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
13
+ const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
14
+ const common_1 = require("./common");
15
+ const aws_elasticache_1 = require("aws-cdk-lib/aws-elasticache");
16
+ const serverless_cache_base_1 = require("./serverless-cache-base");
17
+ const ec2 = require("aws-cdk-lib/aws-ec2");
18
+ const core_1 = require("aws-cdk-lib/core");
19
+ const metadata_resource_1 = require("aws-cdk-lib/core/lib/metadata-resource");
20
+ const prop_injectable_1 = require("aws-cdk-lib/core/lib/prop-injectable");
21
+ const ELASTICACHE_SERVERLESSCACHE_SYMBOL = Symbol.for('@aws-cdk/aws-elasticache.ServerlessCache');
22
+ /**
23
+ * Unit types for data storage usage limits
24
+ */
25
+ var DataStorageUnit;
26
+ (function (DataStorageUnit) {
27
+ /**
28
+ * Gigabytes
29
+ */
30
+ DataStorageUnit["GIGABYTES"] = "GB";
31
+ })(DataStorageUnit || (DataStorageUnit = {}));
32
+ /**
33
+ * Minimum data storage size in GB for ServerlessCache
34
+ */
35
+ const DATA_STORAGE_MIN_GB = 1;
36
+ /**
37
+ * Maximum data storage size in GB for ServerlessCache
38
+ */
39
+ const DATA_STORAGE_MAX_GB = 5000;
40
+ /**
41
+ * Minimum request rate limit in ECPUs per second for ServerlessCache
42
+ */
43
+ const REQUEST_RATE_MIN_ECPU = 1000;
44
+ /**
45
+ * Maximum request rate limit in ECPUs per second for ServerlessCache
46
+ */
47
+ const REQUEST_RATE_MAX_ECPU = 15000000;
48
+ /**
49
+ * A serverless ElastiCache cache
50
+ *
51
+ * @resource AWS::ElastiCache::ServerlessCache
52
+ */
53
+ let ServerlessCache = ServerlessCache_1 = class ServerlessCache extends serverless_cache_base_1.ServerlessCacheBase {
54
+ /**
55
+ * Return whether the given object is a `ServerlessCache`
56
+ */
57
+ static isServerlessCache(x) {
58
+ return x !== null && typeof (x) === 'object' && ELASTICACHE_SERVERLESSCACHE_SYMBOL in x;
59
+ }
60
+ /**
61
+ * Import an existing serverless cache by name
62
+ *
63
+ * @param scope The parent creating construct (usually `this`)
64
+ * @param id The construct's name
65
+ * @param serverlessCacheName The name of the existing serverless cache
66
+ */
67
+ static fromServerlessCacheName(scope, id, serverlessCacheName) {
68
+ return ServerlessCache_1.fromServerlessCacheAttributes(scope, id, { serverlessCacheName });
69
+ }
70
+ /**
71
+ * Import an existing serverless cache by ARN
72
+ *
73
+ * @param scope The parent creating construct (usually `this`)
74
+ * @param id The construct's name
75
+ * @param serverlessCacheArn The ARN of the existing serverless cache
76
+ */
77
+ static fromServerlessCacheArn(scope, id, serverlessCacheArn) {
78
+ return ServerlessCache_1.fromServerlessCacheAttributes(scope, id, { serverlessCacheArn });
79
+ }
80
+ /**
81
+ * Import an existing serverless cache using attributes
82
+ *
83
+ * @param scope The parent creating construct (usually `this`)
84
+ * @param id The construct's name
85
+ * @param attrs A `ServerlessCacheAttributes` object
86
+ */
87
+ static fromServerlessCacheAttributes(scope, id, attrs) {
88
+ try {
89
+ jsiiDeprecationWarnings._aws_cdk_aws_elasticache_alpha_ServerlessCacheAttributes(attrs);
90
+ }
91
+ catch (error) {
92
+ if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
93
+ Error.captureStackTrace(error, this.fromServerlessCacheAttributes);
94
+ }
95
+ throw error;
96
+ }
97
+ let name;
98
+ let arn;
99
+ const stack = core_1.Stack.of(scope);
100
+ if (attrs.serverlessCacheArn && attrs.serverlessCacheName) {
101
+ throw new core_1.ValidationError('Only one of serverlessCacheArn or serverlessCacheName can be provided.', scope);
102
+ }
103
+ if (attrs.serverlessCacheArn) {
104
+ arn = attrs.serverlessCacheArn;
105
+ const extractedServerlessCacheName = stack.splitArn(attrs.serverlessCacheArn, core_1.ArnFormat.SLASH_RESOURCE_NAME).resourceName;
106
+ if (!extractedServerlessCacheName) {
107
+ throw new core_1.ValidationError('Unable to extract serverless cache name from ARN.', scope);
108
+ }
109
+ name = extractedServerlessCacheName;
110
+ }
111
+ else if (attrs.serverlessCacheName) {
112
+ name = attrs.serverlessCacheName;
113
+ arn = stack.formatArn({
114
+ service: 'elasticache',
115
+ resource: 'serverlesscache',
116
+ resourceName: attrs.serverlessCacheName,
117
+ });
118
+ }
119
+ else {
120
+ throw new core_1.ValidationError('One of serverlessCacheName or serverlessCacheArn is required.', scope);
121
+ }
122
+ class Import extends serverless_cache_base_1.ServerlessCacheBase {
123
+ constructor(serverlessCacheArn, serverlessCacheName) {
124
+ super(scope, id);
125
+ this.engine = attrs.engine;
126
+ this.backupArnsToRestore = attrs.backupArnsToRestore;
127
+ this.kmsKey = attrs.kmsKey;
128
+ this.vpc = attrs.vpc;
129
+ this.subnets = attrs.subnets;
130
+ this.securityGroups = attrs.securityGroups;
131
+ this.userGroup = attrs.userGroup;
132
+ this.serverlessCacheArn = serverlessCacheArn;
133
+ this.serverlessCacheName = serverlessCacheName;
134
+ if (this.engine) {
135
+ let defaultPort;
136
+ switch (this.engine) {
137
+ case serverless_cache_base_1.CacheEngine.VALKEY_LATEST:
138
+ case serverless_cache_base_1.CacheEngine.VALKEY_7:
139
+ case serverless_cache_base_1.CacheEngine.VALKEY_8:
140
+ case serverless_cache_base_1.CacheEngine.REDIS_LATEST:
141
+ // Document showing the default port
142
+ // https://docs.aws.amazon.com/AmazonElastiCache/latest/dg/set-up.html#elasticache-install-grant-access-VPN
143
+ defaultPort = ec2.Port.tcp(6379);
144
+ break;
145
+ case serverless_cache_base_1.CacheEngine.MEMCACHED_LATEST:
146
+ // Document showing the default port
147
+ // https://docs.aws.amazon.com/AmazonElastiCache/latest/dg/set-up.html#elasticache-install-grant-access-VPN
148
+ defaultPort = ec2.Port.tcp(11211);
149
+ break;
150
+ default:
151
+ throw new core_1.ValidationError(`Unsupported cache engine: ${this.engine}`, scope);
152
+ }
153
+ this.connections = new ec2.Connections({
154
+ securityGroups: this.securityGroups,
155
+ defaultPort: defaultPort,
156
+ });
157
+ }
158
+ else {
159
+ this.connections = new ec2.Connections({
160
+ securityGroups: this.securityGroups,
161
+ });
162
+ }
163
+ }
164
+ }
165
+ return new Import(arn, name);
166
+ }
167
+ constructor(scope, id, props) {
168
+ super(scope, id, {});
169
+ try {
170
+ jsiiDeprecationWarnings._aws_cdk_aws_elasticache_alpha_ServerlessCacheProps(props);
171
+ }
172
+ catch (error) {
173
+ if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
174
+ Error.captureStackTrace(error, ServerlessCache);
175
+ }
176
+ throw error;
177
+ }
178
+ // Enhanced CDK Analytics Telemetry
179
+ (0, metadata_resource_1.addConstructMetadata)(this, props);
180
+ this.engine = props.engine ?? serverless_cache_base_1.CacheEngine.VALKEY_LATEST;
181
+ this.serverlessCacheName = props.serverlessCacheName ?? core_1.Lazy.string({ produce: () => core_1.Names.uniqueId(this) });
182
+ this.kmsKey = props.kmsKey;
183
+ this.vpc = props.vpc;
184
+ this.userGroup = props.userGroup;
185
+ this.validateDescription(props.description);
186
+ this.validateDataStorageLimits(props.cacheUsageLimits);
187
+ this.validateRequestRateLimits(props.cacheUsageLimits);
188
+ this.validateBackupSettings(props.backup);
189
+ this.validateUserGroupCompatibility(this.engine, this.userGroup);
190
+ const subnetConfig = this.configureSubnets(props);
191
+ const subnetIds = subnetConfig.subnetIds;
192
+ this.subnets = subnetConfig.subnets;
193
+ const securityGroupConfig = this.configureSecurityGroups(props);
194
+ const securityGroupIds = securityGroupConfig.securityGroupIds;
195
+ this.securityGroups = securityGroupConfig.securityGroups;
196
+ const [engine, version] = this.engine.split('_');
197
+ const resource = new aws_elasticache_1.CfnServerlessCache(this, 'Resource', {
198
+ engine: engine,
199
+ majorEngineVersion: version,
200
+ serverlessCacheName: this.serverlessCacheName,
201
+ description: props.description,
202
+ cacheUsageLimits: this.renderCacheUsageLimits(props.cacheUsageLimits),
203
+ dailySnapshotTime: props.backup?.backupTime ? this.formatBackupTime(props.backup.backupTime) : undefined,
204
+ snapshotRetentionLimit: props.backup?.backupRetentionLimit,
205
+ finalSnapshotName: props.backup?.backupNameBeforeDeletion,
206
+ snapshotArnsToRestore: props.backup?.backupArnsToRestore,
207
+ kmsKeyId: props.kmsKey?.keyId,
208
+ subnetIds: subnetIds,
209
+ securityGroupIds: securityGroupIds,
210
+ userGroupId: props.userGroup?.userGroupName,
211
+ });
212
+ if (props.userGroup) {
213
+ const userGroupResource = props.userGroup.node.findChild('Resource');
214
+ resource.addDependency(userGroupResource);
215
+ }
216
+ this.backupArnsToRestore = resource.snapshotArnsToRestore;
217
+ this.serverlessCacheArn = resource.attrArn;
218
+ this.serverlessCacheEndpointAddress = resource.attrEndpointAddress;
219
+ this.serverlessCacheEndpointPort = resource.attrEndpointPort;
220
+ this.serverlessCacheReaderEndpointAddress = resource.attrReaderEndpointAddress;
221
+ this.serverlessCacheReaderEndpointPort = resource.attrReaderEndpointPort;
222
+ this.serverlessCacheStatus = resource.attrStatus;
223
+ this.connections = new ec2.Connections({
224
+ securityGroups: this.securityGroups,
225
+ defaultPort: ec2.Port.tcp(core_1.Lazy.number({ produce: () => parseInt(this.serverlessCacheEndpointPort) })),
226
+ });
227
+ Object.defineProperty(this, ELASTICACHE_SERVERLESSCACHE_SYMBOL, { value: true });
228
+ }
229
+ /**
230
+ * Validate description meets AWS requirements
231
+ *
232
+ * @param description The description to validate
233
+ */
234
+ validateDescription(description) {
235
+ if (!description || core_1.Token.isUnresolved(description))
236
+ return;
237
+ if (description.length > 255) {
238
+ throw new core_1.ValidationError(`Description must not exceed 255 characters, currently has ${description.length}`, this);
239
+ }
240
+ if (description.includes('<') || description.includes('>')) {
241
+ throw new core_1.ValidationError('Description must not contain < or > characters', this);
242
+ }
243
+ }
244
+ /**
245
+ * Validate data storage size limits
246
+ *
247
+ * @param limits The usage limits containing data storage settings
248
+ */
249
+ validateDataStorageLimits(limits) {
250
+ if (!limits)
251
+ return;
252
+ if (limits.dataStorageMinimumSize && !limits.dataStorageMinimumSize.isUnresolved() &&
253
+ (limits.dataStorageMinimumSize.toGibibytes() < DATA_STORAGE_MIN_GB || limits.dataStorageMinimumSize.toGibibytes() > DATA_STORAGE_MAX_GB)) {
254
+ throw new core_1.ValidationError('Data storage minimum must be between 1 and 5000 GB.', this);
255
+ }
256
+ if (limits.dataStorageMaximumSize && !limits.dataStorageMaximumSize.isUnresolved() &&
257
+ (limits.dataStorageMaximumSize.toGibibytes() < DATA_STORAGE_MIN_GB || limits.dataStorageMaximumSize.toGibibytes() > DATA_STORAGE_MAX_GB)) {
258
+ throw new core_1.ValidationError('Data storage maximum must be between 1 and 5000 GB.', this);
259
+ }
260
+ if (limits.dataStorageMinimumSize && limits.dataStorageMaximumSize &&
261
+ !limits.dataStorageMinimumSize.isUnresolved() && !limits.dataStorageMaximumSize.isUnresolved() &&
262
+ limits.dataStorageMinimumSize.toGibibytes() > limits.dataStorageMaximumSize.toGibibytes()) {
263
+ throw new core_1.ValidationError('Data storage minimum cannot be greater than maximum', this);
264
+ }
265
+ }
266
+ /**
267
+ * Validate request rate limits
268
+ *
269
+ * @param limits The usage limits containing request rate settings
270
+ */
271
+ validateRequestRateLimits(limits) {
272
+ if (!limits)
273
+ return;
274
+ if (limits.requestRateLimitMinimum !== undefined && !core_1.Token.isUnresolved(limits.requestRateLimitMinimum) &&
275
+ (limits.requestRateLimitMinimum < REQUEST_RATE_MIN_ECPU || limits.requestRateLimitMinimum > REQUEST_RATE_MAX_ECPU)) {
276
+ throw new core_1.ValidationError('Request rate minimum must be between 1,000 and 15,000,000 ECPUs per second', this);
277
+ }
278
+ if (limits.requestRateLimitMaximum !== undefined && !core_1.Token.isUnresolved(limits.requestRateLimitMaximum) &&
279
+ (limits.requestRateLimitMaximum < REQUEST_RATE_MIN_ECPU || limits.requestRateLimitMaximum > REQUEST_RATE_MAX_ECPU)) {
280
+ throw new core_1.ValidationError('Request rate maximum must be between 1,000 and 15,000,000 ECPUs per second', this);
281
+ }
282
+ if (!core_1.Token.isUnresolved(limits.requestRateLimitMinimum) && !core_1.Token.isUnresolved(limits.requestRateLimitMaximum) &&
283
+ limits.requestRateLimitMinimum !== undefined && limits.requestRateLimitMaximum !== undefined &&
284
+ limits.requestRateLimitMinimum > limits.requestRateLimitMaximum) {
285
+ throw new core_1.ValidationError('Request rate minimum cannot be greater than maximum', this);
286
+ }
287
+ }
288
+ /**
289
+ * Validate backup settings meet AWS requirements
290
+ *
291
+ * @param backup The backup settings to validate
292
+ */
293
+ validateBackupSettings(backup) {
294
+ if (!core_1.Token.isUnresolved(backup?.backupRetentionLimit) && backup?.backupRetentionLimit !== undefined) {
295
+ const limit = backup.backupRetentionLimit;
296
+ if (limit < 1 || limit > 35) {
297
+ throw new core_1.ValidationError('Backup retention limit must be between 1 and 35 days', this);
298
+ }
299
+ }
300
+ if (!core_1.Token.isUnresolved(backup?.backupNameBeforeDeletion) && backup?.backupNameBeforeDeletion !== undefined) {
301
+ const name = backup.backupNameBeforeDeletion;
302
+ if (!/^[a-zA-Z]/.test(name)) {
303
+ throw new core_1.ValidationError('Final backup name must begin with a letter', this);
304
+ }
305
+ if (!/^[a-zA-Z0-9-]+$/.test(name)) {
306
+ throw new core_1.ValidationError('Final backup name must contain only ASCII letters, digits, and hyphens', this);
307
+ }
308
+ if (name.endsWith('-')) {
309
+ throw new core_1.ValidationError('Final backup name must not end with a hyphen', this);
310
+ }
311
+ if (name.includes('--')) {
312
+ throw new core_1.ValidationError('Final backup name must not contain two consecutive hyphens', this);
313
+ }
314
+ }
315
+ }
316
+ /**
317
+ * Validate user group compatibility with cache engine
318
+ *
319
+ * @param engine The cache engine
320
+ * @param userGroup The user group to validate
321
+ */
322
+ validateUserGroupCompatibility(engine, userGroup) {
323
+ if (!userGroup)
324
+ return;
325
+ if (engine === serverless_cache_base_1.CacheEngine.MEMCACHED_LATEST) {
326
+ throw new core_1.ValidationError('User groups cannot be used with Memcached engines. Only Redis and Valkey engines support user groups.', this);
327
+ }
328
+ if (engine === serverless_cache_base_1.CacheEngine.REDIS_LATEST && userGroup.engine !== common_1.UserEngine.REDIS) {
329
+ throw new core_1.ValidationError('Redis cache can only use Redis user groups.', this);
330
+ }
331
+ }
332
+ /**
333
+ * Render cache usage limits for CloudFormation
334
+ *
335
+ * @param limits The usage limits to render
336
+ * @returns CloudFormation-compatible usage limits object or undefined
337
+ */
338
+ renderCacheUsageLimits(limits) {
339
+ if (!limits)
340
+ return undefined;
341
+ const cacheUsageLimits = {};
342
+ if (limits.dataStorageMinimumSize !== undefined || limits.dataStorageMaximumSize !== undefined) {
343
+ cacheUsageLimits.dataStorage = {
344
+ unit: DataStorageUnit.GIGABYTES,
345
+ ...(limits.dataStorageMinimumSize !== undefined && { minimum: limits.dataStorageMinimumSize.toGibibytes() }),
346
+ ...(limits.dataStorageMaximumSize !== undefined && { maximum: limits.dataStorageMaximumSize.toGibibytes() }),
347
+ };
348
+ }
349
+ if (limits.requestRateLimitMinimum !== undefined || limits.requestRateLimitMaximum !== undefined) {
350
+ cacheUsageLimits.ecpuPerSecond = {
351
+ ...(limits.requestRateLimitMinimum !== undefined && { minimum: limits.requestRateLimitMinimum }),
352
+ ...(limits.requestRateLimitMaximum !== undefined && { maximum: limits.requestRateLimitMaximum }),
353
+ };
354
+ }
355
+ return Object.keys(cacheUsageLimits).length > 0 ? cacheUsageLimits : undefined;
356
+ }
357
+ /**
358
+ * Configure subnets for the cache
359
+ *
360
+ * @param props The ServerlessCache properties
361
+ * @returns Object containing subnet IDs and subnet objects
362
+ */
363
+ configureSubnets(props) {
364
+ let selectedSubnets;
365
+ if (props.vpcSubnets) {
366
+ selectedSubnets = props.vpc.selectSubnets(props.vpcSubnets);
367
+ }
368
+ else {
369
+ selectedSubnets = props.vpc.selectSubnets({
370
+ subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
371
+ });
372
+ }
373
+ return {
374
+ subnetIds: selectedSubnets.subnetIds.length > 0 ? selectedSubnets.subnetIds : undefined,
375
+ subnets: selectedSubnets.subnets.length > 0 ? selectedSubnets.subnets : undefined,
376
+ };
377
+ }
378
+ /**
379
+ * Configure security groups for the cache
380
+ *
381
+ * @param props The ServerlessCache properties
382
+ * @returns Object containing security group IDs and security group objects
383
+ */
384
+ configureSecurityGroups(props) {
385
+ if (props.securityGroups && props.securityGroups.length > 0) {
386
+ return {
387
+ securityGroupIds: props.securityGroups.map(sg => sg.securityGroupId),
388
+ securityGroups: props.securityGroups,
389
+ };
390
+ }
391
+ else {
392
+ const newSecurityGroup = new ec2.SecurityGroup(this, 'SecurityGroup', {
393
+ description: `Security group for ${this.node.id} cache.`,
394
+ vpc: props.vpc,
395
+ });
396
+ return {
397
+ securityGroupIds: [newSecurityGroup.securityGroupId],
398
+ securityGroups: [newSecurityGroup],
399
+ };
400
+ }
401
+ }
402
+ /**
403
+ * Format schedule to HH:MM format for daily backups
404
+ *
405
+ * @param schedule The schedule to format
406
+ * @returns Time string in HH:MM format
407
+ */
408
+ formatBackupTime(schedule) {
409
+ const WILD_CARD = '*';
410
+ const [minuteExpression, hourExpression, dayExpression, monthExpression, weekDayExpression, yearExpression,] = schedule.expressionString.substr(5).slice(0, -1).split(' ');
411
+ if (dayExpression != WILD_CARD || monthExpression != WILD_CARD || yearExpression != WILD_CARD || weekDayExpression != '?') {
412
+ throw new core_1.ValidationError('For now, only daily backup time is available (supports just hour and minute). Day, month, year, and weekDay are not allowed', this);
413
+ }
414
+ const hour = hourExpression == WILD_CARD ? '0' : hourExpression;
415
+ const minute = minuteExpression == WILD_CARD ? '0' : minuteExpression;
416
+ return `${hour.padStart(2, '0')}:${minute.padStart(2, '0')}`;
417
+ }
418
+ };
419
+ exports.ServerlessCache = ServerlessCache;
420
+ _a = JSII_RTTI_SYMBOL_1;
421
+ ServerlessCache[_a] = { fqn: "@aws-cdk/aws-elasticache-alpha.ServerlessCache", version: "2.218.0-alpha.0" };
422
+ /**
423
+ * Uniquely identifies this class.
424
+ */
425
+ ServerlessCache.PROPERTY_INJECTION_ID = 'aws-cdk-lib.aws-elasticache.ServerlessCache';
426
+ exports.ServerlessCache = ServerlessCache = ServerlessCache_1 = __decorate([
427
+ prop_injectable_1.propertyInjectable
428
+ ], ServerlessCache);
429
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVybGVzcy1jYWNoZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInNlcnZlcmxlc3MtY2FjaGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7OztBQUNBLHFDQUFzQztBQUN0QyxpRUFBK0U7QUFDL0UsbUVBQTZGO0FBRTdGLDJDQUEyQztBQUczQywyQ0FBK0Y7QUFDL0YsOEVBQThFO0FBQzlFLDBFQUEwRTtBQUUxRSxNQUFNLGtDQUFrQyxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsMENBQTBDLENBQUMsQ0FBQztBQUVsRzs7R0FFRztBQUNILElBQUssZUFLSjtBQUxELFdBQUssZUFBZTtJQUNsQjs7T0FFRztJQUNILG1DQUFnQixDQUFBO0FBQ2xCLENBQUMsRUFMSSxlQUFlLEtBQWYsZUFBZSxRQUtuQjtBQUVEOztHQUVHO0FBQ0gsTUFBTSxtQkFBbUIsR0FBRyxDQUFDLENBQUM7QUFDOUI7O0dBRUc7QUFDSCxNQUFNLG1CQUFtQixHQUFHLElBQUksQ0FBQztBQUNqQzs7R0FFRztBQUNILE1BQU0scUJBQXFCLEdBQUcsSUFBSSxDQUFDO0FBQ25DOztHQUVHO0FBQ0gsTUFBTSxxQkFBcUIsR0FBRyxRQUFRLENBQUM7QUFnTXZDOzs7O0dBSUc7QUFFSSxJQUFNLGVBQWUsdUJBQXJCLE1BQU0sZUFBZ0IsU0FBUSwyQ0FBbUI7SUFNdEQ7O09BRUc7SUFDSSxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBTTtRQUNwQyxPQUFPLENBQUMsS0FBSyxJQUFJLElBQUksT0FBTyxDQUFDLENBQUMsQ0FBQyxLQUFLLFFBQVEsSUFBSSxrQ0FBa0MsSUFBSSxDQUFDLENBQUM7S0FDekY7SUFFRDs7Ozs7O09BTUc7SUFDSSxNQUFNLENBQUMsdUJBQXVCLENBQUMsS0FBZ0IsRUFBRSxFQUFVLEVBQUUsbUJBQTJCO1FBQzdGLE9BQU8saUJBQWUsQ0FBQyw2QkFBNkIsQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFLEVBQUUsbUJBQW1CLEVBQUUs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QVMsSUFBSSxpQkFBaUIsSUFBSSxHQUFHLEVBQUUsQ0FBQztZQUMxSCxNQUFNLElBQUksc0JBQWUsQ0FBQyw2SEFBNkgsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUNqSyxDQUFDO1FBRUQsTUFBTSxJQUFJLEdBQUcsY0FBYyxJQUFJLFNBQVMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxjQUFjLENBQUM7UUFDaEUsTUFBTSxNQUFNLEdBQUcsZ0JBQWdCLElBQUksU0FBUyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLGdCQUFnQixDQUFDO1FBRXRFLE9BQU8sR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsSUFBSSxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDO0tBQzlEOztBQXJjVSwwQ0FBZTs7O0FBQzFCOztHQUVHO0FBQ29CLHFDQUFxQixHQUFXLDZDQUE2QyxBQUF4RCxDQUF5RDswQkFKMUYsZUFBZTtJQUQzQixvQ0FBa0I7R0FDTixlQUFlLENBc2MzQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0IHsgVXNlckVuZ2luZSB9IGZyb20gJy4vY29tbW9uJztcbmltcG9ydCB7IENmblNlcnZlcmxlc3NDYWNoZSwgQ2ZuVXNlckdyb3VwIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWVsYXN0aWNhY2hlJztcbmltcG9ydCB7IElTZXJ2ZXJsZXNzQ2FjaGUsIFNlcnZlcmxlc3NDYWNoZUJhc2UsIENhY2hlRW5naW5lIH0gZnJvbSAnLi9zZXJ2ZXJsZXNzLWNhY2hlLWJhc2UnO1xuaW1wb3J0IHsgSVVzZXJHcm91cCB9IGZyb20gJy4vdXNlci1ncm91cCc7XG5pbXBvcnQgKiBhcyBlYzIgZnJvbSAnYXdzLWNkay1saWIvYXdzLWVjMic7XG5pbXBvcnQgKiBhcyBldmVudHMgZnJvbSAnYXdzLWNkay1saWIvYXdzLWV2ZW50cyc7XG5pbXBvcnQgKiBhcyBrbXMgZnJvbSAnYXdzLWNkay1saWIvYXdzLWttcyc7XG5pbXBvcnQgeyBBcm5Gb3JtYXQsIFN0YWNrLCBTaXplLCBMYXp5LCBWYWxpZGF0aW9uRXJyb3IsIE5hbWVzLCBUb2tlbiB9IGZyb20gJ2F3cy1jZGstbGliL2NvcmUnO1xuaW1wb3J0IHsgYWRkQ29uc3RydWN0TWV0YWRhdGEgfSBmcm9tICdhd3MtY2RrLWxpYi9jb3JlL2xpYi9tZXRhZGF0YS1yZXNvdXJjZSc7XG5pbXBvcnQgeyBwcm9wZXJ0eUluamVjdGFibGUgfSBmcm9tICdhd3MtY2RrLWxpYi9jb3JlL2xpYi9wcm9wLWluamVjdGFibGUnO1xuXG5jb25zdCBFTEFTVElDQUNIRV9TRVJWRVJMRVNTQ0FDSEVfU1lNQk9MID0gU3ltYm9sLmZvcignQGF3cy1jZGsvYXdzLWVsYXN0aWNhY2hlLlNlcnZlcmxlc3NDYWNoZScpO1xuXG4vKipcbiAqIFVuaXQgdHlwZXMgZm9yIGRhdGEgc3RvcmFnZSB1c2FnZSBsaW1pdHNcbiAqL1xuZW51bSBEYXRhU3RvcmFnZVVuaXQge1xuICAvKipcbiAgICogR2lnYWJ5dGVzXG4gICAqL1xuICBHSUdBQllURVMgPSAnR0InLFxufVxuXG4vKipcbiAqIE1pbmltdW0gZGF0YSBzdG9yYWdlIHNpemUgaW4gR0IgZm9yIFNlcnZlcmxlc3NDYWNoZVxuICovXG5jb25zdCBEQVRBX1NUT1JBR0VfTUlOX0dCID0gMTtcbi8qKlxuICogTWF4aW11bSBkYXRhIHN0b3JhZ2Ugc2l6ZSBpbiBHQiBmb3IgU2VydmVybGVzc0NhY2hlXG4gKi9cbmNvbnN0IERBVEFfU1RPUkFHRV9NQVhfR0IgPSA1MDAwO1xuLyoqXG4gKiBNaW5pbXVtIHJlcXVlc3QgcmF0ZSBsaW1pdCBpbiBFQ1BVcyBwZXIgc2Vjb25kIGZvciBTZXJ2ZXJsZXNzQ2FjaGVcbiAqL1xuY29uc3QgUkVRVUVTVF9SQVRFX01JTl9FQ1BVID0gMTAwMDtcbi8qKlxuICogTWF4aW11bSByZXF1ZXN0IHJhdGUgbGltaXQgaW4gRUNQVXMgcGVyIHNlY29uZCBmb3IgU2VydmVybGVzc0NhY2hlXG4gKi9cbmNvbnN0IFJFUVVFU1RfUkFURV9NQVhfRUNQVSA9IDE1MDAwMDAwO1xuXG4vKipcbiAqIFVzYWdlIGxpbWl0cyBjb25maWd1cmF0aW9uIGZvciBTZXJ2ZXJsZXNzQ2FjaGVcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDYWNoZVVzYWdlTGltaXRzUHJvcGVydHkge1xuICAvKipcbiAgICogTWluaW11bSBkYXRhIHN0b3JhZ2Ugc2l6ZSAoMSBHQilcbiAgICpcbiAgICogQGRlZmF1bHQgLSBObyBtaW5pbXVtIGxpbWl0XG4gICAqL1xuICByZWFkb25seSBkYXRhU3RvcmFnZU1pbmltdW1TaXplPzogU2l6ZTtcbiAgLyoqXG4gICAqIE1heGltdW0gZGF0YSBzdG9yYWdlIHNpemUgKDUwMDAgR0IpXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gbWF4aW11bSBsaW1pdFxuICAgKi9cbiAgcmVhZG9ubHkgZGF0YVN0b3JhZ2VNYXhpbXVtU2l6ZT86IFNpemU7XG4gIC8qKlxuICAgKiBNaW5pbXVtIHJlcXVlc3QgcmF0ZSBsaW1pdCAoMTAwMCBFQ1BVcyBwZXIgc2Vjb25kKVxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIG1pbmltdW0gbGltaXRcbiAgICovXG4gIHJlYWRvbmx5IHJlcXVlc3RSYXRlTGltaXRNaW5pbXVtPzogbnVtYmVyO1xuICAvKipcbiAgICogTWF4aW11bSByZXF1ZXN0IHJhdGUgbGltaXQgKDE1MDAwMDAwIEVDUFVzIHBlciBzZWNvbmQpXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gbWF4aW11bSBsaW1pdFxuICAgKi9cbiAgcmVhZG9ubHkgcmVxdWVzdFJhdGVMaW1pdE1heGltdW0/OiBudW1iZXI7XG59XG5cbi8qKlxuICogQmFja3VwIGNvbmZpZ3VyYXRpb24gZm9yIFNlcnZlcmxlc3NDYWNoZVxuICovXG5leHBvcnQgaW50ZXJmYWNlIEJhY2t1cFNldHRpbmdzIHtcbiAgLyoqXG4gICAqIEF1dG9tYXRlZCBkYWlseSBiYWNrdXAgVVRDIHRpbWVcbiAgICpcbiAgICogQGRlZmF1bHQgLSBObyBhdXRvbWF0ZWQgYmFja3Vwc1xuICAgKi9cbiAgcmVhZG9ubHkgYmFja3VwVGltZT86IGV2ZW50cy5TY2hlZHVsZTtcbiAgLyoqXG4gICAqIE51bWJlciBvZiBkYXlzIHRvIHJldGFpbiBiYWNrdXBzICgxLTM1KVxuICAgKlxuICAgKiBAZGVmYXVsdCAtIEJhY2t1cHMgYXJlIG5vdCByZXRhaW5lZFxuICAgKi9cbiAgcmVhZG9ubHkgYmFja3VwUmV0ZW50aW9uTGltaXQ/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBOYW1lIGZvciB0aGUgZmluYWwgYmFja3VwIHRha2VuIGJlZm9yZSBkZWxldGlvblxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIGZpbmFsIGJhY2t1cFxuICAgKi9cbiAgcmVhZG9ubHkgYmFja3VwTmFtZUJlZm9yZURlbGV0aW9uPzogc3RyaW5nO1xuICAvKipcbiAgICogQVJOcyBvZiBiYWNrdXBzIGZyb20gd2hpY2ggdG8gcmVzdG9yZSBkYXRhIGludG8gdGhlIG5ldyBjYWNoZVxuICAgKlxuICAgKiBAZGVmYXVsdCAtIENyZWF0ZSBhIG5ldyBjYWNoZSB3aXRoIG5vIGV4aXN0aW5nIGRhdGFcbiAgICovXG4gIHJlYWRvbmx5IGJhY2t1cEFybnNUb1Jlc3RvcmU/OiBzdHJpbmdbXTtcbn1cblxuLyoqXG4gKiBQcm9wZXJ0aWVzIGZvciBkZWZpbmluZyBhIFNlcnZlcmxlc3NDYWNoZVxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNlcnZlcmxlc3NDYWNoZVByb3BzIHtcbiAgLyoqXG4gICAqIFRoZSBjYWNoZSBlbmdpbmUgY29tYmluZWQgd2l0aCB0aGUgdmVyc2lvblxuICAgKiBFbnVtIG9wdGlvbnM6IFZBTEtFWV9ERUZBVUxULCBWQUxLRVlfNywgVkFMS0VZXzgsIFJFRElTX0RFRkFVTFQsIE1FTUNBQ0hFRF9ERUZBVUxUXG4gICAqIFRoZSBkZWZhdWx0IG9wdGlvbnMgYnJpbmcgdGhlIGxhdGVzdCB2ZXJzaW9ucyBhdmFpbGFibGUuXG4gICAqXG4gICAqIEBkZWZhdWx0IHdoZW4gbm90IHByb3ZpZGVkLCB0aGUgZGVmYXVsdCBlbmdpbmUgd291bGQgYmUgVmFsa2V5LCBsYXRlc3QgdmVyc2lvbiBhdmFpbGFibGUgKFZBTEtFWV9ERUZBVUxUKVxuICAgKi9cbiAgcmVhZG9ubHkgZW5naW5lPzogQ2FjaGVFbmdpbmU7XG4gIC8qKlxuICAgKiBOYW1lIGZvciB0aGUgc2VydmVybGVzcyBjYWNoZVxuICAgKlxuICAgKiBAZGVmYXVsdCBhdXRvbWF0aWNhbGx5IGdlbmVyYXRlZCBuYW1lIGJ5IFJlc291cmNlXG4gICAqL1xuICByZWFkb25seSBzZXJ2ZXJsZXNzQ2FjaGVOYW1lPzogc3RyaW5nO1xuICAvKipcbiAgICogQSBkZXNjcmlwdGlvbiBmb3IgdGhlIGNhY2hlXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gZGVzY3JpcHRpb25cbiAgICovXG4gIHJlYWRvbmx5IGRlc2NyaXB0aW9uPzogc3RyaW5nO1xuICAvKipcbiAgICogVXNhZ2UgbGltaXRzIGZvciB0aGUgY2FjaGVcbiAgICpcbiAgICogQGRlZmF1bHQgLSBObyB1c2FnZSBsaW1pdHNcbiAgICovXG4gIHJlYWRvbmx5IGNhY2hlVXNhZ2VMaW1pdHM/OiBDYWNoZVVzYWdlTGltaXRzUHJvcGVydHk7XG4gIC8qKlxuICAgKiBCYWNrdXAgY29uZmlndXJhdGlvblxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIGJhY2t1cHMgY29uZmlndXJlZFxuICAgKi9cbiAgcmVhZG9ubHkgYmFja3VwPzogQmFja3VwU2V0dGluZ3M7XG4gIC8qKlxuICAgKiBLTVMga2V5IGZvciBlbmNyeXB0aW9uXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gU2VydmljZSBtYW5hZ2VkIGVuY3J5cHRpb24gKEFXUyBvd25lZCBLTVMga2V5KVxuICAgKi9cbiAgcmVhZG9ubHkga21zS2V5Pzoga21zLklLZXk7XG4gIC8qKlxuICAgKiBUaGUgVlBDIHRvIHBsYWNlIHRoZSBjYWNoZSBpblxuICAgKi9cbiAgcmVhZG9ubHkgdnBjOiBlYzIuSVZwYztcbiAgLyoqXG4gICAqIFdoaWNoIHN1Ym5ldHMgdG8gcGxhY2UgdGhlIGNhY2hlIGluXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gUHJpdmF0ZSBzdWJuZXRzIHdpdGggZWdyZXNzXG4gICAqL1xuICByZWFkb25seSB2cGNTdWJuZXRzPzogZWMyLlN1Ym5ldFNlbGVjdGlvbjtcbiAgLyoqXG4gICAqIFNlY3VyaXR5IGdyb3VwcyBmb3IgdGhlIGNhY2hlXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gQSBuZXcgc2VjdXJpdHkgZ3JvdXAgaXMgY3JlYXRlZFxuICAgKi9cbiAgcmVhZG9ubHkgc2VjdXJpdHlHcm91cHM/OiBlYzIuSVNlY3VyaXR5R3JvdXBbXTtcbiAgLyoqXG4gICAqIFVzZXIgZ3JvdXAgZm9yIGFjY2VzcyBjb250cm9sXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gdXNlciBncm91cFxuICAgKi9cbiAgcmVhZG9ubHkgdXNlckdyb3VwPzogSVVzZXJHcm91cDtcbn1cblxuLyoqXG4gKiBBdHRyaWJ1dGVzIHRoYXQgY2FuIGJlIHNwZWNpZmllZCB3aGVuIGltcG9ydGluZyBhIFNlcnZlcmxlc3NDYWNoZVxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNlcnZlcmxlc3NDYWNoZUF0dHJpYnV0ZXMge1xuICAvKipcbiAgICogVGhlIGNhY2hlIGVuZ2luZSB1c2VkIGJ5IHRoaXMgY2FjaGVcbiAgICpcbiAgICogQGRlZmF1bHQgLSBlbmdpbmUgdHlwZSBpcyB1bmtub3duXG4gICAqL1xuICByZWFkb25seSBlbmdpbmU/OiBDYWNoZUVuZ2luZTtcbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIHRoZSBzZXJ2ZXJsZXNzIGNhY2hlXG4gICAqXG4gICAqIE9uZSBvZiBgc2VydmVybGVzc0NhY2hlTmFtZWAgb3IgYHNlcnZlcmxlc3NDYWNoZUFybmAgaXMgcmVxdWlyZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gZGVyaXZlZCBmcm9tIHNlcnZlcmxlc3NDYWNoZUFyblxuICAgKi9cbiAgcmVhZG9ubHkgc2VydmVybGVzc0NhY2hlTmFtZT86IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSBBUk4gb2YgdGhlIHNlcnZlcmxlc3MgY2FjaGVcbiAgICpcbiAgICogT25lIG9mIGBzZXJ2ZXJsZXNzQ2FjaGVOYW1lYCBvciBgc2VydmVybGVzc0NhY2hlQXJuYCBpcyByZXF1aXJlZC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBkZXJpdmVkIGZyb20gc2VydmVybGVzc0NhY2hlTmFtZVxuICAgKi9cbiAgcmVhZG9ubHkgc2VydmVybGVzc0NhY2hlQXJuPzogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIEFSTnMgb2YgYmFja3VwcyByZXN0b3JlZCBpbiB0aGUgY2FjaGVcbiAgICpcbiAgICogQGRlZmF1bHQgLSBiYWNrdXBzIGFyZSB1bmtub3duXG4gICAqL1xuICByZWFkb25seSBiYWNrdXBBcm5zVG9SZXN0b3JlPzogc3RyaW5nW107XG4gIC8qKlxuICAgKiBUaGUgS01TIGtleSB1c2VkIGZvciBlbmNyeXB0aW9uXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gZW5jcnlwdGlvbiBrZXkgaXMgdW5rbm93blxuICAgKi9cbiAgcmVhZG9ubHkga21zS2V5Pzoga21zLklLZXk7XG4gIC8qKlxuICAgKiBUaGUgVlBDIHRoaXMgY2FjaGUgaXMgZGVwbG95ZWQgaW5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBWUEMgaXMgdW5rbm93blxuICAgKi9cbiAgcmVhZG9ubHkgdnBjPzogZWMyLklWcGM7XG4gIC8qKlxuICAgKiBUaGUgc3VibmV0cyB0aGlzIGNhY2hlIGlzIGRlcGxveWVkIGluXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gc3VibmV0cyBhcmUgdW5rbm93blxuICAgKi9cbiAgcmVhZG9ubHkgc3VibmV0cz86IGVjMi5JU3VibmV0W107XG4gIC8qKlxuICAgKiBUaGUgc2VjdXJpdHkgZ3JvdXBzIGFzc29jaWF0ZWQgd2l0aCB0aGlzIGNhY2hlXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gc2VjdXJpdHkgZ3JvdXBzIGFyZSB1bmtub3duXG4gICAqL1xuICByZWFkb25seSBzZWN1cml0eUdyb3Vwcz86IGVjMi5JU2VjdXJpdHlHcm91cFtdO1xuICAvKipcbiAgICogVGhlIHVzZXIgZ3JvdXAgYXNzb2NpYXRlZCB3aXRoIHRoaXMgY2FjaGVcbiAgICpcbiAgICogQGRlZmF1bHQgLSB1c2VyIGdyb3VwIGlzIHVua25vd25cbiAgICovXG4gIHJlYWRvbmx5IHVzZXJHcm91cD86IElVc2VyR3JvdXA7XG59XG5cbi8qKlxuICogQSBzZXJ2ZXJsZXNzIEVsYXN0aUNhY2hlIGNhY2hlXG4gKlxuICogQHJlc291cmNlIEFXUzo6RWxhc3RpQ2FjaGU6OlNlcnZlcmxlc3NDYWNoZVxuICovXG5AcHJvcGVydHlJbmplY3RhYmxlXG5leHBvcnQgY2xhc3MgU2VydmVybGVzc0NhY2hlIGV4dGVuZHMgU2VydmVybGVzc0NhY2hlQmFzZSB7XG4gIC8qKlxuICAgKiBVbmlxdWVseSBpZGVudGlmaWVzIHRoaXMgY2xhc3MuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IFBST1BFUlRZX0lOSkVDVElPTl9JRDogc3RyaW5nID0gJ2F3cy1jZGstbGliLmF3cy1lbGFzdGljYWNoZS5TZXJ2ZXJsZXNzQ2FjaGUnO1xuXG4gIC8qKlxuICAgKiBSZXR1cm4gd2hldGhlciB0aGUgZ2l2ZW4gb2JqZWN0IGlzIGEgYFNlcnZlcmxlc3NDYWNoZWBcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgaXNTZXJ2ZXJsZXNzQ2FjaGUoeDogYW55KTogeCBpcyBTZXJ2ZXJsZXNzQ2FjaGUge1xuICAgIHJldHVybiB4ICE9PSBudWxsICYmIHR5cGVvZiAoeCkgPT09ICdvYmplY3QnICYmIEVMQVNUSUNBQ0hFX1NFUlZFUkxFU1NDQUNIRV9TWU1CT0wgaW4geDtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbXBvcnQgYW4gZXhpc3Rpbmcgc2VydmVybGVzcyBjYWNoZSBieSBuYW1lXG4gICAqXG4gICAqIEBwYXJhbSBzY29wZSBUaGUgcGFyZW50IGNyZWF0aW5nIGNvbnN0cnVjdCAodXN1YWxseSBgdGhpc2ApXG4gICAqIEBwYXJhbSBpZCBUaGUgY29uc3RydWN0J3MgbmFtZVxuICAgKiBAcGFyYW0gc2VydmVybGVzc0NhY2hlTmFtZSBUaGUgbmFtZSBvZiB0aGUgZXhpc3Rpbmcgc2VydmVybGVzcyBjYWNoZVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBmcm9tU2VydmVybGVzc0NhY2hlTmFtZShzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBzZXJ2ZXJsZXNzQ2FjaGVOYW1lOiBzdHJpbmcpOiBJU2VydmVybGVzc0NhY2hlIHtcbiAgICByZXR1cm4gU2VydmVybGVzc0NhY2hlLmZyb21TZXJ2ZXJsZXNzQ2FjaGVBdHRyaWJ1dGVzKHNjb3BlLCBpZCwgeyBzZXJ2ZXJsZXNzQ2FjaGVOYW1lIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEltcG9ydCBhbiBleGlzdGluZyBzZXJ2ZXJsZXNzIGNhY2hlIGJ5IEFSTlxuICAgKlxuICAgKiBAcGFyYW0gc2NvcGUgVGhlIHBhcmVudCBjcmVhdGluZyBjb25zdHJ1Y3QgKHVzdWFsbHkgYHRoaXNgKVxuICAgKiBAcGFyYW0gaWQgVGhlIGNvbnN0cnVjdCdzIG5hbWVcbiAgICogQHBhcmFtIHNlcnZlcmxlc3NDYWNoZUFybiBUaGUgQVJOIG9mIHRoZSBleGlzdGluZyBzZXJ2ZXJsZXNzIGNhY2hlXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGZyb21TZXJ2ZXJsZXNzQ2FjaGVBcm4oc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgc2VydmVybGVzc0NhY2hlQXJuOiBzdHJpbmcpOiBJU2VydmVybGVzc0NhY2hlIHtcbiAgICByZXR1cm4gU2VydmVybGVzc0NhY2hlLmZyb21TZXJ2ZXJsZXNzQ2FjaGVBdHRyaWJ1dGVzKHNjb3BlLCBpZCwgeyBzZXJ2ZXJsZXNzQ2FjaGVBcm4gfSk7XG4gIH1cblxuICAvKipcbiAgICogSW1wb3J0IGFuIGV4aXN0aW5nIHNlcnZlcmxlc3MgY2FjaGUgdXNpbmcgYXR0cmlidXRlc1xuICAgKlxuICAgKiBAcGFyYW0gc2NvcGUgVGhlIHBhcmVudCBjcmVhdGluZyBjb25zdHJ1Y3QgKHVzdWFsbHkgYHRoaXNgKVxuICAgKiBAcGFyYW0gaWQgVGhlIGNvbnN0cnVjdCdzIG5hbWVcbiAgICogQHBhcmFtIGF0dHJzIEEgYFNlcnZlcmxlc3NDYWNoZUF0dHJpYnV0ZXNgIG9iamVjdFxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBmcm9tU2VydmVybGVzc0NhY2hlQXR0cmlidXRlcyhzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBhdHRyczogU2VydmVybGVzc0NhY2hlQXR0cmlidXRlcyk6IElTZXJ2ZXJsZXNzQ2FjaGUge1xuICAgIGxldCBuYW1lOiBzdHJpbmc7XG4gICAgbGV0IGFybjogc3RyaW5nO1xuICAgIGNvbnN0IHN0YWNrID0gU3RhY2sub2Yoc2NvcGUpO1xuXG4gICAgaWYgKGF0dHJzLnNlcnZlcmxlc3NDYWNoZUFybiAmJiBhdHRycy5zZXJ2ZXJsZXNzQ2FjaGVOYW1lKSB7XG4gICAgICB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKCdPbmx5IG9uZSBvZiBzZXJ2ZXJsZXNzQ2FjaGVBcm4gb3Igc2VydmVybGVzc0NhY2hlTmFtZSBjYW4gYmUgcHJvdmlkZWQuJywgc2NvcGUpO1xuICAgIH1cblxuICAgIGlmIChhdHRycy5zZXJ2ZXJsZXNzQ2FjaGVBcm4pIHtcbiAgICAgIGFybiA9IGF0dHJzLnNlcnZlcmxlc3NDYWNoZUFybjtcbiAgICAgIGNvbnN0IGV4dHJhY3RlZFNlcnZlcmxlc3NDYWNoZU5hbWUgPSBzdGFjay5zcGxpdEFybihhdHRycy5zZXJ2ZXJsZXNzQ2FjaGVBcm4sIEFybkZvcm1hdC5TTEFTSF9SRVNPVVJDRV9OQU1FKS5yZXNvdXJjZU5hbWU7XG4gICAgICBpZiAoIWV4dHJhY3RlZFNlcnZlcmxlc3NDYWNoZU5hbWUpIHtcbiAgICAgICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcignVW5hYmxlIHRvIGV4dHJhY3Qgc2VydmVybGVzcyBjYWNoZSBuYW1lIGZyb20gQVJOLicsIHNjb3BlKTtcbiAgICAgIH1cbiAgICAgIG5hbWUgPSBleHRyYWN0ZWRTZXJ2ZXJsZXNzQ2FjaGVOYW1lO1xuICAgIH0gZWxzZSBpZiAoYXR0cnMuc2VydmVybGVzc0NhY2hlTmFtZSkge1xuICAgICAgbmFtZSA9IGF0dHJzLnNlcnZlcmxlc3NDYWNoZU5hbWU7XG4gICAgICBhcm4gPSBzdGFjay5mb3JtYXRBcm4oe1xuICAgICAgICBzZXJ2aWNlOiAnZWxhc3RpY2FjaGUnLFxuICAgICAgICByZXNvdXJjZTogJ3NlcnZlcmxlc3NjYWNoZScsXG4gICAgICAgIHJlc291cmNlTmFtZTogYXR0cnMuc2VydmVybGVzc0NhY2hlTmFtZSxcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKCdPbmUgb2Ygc2VydmVybGVzc0NhY2hlTmFtZSBvciBzZXJ2ZXJsZXNzQ2FjaGVBcm4gaXMgcmVxdWlyZWQuJywgc2NvcGUpO1xuICAgIH1cblxuICAgIGNsYXNzIEltcG9ydCBleHRlbmRzIFNlcnZlcmxlc3NDYWNoZUJhc2Uge1xuICAgICAgcHVibGljIHJlYWRvbmx5IGVuZ2luZSA9IGF0dHJzLmVuZ2luZTtcbiAgICAgIHB1YmxpYyByZWFkb25seSBzZXJ2ZXJsZXNzQ2FjaGVOYW1lOiBzdHJpbmc7XG4gICAgICBwdWJsaWMgcmVhZG9ubHkgc2VydmVybGVzc0NhY2hlQXJuOiBzdHJpbmc7XG4gICAgICBwdWJsaWMgcmVhZG9ubHkgYmFja3VwQXJuc1RvUmVzdG9yZSA9IGF0dHJzLmJhY2t1cEFybnNUb1Jlc3RvcmU7XG4gICAgICBwdWJsaWMgcmVhZG9ubHkga21zS2V5ID0gYXR0cnMua21zS2V5O1xuICAgICAgcHVibGljIHJlYWRvbmx5IHZwYyA9IGF0dHJzLnZwYztcbiAgICAgIHB1YmxpYyByZWFkb25seSBzdWJuZXRzID0gYXR0cnMuc3VibmV0cztcbiAgICAgIHB1YmxpYyByZWFkb25seSBzZWN1cml0eUdyb3VwcyA9IGF0dHJzLnNlY3VyaXR5R3JvdXBzO1xuICAgICAgcHVibGljIHJlYWRvbmx5IHVzZXJHcm91cCA9IGF0dHJzLnVzZXJHcm91cDtcblxuICAgICAgcHVibGljIHJlYWRvbmx5IGNvbm5lY3Rpb25zOiBlYzIuQ29ubmVjdGlvbnM7XG5cbiAgICAgIGNvbnN0cnVjdG9yKHNlcnZlcmxlc3NDYWNoZUFybjogc3RyaW5nLCBzZXJ2ZXJsZXNzQ2FjaGVOYW1lOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIoc2NvcGUsIGlkKTtcbiAgICAgICAgdGhpcy5zZXJ2ZXJsZXNzQ2FjaGVBcm4gPSBzZXJ2ZXJsZXNzQ2FjaGVBcm47XG4gICAgICAgIHRoaXMuc2VydmVybGVzc0NhY2hlTmFtZSA9IHNlcnZlcmxlc3NDYWNoZU5hbWU7XG5cbiAgICAgICAgaWYgKHRoaXMuZW5naW5lKSB7XG4gICAgICAgICAgbGV0IGRlZmF1bHRQb3J0OiBlYzIuUG9ydDtcbiAgICAgICAgICBzd2l0Y2ggKHRoaXMuZW5naW5lKSB7XG4gICAgICAgICAgICBjYXNlIENhY2hlRW5naW5lLlZBTEtFWV9MQVRFU1Q6XG4gICAgICAgICAgICBjYXNlIENhY2hlRW5naW5lLlZBTEtFWV83OlxuICAgICAgICAgICAgY2FzZSBDYWNoZUVuZ2luZS5WQUxLRVlfODpcbiAgICAgICAgICAgIGNhc2UgQ2FjaGVFbmdpbmUuUkVESVNfTEFURVNUOlxuICAgICAgICAgICAgICAvLyBEb2N1bWVudCBzaG93aW5nIHRoZSBkZWZhdWx0IHBvcnRcbiAgICAgICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FtYXpvbkVsYXN0aUNhY2hlL2xhdGVzdC9kZy9zZXQtdXAuaHRtbCNlbGFzdGljYWNoZS1pbnN0YWxsLWdyYW50LWFjY2Vzcy1WUE5cbiAgICAgICAgICAgICAgZGVmYXVsdFBvcnQgPSBlYzIuUG9ydC50Y3AoNjM3OSk7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBDYWNoZUVuZ2luZS5NRU1DQUNIRURfTEFURVNUOlxuICAgICAgICAgICAgICAvLyBEb2N1bWVudCBzaG93aW5nIHRoZSBkZWZhdWx0IHBvcnRcbiAgICAgICAgICAgICAgLy8gaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FtYXpvbkVsYXN0aUNhY2hlL2xhdGVzdC9kZy9zZXQtdXAuaHRtbCNlbGFzdGljYWNoZS1pbnN0YWxsLWdyYW50LWFjY2Vzcy1WUE5cbiAgICAgICAgICAgICAgZGVmYXVsdFBvcnQgPSBlYzIuUG9ydC50Y3AoMTEyMTEpO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoYFVuc3VwcG9ydGVkIGNhY2hlIGVuZ2luZTogJHt0aGlzLmVuZ2luZX1gLCBzY29wZSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdGhpcy5jb25uZWN0aW9ucyA9IG5ldyBlYzIuQ29ubmVjdGlvbnMoe1xuICAgICAgICAgICAgc2VjdXJpdHlHcm91cHM6IHRoaXMuc2VjdXJpdHlHcm91cHMsXG4gICAgICAgICAgICBkZWZhdWx0UG9ydDogZGVmYXVsdFBvcnQsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5jb25uZWN0aW9ucyA9IG5ldyBlYzIuQ29ubmVjdGlvbnMoe1xuICAgICAgICAgICAgc2VjdXJpdHlHcm91cHM6IHRoaXMuc2VjdXJpdHlHcm91cHMsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IEltcG9ydChhcm4sIG5hbWUpO1xuICB9XG5cbiAgcHVibGljIHJlYWRvbmx5IGVuZ2luZT86IENhY2hlRW5naW5lO1xuICBwdWJsaWMgcmVhZG9ubHkgc2VydmVybGVzc0NhY2hlTmFtZTogc3RyaW5nO1xuICBwdWJsaWMgcmVhZG9ubHkgYmFja3VwQXJuc1RvUmVzdG9yZT86IHN0cmluZ1tdO1xuICBwdWJsaWMgcmVhZG9ubHkga21zS2V5Pzoga21zLklLZXk7XG4gIHB1YmxpYyByZWFkb25seSB2cGM/OiBlYzIuSVZwYztcbiAgcHVibGljIHJlYWRvbmx5IHN1Ym5ldHM/OiBlYzIuSVN1Ym5ldFtdO1xuICBwdWJsaWMgcmVhZG9ubHkgc2VjdXJpdHlHcm91cHM/OiBlYzIuSVNlY3VyaXR5R3JvdXBbXTtcbiAgcHVibGljIHJlYWRvbmx5IHVzZXJHcm91cD86IElVc2VyR3JvdXA7XG5cbiAgLyoqXG4gICAqIFRoZSBBUk4gb2YgdGhlIHNlcnZlcmxlc3MgY2FjaGVcbiAgICpcbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHNlcnZlcmxlc3NDYWNoZUFybjogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIGVuZHBvaW50IGFkZHJlc3Mgb2YgdGhlIHNlcnZlcmxlc3MgY2FjaGVcbiAgICpcbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHNlcnZlcmxlc3NDYWNoZUVuZHBvaW50QWRkcmVzczogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIGVuZHBvaW50IHBvcnQgb2YgdGhlIHNlcnZlcmxlc3MgY2FjaGVcbiAgICpcbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHNlcnZlcmxlc3NDYWNoZUVuZHBvaW50UG9ydDogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIHJlYWRlciBlbmRwb2ludCBhZGRyZXNzIG9mIHRoZSBzZXJ2ZXJsZXNzIGNhY2hlXG4gICAqXG4gICAqIEBhdHRyaWJ1dGVcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBzZXJ2ZXJsZXNzQ2FjaGVSZWFkZXJFbmRwb2ludEFkZHJlc3M6IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSByZWFkZXIgZW5kcG9pbnQgcG9ydCBvZiB0aGUgc2VydmVybGVzcyBjYWNoZVxuICAgKlxuICAgKiBAYXR0cmlidXRlXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgc2VydmVybGVzc0NhY2hlUmVhZGVyRW5kcG9pbnRQb3J0OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgY3VycmVudCBzdGF0dXMgb2YgdGhlIHNlcnZlcmxlc3MgY2FjaGVcbiAgICogQ2FuIGJlICdDUkVBVElORycsICdBVkFJTEFCTEUnLCAnREVMRVRJTkcnLCAnQ1JFQVRFLUZBSUxFRCcsICdNT0RJRllJTkcnXG4gICAqXG4gICAqIEBhdHRyaWJ1dGVcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBzZXJ2ZXJsZXNzQ2FjaGVTdGF0dXM6IHN0cmluZztcblxuICAvKipcbiAgICogQWNjZXNzIHRvIG5ldHdvcmsgY29ubmVjdGlvbnNcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBjb25uZWN0aW9uczogZWMyLkNvbm5lY3Rpb25zO1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBTZXJ2ZXJsZXNzQ2FjaGVQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCwge30pO1xuXG4gICAgLy8gRW5oYW5jZWQgQ0RLIEFuYWx5dGljcyBUZWxlbWV0cnlcbiAgICBhZGRDb25zdHJ1Y3RNZXRhZGF0YSh0aGlzLCBwcm9wcyk7XG5cbiAgICB0aGlzLmVuZ2luZSA9IHByb3BzLmVuZ2luZSA/PyBDYWNoZUVuZ2luZS5WQUxLRVlfTEFURVNUO1xuICAgIHRoaXMuc2VydmVybGVzc0NhY2hlTmFtZSA9IHByb3BzLnNlcnZlcmxlc3NDYWNoZU5hbWUgPz8gTGF6eS5zdHJpbmcoeyBwcm9kdWNlOiAoKSA9PiBOYW1lcy51bmlxdWVJZCh0aGlzKSB9KTtcbiAgICB0aGlzLmttc0tleSA9IHByb3BzLmttc0tleTtcbiAgICB0aGlzLnZwYyA9IHByb3BzLnZwYztcbiAgICB0aGlzLnVzZXJHcm91cCA9IHByb3BzLnVzZXJHcm91cDtcblxuICAgIHRoaXMudmFsaWRhdGVEZXNjcmlwdGlvbihwcm9wcy5kZXNjcmlwdGlvbik7XG4gICAgdGhpcy52YWxpZGF0ZURhdGFTdG9yYWdlTGltaXRzKHByb3BzLmNhY2hlVXNhZ2VMaW1pdHMpO1xuICAgIHRoaXMudmFsaWRhdGVSZXF1ZXN0UmF0ZUxpbWl0cyhwcm9wcy5jYWNoZVVzYWdlTGltaXRzKTtcbiAgICB0aGlzLnZhbGlkYXRlQmFja3VwU2V0dGluZ3MocHJvcHMuYmFja3VwKTtcbiAgICB0aGlzLnZhbGlkYXRlVXNlckdyb3VwQ29tcGF0aWJpbGl0eSh0aGlzLmVuZ2luZSwgdGhpcy51c2VyR3JvdXApO1xuXG4gICAgY29uc3Qgc3VibmV0Q29uZmlnID0gdGhpcy5jb25maWd1cmVTdWJuZXRzKHByb3BzKTtcbiAgICBjb25zdCBzdWJuZXRJZHMgPSBzdWJuZXRDb25maWcuc3VibmV0SWRzO1xuICAgIHRoaXMuc3VibmV0cyA9IHN1Ym5ldENvbmZpZy5zdWJuZXRzO1xuXG4gICAgY29uc3Qgc2VjdXJpdHlHcm91cENvbmZpZyA9IHRoaXMuY29uZmlndXJlU2VjdXJpdHlHcm91cHMocHJvcHMpO1xuICAgIGNvbnN0IHNlY3VyaXR5R3JvdXBJZHMgPSBzZWN1cml0eUdyb3VwQ29uZmlnLnNlY3VyaXR5R3JvdXBJZHM7XG4gICAgdGhpcy5zZWN1cml0eUdyb3VwcyA9IHNlY3VyaXR5R3JvdXBDb25maWcuc2VjdXJpdHlHcm91cHM7XG5cbiAgICBjb25zdCBbZW5naW5lLCB2ZXJzaW9uXSA9IHRoaXMuZW5naW5lLnNwbGl0KCdfJyk7XG5cbiAgICBjb25zdCByZXNvdXJjZSA9IG5ldyBDZm5TZXJ2ZXJsZXNzQ2FjaGUodGhpcywgJ1Jlc291cmNlJywge1xuICAgICAgZW5naW5lOiBlbmdpbmUsXG4gICAgICBtYWpvckVuZ2luZVZlcnNpb246IHZlcnNpb24sXG4gICAgICBzZXJ2ZXJsZXNzQ2FjaGVOYW1lOiB0aGlzLnNlcnZlcmxlc3NDYWNoZU5hbWUsXG4gICAgICBkZXNjcmlwdGlvbjogcHJvcHMuZGVzY3JpcHRpb24sXG4gICAgICBjYWNoZVVzYWdlTGltaXRzOiB0aGlzLnJlbmRlckNhY2hlVXNhZ2VMaW1pdHMocHJvcHMuY2FjaGVVc2FnZUxpbWl0cyksXG4gICAgICBkYWlseVNuYXBzaG90VGltZTogcHJvcHMuYmFja3VwPy5iYWNrdXBUaW1lID8gdGhpcy5mb3JtYXRCYWNrdXBUaW1lKHByb3BzLmJhY2t1cC5iYWNrdXBUaW1lKSA6IHVuZGVmaW5lZCxcbiAgICAgIHNuYXBzaG90UmV0ZW50aW9uTGltaXQ6IHByb3BzLmJhY2t1cD8uYmFja3VwUmV0ZW50aW9uTGltaXQsXG4gICAgICBmaW5hbFNuYXBzaG90TmFtZTogcHJvcHMuYmFja3VwPy5iYWNrdXBOYW1lQmVmb3JlRGVsZXRpb24sXG4gICAgICBzbmFwc2hvdEFybnNUb1Jlc3RvcmU6IHByb3BzLmJhY2t1cD8uYmFja3VwQXJuc1RvUmVzdG9yZSxcbiAgICAgIGttc0tleUlkOiBwcm9wcy5rbXNLZXk/LmtleUlkLFxuICAgICAgc3VibmV0SWRzOiBzdWJuZXRJZHMsXG4gICAgICBzZWN1cml0eUdyb3VwSWRzOiBzZWN1cml0eUdyb3VwSWRzLFxuICAgICAgdXNlckdyb3VwSWQ6IHByb3BzLnVzZXJHcm91cD8udXNlckdyb3VwTmFtZSxcbiAgICB9KTtcblxuICAgIGlmIChwcm9wcy51c2VyR3JvdXApIHtcbiAgICAgIGNvbnN0IHVzZXJHcm91cFJlc291cmNlID0gcHJvcHMudXNlckdyb3VwLm5vZGUuZmluZENoaWxkKCdSZXNvdXJjZScpIGFzIENmblVzZXJHcm91cDtcbiAgICAgIHJlc291cmNlLmFkZERlcGVuZGVuY3kodXNlckdyb3VwUmVzb3VyY2UpO1xuICAgIH1cblxuICAgIHRoaXMuYmFja3VwQXJuc1RvUmVzdG9yZSA9IHJlc291cmNlLnNuYXBzaG90QXJuc1RvUmVzdG9yZTtcbiAgICB0aGlzLnNlcnZlcmxlc3NDYWNoZUFybiA9IHJlc291cmNlLmF0dHJBcm47XG4gICAgdGhpcy5zZXJ2ZXJsZXNzQ2FjaGVFbmRwb2ludEFkZHJlc3MgPSByZXNvdXJjZS5hdHRyRW5kcG9pbnRBZGRyZXNzO1xuICAgIHRoaXMuc2VydmVybGVzc0NhY2hlRW5kcG9pbnRQb3J0ID0gcmVzb3VyY2UuYXR0ckVuZHBvaW50UG9ydDtcbiAgICB0aGlzLnNlcnZlcmxlc3NDYWNoZVJlYWRlckVuZHBvaW50QWRkcmVzcyA9IHJlc291cmNlLmF0dHJSZWFkZXJFbmRwb2ludEFkZHJlc3M7XG4gICAgdGhpcy5zZXJ2ZXJsZXNzQ2FjaGVSZWFkZXJFbmRwb2ludFBvcnQgPSByZXNvdXJjZS5hdHRyUmVhZGVyRW5kcG9pbnRQb3J0O1xuICAgIHRoaXMuc2VydmVybGVzc0NhY2hlU3RhdHVzID0gcmVzb3VyY2UuYXR0clN0YXR1cztcblxuICAgIHRoaXMuY29ubmVjdGlvbnMgPSBuZXcgZWMyLkNvbm5lY3Rpb25zKHtcbiAgICAgIHNlY3VyaXR5R3JvdXBzOiB0aGlzLnNlY3VyaXR5R3JvdXBzLFxuICAgICAgZGVmYXVsdFBvcnQ6IGVjMi5Qb3J0LnRjcChMYXp5Lm51bWJlcih7IHByb2R1Y2U6ICgpID0+IHBhcnNlSW50KHRoaXMuc2VydmVybGVzc0NhY2hlRW5kcG9pbnRQb3J0KSB9KSksXG4gICAgfSk7XG5cbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgRUxBU1RJQ0FDSEVfU0VSVkVSTEVTU0NBQ0hFX1NZTUJPTCwgeyB2YWx1ZTogdHJ1ZSB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZSBkZXNjcmlwdGlvbiBtZWV0cyBBV1MgcmVxdWlyZW1lbnRzXG4gICAqXG4gICAqIEBwYXJhbSBkZXNjcmlwdGlvbiBUaGUgZGVzY3JpcHRpb24gdG8gdmFsaWRhdGVcbiAgICovXG4gIHByaXZhdGUgdmFsaWRhdGVEZXNjcmlwdGlvbihkZXNjcmlwdGlvbj86IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICghZGVzY3JpcHRpb24gfHwgVG9rZW4uaXNVbnJlc29sdmVkKGRlc2NyaXB0aW9uKSkgcmV0dXJuO1xuXG4gICAgaWYgKGRlc2NyaXB0aW9uLmxlbmd0aCA+IDI1NSkge1xuICAgICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihgRGVzY3JpcHRpb24gbXVzdCBub3QgZXhjZWVkIDI1NSBjaGFyYWN0ZXJzLCBjdXJyZW50bHkgaGFzICR7ZGVzY3JpcHRpb24ubGVuZ3RofWAsIHRoaXMpO1xuICAgIH1cblxuICAgIGlmIChkZXNjcmlwdGlvbi5pbmNsdWRlcygnPCcpIHx8IGRlc2NyaXB0aW9uLmluY2x1ZGVzKCc+JykpIHtcbiAgICAgIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoJ0Rlc2NyaXB0aW9uIG11c3Qgbm90IGNvbnRhaW4gPCBvciA+IGNoYXJhY3RlcnMnLCB0aGlzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgZGF0YSBzdG9yYWdlIHNpemUgbGltaXRzXG4gICAqXG4gICAqIEBwYXJhbSBsaW1pdHMgVGhlIHVzYWdlIGxpbWl0cyBjb250YWluaW5nIGRhdGEgc3RvcmFnZSBzZXR0aW5nc1xuICAgKi9cbiAgcHJpdmF0ZSB2YWxpZGF0ZURhdGFTdG9yYWdlTGltaXRzKGxpbWl0cz86IENhY2hlVXNhZ2VMaW1pdHNQcm9wZXJ0eSk6IHZvaWQge1xuICAgIGlmICghbGltaXRzKSByZXR1cm47XG5cbiAgICBpZiAobGltaXRzLmRhdGFTdG9yYWdlTWluaW11bVNpemUgJiYgIWxpbWl0cy5kYXRhU3RvcmFnZU1pbmltdW1TaXplLmlzVW5yZXNvbHZlZCgpICYmXG4gICAgICAobGltaXRzLmRhdGFTdG9yYWdlTWluaW11bVNpemUudG9HaWJpYnl0ZXMoKSA8IERBVEFfU1RPUkFHRV9NSU5fR0IgfHwgbGltaXRzLmRhdGFTdG9yYWdlTWluaW11bVNpemUudG9HaWJpYnl0ZXMoKSA+IERBVEFfU1RPUkFHRV9NQVhfR0IpKSB7XG4gICAgICB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKCdEYXRhIHN0b3JhZ2UgbWluaW11bSBtdXN0IGJlIGJldHdlZW4gMSBhbmQgNTAwMCBHQi4nLCB0aGlzKTtcbiAgICB9XG4gICAgaWYgKGxpbWl0cy5kYXRhU3RvcmFnZU1heGltdW1TaXplICYmICFsaW1pdHMuZGF0YVN0b3JhZ2VNYXhpbXVtU2l6ZS5pc1VucmVzb2x2ZWQoKSAmJlxuICAgICAgKGxpbWl0cy5kYXRhU3RvcmFnZU1heGltdW1TaXplLnRvR2liaWJ5dGVzKCkgPCBEQVRBX1NUT1JBR0VfTUlOX0dCIHx8IGxpbWl0cy5kYXRhU3RvcmFnZU1heGltdW1TaXplLnRvR2liaWJ5dGVzKCkgPiBEQVRBX1NUT1JBR0VfTUFYX0dCKSkge1xuICAgICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcignRGF0YSBzdG9yYWdlIG1heGltdW0gbXVzdCBiZSBiZXR3ZWVuIDEgYW5kIDUwMDAgR0IuJywgdGhpcyk7XG4gICAgfVxuXG4gICAgaWYgKGxpbWl0cy5kYXRhU3RvcmFnZU1pbmltdW1TaXplICYmIGxpbWl0cy5kYXRhU3RvcmFnZU1heGltdW1TaXplICYmXG4gICAgICAhbGltaXRzLmRhdGFTdG9yYWdlTWluaW11bVNpemUuaXNVbnJlc29sdmVkKCkgJiYgIWxpbWl0cy5kYXRhU3RvcmFnZU1heGltdW1TaXplLmlzVW5yZXNvbHZlZCgpICYmXG4gICAgICBsaW1pdHMuZGF0YVN0b3JhZ2VNaW5pbXVtU2l6ZS50b0dpYmlieXRlcygpID4gbGltaXRzLmRhdGFTdG9yYWdlTWF4aW11bVNpemUudG9HaWJpYnl0ZXMoKSkge1xuICAgICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcignRGF0YSBzdG9yYWdlIG1pbmltdW0gY2Fubm90IGJlIGdyZWF0ZXIgdGhhbiBtYXhpbXVtJywgdGhpcyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlIHJlcXVlc3QgcmF0ZSBsaW1pdHNcbiAgICpcbiAgICogQHBhcmFtIGxpbWl0cyBUaGUgdXNhZ2UgbGltaXRzIGNvbnRhaW5pbmcgcmVxdWVzdCByYXRlIHNldHRpbmdzXG4gICAqL1xuICBwcml2YXRlIHZhbGlkYXRlUmVxdWVzdFJhdGVMaW1pdHMobGltaXRzPzogQ2FjaGVVc2FnZUxpbWl0c1Byb3BlcnR5KTogdm9pZCB7XG4gICAgaWYgKCFsaW1pdHMpIHJldHVybjtcblxuICAgIGlmIChsaW1pdHMucmVxdWVzdFJhdGVMaW1pdE1pbmltdW0gIT09IHVuZGVmaW5lZCAmJiAhVG9rZW4uaXNVbnJlc29sdmVkKGxpbWl0cy5yZXF1ZXN0UmF0ZUxpbWl0TWluaW11bSkgJiZcbiAgICAgIChsaW1pdHMucmVxdWVzdFJhdGVMaW1pdE1pbmltdW0gPCBSRVFVRVNUX1JBVEVfTUlOX0VDUFUgfHwgbGltaXRzLnJlcXVlc3RSYXRlTGltaXRNaW5pbXVtID4gUkVRVUVTVF9SQVRFX01BWF9FQ1BVKSkge1xuICAgICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcignUmVxdWVzdCByYXRlIG1pbmltdW0gbXVzdCBiZSBiZXR3ZWVuIDEsMDAwIGFuZCAxNSwwMDAsMDAwIEVDUFVzIHBlciBzZWNvbmQnLCB0aGlzKTtcbiAgICB9XG4gICAgaWYgKGxpbWl0cy5yZXF1ZXN0UmF0ZUxpbWl0TWF4aW11bSAhPT0gdW5kZWZpbmVkICYmICFUb2tlbi5pc1VucmVzb2x2ZWQobGltaXRzLnJlcXVlc3RSYXRlTGltaXRNYXhpbXVtKSAmJlxuICAgICAgKGxpbWl0cy5yZXF1ZXN0UmF0ZUxpbWl0TWF4aW11bSA8IFJFUVVFU1RfUkFURV9NSU5fRUNQVSB8fCBsaW1pdHMucmVxdWVzdFJhdGVMaW1pdE1heGltdW0gPiBSRVFVRVNUX1JBVEVfTUFYX0VDUFUpKSB7XG4gICAgICB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKCdSZXF1ZXN0IHJhdGUgbWF4aW11bSBtdXN0IGJlIGJldHdlZW4gMSwwMDAgYW5kIDE1LDAwMCwwMDAgRUNQVXMgcGVyIHNlY29uZCcsIHRoaXMpO1xuICAgIH1cblxuICAgIGlmICghVG9rZW4uaXNVbnJlc29sdmVkKGxpbWl0cy5yZXF1ZXN0UmF0ZUxpbWl0TWluaW11bSkgJiYgIVRva2VuLmlzVW5yZXNvbHZlZChsaW1pdHMucmVxdWVzdFJhdGVMaW1pdE1heGltdW0pICYmXG4gICAgICBsaW1pdHMucmVxdWVzdFJhdGVMaW1pdE1pbmltdW0gIT09IHVuZGVmaW5lZCAmJiBsaW1pdHMucmVxdWVzdFJhdGVMaW1pdE1heGltdW0gIT09IHVuZGVmaW5lZCAmJlxuICAgICAgbGltaXRzLnJlcXVlc3RSYXRlTGltaXRNaW5pbXVtID4gbGltaXRzLnJlcXVlc3RSYXRlTGltaXRNYXhpbXVtKSB7XG4gICAgICB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKCdSZXF1ZXN0IHJhdGUgbWluaW11bSBjYW5ub3QgYmUgZ3JlYXRlciB0aGFuIG1heGltdW0nLCB0aGlzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgYmFja3VwIHNldHRpbmdzIG1lZXQgQVdTIHJlcXVpcmVtZW50c1xuICAgKlxuICAgKiBAcGFyYW0gYmFja3VwIFRoZSBiYWNrdXAgc2V0dGluZ3MgdG8gdmFsaWRhdGVcbiAgICovXG4gIHByaXZhdGUgdmFsaWRhdGVCYWNrdXBTZXR0aW5ncyhiYWNrdXA/OiBCYWNrdXBTZXR0aW5ncyk6IHZvaWQge1xuICAgIGlmICghVG9rZW4uaXNVbnJlc29sdmVkKGJhY2t1cD8uYmFja3VwUmV0ZW50aW9uTGltaXQpICYmIGJhY2t1cD8uYmFja3VwUmV0ZW50aW9uTGltaXQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgY29uc3QgbGltaXQgPSBiYWNrdXAuYmFja3VwUmV0ZW50aW9uTGltaXQ7XG4gICAgICBpZiAobGltaXQgPCAxIHx8IGxpbWl0ID4gMzUpIHtcbiAgICAgICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcignQmFja3VwIHJldGVudGlvbiBsaW1pdCBtdXN0IGJlIGJldHdlZW4gMSBhbmQgMzUgZGF5cycsIHRoaXMpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICghVG9rZW4uaXNVbnJlc29sdmVkKGJhY2t1cD8uYmFja3VwTmFtZUJlZm9yZURlbGV0aW9uKSAmJiBiYWNrdXA/LmJhY2t1cE5hbWVCZWZvcmVEZWxldGlvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBjb25zdCBuYW1lID0gYmFja3VwLmJhY2t1cE5hbWVCZWZvcmVEZWxldGlvbjtcblxuICAgICAgaWYgKCEvXlthLXpBLVpdLy50ZXN0KG5hbWUpKSB7XG4gICAgICAgIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoJ0ZpbmFsIGJhY2t1cCBuYW1lIG11c3QgYmVnaW4gd2l0aCBhIGxldHRlcicsIHRoaXMpO1xuICAgICAgfVxuXG4gICAgICBpZiAoIS9eW2EtekEtWjAtOS1dKyQvLnRlc3QobmFtZSkpIHtcbiAgICAgICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcignRmluYWwgYmFja3VwIG5hbWUgbXVzdCBjb250YWluIG9ubHkgQVNDSUkgbGV0dGVycywgZGlnaXRzLCBhbmQgaHlwaGVucycsIHRoaXMpO1xuICAgICAgfVxuXG4gICAgICBpZiAobmFtZS5lbmRzV2l0aCgnLScpKSB7XG4gICAgICAgIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoJ0ZpbmFsIGJhY2t1cCBuYW1lIG11c3Qgbm90IGVuZCB3aXRoIGEgaHlwaGVuJywgdGhpcyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChuYW1lLmluY2x1ZGVzKCctLScpKSB7XG4gICAgICAgIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoJ0ZpbmFsIGJhY2t1cCBuYW1lIG11c3Qgbm90IGNvbnRhaW4gdHdvIGNvbnNlY3V0aXZlIGh5cGhlbnMnLCB0aGlzKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgdXNlciBncm91cCBjb21wYXRpYmlsaXR5IHdpdGggY2FjaGUgZW5naW5lXG4gICAqXG4gICAqIEBwYXJhbSBlbmdpbmUgVGhlIGNhY2hlIGVuZ2luZVxuICAgKiBAcGFyYW0gdXNlckdyb3VwIFRoZSB1c2VyIGdyb3VwIHRvIHZhbGlkYXRlXG4gICAqL1xuICBwcml2YXRlIHZhbGlkYXRlVXNlckdyb3VwQ29tcGF0aWJpbGl0eShlbmdpbmU6IENhY2hlRW5naW5lLCB1c2VyR3JvdXA/OiBJVXNlckdyb3VwKTogdm9pZCB7XG4gICAgaWYgKCF1c2VyR3JvdXApIHJldHVybjtcblxuICAgIGlmIChlbmdpbmUgPT09IENhY2hlRW5naW5lLk1FTUNBQ0hFRF9MQVRFU1QpIHtcbiAgICAgIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoJ1VzZXIgZ3JvdXBzIGNhbm5vdCBiZSB1c2VkIHdpdGggTWVtY2FjaGVkIGVuZ2luZXMuIE9ubHkgUmVkaXMgYW5kIFZhbGtleSBlbmdpbmVzIHN1cHBvcnQgdXNlciBncm91cHMuJywgdGhpcyk7XG4gICAgfVxuXG4gICAgaWYgKGVuZ2luZSA9PT0gQ2FjaGVFbmdpbmUuUkVESVNfTEFURVNUICYmIHVzZXJHcm91cC5lbmdpbmUgIT09IFVzZXJFbmdpbmUuUkVESVMpIHtcbiAgICAgIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoJ1JlZGlzIGNhY2hlIGNhbiBvbmx5IHVzZSBSZWRpcyB1c2VyIGdyb3Vwcy4nLCB0aGlzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVuZGVyIGNhY2hlIHVzYWdlIGxpbWl0cyBmb3IgQ2xvdWRGb3JtYXRpb25cbiAgICpcbiAgICogQHBhcmFtIGxpbWl0cyBUaGUgdXNhZ2UgbGltaXRzIHRvIHJlbmRlclxuICAgKiBAcmV0dXJucyBDbG91ZEZvcm1hdGlvbi1jb21wYXRpYmxlIHVzYWdlIGxpbWl0cyBvYmplY3Qgb3IgdW5kZWZpbmVkXG4gICAqL1xuICBwcml2YXRlIHJlbmRlckNhY2hlVXNhZ2VMaW1pdHMobGltaXRzPzogQ2FjaGVVc2FnZUxpbWl0c1Byb3BlcnR5KTogYW55IHtcbiAgICBpZiAoIWxpbWl0cykgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAgIGNvbnN0IGNhY2hlVXNhZ2VMaW1pdHM6IGFueSA9IHt9O1xuXG4gICAgaWYgKGxpbWl0cy5kYXRhU3RvcmFnZU1pbmltdW1TaXplICE9PSB1bmRlZmluZWQgfHwgbGltaXRzLmRhdGFTdG9yYWdlTWF4aW11bVNpemUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgY2FjaGVVc2FnZUxpbWl0cy5kYXRhU3RvcmFnZSA9IHtcbiAgICAgICAgdW5pdDogRGF0YVN0b3JhZ2VVbml0LkdJR0FCWVRFUyxcbiAgICAgICAgLi4uKGxpbWl0cy5kYXRhU3RvcmFnZU1pbmltdW1TaXplICE9PSB1bmRlZmluZWQgJiYgeyBtaW5pbXVtOiBsaW1pdHMuZGF0YVN0b3JhZ2VNaW5pbXVtU2l6ZS50b0dpYmlieXRlcygpIH0pLFxuICAgICAgICAuLi4obGltaXRzLmRhdGFTdG9yYWdlTWF4aW11bVNpemUgIT09IHVuZGVmaW5lZCAmJiB7IG1heGltdW06IGxpbWl0cy5kYXRhU3RvcmFnZU1heGltdW1TaXplLnRvR2liaWJ5dGVzKCkgfSksXG4gICAgICB9O1xuICAgIH1cblxuICAgIGlmIChsaW1pdHMucmVxdWVzdFJhdGVMaW1pdE1pbmltdW0gIT09IHVuZGVmaW5lZCB8fCBsaW1pdHMucmVxdWVzdFJhdGVMaW1pdE1heGltdW0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgY2FjaGVVc2FnZUxpbWl0cy5lY3B1UGVyU2Vjb25kID0ge1xuICAgICAgICAuLi4obGltaXRzLnJlcXVlc3RSYXRlTGltaXRNaW5pbXVtICE9PSB1bmRlZmluZWQgJiYgeyBtaW5pbXVtOiBsaW1pdHMucmVxdWVzdFJhdGVMaW1pdE1pbmltdW0gfSksXG4gICAgICAgIC4uLihsaW1pdHMucmVxdWVzdFJhdGVMaW1pdE1heGltdW0gIT09IHVuZGVmaW5lZCAmJiB7IG1heGltdW06IGxpbWl0cy5yZXF1ZXN0UmF0ZUxpbWl0TWF4aW11bSB9KSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKGNhY2hlVXNhZ2VMaW1pdHMpLmxlbmd0aCA+IDAgPyBjYWNoZVVzYWdlTGltaXRzIDogdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbmZpZ3VyZSBzdWJuZXRzIGZvciB0aGUgY2FjaGVcbiAgICpcbiAgICogQHBhcmFtIHByb3BzIFRoZSBTZXJ2ZXJsZXNzQ2FjaGUgcHJvcGVydGllc1xuICAgKiBAcmV0dXJucyBPYmplY3QgY29udGFpbmluZyBzdWJuZXQgSURzIGFuZCBzdWJuZXQgb2JqZWN0c1xuICAgKi9cbiAgcHJpdmF0ZSBjb25maWd1cmVTdWJuZXRzKHByb3BzOiBTZXJ2ZXJsZXNzQ2FjaGVQcm9wcyk6IHsgc3VibmV0SWRzOiBzdHJpbmdbXSB8IHVuZGVmaW5lZDsgc3VibmV0czogZWMyLklTdWJuZXRbXSB8IHVuZGVmaW5lZCB9IHtcbiAgICBsZXQgc2VsZWN0ZWRTdWJuZXRzO1xuICAgIGlmIChwcm9wcy52cGNTdWJuZXRzKSB7XG4gICAgICBzZWxlY3RlZFN1Ym5ldHMgPSBwcm9wcy52cGMuc2VsZWN0U3VibmV0cyhwcm9wcy52cGNTdWJuZXRzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc2VsZWN0ZWRTdWJuZXRzID0gcHJvcHMudnBjLnNlbGVjdFN1Ym5ldHMoe1xuICAgICAgICBzdWJuZXRUeXBlOiBlYzIuU3VibmV0VHlwZS5QUklWQVRFX1dJVEhfRUdSRVNTLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHN1Ym5ldElkczogc2VsZWN0ZWRTdWJuZXRzLnN1Ym5ldElkcy5sZW5ndGggPiAwID8gc2VsZWN0ZWRTdWJuZXRzLnN1Ym5ldElkcyA6IHVuZGVmaW5lZCxcbiAgICAgIHN1Ym5ldHM6IHNlbGVjdGVkU3VibmV0cy5zdWJuZXRzLmxlbmd0aCA+IDAgPyBzZWxlY3RlZFN1Ym5ldHMuc3VibmV0cyA6IHVuZGVmaW5lZCxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIENvbmZpZ3VyZSBzZWN1cml0eSBncm91cHMgZm9yIHRoZSBjYWNoZVxuICAgKlxuICAgKiBAcGFyYW0gcHJvcHMgVGhlIFNlcnZlcmxlc3NDYWNoZSBwcm9wZXJ0aWVzXG4gICAqIEByZXR1cm5zIE9iamVjdCBjb250YWluaW5nIHNlY3VyaXR5IGdyb3VwIElEcyBhbmQgc2VjdXJpdHkgZ3JvdXAgb2JqZWN0c1xuICAgKi9cbiAgcHJpdmF0ZSBjb25maWd1cmVTZWN1cml0eUdyb3Vwcyhwcm9wczogU2VydmVybGVzc0NhY2hlUHJvcHMpOiB7IHNlY3VyaXR5R3JvdXBJZHM6IHN0cmluZ1tdOyBzZWN1cml0eUdyb3VwczogZWMyLklTZWN1cml0eUdyb3VwW10gfSB7XG4gICAgaWYgKHByb3BzLnNlY3VyaXR5R3JvdXBzICYmIHByb3BzLnNlY3VyaXR5R3JvdXBzLmxlbmd0aCA+IDApIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHNlY3VyaXR5R3JvdXBJZHM6IHByb3BzLnNlY3VyaXR5R3JvdXBzLm1hcChzZyA9PiBzZy5zZWN1cml0eUdyb3VwSWQpLFxuICAgICAgICBzZWN1cml0eUdyb3VwczogcHJvcHMuc2VjdXJpdHlHcm91cHMsXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBuZXdTZWN1cml0eUdyb3VwID0gbmV3IGVjMi5TZWN1cml0eUdyb3VwKHRoaXMsICdTZWN1cml0eUdyb3VwJywge1xuICAgICAgICBkZXNjcmlwdGlvbjogYFNlY3VyaXR5IGdyb3VwIGZvciAke3RoaXMubm9kZS5pZH0gY2FjaGUuYCxcbiAgICAgICAgdnBjOiBwcm9wcy52cGMsXG4gICAgICB9KTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHNlY3VyaXR5R3JvdXBJZHM6IFtuZXdTZWN1cml0eUdyb3VwLnNlY3VyaXR5R3JvdXBJZF0sXG4gICAgICAgIHNlY3VyaXR5R3JvdXBzOiBbbmV3U2VjdXJpdHlHcm91cF0sXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBGb3JtYXQgc2NoZWR1bGUgdG8gSEg6TU0gZm9ybWF0IGZvciBkYWlseSBiYWNrdXBzXG4gICAqXG4gICAqIEBwYXJhbSBzY2hlZHVsZSBUaGUgc2NoZWR1bGUgdG8gZm9ybWF0XG4gICAqIEByZXR1cm5zIFRpbWUgc3RyaW5nIGluIEhIOk1NIGZvcm1hdFxuICAgKi9cbiAgcHJpdmF0ZSBmb3JtYXRCYWNrdXBUaW1lKHNjaGVkdWxlOiBldmVudHMuU2NoZWR1bGUpOiBzdHJpbmcge1xuICAgIGNvbnN0IFdJTERfQ0FSRCA9ICcqJztcbiAgICBjb25zdCBbXG4gICAgICBtaW51dGVFeHByZXNzaW9uLCBob3VyRXhwcmVzc2lvbixcbiAgICAgIGRheUV4cHJlc3Npb24sIG1vbnRoRXhwcmVzc2lvbixcbiAgICAgIHdlZWtEYXlFeHByZXNzaW9uLCB5ZWFyRXhwcmVzc2lvbixcbiAgICBdID0gc2NoZWR1bGUuZXhwcmVzc2lvblN0cmluZy5zdWJzdHIoNSkuc2xpY2UoMCwgLTEpLnNwbGl0KCcgJyk7XG5cbiAgICBpZiAoZGF5RXhwcmVzc2lvbiAhPSBXSUxEX0NBUkQgfHwgbW9udGhFeHByZXNzaW9uICE9IFdJTERfQ0FSRCB8fCB5ZWFyRXhwcmVzc2lvbiAhPSBXSUxEX0NBUkQgfHwgd2Vla0RheUV4cHJlc3Npb24gIT0gJz8nKSB7XG4gICAgICB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKCdGb3Igbm93LCBvbmx5IGRhaWx5IGJhY2t1cCB0aW1lIGlzIGF2YWlsYWJsZSAoc3VwcG9ydHMganVzdCBob3VyIGFuZCBtaW51dGUpLiBEYXksIG1vbnRoLCB5ZWFyLCBhbmQgd2Vla0RheSBhcmUgbm90IGFsbG93ZWQnLCB0aGlzKTtcbiAgICB9XG5cbiAgICBjb25zdCBob3VyID0gaG91ckV4cHJlc3Npb24gPT0gV0lMRF9DQVJEID8gJzAnIDogaG91ckV4cHJlc3Npb247XG4gICAgY29uc3QgbWludXRlID0gbWludXRlRXhwcmVzc2lvbiA9PSBXSUxEX0NBUkQgPyAnMCcgOiBtaW51dGVFeHByZXNzaW9uO1xuXG4gICAgcmV0dXJuIGAke2hvdXIucGFkU3RhcnQoMiwgJzAnKX06JHttaW51dGUucGFkU3RhcnQoMiwgJzAnKX1gO1xuICB9XG59XG4iXX0=