UNPKG

125 kBJavaScriptView Raw
1"use strict";
2var _a;
3Object.defineProperty(exports, "__esModule", { value: true });
4exports.verifyCodeConfig = exports.Function = exports.Tracing = void 0;
5const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
6const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
7const cloudwatch = require("@aws-cdk/aws-cloudwatch");
8const aws_codeguruprofiler_1 = require("@aws-cdk/aws-codeguruprofiler");
9const ec2 = require("@aws-cdk/aws-ec2");
10const iam = require("@aws-cdk/aws-iam");
11const logs = require("@aws-cdk/aws-logs");
12const sqs = require("@aws-cdk/aws-sqs");
13const core_1 = require("@aws-cdk/core");
14const architecture_1 = require("./architecture");
15const function_base_1 = require("./function-base");
16const function_hash_1 = require("./function-hash");
17const handler_1 = require("./handler");
18const lambda_version_1 = require("./lambda-version");
19const lambda_generated_1 = require("./lambda.generated");
20const layers_1 = require("./layers");
21const runtime_1 = require("./runtime");
22/**
23 * X-Ray Tracing Modes (https://docs.aws.amazon.com/lambda/latest/dg/API_TracingConfig.html)
24 */
25var Tracing;
26(function (Tracing) {
27 /**
28 * Lambda will respect any tracing header it receives from an upstream service.
29 * If no tracing header is received, Lambda will call X-Ray for a tracing decision.
30 */
31 Tracing["ACTIVE"] = "Active";
32 /**
33 * Lambda will only trace the request from an upstream service
34 * if it contains a tracing header with "sampled=1"
35 */
36 Tracing["PASS_THROUGH"] = "PassThrough";
37 /**
38 * Lambda will not trace any request.
39 */
40 Tracing["DISABLED"] = "Disabled";
41})(Tracing = exports.Tracing || (exports.Tracing = {}));
42/**
43 * Deploys a file from inside the construct library as a function.
44 *
45 * The supplied file is subject to the 4096 bytes limit of being embedded in a
46 * CloudFormation template.
47 *
48 * The construct includes an associated role with the lambda.
49 *
50 * This construct does not yet reproduce all features from the underlying resource
51 * library.
52 */
53class Function extends function_base_1.FunctionBase {
54 constructor(scope, id, props) {
55 var _b, _c, _d, _e, _f, _g, _h, _j, _k;
56 super(scope, id, {
57 physicalName: props.functionName,
58 });
59 this.permissionsNode = this.node;
60 this.canCreatePermissions = true;
61 this.layers = [];
62 /**
63 * Environment variables for this function
64 */
65 this.environment = {};
66 try {
67 jsiiDeprecationWarnings._aws_cdk_aws_lambda_FunctionProps(props);
68 }
69 catch (error) {
70 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
71 Error.captureStackTrace(error, this.constructor);
72 }
73 throw error;
74 }
75 if (props.functionName && !core_1.Token.isUnresolved(props.functionName)) {
76 if (props.functionName.length > 64) {
77 throw new Error(`Function name can not be longer than 64 characters but has ${props.functionName.length} characters.`);
78 }
79 if (!/^[a-zA-Z0-9-_]+$/.test(props.functionName)) {
80 throw new Error(`Function name ${props.functionName} can contain only letters, numbers, hyphens, or underscores with no spaces.`);
81 }
82 }
83 const managedPolicies = new Array();
84 // the arn is in the form of - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
85 managedPolicies.push(iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole'));
86 if (props.vpc) {
87 // Policy that will have ENI creation permissions
88 managedPolicies.push(iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaVPCAccessExecutionRole'));
89 }
90 this.role = props.role || new iam.Role(this, 'ServiceRole', {
91 assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
92 managedPolicies,
93 });
94 this.grantPrincipal = this.role;
95 // add additional managed policies when necessary
96 if (props.filesystem) {
97 const config = props.filesystem.config;
98 if (config.policies) {
99 config.policies.forEach(p => {
100 var _b;
101 (_b = this.role) === null || _b === void 0 ? void 0 : _b.addToPrincipalPolicy(p);
102 });
103 }
104 }
105 for (const statement of (props.initialPolicy || [])) {
106 this.role.addToPrincipalPolicy(statement);
107 }
108 const code = props.code.bind(this);
109 verifyCodeConfig(code, props);
110 let profilingGroupEnvironmentVariables = {};
111 if (props.profilingGroup && props.profiling !== false) {
112 this.validateProfiling(props);
113 props.profilingGroup.grantPublish(this.role);
114 profilingGroupEnvironmentVariables = {
115 AWS_CODEGURU_PROFILER_GROUP_ARN: core_1.Stack.of(scope).formatArn({
116 service: 'codeguru-profiler',
117 resource: 'profilingGroup',
118 resourceName: props.profilingGroup.profilingGroupName,
119 }),
120 AWS_CODEGURU_PROFILER_ENABLED: 'TRUE',
121 };
122 }
123 else if (props.profiling) {
124 this.validateProfiling(props);
125 const profilingGroup = new aws_codeguruprofiler_1.ProfilingGroup(this, 'ProfilingGroup', {
126 computePlatform: aws_codeguruprofiler_1.ComputePlatform.AWS_LAMBDA,
127 });
128 profilingGroup.grantPublish(this.role);
129 profilingGroupEnvironmentVariables = {
130 AWS_CODEGURU_PROFILER_GROUP_ARN: profilingGroup.profilingGroupArn,
131 AWS_CODEGURU_PROFILER_ENABLED: 'TRUE',
132 };
133 }
134 const env = { ...profilingGroupEnvironmentVariables, ...props.environment };
135 for (const [key, value] of Object.entries(env)) {
136 this.addEnvironment(key, value);
137 }
138 // DLQ can be either sns.ITopic or sqs.IQueue
139 const dlqTopicOrQueue = this.buildDeadLetterQueue(props);
140 if (dlqTopicOrQueue !== undefined) {
141 if (this.isQueue(dlqTopicOrQueue)) {
142 this.deadLetterQueue = dlqTopicOrQueue;
143 }
144 else {
145 this.deadLetterTopic = dlqTopicOrQueue;
146 }
147 }
148 let fileSystemConfigs = undefined;
149 if (props.filesystem) {
150 fileSystemConfigs = [{
151 arn: props.filesystem.config.arn,
152 localMountPath: props.filesystem.config.localMountPath,
153 }];
154 }
155 if (props.architecture && props.architectures !== undefined) {
156 throw new Error('Either architecture or architectures must be specified but not both.');
157 }
158 if (props.architectures && props.architectures.length > 1) {
159 throw new Error('Only one architecture must be specified.');
160 }
161 this._architecture = (_b = props.architecture) !== null && _b !== void 0 ? _b : (props.architectures && props.architectures[0]);
162 if (props.ephemeralStorageSize && !props.ephemeralStorageSize.isUnresolved()
163 && (props.ephemeralStorageSize.toMebibytes() < 512 || props.ephemeralStorageSize.toMebibytes() > 10240)) {
164 throw new Error(`Ephemeral storage size must be between 512 and 10240 MB, received ${props.ephemeralStorageSize}.`);
165 }
166 const resource = new lambda_generated_1.CfnFunction(this, 'Resource', {
167 functionName: this.physicalName,
168 description: props.description,
169 code: {
170 s3Bucket: code.s3Location && code.s3Location.bucketName,
171 s3Key: code.s3Location && code.s3Location.objectKey,
172 s3ObjectVersion: code.s3Location && code.s3Location.objectVersion,
173 zipFile: code.inlineCode,
174 imageUri: (_c = code.image) === null || _c === void 0 ? void 0 : _c.imageUri,
175 },
176 layers: core_1.Lazy.list({ produce: () => this.layers.map(layer => layer.layerVersionArn) }, { omitEmpty: true }),
177 handler: props.handler === handler_1.Handler.FROM_IMAGE ? undefined : props.handler,
178 timeout: props.timeout && props.timeout.toSeconds(),
179 packageType: props.runtime === runtime_1.Runtime.FROM_IMAGE ? 'Image' : undefined,
180 runtime: props.runtime === runtime_1.Runtime.FROM_IMAGE ? undefined : props.runtime.name,
181 role: this.role.roleArn,
182 // Uncached because calling '_checkEdgeCompatibility', which gets called in the resolve of another
183 // Token, actually *modifies* the 'environment' map.
184 environment: core_1.Lazy.uncachedAny({ produce: () => this.renderEnvironment() }),
185 memorySize: props.memorySize,
186 ephemeralStorage: props.ephemeralStorageSize ? {
187 size: props.ephemeralStorageSize.toMebibytes(),
188 } : undefined,
189 vpcConfig: this.configureVpc(props),
190 deadLetterConfig: this.buildDeadLetterConfig(dlqTopicOrQueue),
191 tracingConfig: this.buildTracingConfig(props),
192 reservedConcurrentExecutions: props.reservedConcurrentExecutions,
193 imageConfig: undefinedIfNoKeys({
194 command: (_d = code.image) === null || _d === void 0 ? void 0 : _d.cmd,
195 entryPoint: (_e = code.image) === null || _e === void 0 ? void 0 : _e.entrypoint,
196 workingDirectory: (_f = code.image) === null || _f === void 0 ? void 0 : _f.workingDirectory,
197 }),
198 kmsKeyArn: (_g = props.environmentEncryption) === null || _g === void 0 ? void 0 : _g.keyArn,
199 fileSystemConfigs,
200 codeSigningConfigArn: (_h = props.codeSigningConfig) === null || _h === void 0 ? void 0 : _h.codeSigningConfigArn,
201 architectures: this._architecture ? [this._architecture.name] : undefined,
202 });
203 resource.node.addDependency(this.role);
204 this.functionName = this.getResourceNameAttribute(resource.ref);
205 this.functionArn = this.getResourceArnAttribute(resource.attrArn, {
206 service: 'lambda',
207 resource: 'function',
208 resourceName: this.physicalName,
209 arnFormat: core_1.ArnFormat.COLON_RESOURCE_NAME,
210 });
211 this.runtime = props.runtime;
212 this.timeout = props.timeout;
213 this.architecture = (_j = props.architecture) !== null && _j !== void 0 ? _j : architecture_1.Architecture.X86_64;
214 if (props.layers) {
215 if (props.runtime === runtime_1.Runtime.FROM_IMAGE) {
216 throw new Error('Layers are not supported for container image functions');
217 }
218 this.addLayers(...props.layers);
219 }
220 for (const event of props.events || []) {
221 this.addEventSource(event);
222 }
223 // Log retention
224 if (props.logRetention) {
225 const logRetention = new logs.LogRetention(this, 'LogRetention', {
226 logGroupName: `/aws/lambda/${this.functionName}`,
227 retention: props.logRetention,
228 role: props.logRetentionRole,
229 logRetentionRetryOptions: props.logRetentionRetryOptions,
230 });
231 this._logGroup = logs.LogGroup.fromLogGroupArn(this, 'LogGroup', logRetention.logGroupArn);
232 }
233 props.code.bindToResource(resource);
234 // Event Invoke Config
235 if (props.onFailure || props.onSuccess || props.maxEventAge || props.retryAttempts !== undefined) {
236 this.configureAsyncInvoke({
237 onFailure: props.onFailure,
238 onSuccess: props.onSuccess,
239 maxEventAge: props.maxEventAge,
240 retryAttempts: props.retryAttempts,
241 });
242 }
243 this.currentVersionOptions = props.currentVersionOptions;
244 if (props.filesystem) {
245 if (!props.vpc) {
246 throw new Error('Cannot configure \'filesystem\' without configuring a VPC.');
247 }
248 const config = props.filesystem.config;
249 if (config.dependency) {
250 this.node.addDependency(...config.dependency);
251 }
252 // There could be a race if the Lambda is used in a CustomResource. It is possible for the Lambda to
253 // fail to attach to a given FileSystem if we do not have a dependency on the SecurityGroup ingress/egress
254 // rules that were created between this Lambda's SG & the Filesystem SG.
255 this.connections.securityGroups.forEach(sg => {
256 sg.node.findAll().forEach(child => {
257 if (child instanceof core_1.CfnResource && child.cfnResourceType === 'AWS::EC2::SecurityGroupEgress') {
258 resource.node.addDependency(child);
259 }
260 });
261 });
262 (_k = config.connections) === null || _k === void 0 ? void 0 : _k.securityGroups.forEach(sg => {
263 sg.node.findAll().forEach(child => {
264 if (child instanceof core_1.CfnResource && child.cfnResourceType === 'AWS::EC2::SecurityGroupIngress') {
265 resource.node.addDependency(child);
266 }
267 });
268 });
269 }
270 // Configure Lambda insights
271 this.configureLambdaInsights(props);
272 }
273 /**
274 * Returns a `lambda.Version` which represents the current version of this
275 * Lambda function. A new version will be created every time the function's
276 * configuration changes.
277 *
278 * You can specify options for this version using the `currentVersionOptions`
279 * prop when initializing the `lambda.Function`.
280 */
281 get currentVersion() {
282 if (this._currentVersion) {
283 return this._currentVersion;
284 }
285 if (this._warnIfCurrentVersionCalled) {
286 this.warnInvokeFunctionPermissions(this);
287 }
288 ;
289 this._currentVersion = new lambda_version_1.Version(this, 'CurrentVersion', {
290 lambda: this,
291 ...this.currentVersionOptions,
292 });
293 // override the version's logical ID with a lazy string which includes the
294 // hash of the function itself, so a new version resource is created when
295 // the function configuration changes.
296 const cfn = this._currentVersion.node.defaultChild;
297 const originalLogicalId = this.stack.resolve(cfn.logicalId);
298 cfn.overrideLogicalId(core_1.Lazy.uncachedString({
299 produce: () => {
300 const hash = function_hash_1.calculateFunctionHash(this);
301 const logicalId = function_hash_1.trimFromStart(originalLogicalId, 255 - 32);
302 return `${logicalId}${hash}`;
303 },
304 }));
305 return this._currentVersion;
306 }
307 get resourceArnsForGrantInvoke() {
308 return [this.functionArn, `${this.functionArn}:*`];
309 }
310 /**
311 * Record whether specific properties in the `AWS::Lambda::Function` resource should
312 * also be associated to the Version resource.
313 * See 'currentVersion' section in the module README for more details.
314 * @param propertyName The property to classify
315 * @param locked whether the property should be associated to the version or not.
316 */
317 static classifyVersionProperty(propertyName, locked) {
318 this._VER_PROPS[propertyName] = locked;
319 }
320 /**
321 * Import a lambda function into the CDK using its name
322 */
323 static fromFunctionName(scope, id, functionName) {
324 return Function.fromFunctionAttributes(scope, id, {
325 functionArn: core_1.Stack.of(scope).formatArn({
326 service: 'lambda',
327 resource: 'function',
328 resourceName: functionName,
329 arnFormat: core_1.ArnFormat.COLON_RESOURCE_NAME,
330 }),
331 });
332 }
333 /**
334 * Import a lambda function into the CDK using its ARN
335 */
336 static fromFunctionArn(scope, id, functionArn) {
337 return Function.fromFunctionAttributes(scope, id, { functionArn });
338 }
339 /**
340 * Creates a Lambda function object which represents a function not defined
341 * within this stack.
342 *
343 * @param scope The parent construct
344 * @param id The name of the lambda construct
345 * @param attrs the attributes of the function to import
346 */
347 static fromFunctionAttributes(scope, id, attrs) {
348 try {
349 jsiiDeprecationWarnings._aws_cdk_aws_lambda_FunctionAttributes(attrs);
350 }
351 catch (error) {
352 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
353 Error.captureStackTrace(error, this.fromFunctionAttributes);
354 }
355 throw error;
356 }
357 const functionArn = attrs.functionArn;
358 const functionName = extractNameFromArn(attrs.functionArn);
359 const role = attrs.role;
360 class Import extends function_base_1.FunctionBase {
361 constructor(s, i) {
362 var _b, _c, _d;
363 super(s, i, {
364 environmentFromArn: functionArn,
365 });
366 this.functionName = functionName;
367 this.functionArn = functionArn;
368 this.role = role;
369 this.permissionsNode = this.node;
370 this.architecture = (_b = attrs.architecture) !== null && _b !== void 0 ? _b : architecture_1.Architecture.X86_64;
371 this.resourceArnsForGrantInvoke = [this.functionArn, `${this.functionArn}:*`];
372 this.canCreatePermissions = (_c = attrs.sameEnvironment) !== null && _c !== void 0 ? _c : this._isStackAccount();
373 this._skipPermissions = (_d = attrs.skipPermissions) !== null && _d !== void 0 ? _d : false;
374 this.grantPrincipal = role || new iam.UnknownPrincipal({ resource: this });
375 if (attrs.securityGroup) {
376 this._connections = new ec2.Connections({
377 securityGroups: [attrs.securityGroup],
378 });
379 }
380 else if (attrs.securityGroupId) {
381 this._connections = new ec2.Connections({
382 securityGroups: [ec2.SecurityGroup.fromSecurityGroupId(scope, 'SecurityGroup', attrs.securityGroupId)],
383 });
384 }
385 }
386 }
387 return new Import(scope, id);
388 }
389 /**
390 * Return the given named metric for this Lambda
391 */
392 static metricAll(metricName, props) {
393 return new cloudwatch.Metric({
394 namespace: 'AWS/Lambda',
395 metricName,
396 ...props,
397 });
398 }
399 /**
400 * Metric for the number of Errors executing all Lambdas
401 *
402 * @default sum over 5 minutes
403 */
404 static metricAllErrors(props) {
405 return this.metricAll('Errors', { statistic: 'sum', ...props });
406 }
407 /**
408 * Metric for the Duration executing all Lambdas
409 *
410 * @default average over 5 minutes
411 */
412 static metricAllDuration(props) {
413 return this.metricAll('Duration', props);
414 }
415 /**
416 * Metric for the number of invocations of all Lambdas
417 *
418 * @default sum over 5 minutes
419 */
420 static metricAllInvocations(props) {
421 return this.metricAll('Invocations', { statistic: 'sum', ...props });
422 }
423 /**
424 * Metric for the number of throttled invocations of all Lambdas
425 *
426 * @default sum over 5 minutes
427 */
428 static metricAllThrottles(props) {
429 return this.metricAll('Throttles', { statistic: 'sum', ...props });
430 }
431 /**
432 * Metric for the number of concurrent executions across all Lambdas
433 *
434 * @default max over 5 minutes
435 */
436 static metricAllConcurrentExecutions(props) {
437 // Mini-FAQ: why max? This metric is a gauge that is emitted every
438 // minute, so either max or avg or a percentile make sense (but sum
439 // doesn't). Max is more sensitive to spiky load changes which is
440 // probably what you're interested in if you're looking at this metric
441 // (Load spikes may lead to concurrent execution errors that would
442 // otherwise not be visible in the avg)
443 return this.metricAll('ConcurrentExecutions', { statistic: 'max', ...props });
444 }
445 /**
446 * Metric for the number of unreserved concurrent executions across all Lambdas
447 *
448 * @default max over 5 minutes
449 */
450 static metricAllUnreservedConcurrentExecutions(props) {
451 return this.metricAll('UnreservedConcurrentExecutions', { statistic: 'max', ...props });
452 }
453 /**
454 * Adds an environment variable to this Lambda function.
455 * If this is a ref to a Lambda function, this operation results in a no-op.
456 * @param key The environment variable key.
457 * @param value The environment variable's value.
458 * @param options Environment variable options.
459 */
460 addEnvironment(key, value, options) {
461 try {
462 jsiiDeprecationWarnings._aws_cdk_aws_lambda_EnvironmentOptions(options);
463 }
464 catch (error) {
465 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
466 Error.captureStackTrace(error, this.addEnvironment);
467 }
468 throw error;
469 }
470 this.environment[key] = { value, ...options };
471 return this;
472 }
473 /**
474 * Adds one or more Lambda Layers to this Lambda function.
475 *
476 * @param layers the layers to be added.
477 *
478 * @throws if there are already 5 layers on this function, or the layer is incompatible with this function's runtime.
479 */
480 addLayers(...layers) {
481 try {
482 jsiiDeprecationWarnings._aws_cdk_aws_lambda_ILayerVersion(layers);
483 }
484 catch (error) {
485 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
486 Error.captureStackTrace(error, this.addLayers);
487 }
488 throw error;
489 }
490 for (const layer of layers) {
491 if (this.layers.length === 5) {
492 throw new Error('Unable to add layer: this lambda function already uses 5 layers.');
493 }
494 if (layer.compatibleRuntimes && !layer.compatibleRuntimes.find(runtime => runtime.runtimeEquals(this.runtime))) {
495 const runtimes = layer.compatibleRuntimes.map(runtime => runtime.name).join(', ');
496 throw new Error(`This lambda function uses a runtime that is incompatible with this layer (${this.runtime.name} is not in [${runtimes}])`);
497 }
498 // Currently no validations for compatible architectures since Lambda service
499 // allows layers configured with one architecture to be used with a Lambda function
500 // from another architecture.
501 this.layers.push(layer);
502 }
503 }
504 /**
505 * Add a new version for this Lambda
506 *
507 * If you want to deploy through CloudFormation and use aliases, you need to
508 * add a new version (with a new name) to your Lambda every time you want to
509 * deploy an update. An alias can then refer to the newly created Version.
510 *
511 * All versions should have distinct names, and you should not delete versions
512 * as long as your Alias needs to refer to them.
513 *
514 * @param name A unique name for this version.
515 * @param codeSha256 The SHA-256 hash of the most recently deployed Lambda
516 * source code, or omit to skip validation.
517 * @param description A description for this version.
518 * @param provisionedExecutions A provisioned concurrency configuration for a
519 * function's version.
520 * @param asyncInvokeConfig configuration for this version when it is invoked
521 * asynchronously.
522 * @returns A new Version object.
523 *
524 * @deprecated This method will create an AWS::Lambda::Version resource which
525 * snapshots the AWS Lambda function *at the time of its creation* and it
526 * won't get updated when the function changes. Instead, use
527 * `this.currentVersion` to obtain a reference to a version resource that gets
528 * automatically recreated when the function configuration (or code) changes.
529 */
530 addVersion(name, codeSha256, description, provisionedExecutions, asyncInvokeConfig = {}) {
531 try {
532 jsiiDeprecationWarnings.print("@aws-cdk/aws-lambda.Function#addVersion", "This method will create an AWS::Lambda::Version resource which\nsnapshots the AWS Lambda function *at the time of its creation* and it\nwon't get updated when the function changes. Instead, use\n`this.currentVersion` to obtain a reference to a version resource that gets\nautomatically recreated when the function configuration (or code) changes.");
533 jsiiDeprecationWarnings._aws_cdk_aws_lambda_EventInvokeConfigOptions(asyncInvokeConfig);
534 }
535 catch (error) {
536 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
537 Error.captureStackTrace(error, this.addVersion);
538 }
539 throw error;
540 }
541 return new lambda_version_1.Version(this, 'Version' + name, {
542 lambda: this,
543 codeSha256,
544 description,
545 provisionedConcurrentExecutions: provisionedExecutions,
546 ...asyncInvokeConfig,
547 });
548 }
549 /**
550 * The LogGroup where the Lambda function's logs are made available.
551 *
552 * If either `logRetention` is set or this property is called, a CloudFormation custom resource is added to the stack that
553 * pre-creates the log group as part of the stack deployment, if it already doesn't exist, and sets the correct log retention
554 * period (never expire, by default).
555 *
556 * Further, if the log group already exists and the `logRetention` is not set, the custom resource will reset the log retention
557 * to never expire even if it was configured with a different value.
558 */
559 get logGroup() {
560 if (!this._logGroup) {
561 const logRetention = new logs.LogRetention(this, 'LogRetention', {
562 logGroupName: `/aws/lambda/${this.functionName}`,
563 retention: logs.RetentionDays.INFINITE,
564 });
565 this._logGroup = logs.LogGroup.fromLogGroupArn(this, `${this.node.id}-LogGroup`, logRetention.logGroupArn);
566 }
567 return this._logGroup;
568 }
569 /** @internal */
570 _checkEdgeCompatibility() {
571 // Check env vars
572 const envEntries = Object.entries(this.environment);
573 for (const [key, config] of envEntries) {
574 if (config.removeInEdge) {
575 delete this.environment[key];
576 core_1.Annotations.of(this).addInfo(`Removed ${key} environment variable for Lambda@Edge compatibility`);
577 }
578 }
579 const envKeys = Object.keys(this.environment);
580 if (envKeys.length !== 0) {
581 throw new Error(`The function ${this.node.path} contains environment variables [${envKeys}] and is not compatible with Lambda@Edge. \
582Environment variables can be marked for removal when used in Lambda@Edge by setting the \'removeInEdge\' property in the \'addEnvironment()\' API.`);
583 }
584 return;
585 }
586 /**
587 * Configured lambda insights on the function if specified. This is acheived by adding an imported layer which is added to the
588 * list of lambda layers on synthesis.
589 *
590 * https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Lambda-Insights-extension-versions.html
591 */
592 configureLambdaInsights(props) {
593 var _b;
594 if (props.insightsVersion === undefined) {
595 return;
596 }
597 if (props.runtime !== runtime_1.Runtime.FROM_IMAGE) {
598 // Layers cannot be added to Lambda container images. The image should have the insights agent installed.
599 // See https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/Lambda-Insights-Getting-Started-docker.html
600 this.addLayers(layers_1.LayerVersion.fromLayerVersionArn(this, 'LambdaInsightsLayer', props.insightsVersion._bind(this, this).arn));
601 }
602 (_b = this.role) === null || _b === void 0 ? void 0 : _b.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('CloudWatchLambdaInsightsExecutionRolePolicy'));
603 }
604 renderEnvironment() {
605 if (!this.environment || Object.keys(this.environment).length === 0) {
606 return undefined;
607 }
608 const variables = {};
609 // Sort environment so the hash of the function used to create
610 // `currentVersion` is not affected by key order (this is how lambda does
611 // it). For backwards compatibility we do not sort environment variables in case
612 // _currentVersion is not defined. Otherwise, this would have invalidated
613 // the template, and for example, may cause unneeded updates for nested
614 // stacks.
615 const keys = this._currentVersion
616 ? Object.keys(this.environment).sort()
617 : Object.keys(this.environment);
618 for (const key of keys) {
619 variables[key] = this.environment[key].value;
620 }
621 return { variables };
622 }
623 /**
624 * If configured, set up the VPC-related properties
625 *
626 * Returns the VpcConfig that should be added to the
627 * Lambda creation properties.
628 */
629 configureVpc(props) {
630 var _b;
631 if ((props.securityGroup || props.allowAllOutbound !== undefined) && !props.vpc) {
632 throw new Error('Cannot configure \'securityGroup\' or \'allowAllOutbound\' without configuring a VPC');
633 }
634 if (!props.vpc) {
635 return undefined;
636 }
637 if (props.securityGroup && props.allowAllOutbound !== undefined) {
638 throw new Error('Configure \'allowAllOutbound\' directly on the supplied SecurityGroup.');
639 }
640 let securityGroups;
641 if (props.securityGroup && props.securityGroups) {
642 throw new Error('Only one of the function props, securityGroup or securityGroups, is allowed');
643 }
644 if (props.securityGroups) {
645 securityGroups = props.securityGroups;
646 }
647 else {
648 const securityGroup = props.securityGroup || new ec2.SecurityGroup(this, 'SecurityGroup', {
649 vpc: props.vpc,
650 description: 'Automatic security group for Lambda Function ' + core_1.Names.uniqueId(this),
651 allowAllOutbound: props.allowAllOutbound,
652 });
653 securityGroups = [securityGroup];
654 }
655 this._connections = new ec2.Connections({ securityGroups });
656 if (props.filesystem) {
657 if (props.filesystem.config.connections) {
658 props.filesystem.config.connections.allowDefaultPortFrom(this);
659 }
660 }
661 const allowPublicSubnet = (_b = props.allowPublicSubnet) !== null && _b !== void 0 ? _b : false;
662 const { subnetIds } = props.vpc.selectSubnets(props.vpcSubnets);
663 const publicSubnetIds = new Set(props.vpc.publicSubnets.map(s => s.subnetId));
664 for (const subnetId of subnetIds) {
665 if (publicSubnetIds.has(subnetId) && !allowPublicSubnet) {
666 throw new Error('Lambda Functions in a public subnet can NOT access the internet. ' +
667 'If you are aware of this limitation and would still like to place the function int a public subnet, set `allowPublicSubnet` to true');
668 }
669 }
670 // List can't be empty here, if we got this far you intended to put your Lambda
671 // in subnets. We're going to guarantee that we get the nice error message by
672 // making VpcNetwork do the selection again.
673 return {
674 subnetIds,
675 securityGroupIds: securityGroups.map(sg => sg.securityGroupId),
676 };
677 }
678 isQueue(deadLetterQueue) {
679 return deadLetterQueue.queueArn !== undefined;
680 }
681 buildDeadLetterQueue(props) {
682 if (!props.deadLetterQueue && !props.deadLetterQueueEnabled && !props.deadLetterTopic) {
683 return undefined;
684 }
685 if (props.deadLetterQueue && props.deadLetterQueueEnabled === false) {
686 throw Error('deadLetterQueue defined but deadLetterQueueEnabled explicitly set to false');
687 }
688 if (props.deadLetterTopic && (props.deadLetterQueue || props.deadLetterQueueEnabled !== undefined)) {
689 throw new Error('deadLetterQueue and deadLetterTopic cannot be specified together at the same time');
690 }
691 let deadLetterQueue;
692 if (props.deadLetterTopic) {
693 deadLetterQueue = props.deadLetterTopic;
694 this.addToRolePolicy(new iam.PolicyStatement({
695 actions: ['sns:Publish'],
696 resources: [deadLetterQueue.topicArn],
697 }));
698 }
699 else {
700 deadLetterQueue = props.deadLetterQueue || new sqs.Queue(this, 'DeadLetterQueue', {
701 retentionPeriod: core_1.Duration.days(14),
702 });
703 this.addToRolePolicy(new iam.PolicyStatement({
704 actions: ['sqs:SendMessage'],
705 resources: [deadLetterQueue.queueArn],
706 }));
707 }
708 return deadLetterQueue;
709 }
710 buildDeadLetterConfig(deadLetterQueue) {
711 if (deadLetterQueue) {
712 return {
713 targetArn: this.isQueue(deadLetterQueue) ? deadLetterQueue.queueArn : deadLetterQueue.topicArn,
714 };
715 }
716 else {
717 return undefined;
718 }
719 }
720 buildTracingConfig(props) {
721 if (props.tracing === undefined || props.tracing === Tracing.DISABLED) {
722 return undefined;
723 }
724 this.addToRolePolicy(new iam.PolicyStatement({
725 actions: ['xray:PutTraceSegments', 'xray:PutTelemetryRecords'],
726 resources: ['*'],
727 }));
728 return {
729 mode: props.tracing,
730 };
731 }
732 validateProfiling(props) {
733 if (!props.runtime.supportsCodeGuruProfiling) {
734 throw new Error(`CodeGuru profiling is not supported by runtime ${props.runtime.name}`);
735 }
736 if (props.environment && (props.environment.AWS_CODEGURU_PROFILER_GROUP_ARN || props.environment.AWS_CODEGURU_PROFILER_ENABLED)) {
737 throw new Error('AWS_CODEGURU_PROFILER_GROUP_ARN and AWS_CODEGURU_PROFILER_ENABLED must not be set when profiling options enabled');
738 }
739 }
740}
741exports.Function = Function;
742_a = JSII_RTTI_SYMBOL_1;
743Function[_a] = { fqn: "@aws-cdk/aws-lambda.Function", version: "1.154.0" };
744/** @internal */
745Function._VER_PROPS = {};
746/**
747 * Given an opaque (token) ARN, returns a CloudFormation expression that extracts the function
748 * name from the ARN.
749 *
750 * Function ARNs look like this:
751 *
752 * arn:aws:lambda:region:account-id:function:function-name
753 *
754 * ..which means that in order to extract the `function-name` component from the ARN, we can
755 * split the ARN using ":" and select the component in index 6.
756 *
757 * @returns `FnSelect(6, FnSplit(':', arn))`
758 */
759function extractNameFromArn(arn) {
760 return core_1.Fn.select(6, core_1.Fn.split(':', arn));
761}
762function verifyCodeConfig(code, props) {
763 // mutually exclusive
764 const codeType = [code.inlineCode, code.s3Location, code.image];
765 if (codeType.filter(x => !!x).length !== 1) {
766 throw new Error('lambda.Code must specify exactly one of: "inlineCode", "s3Location", or "image"');
767 }
768 if (!!code.image === (props.handler !== handler_1.Handler.FROM_IMAGE)) {
769 throw new Error('handler must be `Handler.FROM_IMAGE` when using image asset for Lambda function');
770 }
771 if (!!code.image === (props.runtime !== runtime_1.Runtime.FROM_IMAGE)) {
772 throw new Error('runtime must be `Runtime.FROM_IMAGE` when using image asset for Lambda function');
773 }
774 // if this is inline code, check that the runtime supports
775 if (code.inlineCode && !props.runtime.supportsInlineCode) {
776 throw new Error(`Inline source not allowed for ${props.runtime.name}`);
777 }
778}
779exports.verifyCodeConfig = verifyCodeConfig;
780function undefinedIfNoKeys(struct) {
781 const allUndefined = Object.values(struct).every(val => val === undefined);
782 return allUndefined ? undefined : struct;
783}
784//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnVuY3Rpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJmdW5jdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSxzREFBc0Q7QUFDdEQsd0VBQWlHO0FBQ2pHLHdDQUF3QztBQUN4Qyx3Q0FBd0M7QUFFeEMsMENBQTBDO0FBRTFDLHdDQUF3QztBQUN4Qyx3Q0FBbUg7QUFFbkgsaURBQThDO0FBTTlDLG1EQUE4RTtBQUM5RSxtREFBdUU7QUFDdkUsdUNBQW9DO0FBRXBDLHFEQUEyRDtBQUMzRCx5REFBaUQ7QUFDakQscUNBQXVEO0FBQ3ZELHVDQUFvQztBQU1wQzs7R0FFRztBQUNILElBQVksT0FlWDtBQWZELFdBQVksT0FBTztJQUNqQjs7O09BR0c7SUFDSCw0QkFBaUIsQ0FBQTtJQUNqQjs7O09BR0c7SUFDSCx1Q0FBNEIsQ0FBQTtJQUM1Qjs7T0FFRztJQUNILGdDQUFxQixDQUFBO0FBQ3ZCLENBQUMsRUFmVyxPQUFPLEdBQVAsZUFBTyxLQUFQLGVBQU8sUUFlbEI7QUErVUQ7Ozs7Ozs7Ozs7R0FVRztBQUNILE1BQWEsUUFBUyxTQUFRLDRCQUFZO0lBcVF4QyxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQW9COztRQUM1RCxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRTtZQUNmLFlBQVksRUFBRSxLQUFLLENBQUMsWUFBWTtTQUNqQyxDQUFDLENBQUM7UUF0Qlcsb0JBQWUsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDO1FBR3pCLHlCQUFvQixHQUFHLElBQUksQ0FBQztRQUU5QixXQUFNLEdBQW9CLEVBQUUsQ0FBQztRQUk5Qzs7V0FFRztRQUNLLGdCQUFXLEdBQXlDLEVBQUUsQ0FBQzs7Ozs7Ozs7OztRQVk3RCxJQUFJLEtBQUssQ0FBQyxZQUFZLElBQUksQ0FBQyxZQUFLLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxZQUFZLENBQUMsRUFBRTtZQUNqRSxJQUFJLEtBQUssQ0FBQyxZQUFZLENBQUMsTUFB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QU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxLQUFLLFNBQVMsQ0FBQyxDQUFDO0lBQzNFLE9BQU8sWUFBWSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQztBQUMzQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgY2xvdWR3YXRjaCBmcm9tICdAYXdzLWNkay9hd3MtY2xvdWR3YXRjaCc7XG5pbXBvcnQgeyBJUHJvZmlsaW5nR3JvdXAsIFByb2ZpbGluZ0dyb3VwLCBDb21wdXRlUGxhdGZvcm0gfSBmcm9tICdAYXdzLWNkay9hd3MtY29kZWd1cnVwcm9maWxlcic7XG5pbXBvcnQgKiBhcyBlYzIgZnJvbSAnQGF3cy1jZGsvYXdzLWVjMic7XG5pbXBvcnQgKiBhcyBpYW0gZnJvbSAnQGF3cy1jZGsvYXdzLWlhbSc7XG5pbXBvcnQgKiBhcyBrbXMgZnJvbSAnQGF3cy1jZGsvYXdzLWttcyc7XG5pbXBvcnQgKiBhcyBsb2dzIGZyb20gJ0Bhd3MtY2RrL2F3cy1sb2dzJztcbmltcG9ydCAqIGFzIHNucyBmcm9tICdAYXdzLWNkay9hd3Mtc25zJztcbmltcG9ydCAqIGFzIHNxcyBmcm9tICdAYXdzLWNkay9hd3Mtc3FzJztcbmltcG9ydCB7IEFubm90YXRpb25zLCBBcm5Gb3JtYXQsIENmblJlc291cmNlLCBEdXJhdGlvbiwgRm4sIExhenksIE5hbWVzLCBTaXplLCBTdGFjaywgVG9rZW4gfSBmcm9tICdAYXdzLWNkay9jb3JlJztcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0IHsgQXJjaGl0ZWN0dXJlIH0gZnJvbSAnLi9hcmNoaXRlY3R1cmUnO1xuaW1wb3J0IHsgQ29kZSwgQ29kZUNvbmZpZyB9IGZyb20gJy4vY29kZSc7XG5pbXBvcnQgeyBJQ29kZVNpZ25pbmdDb25maWcgfSBmcm9tICcuL2NvZGUtc2lnbmluZy1jb25maWcnO1xuaW1wb3J0IHsgRXZlbnRJbnZva2VDb25maWdPcHRpb25zIH0gZnJvbSAnLi9ldmVudC1pbnZva2UtY29uZmlnJztcbmltcG9ydCB7IElFdmVudFNvdXJjZSB9IGZyb20gJy4vZXZlbnQtc291cmNlJztcbmltcG9ydCB7IEZpbGVTeXN0ZW0gfSBmcm9tICcuL2ZpbGVzeXN0ZW0nO1xuaW1wb3J0IHsgRnVuY3Rpb25BdHRyaWJ1dGVzLCBGdW5jdGlvbkJhc2UsIElGdW5jdGlvbiB9IGZyb20gJy4vZnVuY3Rpb24tYmFzZSc7XG5pbXBvcnQgeyBjYWxjdWxhdGVGdW5jdGlvbkhhc2gsIHRyaW1Gcm9tU3RhcnQgfSBmcm9tICcuL2Z1bmN0aW9uLWhhc2gnO1xuaW1wb3J0IHsgSGFuZGxlciB9IGZyb20gJy4vaGFuZGxlcic7XG5pbXBvcnQgeyBMYW1iZGFJbnNpZ2h0c1ZlcnNpb24gfSBmcm9tICcuL2xhbWJkYS1pbnNpZ2h0cyc7XG5pbXBvcnQgeyBWZXJzaW9uLCBWZXJzaW9uT3B0aW9ucyB9IGZyb20gJy4vbGFtYmRhLXZlcnNpb24nO1xuaW1wb3J0IHsgQ2ZuRnVuY3Rpb24gfSBmcm9tICcuL2xhbWJkYS5nZW5lcmF0ZWQnO1xuaW1wb3J0IHsgTGF5ZXJWZXJzaW9uLCBJTGF5ZXJWZXJzaW9uIH0gZnJvbSAnLi9sYXllcnMnO1xuaW1wb3J0IHsgUnVudGltZSB9IGZyb20gJy4vcnVudGltZSc7XG5cbi8vIGtlZXAgdGhpcyBpbXBvcnQgc2VwYXJhdGUgZnJvbSBvdGhlciBpbXBvcnRzIHRvIHJlZHVjZSBjaGFuY2UgZm9yIG1lcmdlIGNvbmZsaWN0cyB3aXRoIHYyLW1haW5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuaW1wb3J0IHsgTG9nUmV0ZW50aW9uUmV0cnlPcHRpb25zIH0gZnJvbSAnLi9sb2ctcmV0ZW50aW9uJztcblxuLyoqXG4gKiBYLVJheSBUcmFjaW5nIE1vZGVzIChodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vbGFtYmRhL2xhdGVzdC9kZy9BUElfVHJhY2luZ0NvbmZpZy5odG1sKVxuICovXG5leHBvcnQgZW51bSBUcmFjaW5nIHtcbiAgLyoqXG4gICAqIExhbWJkYSB3aWxsIHJlc3BlY3QgYW55IHRyYWNpbmcgaGVhZGVyIGl0IHJlY2VpdmVzIGZyb20gYW4gdXBzdHJlYW0gc2VydmljZS5cbiAgICogSWYgbm8gdHJhY2luZyBoZWFkZXIgaXMgcmVjZWl2ZWQsIExhbWJkYSB3aWxsIGNhbGwgWC1SYXkgZm9yIGEgdHJhY2luZyBkZWNpc2lvbi5cbiAgICovXG4gIEFDVElWRSA9ICdBY3RpdmUnLFxuICAvKipcbiAgICogTGFtYmRhIHdpbGwgb25seSB0cmFjZSB0aGUgcmVxdWVzdCBmcm9tIGFuIHVwc3RyZWFtIHNlcnZpY2VcbiAgICogaWYgaXQgY29udGFpbnMgYSB0cmFjaW5nIGhlYWRlciB3aXRoIFwic2FtcGxlZD0xXCJcbiAgICovXG4gIFBBU1NfVEhST1VHSCA9ICdQYXNzVGhyb3VnaCcsXG4gIC8qKlxuICAgKiBMYW1iZGEgd2lsbCBub3QgdHJhY2UgYW55IHJlcXVlc3QuXG4gICAqL1xuICBESVNBQkxFRCA9ICdEaXNhYmxlZCdcbn1cblxuLyoqXG4gKiBOb24gcnVudGltZSBvcHRpb25zXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRnVuY3Rpb25PcHRpb25zIGV4dGVuZHMgRXZlbnRJbnZva2VDb25maWdPcHRpb25zIHtcbiAgLyoqXG4gICAqIEEgZGVzY3JpcHRpb24gb2YgdGhlIGZ1bmN0aW9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIGRlc2NyaXB0aW9uLlxuICAgKi9cbiAgcmVhZG9ubHkgZGVzY3JpcHRpb24/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBmdW5jdGlvbiBleGVjdXRpb24gdGltZSAoaW4gc2Vjb25kcykgYWZ0ZXIgd2hpY2ggTGFtYmRhIHRlcm1pbmF0ZXNcbiAgICogdGhlIGZ1bmN0aW9uLiBCZWNhdXNlIHRoZSBleGVjdXRpb24gdGltZSBhZmZlY3RzIGNvc3QsIHNldCB0aGlzIHZhbHVlXG4gICAqIGJhc2VkIG9uIHRoZSBmdW5jdGlvbidzIGV4cGVjdGVkIGV4ZWN1dGlvbiB0aW1lLlxuICAgKlxuICAgKiBAZGVmYXVsdCBEdXJhdGlvbi5zZWNvbmRzKDMpXG4gICAqL1xuICByZWFkb25seSB0aW1lb3V0PzogRHVyYXRpb247XG5cbiAgLyoqXG4gICAqIEtleS12YWx1ZSBwYWlycyB0aGF0IExhbWJkYSBjYWNoZXMgYW5kIG1ha2VzIGF2YWlsYWJsZSBmb3IgeW91ciBMYW1iZGFcbiAgICogZnVuY3Rpb25zLiBVc2UgZW52aXJvbm1lbnQgdmFyaWFibGVzIHRvIGFwcGx5IGNvbmZpZ3VyYXRpb24gY2hhbmdlcywgc3VjaFxuICAgKiBhcyB0ZXN0IGFuZCBwcm9kdWN0aW9uIGVudmlyb25tZW50IGNvbmZpZ3VyYXRpb25zLCB3aXRob3V0IGNoYW5naW5nIHlvdXJcbiAgICogTGFtYmRhIGZ1bmN0aW9uIHNvdXJjZSBjb2RlLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIGVudmlyb25tZW50IHZhcmlhYmxlcy5cbiAgICovXG4gIHJlYWRvbmx5IGVudmlyb25tZW50PzogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfTtcblxuICAvKipcbiAgICogQSBuYW1lIGZvciB0aGUgZnVuY3Rpb24uXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gQVdTIENsb3VkRm9ybWF0aW9uIGdlbmVyYXRlcyBhIHVuaXF1ZSBwaHlzaWNhbCBJRCBhbmQgdXNlcyB0aGF0XG4gICAqIElEIGZvciB0aGUgZnVuY3Rpb24ncyBuYW1lLiBGb3IgbW9yZSBpbmZvcm1hdGlvbiwgc2VlIE5hbWUgVHlwZS5cbiAgICovXG4gIHJlYWRvbmx5IGZ1bmN0aW9uTmFtZT86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIGFtb3VudCBvZiBtZW1vcnksIGluIE1CLCB0aGF0IGlzIGFsbG9jYXRlZCB0byB5b3VyIExhbWJkYSBmdW5jdGlvbi5cbiAgICogTGFtYmRhIHVzZXMgdGhpcyB2YWx1ZSB0byBwcm9wb3J0aW9uYWxseSBhbGxvY2F0ZSB0aGUgYW1vdW50IG9mIENQVVxuICAgKiBwb3dlci4gRm9yIG1vcmUgaW5mb3JtYXRpb24sIHNlZSBSZXNvdXJjZSBNb2RlbCBpbiB0aGUgQVdTIExhbWJkYVxuICAgKiBEZXZlbG9wZXIgR3VpZGUuXG4gICAqXG4gICAqIEBkZWZhdWx0IDEyOFxuICAgKi9cbiAgcmVhZG9ubHkgbWVtb3J5U2l6ZT86IG51bWJlcjtcblxuICAvKipcbiAgICogVGhlIHNpemUgb2YgdGhlIGZ1bmN0aW9u4oCZcyAvdG1wIGRpcmVjdG9yeSBpbiBNaUIuXG4gICAqXG4gICAqIEBkZWZhdWx0IDUxMiBNaUJcbiAgICovXG4gIHJlYWRvbmx5IGVwaGVtZXJhbFN0b3JhZ2VTaXplPzogU2l6ZTtcblxuICAvKipcbiAgICogSW5pdGlhbCBwb2xpY3kgc3RhdGVtZW50cyB0byBhZGQgdG8gdGhlIGNyZWF0ZWQgTGFtYmRhIFJvbGUuXG4gICAqXG4gICAqIFlvdSBjYW4gY2FsbCBgYWRkVG9Sb2xlUG9saWN5YCB0byB0aGUgY3JlYXRlZCBsYW1iZGEgdG8gYWRkIHN0YXRlbWVudHMgcG9zdCBjcmVhdGlvbi5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBObyBwb2xpY3kgc3RhdGVtZW50cyBhcmUgYWRkZWQgdG8gdGhlIGNyZWF0ZWQgTGFtYmRhIHJvbGUuXG4gICAqL1xuICByZWFkb25seSBpbml0aWFsUG9saWN5PzogaWFtLlBvbGljeVN0YXRlbWVudFtdO1xuXG4gIC8qKlxuICAgKiBMYW1iZGEgZXhlY3V0aW9uIHJvbGUuXG4gICAqXG4gICAqIFRoaXMgaXMgdGhlIHJvbGUgdGhhdCB3aWxsIGJlIGFzc3VtZWQgYnkgdGhlIGZ1bmN0aW9uIHVwb24gZXhlY3V0aW9uLlxuICAgKiBJdCBjb250cm9scyB0aGUgcGVybWlzc2lvbnMgdGhhdCB0aGUgZnVuY3Rpb24gd2lsbCBoYXZlLiBUaGUgUm9sZSBtdXN0XG4gICAqIGJlIGFzc3VtYWJsZSBieSB0aGUgJ2xhbWJkYS5hbWF6b25hd3MuY29tJyBzZXJ2aWNlIHByaW5jaXBhbC5cbiAgICpcbiAgICogVGhlIGRlZmF1bHQgUm9sZSBhdXRvbWF0aWNhbGx5IGhhcyBwZXJtaXNzaW9ucyBncmFudGVkIGZvciBMYW1iZGEgZXhlY3V0aW9uLiBJZiB5b3VcbiAgICogcHJvdmlkZSBhIFJvbGUsIHlvdSBtdXN0IGFkZCB0aGUgcmVsZXZhbnQgQVdTIG1hbmFnZWQgcG9saWNpZXMgeW91cnNlbGYuXG4gICAqXG4gICAqIFRoZSByZWxldmFudCBtYW5hZ2VkIHBvbGljaWVzIGFyZSBcInNlcnZpY2Utcm9sZS9BV1NMYW1iZGFCYXNpY0V4ZWN1dGlvblJvbGVcIiBhbmRcbiAgICogXCJzZXJ2aWNlLXJvbGUvQVdTTGFtYmRhVlBDQWNjZXNzRXhlY3V0aW9uUm9sZVwiLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIEEgdW5pcXVlIHJvbGUgd2lsbCBiZSBnZW5lcmF0ZWQgZm9yIHRoaXMgbGFtYmRhIGZ1bmN0aW9uLlxuICAgKiBCb3RoIHN1cHBsaWVkIGFuZCBnZW5lcmF0ZWQgcm9sZXMgY2FuIGFsd2F5cyBiZSBjaGFuZ2VkIGJ5IGNhbGxpbmcgYGFkZFRvUm9sZVBvbGljeWAuXG4gICAqL1xuICByZWFkb25seSByb2xlPzogaWFtLklSb2xlO1xuXG4gIC8qKlxuICAgKiBWUEMgbmV0d29yayB0byBwbGFjZSBMYW1iZGEgbmV0d29yayBpbnRlcmZhY2VzXG4gICAqXG4gICAqIFNwZWNpZnkgdGhpcyBpZiB0aGUgTGFtYmRhIGZ1bmN0aW9uIG5lZWRzIHRvIGFjY2VzcyByZXNvdXJjZXMgaW4gYSBWUEMuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gRnVuY3Rpb24gaXMgbm90IHBsYWNlZCB3aXRoaW4gYSBWUEMuXG4gICAqL1xuICByZWFkb25seSB2cGM/OiBlYzIuSVZwYztcblxuICAvKipcbiAgICogV2hlcmUgdG8gcGxhY2UgdGhlIG5ldHdvcmsgaW50ZXJmYWNlcyB3aXRoaW4gdGhlIFZQQy5cbiAgICpcbiAgICogT25seSB1c2VkIGlmICd2cGMnIGlzIHN1cHBsaWVkLiBOb3RlOiBpbnRlcm5ldCBhY2Nlc3MgZm9yIExhbWJkYXNcbiAgICogcmVxdWlyZXMgYSBOQVQgZ2F0ZXdheSwgc28gcGlja2luZyBQdWJsaWMgc3VibmV0cyBpcyBub3QgYWxsb3dlZC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSB0aGUgVnBjIGRlZmF1bHQgc3RyYXRlZ3kgaWYgbm90IHNwZWNpZmllZFxuICAgKi9cbiAgcmVhZG9ubHkgdnBjU3VibmV0cz86IGVjMi5TdWJuZXRTZWxlY3Rpb247XG5cbiAgLyoqXG4gICAqIFdoYXQgc2VjdXJpdHkgZ3JvdXAgdG8gYXNzb2NpYXRlIHdpdGggdGhlIExhbWJkYSdzIG5ldHdvcmsgaW50ZXJmYWNlcy5cbiAgICogVGhpcyBwcm9wZXJ0eSBpcyBiZWluZyBkZXByZWNhdGVkLCBjb25zaWRlciB1c2luZyBzZWN1cml0eUdyb3VwcyBpbnN0ZWFkLlxuICAgKlxuICAgKiBPbmx5IHVzZWQgaWYgJ3ZwYycgaXMgc3VwcGxpZWQuXG4gICAqXG4gICAqIFVzZSBzZWN1cml0eUdyb3VwcyBwcm9wZXJ0eSBpbnN0ZWFkLlxuICAgKiBGdW5jdGlvbiBjb25zdHJ1Y3RvciB3aWxsIHRocm93IGFuIGVycm9yIGlmIGJvdGggYXJlIHNwZWNpZmllZC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBJZiB0aGUgZnVuY3Rpb24gaXMgcGxhY2VkIHdpdGhpbiBhIFZQQyBhbmQgYSBzZWN1cml0eSBncm91cCBpc1xuICAgKiBub3Qgc3BlY2lmaWVkLCBlaXRoZXIgYnkgdGhpcyBvciBzZWN1cml0eUdyb3VwcyBwcm9wLCBhIGRlZGljYXRlZCBzZWN1cml0eVxuICAgKiBncm91cCB3aWxsIGJlIGNyZWF0ZWQgZm9yIHRoaXMgZnVuY3Rpb24uXG4gICAqXG4gICAqIEBkZXByZWNhdGVkIC0gVGhpcyBwcm9wZXJ0eSBpcyBkZXByZWNhdGVkLCB1c2Ugc2VjdXJpdHlHcm91cHMgaW5zdGVhZFxuICAgKi9cbiAgcmVhZG9ubHkgc2VjdXJpdHlHcm91cD86IGVjMi5JU2VjdXJpdHlHcm91cDtcblxuICAvKipcbiAgICogVGhlIGxpc3Qgb2Ygc2VjdXJpdHkgZ3JvdXBzIHRvIGFzc29jaWF0ZSB3aXRoIHRoZSBMYW1iZGEncyBuZXR3b3JrIGludGVyZmFjZXMuXG4gICAqXG4gICAqIE9ubHkgdXNlZCBpZiAndnBjJyBpcyBzdXBwbGllZC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBJZiB0aGUgZnVuY3Rpb24gaXMgcGxhY2VkIHdpdGhpbiBhIFZQQyBhbmQgYSBzZWN1cml0eSBncm91cCBpc1xuICAgKiBub3Qgc3BlY2lmaWVkLCBlaXRoZXIgYnkgdGhpcyBvciBzZWN1cml0eUdyb3VwIHByb3AsIGEgZGVkaWNhdGVkIHNlY3VyaXR5XG4gICAqIGdyb3VwIHdpbGwgYmUgY3JlYXRlZCBmb3IgdGhpcyBmdW5jdGlvbi5cbiAgICovXG4gIHJlYWRvbmx5IHNlY3VyaXR5R3JvdXBzPzogZWMyLklTZWN1cml0eUdyb3VwW107XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gYWxsb3cgdGhlIExhbWJkYSB0byBzZW5kIGFsbCBuZXR3b3JrIHRyYWZmaWNcbiAgICpcbiAgICogSWYgc2V0IHRvIGZhbHNlLCB5b3UgbXVzdCBpbmRpdmlkdWFsbHkgYWRkIHRyYWZmaWMgcnVsZXMgdG8gYWxsb3cgdGhlXG4gICAqIExhbWJkYSB0byBjb25uZWN0IHRvIG5ldHdvcmsgdGFyZ2V0cy5cbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgYWxsb3dBbGxPdXRib3VuZD86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEVuYWJsZWQgRExRLiBJZiBgZGVhZExldHRlclF1ZXVlYCBpcyB1bmRlZmluZWQsXG4gICAqIGFuIFNRUyBxdWV1ZSB3aXRoIGRlZmF1bHQgb3B0aW9ucyB3aWxsIGJlIGRlZmluZWQgZm9yIHlvdXIgRnVuY3Rpb24uXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gZmFsc2UgdW5sZXNzIGBkZWFkTGV0dGVyUXVldWVgIGlzIHNldCwgd2hpY2ggaW1wbGllcyBETFEgaXMgZW5hYmxlZC5cbiAgICovXG4gIHJlYWRvbmx5IGRlYWRMZXR0ZXJRdWV1ZUVuYWJsZWQ/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBUaGUgU1FTIHF1ZXVlIHRvIHVzZSBpZiBETFEgaXMgZW5hYmxlZC5cbiAgICogSWYgU05TIHRvcGljIGlzIGRlc2lyZWQsIHNwZWNpZnkgYGRlYWRMZXR0ZXJUb3BpY2AgcHJvcGVydHkgaW5zdGVhZC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBTUVMgcXVldWUgd2l0aCAxNCBkYXkgcmV0ZW50aW9uIHBlcmlvZCBpZiBgZGVhZExldHRlclF1ZXVlRW5hYmxlZGAgaXMgYHRydWVgXG4gICAqL1xuICByZWFkb25seSBkZWFkTGV0dGVyUXVldWU/OiBzcXMuSVF1ZXVlO1xuXG4gIC8qKlxuICAgKiBUaGUgU05TIHRvcGljIHRvIHVzZSBhcyBhIERMUS5cbiAgICogTm90ZSB0aGF0IGlmIGBkZWFkTGV0dGVyUXVldWVFbmFibGVkYCBpcyBzZXQgdG8gYHRydWVgLCBhbiBTUVMgcXVldWUgd2lsbCBiZSBjcmVhdGVkXG4gICAqIHJhdGhlciB0aGFuIGFuIFNOUyB0b3BpYy4gVXNpbmcgYW4gU05TIHRvcGljIGFzIGEgRExRIHJlcXVpcmVzIHRoaXMgcHJvcGVydHkgdG8gYmUgc2V0IGV4cGxpY2l0bHkuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm8gU05TIHRvcGljXG4gICAqL1xuICByZWFkb25seSBkZWFkTGV0dGVyVG9waWM/OiBzbnMuSVRvcGljO1xuXG4gIC8qKlxuICAgKiBFbmFibGUgQVdTIFgtUmF5IFRyYWNpbmcgZm9yIExhbWJkYSBGdW5jdGlvbi5cbiAgICpcbiAgICogQGRlZmF1bHQgVHJhY2luZy5EaXNhYmxlZFxuICAgKi9cbiAgcmVhZG9ubHkgdHJhY2luZz86IFRyYWNpbmc7XG5cbiAgLyoqXG4gICAqIEVuYWJsZSBwcm9maWxpbmcuXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2NvZGVndXJ1L2xhdGVzdC9wcm9maWxlci11Zy9zZXR0aW5nLXVwLWxhbWJkYS5odG1sXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gcHJvZmlsaW5nLlxuICAgKi9cbiAgcmVhZG9ubHkgcHJvZmlsaW5nPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogUHJvZmlsaW5nIEdyb3VwLlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9jb2RlZ3VydS9sYXRlc3QvcHJvZmlsZXItdWcvc2V0dGluZy11cC1sYW1iZGEuaHRtbFxuICAgKlxuICAgKiBAZGVmYXVsdCAtIEEgbmV3IHByb2ZpbGluZyBncm91cCB3aWxsIGJlIGNyZWF0ZWQgaWYgYHByb2ZpbGluZ2AgaXMgc2V0LlxuICAgKi9cbiAgcmVhZG9ubHkgcHJvZmlsaW5nR3JvdXA/OiBJUHJvZmlsaW5nR3JvdXA7XG5cbiAgLyoqXG4gICAqIFNwZWNpZnkgdGhlIHZlcnNpb24gb2YgQ2xvdWRXYXRjaCBMYW1iZGEgaW5zaWdodHMgdG8gdXNlIGZvciBtb25pdG9yaW5nXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FtYXpvbkNsb3VkV2F0Y2gvbGF0ZXN0L21vbml0b3JpbmcvTGFtYmRhLUluc2lnaHRzLmh0bWxcbiAgICpcbiAgICogV2hlbiB1c2VkIHdpdGggYERvY2tlckltYWdlRnVuY3Rpb25gIG9yIGBEb2NrZXJJbWFnZUNvZGVgLCB0aGUgRG9ja2VyIGltYWdlIHNob3VsZCBoYXZlXG4gICAqIHRoZSBMYW1iZGEgaW5zaWdodHMgYWdlbnQgaW5zdGFsbGVkLlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BbWF6b25DbG91ZFdhdGNoL2xhdGVzdC9tb25pdG9yaW5nL0xhbWJkYS1JbnNpZ2h0cy1HZXR0aW5nLVN0YXJ0ZWQtZG9ja2VyLmh0bWxcbiAgICpcbiAgICogQGRlZmF1bHQgLSBObyBMYW1iZGEgSW5zaWdodHNcbiAgICovXG4gIHJlYWRvbmx5IGluc2lnaHRzVmVyc2lvbj86IExhbWJkYUluc2lnaHRzVmVyc2lvbjtcblxuICAvKipcbiAgICogQSBsaXN0IG9mIGxheWVycyB0byBhZGQgdG8gdGhlIGZ1bmN0aW9uJ3MgZXhlY3V0aW9uIGVudmlyb25tZW50LiBZb3UgY2FuIGNvbmZpZ3VyZSB5b3VyIExhbWJkYSBmdW5jdGlvbiB0byBwdWxsIGluXG4gICAqIGFkZGl0aW9uYWwgY29kZSBkdXJpbmcgaW5pdGlhbGl6YXRpb24gaW4gdGhlIGZvcm0gb2YgbGF5ZXJzLiBMYXllcnMgYXJlIHBhY2thZ2VzIG9mIGxpYnJhcmllcyBvciBvdGhlciBkZXBlbmRlbmNpZXNcbiAgICogdGhhdCBjYW4gYmUgdXNlZCBieSBtdWx0aXBsZSBmdW5jdGlvbnMuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gbGF5ZXJzLlxuICAgKi9cbiAgcmVhZG9ubHkgbGF5ZXJzPzogSUxheWVyVmVyc2lvbltdO1xuXG4gIC8qKlxuICAgKiBUaGUgbWF4aW11bSBvZiBjb25jdXJyZW50IGV4ZWN1dGlvbnMgeW91IHdhbnQgdG8gcmVzZXJ2ZSBmb3IgdGhlIGZ1bmN0aW9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIHNwZWNpZmljIGxpbWl0IC0gYWNjb3VudCBsaW1pdC5cbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vbGFtYmRhL2xhdGVzdC9kZy9jb25jdXJyZW50LWV4ZWN1dGlvbnMuaHRtbFxuICAgKi9cbiAgcmVhZG9ubHkgcmVzZXJ2ZWRDb25jdXJyZW50RXhlY3V0aW9ucz86IG51bWJlcjtcblxuICAvKipcbiAgICogRXZlbnQgc291cmNlcyBmb3IgdGhpcyBmdW5jdGlvbi5cbiAgICpcbiAgICogWW91IGNhbiBhbHNvIGFkZCBldmVudCBzb3VyY2VzIHVzaW5nIGBhZGRFdmVudFNvdXJjZWAuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gZXZlbnQgc291cmNlcy5cbiAgICovXG4gIHJlYWRvbmx5IGV2ZW50cz86IElFdmVudFNvdXJjZVtdO1xuXG4gIC8qKlxuICAgKiBUaGUgbnVtYmVyIG9mIGRheXMgbG9nIGV2ZW50cyBhcmUga2VwdCBpbiBDbG91ZFdhdGNoIExvZ3MuIFdoZW4gdXBkYXRpbmdcbiAgICogdGhpcyBwcm9wZXJ0eSwgdW5zZXR0aW5nIGl0IGRvZXNuJ3QgcmVtb3ZlIHRoZSBsb2cgcmV0ZW50aW9uIHBvbGljeS4gVG9cbiAgICogcmVtb3ZlIHRoZSByZXRlbnRpb24gcG9saWN5LCBzZXQgdGhlIHZhbHVlIHRvIGBJTkZJTklURWAuXG4gICAqXG4gICAqIEBkZWZhdWx0IGxvZ3MuUmV0ZW50aW9uRGF5cy5JTkZJTklURVxuICAgKi9cbiAgcmVhZG9ubHkgbG9nUmV0ZW50aW9uPzogbG9ncy5SZXRlbnRpb25EYXlzO1xuXG4gIC8qKlxuICAgKiBUaGUgSUFNIHJvbGUgZm9yIHRoZSBMYW1iZGEgZnVuY3Rpb24gYXNzb2NpYXRlZCB3aXRoIHRoZSBjdXN0b20gcmVzb3VyY2VcbiAgICogdGhhdCBzZXRzIHRoZSByZXRlbnRpb24gcG9saWN5LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIEEgbmV3IHJvbGUgaXMgY3JlYXRlZC5cbiAgICovXG4gIHJlYWRvbmx5IGxvZ1JldGVudGlvblJvbGU/OiBpYW0uSVJvbGU7XG5cbiAgLyoqXG4gICAqIFdoZW4gbG9nIHJldGVudGlvbiBpcyBzcGVjaWZpZWQsIGEgY3VzdG9tIHJlc291cmNlIGF0dGVtcHRzIHRvIGNyZWF0ZSB0aGUgQ2xvdWRXYXRjaCBsb2cgZ3JvdXAuXG4gICAqIFRoZXNlIG9wdGlvbnMgY29udHJvbCB0aGUgcmV0cnkgcG9saWN5IHdoZW4gaW50ZXJhY3Rpbmcgd2l0aCBDbG91ZFdhdGNoIEFQSXMuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gRGVmYXVsdCBBV1MgU0RLIHJldHJ5IG9wdGlvbnMuXG4gICAqL1xuICByZWFkb25seSBsb2dSZXRlbnRpb25SZXRyeU9wdGlvbnM/OiBMb2dSZXRlbnRpb25SZXRyeU9wdGlvbnM7XG5cbiAgLyoqXG4gICAqIE9wdGlvbnMgZm9yIHRoZSBgbGFtYmRhLlZlcnNpb25gIHJlc291cmNlIGF1dG9tYXRpY2FsbHkgY3JlYXRlZCBieSB0aGVcbiAgICogYGZuLmN1cnJlbnRWZXJzaW9uYCBtZXRob2QuXG4gICAqIEBkZWZhdWx0IC0gZGVmYXVsdCBvcHRpb25zIGFzIGRlc2NyaWJlZCBpbiBgVmVyc2lvbk9wdGlvbnNgXG4gICAqL1xuICByZWFkb25seSBjdXJyZW50VmVyc2lvbk9wdGlvbnM/OiBWZXJzaW9uT3B0aW9ucztcblxuICAvKipcbiAgICogVGhlIGZpbGVzeXN0ZW0gY29uZmlndXJhdGlvbiBmb3IgdGhlIGxhbWJkYSBmdW5jdGlvblxuICAgKlxuICAgKiBAZGVmYXVsdCAtIHdpbGwgbm90IG1vdW50IGFueSBmaWxlc3lzdGVtXG4gICAqL1xuICByZWFkb25seSBmaWxlc3lzdGVtPzogRmlsZVN5c3RlbTtcblxuICAvKipcbiAgICogTGFtYmRhIEZ1bmN0aW9ucyBpbiBhIHB1YmxpYyBzdWJuZXQgY2FuIE5PVCBhY2Nlc3MgdGhlIGludGVybmV0LlxuICAgKiBVc2UgdGhpcyBwcm9wZXJ0eSB0byBhY2tub3dsZWRnZSB0aGlzIGxpbWl0YXRpb24gYW5kIHN0aWxsIHBsYWNlIHRoZSBmdW5jdGlvbiBpbiBhIHB1YmxpYyBzdWJuZXQuXG4gICAqIEBzZWUgaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvNTI5OTIwODUvd2h5LWNhbnQtYW4tYXdzLWxhbWJkYS1mdW5jdGlvbi1pbnNpZGUtYS1wdWJsaWMtc3VibmV0LWluLWEtdnBjLWNvbm5lY3QtdG8tdGhlLzUyOTk0ODQxIzUyOTk0ODQxXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBhbGxvd1B1YmxpY1N1Ym5ldD86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFRoZSBBV1MgS01TIGtleSB0aGF0J3MgdXNlZCB0byBlbmNyeXB0IHlvdXIgZnVuY3Rpb24ncyBlbnZpcm9ubWVudCB2YXJpYWJsZXMuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gQVdTIExhbWJkYSBjcmVhdGVzIGFuZCB1c2VzIGFuIEFXUyBtYW5hZ2VkIGN1c3RvbWVyIG1hc3RlciBrZXkgKENNSykuXG4gICAqL1xuICByZWFkb25seSBlbnZpcm9ubWVudEVuY3J5cHRpb24/OiBrbXMuSUtleTtcblxuICAvKipcbiAgICogQ29kZSBzaWduaW5nIGNvbmZpZyBhc3NvY2lhdGVkIHdpdGggdGhpcyBmdW5jdGlvblxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vdCBTaWduIHRoZSBDb2RlXG4gICAqL1xuICByZWFkb25seSBjb2RlU2lnbmluZ0NvbmZpZz86IElDb2RlU2lnbmluZ0NvbmZpZztcblxuICAvKipcbiAgICogREVQUkVDQVRFRFxuICAgKiBAZGVmYXVsdCBbQXJjaGl0ZWN0dXJlLlg4Nl82NF1cbiAgICogQGRlcHJlY2F0ZWQgdXNlIGBhcmNoaXRlY3R1cmVgXG4gICAqL1xuICByZWFkb25seSBhcmNoaXRlY3R1cmVzPzogQXJjaGl0ZWN0dXJlW107XG5cbiAgLyoqXG4gICAqIFRoZSBzeXN0ZW0gYXJjaGl0ZWN0dXJlcyBjb21wYXRpYmxlIHdpdGggdGhpcyBsYW1iZGEgZnVuY3Rpb24uXG4gICAqIEBkZWZhdWx0IEFyY2hpdGVjdHVyZS5YODZfNjRcbiAgICovXG4gIHJlYWRvbmx5IGFyY2hpdGVjdHVyZT86IEFyY2hpdGVjdHVyZTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBGdW5jdGlvblByb3BzIGV4dGVuZHMgRnVuY3Rpb25PcHRpb25zIHtcbiAgLyoqXG4gICAqIFRoZSBydW50aW1lIGVudmlyb25tZW50IGZvciB0aGUgTGFtYmRhIGZ1bmN0aW9uIHRoYXQgeW91IGFyZSB1cGxvYWRpbmcuXG4gICAqIEZvciB2YWxpZCB2YWx1ZXMsIHNlZSB0aGUgUnVudGltZSBwcm9wZXJ0eSBpbiB0aGUgQVdTIExhbWJkYSBEZXZlbG9wZXJcbiAgICogR3VpZGUuXG4gICAqXG4gICAqIFVzZSBgUnVudGltZS5GUk9NX0lNQUdFYCB3aGVuIHdoZW4gZGVmaW5pbmcgYSBmdW5jdGlvbiBmcm9tIGEgRG9ja2VyIGltYWdlLlxuICAgKi9cbiAgcmVhZG9ubHkgcnVudGltZTogUnVudGltZTtcblxuICAvKipcbiAgICogVGhlIHNvdXJjZSBjb2RlIG9mIHlvdXIgTGFtYmRhIGZ1bmN0aW9uLiBZb3UgY2FuIHBvaW50IHRvIGEgZmlsZSBpbiBhblxuICAgKiBBbWF6b24gU2ltcGxlIFN0b3JhZ2UgU2VydmljZSAoQW1hem9uIFMzKSBidWNrZXQgb3Igc3BlY2lmeSB5b3VyIHNvdXJjZVxuICAgKiBjb2RlIGFzIGlubGluZSB0ZXh0LlxuICAgKi9cbiAgcmVhZG9ubHkgY29kZTogQ29kZTtcblxuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIG1ldGhvZCB3aXRoaW4geW91ciBjb2RlIHRoYXQgTGFtYmRhIGNhbGxzIHRvIGV4ZWN1dGVcbiAgICogeW91ciBmdW5jdGlvbi4gVGhlIGZvcm1hdCBpbmNsdWRlcyB0aGUgZmlsZSBuYW1lLiBJdCBjYW4gYWxzbyBpbmNsdWRlXG4gICAqIG5hbWVzcGFjZXMgYW5kIG90aGVyIHF1YWxpZmllcnMsIGRlcGVuZGluZyBvbiB0aGUgcnVudGltZS5cbiAgICogRm9yIG1vcmUgaW5mb3JtYXRpb24sIHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vbGFtYmRhL2xhdGVzdC9kZy9nZXR0aW5nc3RhcnRlZC1mZWF0dXJlcy5odG1sI2dldHRpbmdzdGFydGVkLWZlYXR1cmVzLXByb2dyYW1taW5nbW9kZWwuXG4gICAqXG4gICAqIFVzZSBgSGFuZGxlci5GUk9NX0lNQUdFYCB3aGVuIGRlZmluaW5nIGEgZnVuY3Rpb24gZnJvbSBhIERvY2tlciBpbWFnZS5cbiAgICpcbiAgICogTk9URTogSWYgeW91IHNwZWNpZnkgeW91ciBzb3VyY2UgY29kZSBhcyBpbmxpbmUgdGV4dCBieSBzcGVjaWZ5aW5nIHRoZVxuICAgKiBaaXBGaWxlIHByb3BlcnR5IHdpdGhpbiB0aGUgQ29kZSBwcm9wZXJ0eSwgc3BlY2lmeSBpbmRleC5mdW5jdGlvbl9uYW1lIGFzXG4gICAqIHRoZSBoYW5kbGVyLlxuICAgKi9cbiAgcmVhZG9ubHkgaGFuZGxlcjogc3RyaW5nO1xufVxuXG4vKipcbiAqIERlcGxveXMgYSBmaWxlIGZyb20gaW5zaWRlIHRoZSBjb25zdHJ1Y3QgbGlicmFyeSBhcyBhIGZ1bmN0aW9uLlxuICpcbiAqIFRoZSBzdXBwbGllZCBmaWxlIGlzIHN1YmplY3QgdG8gdGhlIDQwOTYgYnl0ZXMgbGltaXQgb2YgYmVpbmcgZW1iZWRkZWQgaW4gYVxuICogQ2xvdWRGb3JtYXRpb24gdGVtcGxhdGUuXG4gKlxuICogVGhlIGNvbnN0cnVjdCBpbmNsdWRlcyBhbiBhc3NvY2lhdGVkIHJvbGUgd2l0aCB0aGUgbGFtYmRhLlxuICpcbiAqIFRoaXMgY29uc3RydWN0IGRvZXMgbm90IHlldCByZXByb2R1Y2UgYWxsIGZlYXR1cmVzIGZyb20gdGhlIHVuZGVybHlpbmcgcmVzb3VyY2VcbiAqIGxpYnJhcnkuXG4gKi9cbmV4cG9ydCBjbGFzcyBGdW5jdGlvbiBleHRlbmRzIEZ1bmN0aW9uQmFzZSB7XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBgbGFtYmRhLlZlcnNpb25gIHdoaWNoIHJlcHJlc2VudHMgdGhlIGN1cnJlbnQgdmVyc2lvbiBvZiB0aGlzXG4gICAqIExhbWJkYSBmdW5jdGlvbi4gQSBuZXcgdmVyc2lvbiB3aWxsIGJlIGNyZWF0ZWQgZXZlcnkgdGltZSB0aGUgZnVuY3Rpb24nc1xuICAgKiBjb25maWd1cmF0aW9uIGNoYW5nZXMuXG4gICAqXG4gICAqIFlvdSBjYW4gc3BlY2lmeSBvcHRpb25zIGZvciB0aGlzIHZlcnNpb24gdXNpbmcgdGhlIGBjdXJyZW50VmVyc2lvbk9wdGlvbnNgXG4gICAqIHByb3Agd2hlbiBpbml0aWFsaXppbmcgdGhlIGBsYW1iZGEuRnVuY3Rpb25gLlxuICAgKi9cbiAgcHVibGljIGdldCBjdXJyZW50VmVyc2lvbigpOiBWZXJzaW9uIHtcbiAgICBpZiAodGhpcy5fY3VycmVudFZlcnNpb24pIHtcbiAgICAgIHJldHVybiB0aGlzLl9jdXJyZW50VmVyc2lvbjtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5fd2FybklmQ3VycmVudFZlcnNpb25DYWxsZWQpIHtcbiAgICAgIHRoaXMud2Fybkludm9rZUZ1bmN0aW9uUGVybWlzc2lvbnModGhpcyk7XG4gICAgfTtcblxuICAgIHRoaXMuX2N1cnJlbnRWZXJzaW9uID0gbmV3IFZlcnNpb24odGhpcywgJ0N1cnJlbnRWZXJzaW9uJywge1xuICAgICAgbGFtYmRhOiB0aGlzLFxuICAgICAgLi4udGhpcy5jdXJyZW50VmVyc2lvbk9wdGlvbnMsXG4gICAgfSk7XG5cbiAgICAvLyBvdmVycmlkZSB0aGUgdmVyc2lvbidzIGxvZ2ljYWwgSUQgd2l0aCBhIGxhenkgc3RyaW5nIHdoaWNoIGluY2x1ZGVzIHRoZVxuICAgIC8vIGhhc2ggb2YgdGhlIGZ1bmN0aW9uIGl0c2VsZiwgc28gYSBuZXcgdmVyc2lvbiByZXNvdXJjZSBpcyBjcmVhdGVkIHdoZW5cbiAgICAvLyB0aGUgZnVuY3Rpb24gY29uZmlndXJhdGlvbiBjaGFuZ2VzLlxuICAgIGNvbnN0IGNmbiA9IHRoaXMuX2N1cnJlbnRWZXJzaW9uLm5vZGUuZGVmYXVsdENoaWxkIGFzIENmblJlc291cmNlO1xuICAgIGNvbnN0IG9yaWdpbmFsTG9naWNhbElkID0gdGhpcy5zdGFjay5yZXNvbHZlKGNmbi5sb2dpY2FsSWQpIGFzIHN0cmluZztcblxuICAgIGNmbi5vdmVycmlkZUxvZ2ljYWxJZChMYXp5LnVuY2FjaGVkU3RyaW5nKHtcbiAgICAgIHByb2R1Y2U6ICgpID0+IHtcbiAgICAgICAgY29uc3QgaGFzaCA9IGNhbGN1bGF0ZUZ1bmN0aW9uSGFzaCh0aGlzKTtcbiAgICAgICAgY29uc3QgbG9naWNhbElkID0gdHJpbUZyb21TdGFydChvcmlnaW5hbExvZ2ljYWxJZCwgMjU1IC0gMzIpO1xuICAgICAgICByZXR1cm4gYCR7bG9naWNhbElkfSR7aGFzaH1gO1xuICAgICAgfSxcbiAgICB9KSk7XG5cbiAgICByZXR1cm4gdGhpcy5fY3VycmVudFZlcnNpb247XG4gIH1cblxuICBwdWJsaWMgZ2V0IHJlc291cmNlQXJuc0ZvckdyYW50SW52b2tlKCkge1xuICAgIHJldHVybiBbdGhpcy5mdW5jdGlvbkFybiwgYCR7dGhpcy5mdW5jdGlvbkFybn06KmBdO1xuICB9XG5cbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBwdWJsaWMgc3RhdGljIF9WRVJfUFJPUFM6IHsgW2tleTogc3RyaW5nXTogYm9vbGVhbiB9ID0ge307XG5cbiAgLyoqXG4gICAqIFJlY29yZCB3aGV0aGVyIHNwZWNpZmljIHByb3BlcnRpZXMgaW4gdGhlIGBBV1M6OkxhbWJkYTo6RnVuY3Rpb25gIHJlc291cmNlIHNob3VsZFxuICAgKiBhbHNvIGJlIGFzc29jaWF0ZWQgdG8gdGhlIFZlcnNpb24gcmVzb3VyY2UuXG4gICAqIFNlZSAnY3VycmVudFZlcnNpb24nIHNlY3Rpb24gaW4gdGhlIG1vZHVsZSBSRUFETUUgZm9yIG1vcmUgZGV0YWlscy5cbiAgICogQHBhcmFtIHByb3BlcnR5TmFtZSBUaGUgcHJvcGVydHkgdG8gY2xhc3NpZnlcbiAgICogQHBhcmFtIGxvY2tlZCB3aGV0aGVyIHRoZSBwcm9wZXJ0eSBzaG91bGQgYmUgYXNzb2NpYXRlZCB0byB0aGUgdmVyc2lvbiBvciBub3QuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGNsYXNzaWZ5VmVyc2lvblByb3BlcnR5KHByb3BlcnR5TmFtZTogc3RyaW5nLCBsb2NrZWQ6IGJvb2xlYW4pIHtcbiAgICB0aGlzLl9WRVJfUFJPUFNbcHJvcGVydHlOYW1lXSA9IGxvY2tlZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbXBvcnQgYSBsYW1iZGEgZnVuY3Rpb24gaW50byB0aGUgQ0RLIHVzaW5nIGl0cyBuYW1lXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGZyb21GdW5jdGlvbk5hbWUoc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgZnVuY3Rpb25OYW1lOiBzdHJpbmcpOiBJRnVuY3Rpb24ge1xuICAgIHJldHVybiBGdW5jdGlvbi5mcm9tRnVuY3Rpb25BdHRyaWJ1dGVzKHNjb3BlLCBpZCwge1xuICAgICAgZnVuY3Rpb25Bcm46IFN0YWNrLm9mKHNjb3BlKS5mb3JtYXRBcm4oe1xuICAgICAgICBzZXJ2aWNlOiAnbGFtYmRhJyxcbiAgICAgICAgcmVzb3VyY2U6ICdmdW5jdGlvbicsXG4gICAgICAgIHJlc291cmNlTmFtZTogZnVuY3Rpb25OYW1lLFxuICAgICAgICBhcm5Gb3JtYXQ6IEFybkZvcm1hdC5DT0xPTl9SRVNPVVJDRV9OQU1FLFxuICAgICAgfSksXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogSW1wb3J0IGEgbGFtYmRhIGZ1bmN0aW9uIGludG8gdGhlIENESyB1c2luZyBpdHMgQVJOXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGZyb21GdW5jdGlvbkFybihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBmdW5jdGlvbkFybjogc3RyaW5nKTogSUZ1bmN0aW9uIHtcbiAgICByZXR1cm4gRnVuY3Rpb24uZnJvbUZ1bmN0aW9uQXR0cmlidXRlcyhzY29wZSwgaWQsIHsgZnVuY3Rpb25Bcm4gfSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIExhbWJkYSBmdW5jdGlvbiBvYmplY3Qgd2hpY2ggcmVwcmVzZW50cyBhIGZ1bmN0aW9uIG5vdCBkZWZpbmVkXG4gICAqIHdpdGhpbiB0aGlzIHN0YWNrLlxuICAgKlxuICAgKiBAcGFyYW0gc2NvcGUgVGhlIHBhcmVudCBjb25zdHJ1Y3RcbiAgICogQHBhcmFtIGlkIFRoZSBuYW1lIG9mIHRoZSBsYW1iZGEgY29uc3RydWN0XG4gICAqIEBwYXJhbSBhdHRycyB0aGUgYXR0cmlidXRlcyBvZiB0aGUgZnVuY3Rpb24gdG8gaW1wb3J0XG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGZyb21GdW5jdGlvbkF0dHJpYnV0ZXMoc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgYXR0cnM6IEZ1bmN0aW9uQXR0cmlidXRlcyk6IElGdW5jdGlvbiB7XG4gICAgY29uc3QgZnVuY3Rpb25Bcm4gPSBhdHRycy5mdW5jdGlvbkFybjtcbiAgICBjb25zdCBmdW5jdGlvbk5hbWUgPSBleHRyYWN0TmFtZUZyb21Bcm4oYXR0cnMuZnVuY3Rpb25Bcm4pO1xuICAgIGNvbnN0IHJvbGUgPSBhdHRycy5yb2xlO1xuXG4gICAgY2xhc3MgSW1wb3J0IGV4dGVuZHMgRnVuY3Rpb25CYXNlIHtcbiAgICAgIHB1YmxpYyByZWFkb25seSBmdW5jdGlvbk5hbWUgPSBmdW5jdGlvbk5hbWU7XG4gICAgICBwdWJsaWMgcmVhZG9ubHkgZnVuY3Rpb25Bcm4gPSBmdW5jdGlvbkFybjtcbiAgICAgIHB1YmxpYyByZWFkb25seSBncmFudFByaW5jaXBhbDogaWFtLklQcmluY2lwYWw7XG4gICAgICBwdWJsaWMgcmVhZG9ubHkgcm9sZSA9IHJvbGU7XG4gICAgICBwdWJsaWMgcmVhZG9ubHkgcGVybWlzc2lvbnNOb2RlID0gdGhpcy5ub2RlO1xuICAgICAgcHVibGljIHJlYWRvbmx5IGFyY2hpdGVjdHVyZSA9IGF0dHJzLmFyY2hpdGVjdHVyZSA/PyBBcmNoaXRlY3R1cmUuWDg2XzY0O1xuICAgICAgcHVibGljIHJlYWRvbmx5IHJlc291cmNlQXJuc0ZvckdyYW50SW52b2tlID0gW3RoaXMuZnVuY3Rpb25Bcm4sIGAke3RoaXMuZnVuY3Rpb25Bcm59OipgXTtcblxuICAgICAgcHJvdGVjdGVkIHJlYWRvbmx5IGNhbkNyZWF0ZVBlcm1pc3Npb25zID0gYXR0cnMuc2FtZUVudmlyb25tZW50ID8/IHRoaXMuX2lzU3RhY2tBY2NvdW50KCk7XG4gICAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgX3NraXBQZXJtaXNzaW9ucyA9IGF0dHJzLnNraXBQZXJtaXNzaW9ucyA/PyBmYWxzZTtcblxuICAgICAgY29uc3RydWN0b3IoczogQ29uc3RydWN0LCBpOiBzdHJpbmcpIHtcbiAgICAgICAgc3VwZXIocywgaSwge1xuICAgICAgICAgIGVudmlyb25tZW50RnJvbUFybjogZnVuY3Rpb25Bcm4sXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMuZ3JhbnRQcmluY2lwYWwgPSByb2xlIHx8IG5ldyBpYW0uVW5rbm93blByaW5jaXBhbCh7IHJlc291cmNlOiB0aGlzIH0pO1xuXG4gICAgICAgIGlmIChhdHRycy5zZWN1cml0eUdyb3VwKSB7XG4gICAgICAgICAgdGhpcy5fY29ubmVjdGlvbnMgPSBuZXcgZWMyLkNvbm5lY3Rpb25zKHtcbiAgICAgICAgICAgIHNlY3VyaXR5R3JvdXBzOiBbYXR0cnMuc2VjdXJpdHlHcm91cF0sXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAoYXR0cnMuc2VjdXJpdHlHcm91cElkKSB7XG4gICAgICAgICAgdGhpcy5fY29ubmVjdGlvbnMgPSBuZXcgZWMyLkNvbm5lY3Rpb25zKHtcbiAgICAgICAgICAgIHNlY3VyaXR5R3JvdXBzOiBbZWMyLlNlY3VyaXR5R3JvdXAuZnJvbVNlY3VyaXR5R3JvdXBJZChzY29wZSwgJ1NlY3VyaXR5R3JvdXAnLCBhdHRycy5zZWN1cml0eUdyb3VwSWQpXSxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBuZXcgSW1wb3J0KHNjb3BlLCBpZCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIHRoZSBnaXZlbiBuYW1lZCBtZXRyaWMgZm9yIHRoaXMgTGFtYmRhXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIG1ldHJpY0FsbChtZXRyaWNOYW1lOiBzdHJpbmcsIHByb3BzPzogY2xvdWR3YXRjaC5NZXRyaWNPcHRpb25zKTogY2xvdWR3YXRjaC5NZXRyaWMge1xuICAgIHJldHVybiBuZXcgY2xvdWR3YXRjaC5NZXRyaWMoe1xuICAgICAgbmFtZXNwYWNlOiAnQVdTL0xhbWJkYScsXG4gICAgICBtZXRyaWNOYW1lLFxuICAgICAgLi4ucHJvcHMsXG4gICAgfSk7XG4gIH1cbiAgLyoqXG4gICAqIE1ldHJpYyBmb3IgdGhlIG51bWJlciBvZiBFcnJvcnMgZXhlY3V0aW5nIGFsbCBMYW1iZGFzXG4gICAqXG4gICAqIEBkZWZhdWx0IHN1bSBvdmVyIDUgbWludXRlc1xuICAgKi9cbiAgcHVibGljIHN0YXRpYyBtZXRyaWNBbGxFcnJvcnMocHJvcHM/OiBjbG91ZHdhdGNoLk1ldHJpY09wdGlvbnMpOiBjbG91ZHdhdGNoLk1ldHJpYyB7XG4gICAgcmV0dXJuIHRoaXMubWV0cmljQWxsKCdFcnJvcnMnLCB7IHN0YXRpc3RpYzogJ3N1bScsIC4uLnByb3BzIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldHJpYyBmb3IgdGhlIER1cmF0aW9uIGV4ZWN1dGluZyBhbGwgTGFtYmRhc1xuICAgKlxuICAgKiBAZGVmYXVsdCBhdmVyYWdlIG92ZXIgNSBtaW51dGVzXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIG1ldHJpY0FsbER1cmF0aW9uKHByb3BzPzogY2xvdWR3YXRjaC5NZXRyaWNPcHRpb25zKTogY2xvdWR3YXRjaC5NZXRyaWMge1xuICAgIHJldHVybiB0aGlzLm1ldHJpY0FsbCgnRHVyYXRpb24nLCBwcm9wcyk7XG4gIH1cblxuICAvKipcbiAgICogTWV0cmljIGZvciB0aGUgbnVtYmVyIG9mIGludm9jYXRpb25zIG9mIGFsbCBMYW1iZGFzXG4gICAqXG4gICAqIEBkZWZhdWx0IHN1bSBvdmVyIDUgbWludXRlc1xuICAgKi9cbiAgcHVibGljIHN0YXRpYyBtZXRyaWNBbGxJbnZvY2F0aW9ucyhwcm9wcz86IGNsb3Vkd2F0Y2guTWV0cmljT3B0aW9ucyk6IGNsb3Vkd2F0Y2guTWV0cmljIHtcbiAgICByZXR1cm4gdGhpcy5tZXRyaWNBbGwoJ0ludm9jYXRpb25zJywgeyBzdGF0aXN0aWM6ICdzdW0nLCAuLi5wcm9wcyB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRyaWMgZm9yIHRoZSBudW1iZXIgb2YgdGhyb3R0bGVkIGludm9jYXRpb25zIG9mIGFsbCBMYW1iZGFzXG4gICAqXG4gICAqIEBkZWZhdWx0IHN1bSBvdmVyIDUgbWludXRlc1xuICAgKi9cbiAgcHVibGljIHN0YXRpYyBtZXRyaWNBbGxUaHJvdHRsZXMocHJvcHM/OiBjbG91ZHdhdGNoLk1ldHJpY09wdGlvbnMpOiBjbG91ZHdhdGNoLk1ldHJpYyB7XG4gICAgcmV0dXJuIHRoaXMubWV0cmljQWxsKCdUaHJvdHRsZXMnLCB7IHN0YXRpc3RpYzogJ3N1bScsIC4uLnByb3BzIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldHJpYyBmb3IgdGhlIG51bWJlciBvZiBjb25jdXJyZW50IGV4ZWN1dGlvbnMgYWNyb3NzIGFsbCBMYW1iZGFzXG4gICAqXG4gICAqIEBkZWZhdWx0IG1heCBvdmVyIDUgbWludXRlc1xuICAgKi9cbiAgcHVibGljIHN0YXRpYyBtZXRyaWNBbGxDb25jdXJyZW50RXhlY3V0aW9ucyhwcm9wcz86IGNsb3Vkd2F0Y2guTWV0cmljT3B0aW9ucyk6IGNsb3Vkd2F0Y2guTWV0cmljIHtcbiAgICAvLyBNaW5pLUZBUTogd2h5IG1heD8gVGhpcyBtZXRyaWMgaXMgYSBnYXVnZSB0aGF0IGlzIGVtaXR0ZWQgZXZlcnlcbiAgICAvLyBtaW51dGUsIHNvIGVpdGhlciBtYXggb3IgYXZnIG9yIGEgcGVyY2VudGlsZSBtYWtlIHNlbnNlIChidXQgc3VtXG4gICAgLy8gZG9lc24ndCkuIE1heCBpcyBtb3JlIHNlbnNpdGl2ZSB0byBzcGlreSBsb2FkIGNoYW5nZXMgd2hpY2ggaXNcbiAgICAvLyBwcm9iYWJseSB3aGF0IHlvdSdyZSBpbnRlcmVzdGVkIGluIGlmIHlvdSdyZSBsb29raW5nIGF0IHRoaXMgbWV0cmljXG4gICAgLy8gKExvYWQgc3Bpa2VzIG1heSBsZWFkIHRvIGNvbmN1cnJlbnQgZXhlY3V0aW9uIGVycm9ycyB0aGF0IHdvdWxkXG4gICAgLy8gb3RoZXJ3aXNlIG5vdCBiZSB2aXNpYmxlIGluIHRoZSBhdmcpXG4gICAgcmV0dXJuIHRoaXMubWV0cmljQWxsKCdDb25jdXJyZW50RXhlY3V0aW9ucycsIHsgc3RhdGlzdGljOiAnbWF4JywgLi4ucHJvcHMgfSk7XG4gIH1cblxuICAvKipcbiAgICogTWV0cmljIGZvciB0aGUgbnVtYmVyIG9mIHVucmVzZXJ2ZWQgY29uY3VycmVudCBleGVjdXRpb25zIGFjcm9zcyBhbGwgTGFtYmRhc1xuICAgKlxuICAgKiBAZGVmYXVsdCBtYXggb3ZlciA1IG1pbnV0ZXNcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgbWV0cmljQWxsVW5yZXNlcnZlZENvbmN1cnJlbnRFeGVjdXRpb25zKHByb3BzPzogY2xvdWR3YXRjaC5NZXRyaWNPcHRpb25zKTogY2xvdWR3YXRjaC5NZXRyaWMge1xuICAgIHJldHVybiB0aGlzLm1ldHJpY0FsbCgnVW5yZXNlcnZlZENvbmN1cnJlbnRFeGVjdXRpb25zJywgeyBzdGF0aXN0aWM6ICdtYXgnLCAuLi5wcm9wcyB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBOYW1lIG9mIHRoaXMgZnVuY3Rpb25cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBmdW5jdGlvbk5hbWU6IHN0cmluZztcblxuICAvKipcbiAgICogQVJOIG9mIHRoaXMgZnVuY3Rpb25cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBmdW5jdGlvbkFybjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBFeGVjdXRpb24gcm9sZSBhc3NvY2lhdGVkIHdpdGggdGhpcyBmdW5jdGlvblxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHJvbGU/OiBpYW0uSVJvbGU7XG5cbiAgLyoqXG4gICAqIFRoZSBydW50aW1lIGNvbmZpZ3VyZWQgZm9yIHRoaXMgbGFtYmRhLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHJ1bnRpbWU6IFJ1bnRpbWU7XG5cbiAgLyoqXG4gICAqIFRoZSBwcmluY2lwYWwgdGhpcyBMYW1iZGEgRnVuY3Rpb24gaXMgcnVubmluZyBhc1xuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGdyYW50UHJpbmNpcGFsOiBpYW0uSVByaW5jaXBhbDtcblxuICAvKipcbiAgICogVGhlIERMUSAoYXMgcXVldWUpIGFzc29jaWF0ZWQgd2l0aCB0aGlzIExhbWJkYSBGdW5jdGlvbiAodGhpcyBpcyBhbiBvcHRpb25hbCBhdHRyaWJ1dGUpLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IGRlYWRMZXR0ZXJRdWV1ZT86IHNxcy5JUXVldWU7XG5cbiAgLyoqXG4gICAqIFRoZSBETFEgKGFzIHRvcGljKSBhc3NvY2lhdGVkIHdpdGggdGhpcyBMYW1iZGEgRnVuY3Rpb24gKHRoaXMgaXMgYW4gb3B0aW9uYWwgYXR0cmlidXRlKS5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBkZWFkTGV0dGVyVG9waWM/OiBzbnMuSVRvcGljO1xuXG4gIC8qKlxuICAgKiBUaGUgYXJjaGl0ZWN0dXJlIG9mIHRoaXMgTGFtYmRhIEZ1bmN0aW9uICh0aGlzIGlzIGFuIG9wdGlvbmFsIGF0dHJpYnV0ZSBhbmQgZGVmYXVsdHMgdG8gWDg2XzY0KS5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBhcmNoaXRlY3R1cmU6IEFyY2hpdGVjdHVyZTtcblxuICAvKipcbiAgICogVGhlIHRpbWVvdXQgY29uZmlndXJlZCBmb3IgdGhpcyBsYW1iZGEuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgdGltZW91dD86IER1cmF0aW9uO1xuXG4gIHB1YmxpYyByZWFkb25seSBwZXJtaXNzaW9uc05vZGUgPSB0aGlzLm5vZGU7XG5cblxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgY2FuQ3JlYXRlUGVybWlzc2lvbnMgPSB0cnVlO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgbGF5ZXJzOiBJTGF5ZXJWZXJzaW9uW10gPSBbXTtcblxuICBwcml2YXRlIF9sb2dHcm91cD86IGxvZ3MuSUxvZ0dyb3VwO1xuXG4gIC8qKlxuICAgKiBFbnZpcm9ubWVudCB2YXJpYWJsZXMgZm9yIHRoaXMgZnVuY3Rpb25cbiAgICovXG4gIHByaXZhdGUgZW52aXJvbm1lbnQ6IHsgW2tleTogc3RyaW5nXTogRW52aXJvbm1lbnRDb25maWcgfSA9IHt9O1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgY3VycmVudFZlcnNpb25PcHRpb25zPzogVmVyc2lvbk9wdGlvbnM7XG4gIHByaXZhdGUgX2N1cnJlbnRWZXJzaW9uPzogVmVyc2lvbjtcblxuICBwcml2YXRlIF9hcmNoaXRlY3R1cmU/OiBBcmNoaXRlY3R1cmU7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IEZ1bmN0aW9uUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQsIHtcbiAgICAgIHBoeXNpY2FsTmFtZTogcHJvcHMuZnVuY3Rpb25OYW1lLFxuICAgIH0pO1xuXG4gICAgaWYgKHByb3BzLmZ1bmN0aW9uTmFtZSAmJiAhVG9rZW4uaXNVbnJlc29sdmVkKHByb3BzLmZ1bmN0aW9uTmFtZSkpIHtcbiAgICAgIGlmIChwcm9wcy5mdW5jdGlvbk5hbWUubGVuZ3RoID4gNjQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBGdW5jdGlvbiBuYW1lIGNhbiBub3QgYmUgbG9uZ2VyIHRoYW4gNjQgY2hhcmFjdGVycyBidXQgaGFzICR7cHJvcHMuZnVuY3Rpb25OYW1lLmxlbmd0aH0gY2hhcmFjdGVycy5gKTtcbiAgICAgIH1cbiAgICAgIGlmICghL15bYS16QS1aMC05LV9dKyQvLnRlc3QocHJvcHMuZnVuY3Rpb25OYW1lKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEZ1bmN0aW9uIG5hbWUgJHtwcm9wcy5mdW5jdGlvbk5hbWV9IGNhbiBjb250YWluIG9ubHkgbGV0dGVycywgbnVtYmVycywgaHlwaGVucywgb3IgdW5kZXJzY29yZXMgd2l0aCBubyBzcGFjZXMuYCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgbWFuYWdlZFBvbGljaWVzID0gbmV3IEFycmF5PGlhbS5JTWFuYWdlZFBvbGljeT4oKTtcblxuICAgIC8vIHRoZSBhcm4gaXMgaW4gdGhlIGZvcm0gb2YgLSBhcm46YXdzOmlhbTo6YXdzOnBvbGljeS9zZXJ2aWNlLXJvbGUvQVdTTGFtYmRhQmFzaWNFeGVjdXRpb25Sb2xlXG4gICAgbWFuYWdlZFBvbGljaWVzLnB1c2goaWFtLk1hbmFnZWRQb2xpY3kuZnJvbUF3c01hbmFnZWRQb2xpY3lOYW1lKCdzZXJ2aWNlLXJvbGUvQVdTTGFtYmRhQmFzaWNFeGVjdXRpb25Sb2xlJykpO1xuXG4gICAgaWYgKHByb3BzLnZwYykge1xuICAgICAgLy8gUG9saWN5IHRoYXQgd2lsbCBoYXZlIEVOSSBjcmVhdGlvbiBwZXJtaXNzaW9uc1xuICAgICAgbWFuYWdlZFBvbGljaWVzLnB1c2goaWFtLk1hbmFnZWRQb2xpY3kuZnJvbUF3c01hbmFnZWRQb2xpY3lOYW1lKCdzZXJ2aWNlLXJvbGUvQVdTTGFtYmRhVlBDQWNjZXNzRXhlY3V0aW9uUm9sZScpKTtcbiAgICB9XG5cbiAgICB0aGlzLnJvbGUgPSBwcm9wcy5yb2xlIHx8IG5ldyBpYW0uUm9sZSh0aGlzLCAnU2VydmljZVJvbGUnLCB7XG4gICAgICBhc3N1bWVkQnk6IG5ldyBpYW0uU2VydmljZVByaW5jaXBhbCgnbGFtYmRhLmFtYXpvbmF3cy5jb20nKSxcbiAgICAgIG1hbmFnZWRQb2xpY2llcyxcbiAgICB9KTtcbiAgICB0aGlzLmdyYW50UHJpbmNpcGFsID0gdGhpcy5yb2xlO1xuXG4gICAgLy8gYWRkIGFkZGl0aW9uYWwgbWFuYWdlZCBwb2xpY2llcyB3aGVuIG5lY2Vzc2FyeVxuICAgIGlmIChwcm9wcy5maWxlc3lzdGVtKSB7XG4gICAgICBjb25zdCBjb25maWcgPSBwcm9wcy5maWxlc3lzdGVtLmNvbmZpZztcbiAgICAgIGlmIChjb25maWcucG9saWNpZXMpIHtcbiAgICAgICAgY29uZmlnLnBvbGljaWVzLmZvckVhY2gocCA9PiB7XG4gICAgICAgICAgdGhpcy5yb2xlPy5hZGRUb1ByaW5jaXBhbFBvbGljeShwKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBzdGF0ZW1lbnQgb2YgKHByb3BzLmluaXRpYWxQb2xpY3kgfHwgW10pKSB7XG4gICAgICB0aGlzLnJvbGUuYWRkVG9QcmluY2lwYWxQb2xpY3koc3RhdGVtZW50KTtcbiAgICB9XG5cbiAgICBjb25zdCBjb2RlID0gcHJvcHMuY29kZS5iaW5kKHRoaXMpO1xuICAgIHZlcmlmeUNvZGVDb25maWcoY29kZSwgcHJvcHMpO1xuXG4gICAgbGV0IHByb2ZpbGluZ0dyb3VwRW52aXJvbm1lbnRWYXJpYWJsZXM6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0gPSB7fTtcbiAgICBpZiAocHJvcHMucHJvZmlsaW5nR3JvdXAgJiYgcHJvcHMucHJvZmlsaW5nICE9PSBmYWxzZSkge1xuICAgICAgdGhpcy52YWxpZGF0ZVByb2ZpbGluZyhwcm9wcyk7XG4gICAgICBwcm9wcy5wcm9maWxpbmdHcm91cC5ncmFudFB1Ymxpc2godGhpcy5yb2xlKTtcbiAgICAgIHByb2ZpbGluZ0dyb3VwRW52aXJvbm1lbnRWYXJpYWJsZXMgPSB7XG4gICAgICAgIEFXU19DT0RFR1VSVV9QUk9GSUxFUl9HUk9VUF9BUk46IFN0YWNrLm9mKHNjb3BlKS5mb3JtYXRBcm4oe1xuICAgICAgICAgIHNlcnZpY2U6ICdjb2RlZ3VydS1wcm9maWxlcicsXG4gICAgICAgICAgcmVzb3VyY2U6ICdwcm9maWxpbmdHcm91cCcsXG4gICAgICAgICAgcmVzb3VyY2VOYW1lOiBwcm9wcy5wcm9maWxpbmdHcm91cC5wcm9maWxpbmdHcm91cE5hbWUsXG4gICAgICAgIH0pLFxuICAgICAgICBBV1NfQ09ERUdVUlVfUFJPRklMRVJfRU5BQkxFRDogJ1RSVUUnLFxuICAgICAgfTtcbiAgICB9IGVsc2UgaWYgKHByb3BzLnByb2ZpbGluZykge1xuICAgICAgdGhpcy52YWxpZGF0ZVByb2ZpbGluZyhwcm9wcyk7XG4gICAgICBjb25zdCBwcm9maWxpbmdHcm91cCA9IG5ldyBQcm9maWxpbmdHcm91cCh0aGlzLCAnUHJvZmlsaW5nR3JvdXAnLCB7XG4gICAgICAgIGNvbXB1dGVQbGF0Zm9ybTogQ29tcHV0ZVBsYXRmb3JtLkFXU19MQU1CREEsXG4gICAgICB9KTtcbiAgICAgIHByb2ZpbGluZ0dyb3VwLmdyYW50UHVibGlzaCh0aGlzLnJvbGUpO1xuICAgICAgcHJvZmlsaW5nR3JvdXBFbnZpcm9ubWVudFZhcmlhYmxlcyA9IHtcbiAgICAgICAgQVdTX0NPREVHVVJVX1BST0ZJTEVSX0dST1VQX0FSTjogcHJvZmlsaW5nR3JvdXAucHJvZmlsaW5nR3JvdXBBcm4sXG4gICAgICAgIEFXU19DT0RFR1VSVV9QUk9GSUxFUl9FTkFCTEVEOiAnVFJVRScsXG4gICAgICB9O1xuICAgIH1cblxuICAgIGNvbnN0IGVudiA9IHsgLi4ucHJvZmlsaW5nR3JvdXBFbnZpcm9ubWVudFZhcmlhYmxlcywgLi4ucHJvcHMuZW52aXJvbm1lbnQgfTtcbiAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhlbnYpKSB7XG4gICAgICB0aGlzLmFkZEVudmlyb25tZW50KGtleSwgdmFsdWUpO1xuICAgIH1cblxuICAgIC8vIERMUSBjYW4gYmUgZWl0aGVyIHNucy5JVG9waWMgb3Igc3FzLklRdWV1ZVxuICAgIGNvbnN0IGRscVRvcGljT3JRdWV1ZSA9IHRoaXMuYnVpbGREZWFkTGV0dGVyUXVldWUocHJvcHMpO1xuICAgIGlmIChkbHFUb3BpY09yUXVldWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgaWYgKHRoaXMuaXNRdWV1ZShkbHFUb3BpY09yUXVldWUpKSB7XG4gICAgICAgIHRoaXMuZGVhZExldHRlclF1ZXVlID0gZGxxVG9waWNPclF1ZXVlO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5kZWFkTGV0dGVyVG9waWMgPSBkbHFUb3BpY09yUXVldWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgbGV0IGZpbGVTeXN0ZW1Db25maWdzOiBDZm5GdW5jdGlvbi5GaWxlU3lzdGVtQ29uZmlnUHJvcGVydHlbXSB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZDtcbiAgICBpZiAocHJvcHMuZmlsZXN5c3RlbSkge1xuICAgICAgZmlsZVN5c3RlbUNvbmZpZ3MgPSBbe1xuICAgICAgICBhcm46IHByb3BzLmZpbGVzeXN0ZW0uY29uZmlnLmFybixcbiAgICAgICAgbG9jYWxNb3VudFBhdGg6IHByb3BzLmZpbGVzeXN0ZW0uY29uZmlnLmxvY2FsTW91bnRQYXRoLFxuICAgICAgfV07XG4gICAgfVxuXG4gICAgaWYgKHByb3BzLmFyY2hpdGVjdHVyZSAmJiBwcm9wcy5hcmNoaXRlY3R1cmVzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRWl0aGVyIGFyY2hpdGVjdHVyZSBvciBhcmNoaXRlY3R1cmVzIG11c3QgYmUgc3BlY2lmaWVkIGJ1dCBub3QgYm90aC4nKTtcbiAgICB9XG4gICAgaWYgKHByb3BzLmFyY2hpdGVjdHVyZXMgJiYgcHJvcHMuYXJjaGl0ZWN0dXJlcy5sZW5ndGggPiAxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ09ubHkgb25lIGFyY2hpdGVjdHVyZSBtdXN0IGJlIHNwZWNpZmllZC4nKTtcbiAgICB9XG4gICAgdGhpcy5fYXJjaGl0ZWN0dXJlID0gcHJvcHMuYXJjaGl0ZWN0dXJlID8/IChwcm9wcy5hcmNoaXRlY3R1cmVzICYmIHByb3BzLmFyY2hpdGVjdHVyZXNbMF0pO1xuXG4gICAgaWYgKHByb3BzLmVwaGVtZXJhbFN0b3JhZ2VTaXplICYmICFwcm9wcy5lcGhlbWVyYWxTdG9yYWdlU2l6ZS5pc1VucmVzb2x2ZWQoKVxuICAgICAgJiYgKHByb3BzLmVwaGVtZXJhbFN0b3JhZ2VTaXplLnRvTWViaWJ5dGVzKCkgPCA1MTIgfHwgcHJvcHMuZXBoZW1lcmFsU3RvcmFnZVNpemUudG9NZWJpYnl0ZXMoKSA+IDEwMjQwKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBFcGhlbWVyYWwgc3RvcmFnZSBzaXplIG11c3QgYmUgYmV0d2VlbiA1MTIgYW5kIDEwMjQwIE1CLCByZWNlaXZlZCAke3Byb3BzLmVwaGVtZXJhbFN0b3JhZ2VTaXplfS5gKTtcbiAgICB9XG5cbiAgICBjb25zdCByZXNvdXJjZTogQ2ZuRnVuY3Rpb24gPSBuZXcgQ2ZuRnVuY3Rpb24odGhpcywgJ1Jlc291cmNlJywge1xuICAgICAgZnVuY3Rpb25OYW1lOiB0aGlzLnBoeXNpY2FsTmFtZSxcbiAgICAgIGRlc2NyaXB0aW9uOiBwcm9wcy5kZXNjcmlwdGlvbixcbiAgICAgIGNvZGU6IHtcbiAgICAgICAgczNCdWNrZXQ6IGNvZGUuczNMb2NhdGlvbiAmJiBjb2RlLnMzTG9jYXRpb24uYnVja2V0TmFtZSxcbiAgICAgICAgczNLZXk6IGNvZGUuczNMb2NhdGlvbiAmJiBjb2RlLnMzTG9jYXRpb24ub2JqZWN0S2V5LFxuICAgICAgICBzM09iamVjdFZlcnNpb246IGNvZGUuczNMb2NhdGlvbiAmJiBjb2RlLnMzTG9jYXRpb24ub2JqZWN0VmVyc2lvbixcbiAgICAgICAgemlwRmlsZTogY29kZS5pbmxpbmVDb2RlLFxuICAgICAgICBpbWFnZVVyaTogY29kZS5pbWFnZT8uaW1hZ2VVcmksXG4gICAgICB9LFxuICAgICAgbGF5ZXJzOiBMYXp5Lmxpc3QoeyBwcm9kdWNlOiAoKSA9PiB0aGlzLmxheWVycy5tYXAobGF5ZXIgPT4gbGF5ZXIubGF5ZXJWZXJzaW9uQXJuKSB9LCB7IG9taXRFbXB0eTogdHJ1ZSB9KSwgLy8gRXZhbHVhdGVkIG9uIHN5bnRoZXNpc1xuICAgICAgaGFuZGxlcjogcHJvcHMuaGFuZGxlciA9PT0gSGFuZGxlci5GUk9NX0lNQUdFID8gdW5kZWZpbmVkIDogcHJvcHMuaGFuZGxlcixcbiAgICAgIHRpbWVvdXQ6IHByb3BzLnRpbWVvdXQgJiYgcHJvcHMudGltZW91dC50b1NlY29uZHMoKSxcbiAgICAgIHBhY2thZ2VUeXBlOiBwcm9wcy5ydW50aW1lID09PSBSdW50aW1lLkZST01fSU1BR0UgPyAnSW1hZ2UnIDogdW5kZWZpbmVkLFxuICAgICAgcnVudGltZTogcHJvcHMucnVudGltZSA9PT0gUnVudGltZS5GUk9NX0lNQUdFID8gdW5kZWZpbmVkIDogcHJvcHMucnVudGltZS5uYW1lLFxuICAgICAgcm9sZTogdGhpcy5yb2xlLnJvbGVBcm4sXG4gICAgICAvLyBVbmNhY2hlZCBiZWNhdXNlIGNhbGxpbmcgJ19jaGVja0VkZ2VDb21wYXRpYmlsaXR5Jywgd2hpY2ggZ2V0cyBjYWxsZWQgaW4gdGhlIHJlc29sdmUgb2YgYW5vdGhlclxuICAgICAgLy8gVG9rZW4sIGFjdHVhbGx5ICptb2RpZmllcyogdGhlICdlbnZpcm9ubWVudCcgbWFwLlxuICAgICAgZW52aXJvbm1lbnQ6IExhenkudW5jYWNoZWRBbnkoeyBwcm9kdWNlOiAoKSA9PiB0aGlzLnJlbmRlckVudmlyb25tZW50KCkgfSksXG4gICAgICBtZW1vcnlTaXplOiBwcm9wcy5tZW1vcnlTaXplLFxuICAgICAgZXBoZW1lcmFsU3RvcmFnZTogcHJvcHMuZXBoZW1lcmFsU3RvcmFnZVNpemUgPyB7XG4gICAgICAgIHNpemU6IHByb3BzLmVwaGVtZXJhbFN0b3JhZ2VTaXplLnRvTWViaWJ5dGVzKCksXG4gICAgICB9IDogdW5kZWZpbmVkLFxuICAgICAgdnBjQ29uZmlnOiB0aGlzLmNvbmZpZ3VyZVZwYyhwcm9wcyksXG4gICAgICBkZWFkTGV0dGVyQ29uZmlnOiB0aGlzLmJ1aWxkRGVhZExldHRlckNvbmZpZyhkbHFUb3BpY09yUXVldWUpLFxuICAgICAgdHJhY2luZ0NvbmZpZzogdGhpcy5idWlsZFRyYWNpbmdDb25maWcocHJvcHMpLFxuICAgICAgcmVzZXJ2ZWRDb25jdXJyZW50RXhlY3V0aW9uczogcHJvcHMucmVzZXJ2ZWRDb25jdXJyZW50RXhlY3V0aW9ucyxcbiAgICAgIGltYWdlQ29uZmlnOiB1bmRlZmluZWRJZk5vS2V5cyh7XG4gICAgICAgIGNvbW1hbmQ6IGNvZGUuaW1hZ2U/LmNtZCxcbiAgICAgICAgZW50cnlQb2ludDogY29kZS5pbWFnZT8uZW50cnlwb2ludCxcbiAgICAgICAgd29ya2luZ0RpcmVjdG9yeTogY29kZS5pbWFnZT8ud29ya2luZ0RpcmVjdG9yeSxcbiAgICAgIH0pLFxuICAgICAga21zS2V5QXJuOiBwcm9wcy5lbnZpcm9ubWVudEVuY3J5cHRpb24/LmtleUFybixcbiAgICAgIGZpbGVTeXN0ZW1Db25maWdzLFxuICAgICAgY29kZVNpZ25pbmdDb25maWdBcm46IHByb3BzLmNvZGVTaWduaW5nQ29uZmlnPy5jb2RlU2lnbmluZ0NvbmZpZ0FybixcbiAgICAgIGFyY2hpdGVjdHVyZXM6IHRoaXMuX2FyY2hpdGVjdHVyZSA/IFt0aGlzLl9hcmNoaXRlY3R1cmUubmFtZV0gOiB1bmRlZmluZWQsXG4gICAgfSk7XG5cbiAgICByZXNvdXJjZS5ub2RlLmFkZERlcGVuZGVuY3kodGhpcy5yb2xlKTtcblxuICAgIHRoaXMuZnVuY3Rpb25OYW1lID0gdGhpcy5nZXRSZXNvdXJjZU5hbWVBdHRyaWJ1dGUocmVzb3VyY2UucmVmKTtcbiAgICB0aGlzLmZ1bmN0aW9uQXJuID0gdGhpcy5nZXRSZXNvdXJjZUFybkF0dHJpYnV0ZShyZXNvdXJjZS5hdHRyQXJuLCB7XG4gICAgICBzZXJ2aWNlOiAnbGFtYmRhJyxcbiAgICAgIHJlc291cmNlOiAnZnVuY3Rpb24nLFxuICAgICAgcmVzb3VyY2VOYW1lOiB0aGlzLnBoeXNpY2FsTmFtZSxcbiAgICAgIGFybkZvcm1hdDogQXJuRm9ybWF0LkNPTE9OX1JFU09VUkNFX05BTUUsXG4gICAgfSk7XG5cbiAgICB0aGlzLnJ1bnRpbWUgPSBwcm9wcy5ydW50aW1lO1xuICAgIHRoaXMudGltZW91dCA9IHByb3BzLnRpbWVvdXQ7XG5cbiAgICB0aGlzLmFyY2hpdGVjdHVyZSA9IHByb3BzLmFyY2hpdGVjdHVyZSA/PyBBcmNoaXRlY3R1cmUuWDg2XzY0O1xuXG4gICAgaWYgKHByb3BzLmxheWVycykge1xuICAgICAgaWYgKHByb3BzLnJ1bnRpbWUgPT09IFJ1bnRpbWUuRlJPTV9JTUFHRSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0xheWVycyBhcmUgbm90IHN1cHBvcnRlZCBmb3IgY29udGFpbmVyIGltYWdlIGZ1bmN0aW9ucycpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLmFkZExheWVycyguLi5wcm9wcy5sYXllcnMpO1xuICAgIH1cblxuICAgIGZvciAoY29uc3QgZXZlbnQgb2YgcHJvcHMuZXZlbnRzIHx8IFtdKSB7XG4gICAgICB0aGlzLmFkZEV2ZW50U291cmNlKGV2ZW50KTtcbiAgICB9XG5cbiAgICAvLyBMb2cgcmV0ZW50aW9uXG4gICAgaWYgKHByb3BzLmxvZ1JldGVudGlvbikge1xuICAgICAgY29uc3QgbG9nUmV0ZW50aW9uID0gbmV3IGxvZ3MuTG9nUmV0ZW50aW9uKHRoaXMsICdMb2dSZXRlbnRpb24nLCB7XG4gICAgICAgIGxvZ0dyb3VwTmFtZTogYC9hd3MvbGFtYmRhLyR7dGhpcy5mdW5jdGlvbk5hbWV9YCxcbiAgICAgICAgcmV0ZW50aW9uOiBwcm9wcy5sb2dSZXRlbnRpb24sXG4gICAgICAgIHJvbGU6IHByb3BzLmxvZ1JldGVudGlvblJvbGUsXG4gICAgICAgIGxvZ1JldGVudGlvblJldHJ5T3B0aW9uczogcHJvcHMubG9nUmV0ZW50aW9uUmV0cnlPcHRpb25zIGFzIGxvZ3MuTG9nUmV0ZW50aW9uUmV0cnlPcHRpb25zLFxuICAgICAgfSk7XG4gICAgICB0aGlzLl9sb2dHcm91cCA9IGxvZ3MuTG9nR3JvdXAuZnJvbUxvZ0dyb3VwQXJuKHRoaXMsICdMb2dHcm91cCcsIGxvZ1JldGVudGlvbi5sb2dHcm91cEFybik7XG4gICAgfVxuXG4gICAgcHJvcHMuY29kZS5iaW5kVG9SZXNvdXJjZShyZXNvdXJjZSk7XG5cbiAgICAvLyBFdmVudCBJbnZva2UgQ29uZmlnXG4gICAgaWYgKHByb3BzLm9uRmFpbHVyZSB8fCBwcm9wcy5vblN1Y2Nlc3MgfHwgcHJvcHMubWF4RXZlbnRBZ2UgfHwgcHJvcHMucmV0cnlBdHRlbXB0cyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmNvbmZpZ3VyZUFzeW5jSW52b2tlKHtcbiAgICAgICAgb25GYWlsdXJlOiBwcm9wcy5vbkZhaWx1cmUsXG4gICAgICAgIG9uU3VjY2VzczogcHJvcHMub25TdWNjZXNzLFxuICAgICAgICBtYXhFdmVudEFnZTogcHJvcHMubWF4RXZlbnRBZ2UsXG4gICAgICAgIHJldHJ5QXR0ZW1wdHM6IHByb3BzLnJldHJ5QXR0ZW1wdHMsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICB0aGlzLmN1cnJlbnRWZXJzaW9uT3B0aW9ucyA9IHByb3BzLmN1cnJlbnRWZXJzaW9uT3B0aW9ucztcblxuICAgIGlmIChwcm9wcy5maWxlc3lzdGVtKSB7XG4gICAgICBpZiAoIXByb3BzLnZwYykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBjb25maWd1cmUgXFwnZmlsZXN5c3RlbVxcJyB3aXRob3V0IGNvbmZpZ3VyaW5nIGEgVlBDLicpO1xuICAgICAgfVxuICAgICAgY29uc3QgY29uZmlnID0gcHJvcHMuZmlsZXN5c3RlbS5jb25maWc7XG4gICAgICBpZiAoY29uZmlnLmRlcGVuZGVuY3kpIHtcbiAgICAgICAgdGhpcy5ub2RlLmFkZERlcGVuZGVuY3koLi4uY29uZmlnLmRlcGVuZGVuY3kpO1xuICAgICAgfVxuICAgICAgLy8gVGhlcmUgY291bGQgYmUgYSByYWNlIGlmIHRoZSBMYW1iZGEgaXMgdXNlZCBpbiBhIEN1c3RvbVJlc291cmNlLiBJdCBpcyBwb3NzaWJsZSBmb3IgdGhlIExhbWJkYSB0b1xuICAgICAgLy8gZmFpbCB0byBhdHRhY2ggdG8gYSBnaXZlbiBGaWxlU3lzdGVtIGlmIHdlIGRvIG5vdCBoYXZlIGEgZGVwZW5kZW5jeSBvbiB0aGUgU2VjdXJpdHlHcm91cCBpbmdyZXNzL2VncmVzc1xuICAgICAgLy8gcnVsZXMgdGhhdCB3ZXJlIGNyZWF0ZWQgYmV0d2VlbiB0aGlzIExhbWJkYSdzIFNHICYgdGhlIEZpbGVzeXN0ZW0gU0cuXG4gICAgICB0aGlzLmNvbm5lY3Rpb25zLnNlY3VyaXR5R3JvdXBzLmZvckVhY2goc2cgPT4ge1xuICAgICAgICBzZy5ub2RlLmZpbmRBbGwoKS5mb3JFYWNoKGNoaWxkID0+IHtcbiAgICAgICAgICBpZiAoY2hpbGQgaW5zdGFuY2VvZiBDZm5SZXNvdXJjZSAmJiBjaGlsZC5jZm5SZXNvdXJjZVR5cGUgPT09ICdBV1M6OkVDMjo6U2VjdXJpdHlHcm91cEVncmVzcycpIHtcbiAgICAgICAgICAgIHJlc291cmNlLm5vZGUuYWRkRGVwZW5kZW5jeShjaGlsZCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgICAgY29uZmlnLmNvbm5lY3Rpb25zPy5zZWN1cml0eUdyb3Vwcy5mb3JFYWNoKHNnID0+IHtcbiAgICAgICAgc2cubm9kZS5maW5kQWxsKCkuZm9yRWFjaChjaGlsZCA9PiB7XG4gICAgICAgICAgaWYgKGNoaWxkIGluc3RhbmNlb2YgQ2ZuUmVzb3VyY2UgJiYgY2hpbGQuY2ZuUmVzb3VyY2VUeXBlID09PSAnQVdTOjpFQzI6OlNlY3VyaXR5R3JvdXBJbmdyZXNzJykge1xuICAgICAgICAgICAgcmVzb3VyY2Uubm9kZS5hZGREZXBlbmRlbmN5KGNoaWxkKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gQ29uZmlndXJlIExhbWJkYSBpbnNpZ2h0c1xuICAgIHRoaXMuY29uZmlndXJlTGFtYmRhSW5zaWdodHMocHJvcHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYW4gZW52aXJvbm1lbnQgdmFyaWFibGUgdG8gdGhpcyBMYW1iZGEgZnVuY3Rpb24uXG4gICAqIElmIHRoaXMgaXMgYSByZWYgdG8gYSBMYW1iZGEgZnVuY3Rpb24sIHRoaXMgb3BlcmF0aW9uIHJlc3VsdHMgaW4gYSBuby1vcC5cbiAgICogQHBhcmFtIGtleSBUaGUgZW52aXJvbm1lbnQgdmFyaWFibGUga2V5LlxuICAgKiBAcGFyYW0gdmFsdWUgVGhlIGVudmlyb25tZW50IHZhcmlhYmxlJ3MgdmFsdWUuXG4gICAqIEBwYXJhbSBvcHRpb25zIEVudmlyb25tZW50IHZhcmlhYmxlIG9wdGlvbnMuXG4gICAqL1xuICBwdWJsaWMgYWRkRW52aXJvbm1lbnQoa2V5OiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcsIG9wdGlvbnM/OiBFbnZpcm9ubWVudE9wdGlvbnMpOiB0aGlzIHtcbiAgICB0aGlzLmVudmlyb25tZW50W2tleV0gPSB7IHZhbHVlLCAuLi5vcHRpb25zIH07XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBvbmUgb3IgbW9yZSBMYW1iZGEgTGF5ZXJzIHRvIHRoaXMgTGFtYmRhIGZ1bmN0aW9uLlxuICAgKlxuICAgKiBAcGFyYW0gbGF5ZXJzIHRoZSBsYXllcnMgdG8gYmUgYWRkZWQuXG4gICAqXG4gICAqIEB0aHJvd3MgaWYgdGhlcmUgYXJlIGFscmVhZHkgNSBsYXllcnMgb24gdGhpcyBmdW5jdGlvbiwgb3IgdGhlIGxheWVyIGlzIGluY29tcGF0aWJsZSB3aXRoIHRoaXMgZnVuY3Rpb24ncyBydW50aW1lLlxuICAgKi9cbiAgcHVibGljIGFkZExheWVycyguLi5sYXllcnM6IElMYXllclZlcnNpb25bXSk6IHZvaWQge1xuICAgIGZvciAoY29uc3QgbGF5ZXIgb2YgbGF5ZXJzKSB7XG4gICAgICBpZiAodGhpcy5sYXllcnMubGVuZ3RoID09PSA1KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignVW5hYmxlIHRvIGFkZCBsYXllcjogdGhpcyBsYW1iZGEgZnVuY3Rpb24gYWxyZWFkeSB1c2VzIDUgbGF5ZXJzLicpO1xuICAgICAgfVxuICAgICAgaWYgKGxheWVyLmNvbXBhdGlibGVSdW50aW1lcyAmJiAhbGF5ZXIuY29tcGF0aWJsZVJ1bnRpbWVzLmZpbmQocnVudGltZSA9PiBydW50aW1lLnJ1bnRpbWVFcXVhbHModGhpcy5ydW50aW1lKSkpIHtcbiAgICAgICAgY29uc3QgcnVudGltZXMgPSBsYXllci5jb21wYXRpYmxlUnVudGltZXMubWFwKHJ1bnRpbWUgPT4gcnVudGltZS5uYW1lKS5qb2luKCcsICcpO1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFRoaXMgbGFtYmRhIGZ1bmN0aW9uIHVzZXMgYSBydW50aW1lIHRoYXQgaXMgaW5jb21wYXRpYmxlIHdpdGggdGhpcyBsYXllciAoJHt0aGlzLnJ1bnRpbWUubmFtZX0gaXMgbm90IGluIFske3J1bnRpbWVzfV0pYCk7XG4gICAgICB9XG5cbiAgICAgIC8vIEN1cnJlbnRseSBubyB2YWxpZGF0aW9ucyBmb3IgY29tcGF0aWJsZSBhcmNoaXRlY3R1cmVzIHNpbmNlIExhbWJkYSBzZXJ2aWNlXG4gICAgICAvLyBhbGxvd3MgbGF5ZXJzIGNvbmZpZ3VyZWQgd2l0aCBvbmUgYXJjaGl0ZWN0dXJlIHRvIGJlIHVzZWQgd2l0aCBhIExhbWJkYSBmdW5jdGlvblxuICAgICAgLy8gZnJvbSBhbm90aGVyIGFyY2hpdGVjdHVyZS5cblxuICAgICAgdGhpcy5sYXllcnMucHVzaChsYXllcik7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBhIG5ldyB2ZXJzaW9uIGZvciB0aGlzIExhbWJkYVxuICAgKlxuICAgKiBJZiB5b3Ugd2FudCB0byBkZXBsb3kgdGhyb3VnaCBDbG91ZEZvcm1hdGlvbiBhbmQgdXNlIGFsaWFzZXMsIHlvdSBuZWVkIHRvXG4gICAqIGFkZCBhIG5ldyB2ZXJzaW9uICh3aXRoIGEgbmV3IG5hbWUpIHRvIHlvdXIgTGFtYmRhIGV2ZXJ5IHRpbWUgeW91IHdhbnQgdG9cbiAgICogZGVwbG95IGFuIHVwZGF0ZS4gQW4gYWxpYXMgY2FuIHRoZW4gcmVmZXIgdG8gdGhlIG5ld2x5IGNyZWF0ZWQgVmVyc2lvbi5cbiAgICpcbiAgICogQWxsIHZlcnNpb25zIHNob3VsZCBoYXZlIGRpc3RpbmN0IG5hbWVzLCBhbmQgeW91IHNob3VsZCBub3QgZGVsZXRlIHZlcnNpb25zXG4gICAqIGFzIGxvbmcgYXMgeW91ciBBbGlhcyBuZWVkcyB0byByZWZlciB0byB0aGVtLlxuICAgKlxuICAgKiBAcGFyYW0gbmFtZSBBIHVuaXF1ZSBuYW1lIGZvciB0aGlzIHZlcnNpb24uXG4gICAqIEBwYXJhbSBjb2RlU2hhMjU2IFRoZSBTSEEtMjU2IGhhc2ggb2YgdGhlIG1vc3QgcmVjZW50bHkgZGVwbG95ZWQgTGFtYmRhXG4gICAqICBzb3VyY2UgY29kZSwgb3Igb21pdCB0byBza2lwIHZhbGlkYXRpb24uXG4gICAqIEBwYXJhbSBkZXNjcmlwdGlvbiBBIGRlc2NyaXB0aW9uIGZvciB0aGlzIHZlcnNpb24uXG4gICAqIEBwYXJhbSBwcm92aXNpb25lZEV4ZWN1dGlvbnMgQSBwcm92aXNpb25lZCBjb25jdXJyZW5jeSBjb25maWd1cmF0aW9uIGZvciBhXG4gICAqIGZ1bmN0aW9uJ3MgdmVyc2lvbi5cbiAgICogQHBhcmFtIGFzeW5jSW52b2tlQ29uZmlnIGNvbmZpZ3VyYXRpb24gZm9yIHRoaXMgdmVyc2lvbiB3aGVuIGl0IGlzIGludm9rZWRcbiAgICogYXN5bmNocm9ub3VzbHkuXG4gICAqIEByZXR1cm5zIEEgbmV3IFZlcnNpb24gb2JqZWN0LlxuICAgKlxuICAgKiBAZGVwcmVjYXRlZCBUaGlzIG1ldGhvZCB3aWxsIGNyZWF0ZSBhbiBBV1M6OkxhbWJkYTo6VmVyc2lvbiByZXNvdXJjZSB3aGljaFxuICAgKiBzbmFwc2hvdHMgdGhlIEFXUyBMYW1iZGEgZnVuY3Rpb24gKmF0IHRoZSB0aW1lIG9mIGl0cyBjcmVhdGlvbiogYW5kIGl0XG4gICAqIHdvbid0IGdldCB1cGRhdGVkIHdoZW4gdGhlIGZ1bmN0aW9uIGNoYW5nZXMuIEluc3RlYWQsIHVzZVxuICAgKiBgdGhpcy5jdXJyZW50VmVyc2lvbmAgdG8gb2J0YWluIGEgcmVmZXJlbmNlIHRvIGEgdmVyc2lvbiByZXNvdXJjZSB0aGF0IGdldHNcbiAgICogYXV0b21hdGljYWxseSByZWNyZWF0ZWQgd2hlbiB0aGUgZnVuY3Rpb24gY29uZmlndXJhdGlvbiAob3IgY29kZSkgY2hhbmdlcy5cbiAgICovXG4gIHB1YmxpYyBhZGRWZXJzaW9uKFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICBjb2RlU2hhMjU2Pzogc3RyaW5nLFxuICAgIGRlc2NyaXB0aW9uPzogc3RyaW5nLFxuICAgIHByb3Zpc2lvbmVkRXhlY3V0aW9ucz86IG51bWJlcixcbiAgICBhc3luY0ludm9rZUNvbmZpZzogRXZlbnRJbnZva2VDb25maWdPcHRpb25zID0ge30pOiBWZXJzaW9uIHtcblxuICAgIHJldHVybiBuZXcgVmVyc2lvbih0aGlzLCAnVmVyc2lvbicgKyBuYW1lLCB7XG4gICAgICBsYW1iZGE6IHRoaXMsXG4gICAgICBjb2RlU2hhMjU2LFxuICAgICAgZGVzY3JpcHRpb24sXG4gICAgICBwcm92aXNpb25lZENvbmN1cnJlbnRFeGVjdXRpb25zOiBwcm92aXNpb25lZEV4ZWN1dGlvbnMsXG4gICAgICAuLi5hc3luY0ludm9rZUNvbmZpZyxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgTG9nR3JvdXAgd2hlcmUgdGhlIExhbWJkYSBmdW5jdGlvbidzIGxvZ3MgYXJlIG1hZGUgYXZhaWxhYmxlLlxuICAgKlxuICAgKiBJZiBlaXRoZXIgYGxvZ1JldGVudGlvbmAgaXMgc2V0IG9yIHRoaXMgcHJvcGVydHkgaXMgY2FsbGVkLCBhIENsb3VkRm9ybWF0aW9uIGN1c3RvbSByZXNvdXJjZSBpcyBhZGRlZCB0byB0aGUgc3RhY2sgdGhhdFxuICAgKiBwcmUtY3JlYXRlcyB0aGUgbG9nIGdyb3VwIGFzIHBhcnQgb2YgdGhlIHN0YWNrIGRlcGxveW1lbnQsIGlmIGl0IGFscmVhZHkgZG9lc24ndCBleGlzdCwgYW5kIHNldHMgdGhlIGNvcnJlY3QgbG9nIHJldGVudGlvblxuICAgKiBwZXJpb2QgKG5ldmVyIGV4cGlyZSwgYnkgZGVmYXVsdCkuXG4gICAqXG4gICAqIEZ1cnRoZXIsIGlmIHRoZSBsb2cgZ3JvdXAgYWxyZWFkeSBleGlzdHMgYW5kIHRoZSBgbG9nUmV0ZW50aW9uYCBpcyBub3Qgc2V0LCB0aGUgY3VzdG9tIHJlc291cmNlIHdpbGwgcmVzZXQgdGhlIGxvZyByZXRlbnRpb25cbiAgICogdG8gbmV2ZXIgZXhwaXJlIGV2ZW4gaWYgaXQgd2FzIGNvbmZpZ3VyZWQgd2l0aCBhIGRpZmZlcmVudCB2YWx1ZS5cbiAgICovXG4gIHB1YmxpYyBnZXQgbG9nR3JvdXAoKTogbG9ncy5JTG9nR3JvdXAge1xuICAgIGlmICghdGhpcy5fbG9nR3JvdXApIHtcbiAgICAgIGNvbnN0IGxvZ1JldGVudGlvbiA9IG5ldyBsb2dzLkxvZ1JldGVudGlvbih0aGlzLCAnTG9nUmV0ZW50aW9uJywge1xuICAgICAgICBsb2dHcm91cE5hbWU6IGAvYXdzL2xhbWJkYS8ke3RoaXMuZnVuY3Rpb25OYW1lfWAsXG4gICAgICAgIHJldGVudGlvbjogbG9ncy5SZXRlbnRpb25EYXlzLklORklOSVRFLFxuICAgICAgfSk7XG4gICAgICB0aGlzLl9sb2dHcm91cCA9IGxvZ3MuTG9nR3JvdXAuZnJvbUxvZ0dyb3VwQXJuKHRoaXMsIGAke3RoaXMubm9kZS5pZH0tTG9nR3JvdXBgLCBsb2dSZXRlbnRpb24ubG9nR3JvdXBBcm4pO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fbG9nR3JvdXA7XG4gIH1cblxuICAvKiogQGludGVybmFsICovXG4gIHB1YmxpYyBfY2hlY2tFZGdlQ29tcGF0aWJpbGl0eSgpOiB2b2lkIHtcbiAgICAvLyBDaGVjayBlbnYgdmFyc1xuICAgIGNvbnN0IGVudkVudHJpZXMgPSBPYmplY3QuZW50cmllcyh0aGlzLmVudmlyb25tZW50KTtcbiAgICBmb3IgKGNvbnN0IFtrZXksIGNvbmZpZ10gb2YgZW52RW50cmllcykge1xuICAgICAgaWYgKGNvbmZpZy5yZW1vdmVJbkVkZ2UpIHtcbiAgICAgICAgZGVsZXRlIHRoaXMuZW52aXJvbm1lbnRba2V5XTtcbiAgICAgICAgQW5ub3RhdGlvbnMub2YodGhpcykuYWRkSW5mbyhgUmVtb3ZlZCAke2tleX0gZW52aXJvbm1lbnQgdmFyaWFibGUgZm9yIExhbWJkYUBFZGdlIGNvbXBhdGliaWxpdHlgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgY29uc3QgZW52S2V5cyA9IE9iamVjdC5rZXlzKHRoaXMuZW52aXJvbm1lbnQpO1xuICAgIGlmIChlbnZLZXlzLmxlbmd0aCAhPT0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBUaGUgZnVuY3Rpb24gJHt0aGlzLm5vZGUucGF0aH0gY29udGFpbnMgZW52aXJvbm1lbnQgdmFyaWFibGVzIFske2VudktleXN9XSBhbmQgaXMgbm90IGNvbXBhdGlibGUgd2l0aCBMYW1iZGFARWRnZS4gXFxcbkVudmlyb25tZW50IHZhcmlhYmxlcyBjYW4gYmUgbWFya2VkIGZvciByZW1vdmFsIHdoZW4gdXNlZCBpbiBMYW1iZGFARWRnZSBieSBzZXR0aW5nIHRoZSBcXCdyZW1vdmVJbkVkZ2VcXCcgcHJvcGVydHkgaW4gdGhlIFxcJ2FkZEVudmlyb25tZW50KClcXCcgQVBJLmApO1xuICAgIH1cblxuICAgIHJldHVybjtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb25maWd1cmVkIGxhbWJkYSBpbnNpZ2h0cyBvbiB0aGUgZnVuY3Rpb24gaWYgc3BlY2lmaWVkLiBUaGlzIGlzIGFjaGVpdmVkIGJ5IGFkZGluZyBhbiBpbXBvcnRlZCBsYXllciB3aGljaCBpcyBhZGRlZCB0byB0aGVcbiAgICogbGlzdCBvZiBsYW1iZGEgbGF5ZXJzIG9uIHN5bnRoZXNpcy5cbiAgICpcbiAgICogaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FtYXpvbkNsb3VkV2F0Y2gvbGF0ZXN0L21vbml0b3JpbmcvTGFtYmRhLUluc2lnaHRzLWV4dGVuc2lvbi12ZXJzaW9ucy5odG1sXG4gICAqL1xuICBwcml2YXRlIGNvbmZpZ3VyZUxhbWJkYUluc2lnaHRzKHByb3BzOiBGdW5jdGlvblByb3BzKTogdm9pZCB7XG4gICAgaWYgKHByb3BzLmluc2lnaHRzVmVyc2lvbiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChwcm9wcy5ydW50aW1lICE9PSBSdW50aW1lLkZST01fSU1BR0UpIHtcbiAgICAgIC8vIExheWVycyBjYW5ub3QgYmUgYWRkZWQgdG8gTGFtYmRhIGNvbnRhaW5lciBpbWFnZXMuIFRoZSBpbWFnZSBzaG91bGQgaGF2ZSB0aGUgaW5zaWdodHMgYWdlbnQgaW5zdGFsbGVkLlxuICAgICAgLy8gU2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BbWF6b25DbG91ZFdhdGNoL2xhdGVzdC9tb25pdG9yaW5nL0xhbWJkYS1JbnNpZ2h0cy1HZXR0aW5nLVN0YXJ0ZWQtZG9ja2VyLmh0bWxcbiAgICAgIHRoaXMuYWRkTGF5ZXJzKExheWVyVmVyc2lvbi5mcm9tTGF5ZXJWZXJzaW9uQXJuKHRoaXMsICdMYW1iZGFJbnNpZ2h0c0xheWVyJywgcHJvcHMuaW5zaWdodHNWZXJzaW9uLl9iaW5kKHRoaXMsIHRoaXMpLmFybikpO1xuICAgIH1cbiAgICB0aGlzLnJvbGU/LmFkZE1hbmFnZWRQb2xpY3koaWFtLk1hbmFnZWRQb2xpY3kuZnJvbUF3c01hbmFnZWRQb2xpY3lOYW1lKCdDbG91ZFdhdGNoTGFtYmRhSW5zaWdodHNFeGVjdXRpb25Sb2xlUG9saWN5JykpO1xuICB9XG5cbiAgcHJpdmF0ZSByZW5kZXJFbnZpcm9ubWVudCgpIHtcbiAgICBpZiAoIXRoaXMuZW52aXJvbm1lbnQgfHwgT2JqZWN0LmtleXModGhpcy5lbnZpcm9ubWVudCkubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGNvbnN0IHZhcmlhYmxlczogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSA9IHt9O1xuICAgIC8vIFNvcnQgZW52aXJvbm1lbnQgc28gdGhlIGhhc2ggb2YgdGhlIGZ1bmN0aW9uIHVzZWQgdG8gY3JlYXRlXG4gICAgLy8gYGN1cnJlbnRWZXJzaW9uYCBpcyBub3QgYWZmZWN0ZWQgYnkga2V5IG9yZGVyICh0aGlzIGlzIGhvdyBsYW1iZGEgZG9lc1xuICAgIC8vIGl0KS4gRm9yIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5IHdlIGRvIG5vdCBzb3J0IGVudmlyb25tZW50IHZhcmlhYmxlcyBpbiBjYXNlXG4gICAgLy8gX2N1cnJlbnRWZXJzaW9uIGlzIG5vdCBkZWZpbmVkLiBPdGhlcndpc2UsIHRoaXMgd291bGQgaGF2ZSBpbnZhbGlkYXRlZFxuICAgIC8vIHRoZSB0ZW1wbGF0ZSwgYW5kIGZvciBleGFtcGxlLCBtYXkgY2F1c2UgdW5uZWVkZWQgdXBkYXRlcyBmb3IgbmVzdGVkXG4gICAgLy8gc3RhY2tzLlxuICAgIGNvbnN0IGtleXMgPSB0aGlzLl9jdXJyZW50VmVyc2lvblxuICAgICAgPyBPYmplY3Qua2V5cyh0aGlzLmVudmlyb25tZW50KS5zb3J0KClcbiAgICAgIDogT2JqZWN0LmtleXModGhpcy5lbnZpcm9ubWVudCk7XG5cbiAgICBmb3IgKGNvbnN0IGtleSBvZiBrZXlzKSB7XG4gICAgICB2YXJpYWJsZXNba2V5XSA9IHRoaXMuZW52aXJvbm1lbnRba2V5XS52YWx1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4geyB2YXJpYWJsZXMgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJZiBjb25maWd1cmVkLCBzZXQgdXAgdGhlIFZQQy1yZWxhdGVkIHByb3BlcnRpZXNcbiAgICpcbiAgICogUmV0dXJucyB0aGUgVnBjQ29uZmlnIHRoYXQgc2hvdWxkIGJlIGFkZGVkIHRvIHRoZVxuICAgKiBMYW1iZGEgY3JlYXRpb24gcHJvcGVydGllcy5cbiAgICovXG4gIHByaXZhdGUgY29uZmlndXJlVnBjKHByb3BzOiBGdW5jdGlvblByb3BzKTogQ2ZuRnVuY3Rpb24uVnBjQ29uZmlnUHJvcGVydHkgfCB1bmRlZmluZWQge1xuICAgIGlmICgocHJvcHMuc2VjdXJpdHlHcm91cCB8fCBwcm9wcy5hbGxvd0FsbE91dGJvdW5kICE9PSB1bmRlZmluZWQpICYmICFwcm9wcy52cGMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGNvbmZpZ3VyZSBcXCdzZWN1cml0eUdyb3VwXFwnIG9yIFxcJ2FsbG93QWxsT3V0Ym91bmRcXCcgd2l0aG91dCBjb25maWd1cmluZyBhIFZQQycpO1xuICAgIH1cblxuICAgIGlmICghcHJvcHMudnBjKSB7IHJldHVybiB1bmRlZmluZWQ7IH1cblxuICAgIGlmIChwcm9wcy5zZWN1cml0eUdyb3VwICYmIHByb3BzLmFsbG93QWxsT3V0Ym91bmQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDb25maWd1cmUgXFwnYWxsb3dBbGxPdXRib3VuZFxcJyBkaXJlY3RseSBvbiB0aGUgc3VwcGxpZWQgU2VjdXJpdHlHcm91cC4nKTtcbiAgICB9XG5cbiAgICBsZXQgc2VjdXJpdHlHcm91cHM6IGVjMi5JU2VjdXJpdHlHcm91cFtdO1xuXG4gICAgaWYgKHByb3BzLnNlY3VyaXR5R3JvdXAgJiYgcHJvcHMuc2VjdXJpdHlHcm91cHMpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignT25seSBvbmUgb2YgdGhlIGZ1bmN0aW9uIHByb3BzLCBzZWN1cml0eUdyb3VwIG9yIHNlY3VyaXR5R3JvdXBzLCBpcyBhbGxvd2VkJyk7XG4gICAgfVxuXG4gICAgaWYgKHByb3BzLnNlY3VyaXR5R3JvdXBzKSB7XG4gICAgICBzZWN1cml0eUdyb3VwcyA9IHByb3BzLnNlY3VyaXR5R3JvdXBzO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBzZWN1cml0eUdyb3VwID0gcHJvcHMuc2VjdXJpdHlHcm91cCB8fCBuZXcgZWMyLlNlY3VyaXR5R3JvdXAodGhpcywgJ1NlY3VyaXR5R3JvdXAnLCB7XG4gICAgICAgIHZwYzogcHJvcHMudnBjLFxuICAgICAgICBkZXNjcmlwdGlvbjogJ0F1dG9tYXRpYyBzZWN1cml0eSBncm91cCBmb3IgTGFtYmRhIEZ1bmN0aW9uICcgKyBOYW1lcy51bmlxdWVJZCh0aGlzKSxcbiAgICAgICAgYWxsb3dBbGxPdXRib3VuZDogcHJvcHMuYWxsb3dBbGxPdXRib3VuZCxcbiAgICAgIH0pO1xuICAgICAgc2VjdXJpdHlHcm91cHMgPSBbc2VjdXJpdHlHcm91cF07XG4gICAgfVxuXG4gICAgdGhpcy5fY29ubmVjdGlvbnMgPSBuZXcgZWMyLkNvbm5lY3Rpb25zKHsgc2VjdXJpdHlHcm91cHMgfSk7XG5cbiAgICBpZiAocHJvcHMuZmlsZXN5c3RlbSkge1xuICAgICAgaWYgKHByb3BzLmZpbGVzeXN0ZW0uY29uZmlnLmNvbm5lY3Rpb25zKSB7XG4gICAgICAgIHByb3BzLmZpbGVzeXN0ZW0uY29uZmlnLmNvbm5lY3Rpb25zLmFsbG93RGVmYXVsdFBvcnRGcm9tKHRoaXMpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGFsbG93UHVibGljU3VibmV0ID0gcHJvcHMuYWxsb3dQdWJsaWNTdWJuZXQgPz8gZmFsc2U7XG4gICAgY29uc3QgeyBzdWJuZXRJZHMgfSA9IHByb3BzLnZwYy5zZWxlY3RTdWJuZXRzKHByb3BzLnZwY1N1Ym5ldHMpO1xuICAgIGNvbnN0IHB1YmxpY1N1Ym5ldElkcyA9IG5ldyBTZXQocHJvcHMudnBjLnB1YmxpY1N1Ym5ldHMubWFwKHMgPT4gcy5zdWJuZXRJZCkpO1xuICAgIGZvciAoY29uc3Qgc3VibmV0SWQgb2Ygc3VibmV0SWRzKSB7XG4gICAgICBpZiAocHVibGljU3VibmV0SWRzLmhhcyhzdWJuZXRJZCkgJiYgIWFsbG93UHVibGljU3VibmV0KSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTGFtYmRhIEZ1bmN0aW9ucyBpbiBhIHB1YmxpYyBzdWJuZXQgY2FuIE5PVCBhY2Nlc3MgdGhlIGludGVybmV0LiAnICtcbiAgICAgICAgICAnSWYgeW91IGFyZSBhd2FyZSBvZiB0aGlzIGxpbWl0YXRpb24gYW5kIHdvdWxkIHN0aWxsIGxpa2UgdG8gcGxhY2UgdGhlIGZ1bmN0aW9uIGludCBhIHB1YmxpYyBzdWJuZXQsIHNldCBgYWxsb3dQdWJsaWNTdWJuZXRgIHRvIHRydWUnKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBMaXN0IGNhbid0IGJlIGVtcHR5IGhlcmUsIGlmIHdlIGdvdCB0aGlzIGZhciB5b3UgaW50ZW5kZWQgdG8gcHV0IHlvdXIgTGFtYmRhXG4gICAgLy8gaW4gc3VibmV0cy4gV2UncmUgZ29pbmcgdG8gZ3VhcmFudGVlIHRoYXQgd2UgZ2V0IHRoZSBuaWNlIGVycm9yIG1lc3NhZ2UgYnlcbiAgICAvLyBtYWtpbmcgVnBjTmV0d29yayBkbyB0aGUgc2VsZWN0aW9uIGFnYWluLlxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHN1Ym5ldElkcyxcbiAgICAgIHNlY3VyaXR5R3JvdXBJZHM6IHNlY3VyaXR5R3JvdXBzLm1hcChzZyA9PiBzZy5zZWN1cml0eUdyb3VwSWQpLFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIGlzUXVldWUoZGVhZExldHRlclF1ZXVlOiBzcXMuSVF1ZXVlIHwgc25zLklUb3BpYyk6IGRlYWRMZXR0ZXJRdWV1ZSBpcyBzcXMuSVF1ZXVlIHtcbiAgICByZXR1cm4gKDxzcXMuSVF1ZXVlPmRlYWRMZXR0ZXJRdWV1ZSkucXVldWVBcm4gIT09IHVuZGVmaW5lZDtcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGREZWFkTGV0dGVyUXVldWUocHJvcHM6IEZ1bmN0aW9uUHJvcHMpOiBzcXMuSVF1ZXVlIHwgc25zLklUb3BpYyB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCFwcm9wcy5kZWFkTGV0dGVyUXVldWUgJiYgIXByb3BzLmRlYWRMZXR0ZXJRdWV1ZUVuYWJsZWQgJiYgIXByb3BzLmRlYWRMZXR0ZXJUb3BpYykge1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG4gICAgaWYgKHByb3BzLmRlYWRMZXR0ZXJRdWV1ZSAmJiBwcm9wcy5kZWFkTGV0dGVyUXVldWVFbmFibGVkID09PSBmYWxzZSkge1xuICAgICAgdGhyb3cgRXJyb3IoJ2RlYWRMZXR0ZXJRdWV1ZSBkZWZpbmVkIGJ1dCBkZWFkTGV0dGVyUXVldWVFbmFibGVkIGV4cGxpY2l0bHkgc2V0IHRvIGZhbHNlJyk7XG4gICAgfVxuICAgIGlmIChwcm9wcy5kZWFkTGV0dGVyVG9waWMgJiYgKHByb3BzLmRlYWRMZXR0ZXJRdWV1ZSB8fCBwcm9wcy5kZWFkTGV0dGVyUXVldWVFbmFibGVkICE9PSB1bmRlZmluZWQpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2RlYWRMZXR0ZXJRdWV1ZSBhbmQgZGVhZExldHRlclRvcGljIGNhbm5vdCBiZSBzcGVjaWZpZWQgdG9nZXRoZXIgYXQgdGhlIHNhbWUgdGltZScpO1xuICAgIH1cblxuICAgIGxldCBkZWFkTGV0dGVyUXVldWU6IHNxcy5JUXVldWUgfCBzbnMuSVRvcGljO1xuICAgIGlmIChwcm9wcy5kZWFkTGV0dGVyVG9waWMpIHtcbiAgICAgIGRlYWRMZXR0ZXJRdWV1ZSA9IHByb3BzLmRlYWRMZXR0ZXJUb3BpYztcbiAgICAgIHRoaXMuYWRkVG9Sb2xlUG9saWN5KG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgYWN0aW9uczogWydzbnM6UHVibGlzaCddLFxuICAgICAgICByZXNvdXJjZXM6IFtkZWFkTGV0dGVyUXVldWUudG9waWNBcm5dLFxuICAgICAgfSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBkZWFkTGV0dGVyUXVldWUgPSBwcm9wcy5kZWFkTGV0dGVyUXVldWUgfHwgbmV3IHNxcy5RdWV1ZSh0aGlzLCAnRGVhZExldHRlclF1ZXVlJywge1xuICAgICAgICByZXRlbnRpb25QZXJpb2Q6IER1cmF0aW9uLmRheXMoMTQpLFxuICAgICAgfSk7XG4gICAgICB0aGlzLmFkZFRvUm9sZVBvbGljeShuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgIGFjdGlvbnM6IFsnc3FzOlNlbmRNZXNzYWdlJ10sXG4gICAgICAgIHJlc291cmNlczogW2RlYWRMZXR0ZXJRdWV1ZS5xdWV1ZUFybl0sXG4gICAgICB9KSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGRlYWRMZXR0ZXJRdWV1ZTtcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGREZWFkTGV0dGVyQ29uZmlnKGRlYWRMZXR0ZXJRdWV1ZT86IHNxcy5JUXVldWUgfCBzbnMuSVRvcGljKSB7XG4gICAgaWYgKGRlYWRMZXR0ZXJRdWV1ZSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdGFyZ2V0QXJuOiB0aGlzLmlzUXVldWUoZGVhZExldHRlclF1ZXVlKSA/IGRlYWRMZXR0ZXJRdWV1ZS5xdWV1ZUFybiA6IGRlYWRMZXR0ZXJRdWV1ZS50b3BpY0FybixcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBidWlsZFRyYWNpbmdDb25maWcocHJvcHM6IEZ1bmN0aW9uUHJvcHMpIHtcbiAgICBpZiAocHJvcHMudHJhY2luZyA9PT0gdW5kZWZpbmVkIHx8IHByb3BzLnRyYWNpbmcgPT09IFRyYWNpbmcuRElTQUJMRUQpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgdGhpcy5hZGRUb1JvbGVQb2xpY3kobmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgYWN0aW9uczogWyd4cmF5OlB1dFRyYWNlU2VnbWVudHMnLCAneHJheTpQdXRUZWxlbWV0cnlSZWNvcmRzJ10sXG4gICAgICByZXNvdXJjZXM6IFsnKiddLFxuICAgIH0pKTtcblxuICAgIHJldHVybiB7XG4gICAgICBtb2RlOiBwcm9wcy50cmFjaW5nLFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIHZhbGlkYXRlUHJvZmlsaW5nKHByb3BzOiBGdW5jdGlvblByb3BzKSB7XG4gICAgaWYgKCFwcm9wcy5ydW50aW1lLnN1cHBvcnRzQ29kZUd1cnVQcm9maWxpbmcpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgQ29kZUd1cnUgcHJvZmlsaW5nIGlzIG5vdCBzdXBwb3J0ZWQgYnkgcnVudGltZSAke3Byb3BzLnJ1bnRpbWUubmFtZX1gKTtcbiAgICB9XG4gICAgaWYgKHByb3BzLmVudmlyb25tZW50ICYmIChwcm9wcy5lbnZpcm9ubWVudC5BV1NfQ09ERUdVUlVfUFJPRklMRVJfR1JPVVBfQVJOIHx8IHByb3BzLmVudmlyb25tZW50LkFXU19DT0RFR1VSVV9QUk9GSUxFUl9FTkFCTEVEKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdBV1NfQ09ERUdVUlVfUFJPRklMRVJfR1JPVVBfQVJOIGFuZCBBV1NfQ09ERUdVUlVfUFJPRklMRVJfRU5BQkxFRCBtdXN0IG5vdCBiZSBzZXQgd2hlbiBwcm9maWxpbmcgb3B0aW9ucyBlbmFibGVkJyk7XG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogRW52aXJvbm1lbnQgdmFyaWFibGVzIG9wdGlvbnNcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBFbnZpcm9ubWVudE9wdGlvbnMge1xuICAvKipcbiAgICogV2hlbiB1c2VkIGluIExhbWJkYUBFZGdlIHZpYSBlZGdlQXJuKCkgQVBJLCB0aGVzZSBlbnZpcm9ubWVudFxuICAgKiB2YXJpYWJsZXMgd2lsbCBiZSByZW1vdmVkLiBJZiBub3Qgc2V0LCBhbiBlcnJvciB3aWxsIGJlIHRocm93bi5cbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQW1hem9uQ2xvdWRGcm9udC9sYXRlc3QvRGV2ZWxvcGVyR3VpZGUvbGFtYmRhLXJlcXVpcmVtZW50cy1saW1pdHMuaHRtbCNsYW1iZGEtcmVxdWlyZW1lbnRzLWxhbWJkYS1mdW5jdGlvbi1jb25maWd1cmF0aW9uXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlIC0gdXNpbmcgdGhlIGZ1bmN0aW9uIGluIExhbWJkYUBFZGdlIHdpbGwgdGhyb3dcbiAgICovXG4gIHJlYWRvbmx5IHJlbW92ZUluRWRnZT86IGJvb2xlYW5cbn1cblxuLyoqXG4gKiBDb25maWd1cmF0aW9uIGZvciBhbiBlbnZpcm9ubWVudCB2YXJpYWJsZVxuICovXG5pbnRlcmZhY2UgRW52aXJvbm1lbnRDb25maWcgZXh0ZW5kcyBFbnZpcm9ubWVudE9wdGlvbnMge1xuICByZWFkb25seSB2YWx1ZTogc3RyaW5nO1xufVxuXG4vKipcbiAqIEdpdmVuIGFuIG9wYXF1ZSAodG9rZW4pIEFSTiwgcmV0dXJucyBhIENsb3VkRm9ybWF0aW9uIGV4cHJlc3Npb24gdGhhdCBleHRyYWN0cyB0aGUgZnVuY3Rpb25cbiAqIG5hbWUgZnJvbSB0aGUgQVJOLlxuICpcbiAqIEZ1bmN0aW9uIEFSTnMgbG9vayBsaWtlIHRoaXM6XG4gKlxuICogICBhcm46YXdzOmxhbWJkYTpyZWdpb246YWNjb3VudC1pZDpmdW5jdGlvbjpmdW5jdGlvbi1uYW1lXG4gKlxuICogLi53aGljaCBtZWFucyB0aGF0IGluIG9yZGVyIHRvIGV4dHJhY3QgdGhlIGBmdW5jdGlvbi1uYW1lYCBjb21wb25lbnQgZnJvbSB0aGUgQVJOLCB3ZSBjYW5cbiAqIHNwbGl0IHRoZSBBUk4gdXNpbmcgXCI6XCIgYW5kIHNlbGVjdCB0aGUgY29tcG9uZW50IGluIGluZGV4IDYuXG4gKlxuICogQHJldHVybnMgYEZuU2VsZWN0KDYsIEZuU3BsaXQoJzonLCBhcm4pKWBcbiAqL1xuZnVuY3Rpb24gZXh0cmFjdE5hbWVGcm9tQXJuKGFybjogc3RyaW5nKSB7XG4gIHJldHVybiBGbi5zZWxlY3QoNiwgRm4uc3BsaXQoJzonLCBhcm4pKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHZlcmlmeUNvZGVDb25maWcoY29kZTogQ29kZUNvbmZpZywgcHJvcHM6IEZ1bmN0aW9uUHJvcHMpIHtcbiAgLy8gbXV0dWFsbHkgZXhjbHVzaXZlXG4gIGNvbnN0IGNvZGVUeXBlID0gW2NvZGUuaW5saW5lQ29kZSwgY29kZS5zM0xvY2F0aW9uLCBjb2RlLmltYWdlXTtcblxuICBpZiAoY29kZVR5cGUuZmlsdGVyKHggPT4gISF4KS5sZW5ndGggIT09IDEpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2xhbWJkYS5Db2RlIG11c3Qgc3BlY2lmeSBleGFjdGx5IG9uZSBvZjogXCJpbmxpbmVDb2RlXCIsIFwiczNMb2NhdGlvblwiLCBvciBcImltYWdlXCInKTtcbiAgfVxuXG4gIGlmICghIWNvZGUuaW1hZ2UgPT09IChwcm9wcy5oYW5kbGVyICE9PSBIYW5kbGVyLkZST01fSU1BR0UpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdoYW5kbGVyIG11c3QgYmUgYEhhbmRsZXIuRlJPTV9JTUFHRWAgd2hlbiB1c2luZyBpbWFnZSBhc3NldCBmb3IgTGFtYmRhIGZ1bmN0aW9uJyk7XG4gIH1cblxuICBpZiAoISFjb2RlLmltYWdlID09PSAocHJvcHMucnVudGltZSAhPT0gUnVudGltZS5GUk9NX0lNQUdFKSkge1xuICAgIHRocm93IG5ldyBFcnJvcigncnVudGltZSBtdXN0IGJlIGBSdW50aW1lLkZST01fSU1BR0VgIHdoZW4gdXNpbmcgaW1hZ2UgYXNzZXQgZm9yIExhbWJkYSBmdW5jdGlvbicpO1xuICB9XG5cbiAgLy8gaWYgdGhpcyBpcyBpbmxpbmUgY29kZSwgY2hlY2sgdGhhdCB0aGUgcnVudGltZSBzdXBwb3J0c1xuICBpZiAoY29kZS5pbmxpbmVDb2RlICYmICFwcm9wcy5ydW50aW1lLnN1cHBvcnRzSW5saW5lQ29kZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihgSW5saW5lIHNvdXJjZSBub3QgYWxsb3dlZCBmb3IgJHtwcm9wcy5ydW50aW1lIS5uYW1lfWApO1xuICB9XG59XG5cbmZ1bmN0aW9uIHVuZGVmaW5lZElmTm9LZXlzPEE+KHN0cnVjdDogQSk6IEEgfCB1bmRlZmluZWQge1xuICBjb25zdCBhbGxVbmRlZmluZWQgPSBPYmplY3QudmFsdWVzKHN0cnVjdCkuZXZlcnkodmFsID0+IHZhbCA9PT0gdW5kZWZpbmVkKTtcbiAgcmV0dXJuIGFsbFVuZGVmaW5lZCA/IHVuZGVmaW5lZCA6IHN0cnVjdDtcbn1cbiJdfQ==
\No newline at end of file