1 | ;
|
2 | var _a;
|
3 | Object.defineProperty(exports, "__esModule", { value: true });
|
4 | exports.rootPathTo = exports.Stack = exports.STACK_RESOURCE_LIMIT_CONTEXT = void 0;
|
5 | const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
|
6 | const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
7 | const fs = require("fs");
|
8 | const path = require("path");
|
9 | const cxschema = require("@aws-cdk/cloud-assembly-schema");
|
10 | const cxapi = require("@aws-cdk/cx-api");
|
11 | const constructs_1 = require("constructs");
|
12 | const minimatch = require("minimatch");
|
13 | const annotations_1 = require("./annotations");
|
14 | const app_1 = require("./app");
|
15 | const arn_1 = require("./arn");
|
16 | const cfn_element_1 = require("./cfn-element");
|
17 | const cfn_fn_1 = require("./cfn-fn");
|
18 | const cfn_pseudo_1 = require("./cfn-pseudo");
|
19 | const cfn_resource_1 = require("./cfn-resource");
|
20 | const context_provider_1 = require("./context-provider");
|
21 | const feature_flags_1 = require("./feature-flags");
|
22 | const cloudformation_lang_1 = require("./private/cloudformation-lang");
|
23 | const logical_id_1 = require("./private/logical-id");
|
24 | const resolve_1 = require("./private/resolve");
|
25 | const uniqueid_1 = require("./private/uniqueid");
|
26 | // v2 - keep this import as a separate section to reduce merge conflict when forward merging with the v2 branch.
|
27 | // eslint-disable-next-line
|
28 | const construct_compat_1 = require("./construct-compat");
|
29 | const STACK_SYMBOL = Symbol.for('@aws-cdk/core.Stack');
|
30 | const MY_STACK_CACHE = Symbol.for('@aws-cdk/core.Stack.myStack');
|
31 | exports.STACK_RESOURCE_LIMIT_CONTEXT = '@aws-cdk/core:stackResourceLimit';
|
32 | const VALID_STACK_NAME_REGEX = /^[A-Za-z][A-Za-z0-9-]*$/;
|
33 | const MAX_RESOURCES = 500;
|
34 | /**
|
35 | * A root construct which represents a single CloudFormation stack.
|
36 | */
|
37 | class Stack extends construct_compat_1.Construct {
|
38 | /**
|
39 | * Creates a new stack.
|
40 | *
|
41 | * @param scope Parent of this stack, usually an `App` or a `Stage`, but could be any construct.
|
42 | * @param id The construct ID of this stack. If `stackName` is not explicitly
|
43 | * defined, this id (and any parent IDs) will be used to determine the
|
44 | * physical ID of the stack.
|
45 | * @param props Stack properties.
|
46 | */
|
47 | constructor(scope, id, props = {}) {
|
48 | try {
|
49 | jsiiDeprecationWarnings._aws_cdk_core_StackProps(props);
|
50 | }
|
51 | catch (error) {
|
52 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
53 | Error.captureStackTrace(error, Stack);
|
54 | }
|
55 | throw error;
|
56 | }
|
57 | // For unit test scope and id are optional for stacks, but we still want an App
|
58 | // as the parent because apps implement much of the synthesis logic.
|
59 | scope = scope ?? new app_1.App({
|
60 | autoSynth: false,
|
61 | outdir: fs_1.FileSystem.mkdtemp('cdk-test-app-'),
|
62 | });
|
63 | // "Default" is a "hidden id" from a `node.uniqueId` perspective
|
64 | id = id ?? 'Default';
|
65 | super(scope, id);
|
66 | this._missingContext = new Array();
|
67 | this._stackDependencies = {};
|
68 | this.templateOptions = {};
|
69 | Object.defineProperty(this, STACK_SYMBOL, { value: true });
|
70 | this._logicalIds = new logical_id_1.LogicalIDs();
|
71 | const { account, region, environment } = this.parseEnvironment(props.env);
|
72 | this.account = account;
|
73 | this.region = region;
|
74 | this.environment = environment;
|
75 | this.terminationProtection = props.terminationProtection;
|
76 | if (props.description !== undefined) {
|
77 | // Max length 1024 bytes
|
78 | // Typically 2 bytes per character, may be more for more exotic characters
|
79 | if (props.description.length > 512) {
|
80 | throw new Error(`Stack description must be <= 1024 bytes. Received description: '${props.description}'`);
|
81 | }
|
82 | this.templateOptions.description = props.description;
|
83 | }
|
84 | this._stackName = props.stackName ?? this.generateStackName();
|
85 | if (this._stackName.length > 128) {
|
86 | throw new Error(`Stack name must be <= 128 characters. Stack name: '${this._stackName}'`);
|
87 | }
|
88 | this.tags = new tag_manager_1.TagManager(cfn_resource_1.TagType.KEY_VALUE, 'aws:cdk:stack', props.tags);
|
89 | if (!VALID_STACK_NAME_REGEX.test(this.stackName)) {
|
90 | throw new Error(`Stack name must match the regular expression: ${VALID_STACK_NAME_REGEX.toString()}, got '${this.stackName}'`);
|
91 | }
|
92 | // the preferred behavior is to generate a unique id for this stack and use
|
93 | // it as the artifact ID in the assembly. this allows multiple stacks to use
|
94 | // the same name. however, this behavior is breaking for 1.x so it's only
|
95 | // applied under a feature flag which is applied automatically for new
|
96 | // projects created using `cdk init`.
|
97 | //
|
98 | // Also use the new behavior if we are using the new CI/CD-ready synthesizer; that way
|
99 | // people only have to flip one flag.
|
100 | const featureFlags = feature_flags_1.FeatureFlags.of(this);
|
101 | const stackNameDupeContext = featureFlags.isEnabled(cxapi.ENABLE_STACK_NAME_DUPLICATES_CONTEXT);
|
102 | const newStyleSynthesisContext = featureFlags.isEnabled(cxapi.NEW_STYLE_STACK_SYNTHESIS_CONTEXT);
|
103 | this.artifactId = (stackNameDupeContext || newStyleSynthesisContext)
|
104 | ? this.generateStackArtifactId()
|
105 | : this.stackName;
|
106 | this.templateFile = `${this.artifactId}.template.json`;
|
107 | // Not for nested stacks
|
108 | this._versionReportingEnabled = (props.analyticsReporting ?? this.node.tryGetContext(cxapi.ANALYTICS_REPORTING_ENABLED_CONTEXT))
|
109 | && !this.nestedStackParent;
|
110 | this.synthesizer = props.synthesizer ?? (newStyleSynthesisContext
|
111 | ? new stack_synthesizers_1.DefaultStackSynthesizer()
|
112 | : new stack_synthesizers_1.LegacyStackSynthesizer());
|
113 | this.synthesizer.bind(this);
|
114 | }
|
115 | /**
|
116 | * Return whether the given object is a Stack.
|
117 | *
|
118 | * We do attribute detection since we can't reliably use 'instanceof'.
|
119 | */
|
120 | static isStack(x) {
|
121 | return x !== null && typeof (x) === 'object' && STACK_SYMBOL in x;
|
122 | }
|
123 | /**
|
124 | * Looks up the first stack scope in which `construct` is defined. Fails if there is no stack up the tree.
|
125 | * @param construct The construct to start the search from.
|
126 | */
|
127 | static of(construct) {
|
128 | // we want this to be as cheap as possible. cache this result by mutating
|
129 | // the object. anecdotally, at the time of this writing, @aws-cdk/core unit
|
130 | // tests hit this cache 1,112 times, @aws-cdk/aws-cloudformation unit tests
|
131 | // hit this 2,435 times).
|
132 | const cache = construct[MY_STACK_CACHE];
|
133 | if (cache) {
|
134 | return cache;
|
135 | }
|
136 | else {
|
137 | const value = _lookup(construct);
|
138 | Object.defineProperty(construct, MY_STACK_CACHE, {
|
139 | enumerable: false,
|
140 | writable: false,
|
141 | configurable: false,
|
142 | value,
|
143 | });
|
144 | return value;
|
145 | }
|
146 | function _lookup(c) {
|
147 | if (Stack.isStack(c)) {
|
148 | return c;
|
149 | }
|
150 | const _scope = constructs_1.Node.of(c).scope;
|
151 | if (stage_1.Stage.isStage(c) || !_scope) {
|
152 | throw new Error(`${construct.constructor?.name ?? 'Construct'} at '${constructs_1.Node.of(construct).path}' should be created in the scope of a Stack, but no Stack found`);
|
153 | }
|
154 | return _lookup(_scope);
|
155 | }
|
156 | }
|
157 | /**
|
158 | * Resolve a tokenized value in the context of the current stack.
|
159 | */
|
160 | resolve(obj) {
|
161 | return resolve_1.resolve(obj, {
|
162 | scope: this,
|
163 | prefix: [],
|
164 | resolver: cloudformation_lang_1.CLOUDFORMATION_TOKEN_RESOLVER,
|
165 | preparing: false,
|
166 | });
|
167 | }
|
168 | /**
|
169 | * Convert an object, potentially containing tokens, to a JSON string
|
170 | */
|
171 | toJsonString(obj, space) {
|
172 | return cloudformation_lang_1.CloudFormationLang.toJSON(obj, space).toString();
|
173 | }
|
174 | /**
|
175 | * DEPRECATED
|
176 | * @deprecated use `reportMissingContextKey()`
|
177 | */
|
178 | reportMissingContext(report) {
|
179 | try {
|
180 | jsiiDeprecationWarnings.print("@aws-cdk/core.Stack#reportMissingContext", "use `reportMissingContextKey()`");
|
181 | }
|
182 | catch (error) {
|
183 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
184 | Error.captureStackTrace(error, this.reportMissingContext);
|
185 | }
|
186 | throw error;
|
187 | }
|
188 | if (!Object.values(cxschema.ContextProvider).includes(report.provider)) {
|
189 | throw new Error(`Unknown context provider requested in: ${JSON.stringify(report)}`);
|
190 | }
|
191 | this.reportMissingContextKey(report);
|
192 | }
|
193 | /**
|
194 | * Indicate that a context key was expected
|
195 | *
|
196 | * Contains instructions which will be emitted into the cloud assembly on how
|
197 | * the key should be supplied.
|
198 | *
|
199 | * @param report The set of parameters needed to obtain the context
|
200 | */
|
201 | reportMissingContextKey(report) {
|
202 | this._missingContext.push(report);
|
203 | }
|
204 | /**
|
205 | * Rename a generated logical identities
|
206 | *
|
207 | * To modify the naming scheme strategy, extend the `Stack` class and
|
208 | * override the `allocateLogicalId` method.
|
209 | */
|
210 | renameLogicalId(oldId, newId) {
|
211 | this._logicalIds.addRename(oldId, newId);
|
212 | }
|
213 | /**
|
214 | * Allocates a stack-unique CloudFormation-compatible logical identity for a
|
215 | * specific resource.
|
216 | *
|
217 | * This method is called when a `CfnElement` is created and used to render the
|
218 | * initial logical identity of resources. Logical ID renames are applied at
|
219 | * this stage.
|
220 | *
|
221 | * This method uses the protected method `allocateLogicalId` to render the
|
222 | * logical ID for an element. To modify the naming scheme, extend the `Stack`
|
223 | * class and override this method.
|
224 | *
|
225 | * @param element The CloudFormation element for which a logical identity is
|
226 | * needed.
|
227 | */
|
228 | getLogicalId(element) {
|
229 | try {
|
230 | jsiiDeprecationWarnings._aws_cdk_core_CfnElement(element);
|
231 | }
|
232 | catch (error) {
|
233 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
234 | Error.captureStackTrace(error, this.getLogicalId);
|
235 | }
|
236 | throw error;
|
237 | }
|
238 | const logicalId = this.allocateLogicalId(element);
|
239 | return this._logicalIds.applyRename(logicalId);
|
240 | }
|
241 | /**
|
242 | * Add a dependency between this stack and another stack.
|
243 | *
|
244 | * This can be used to define dependencies between any two stacks within an
|
245 | * app, and also supports nested stacks.
|
246 | */
|
247 | addDependency(target, reason) {
|
248 | try {
|
249 | jsiiDeprecationWarnings._aws_cdk_core_Stack(target);
|
250 | }
|
251 | catch (error) {
|
252 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
253 | Error.captureStackTrace(error, this.addDependency);
|
254 | }
|
255 | throw error;
|
256 | }
|
257 | deps_1.addDependency(this, target, reason);
|
258 | }
|
259 | /**
|
260 | * Return the stacks this stack depends on
|
261 | */
|
262 | get dependencies() {
|
263 | return Object.values(this._stackDependencies).map(x => x.stack);
|
264 | }
|
265 | /**
|
266 | * The concrete CloudFormation physical stack name.
|
267 | *
|
268 | * This is either the name defined explicitly in the `stackName` prop or
|
269 | * allocated based on the stack's location in the construct tree. Stacks that
|
270 | * are directly defined under the app use their construct `id` as their stack
|
271 | * name. Stacks that are defined deeper within the tree will use a hashed naming
|
272 | * scheme based on the construct path to ensure uniqueness.
|
273 | *
|
274 | * If you wish to obtain the deploy-time AWS::StackName intrinsic,
|
275 | * you can use `Aws.stackName` directly.
|
276 | */
|
277 | get stackName() {
|
278 | return this._stackName;
|
279 | }
|
280 | /**
|
281 | * The partition in which this stack is defined
|
282 | */
|
283 | get partition() {
|
284 | // Always return a non-scoped partition intrinsic. These will usually
|
285 | // be used to construct an ARN, but there are no cross-partition
|
286 | // calls anyway.
|
287 | return cfn_pseudo_1.Aws.PARTITION;
|
288 | }
|
289 | /**
|
290 | * The Amazon domain suffix for the region in which this stack is defined
|
291 | */
|
292 | get urlSuffix() {
|
293 | // Since URL Suffix always follows partition, it is unscoped like partition is.
|
294 | return cfn_pseudo_1.Aws.URL_SUFFIX;
|
295 | }
|
296 | /**
|
297 | * The ID of the stack
|
298 | *
|
299 | * @example
|
300 | * // After resolving, looks like
|
301 | * 'arn:aws:cloudformation:us-west-2:123456789012:stack/teststack/51af3dc0-da77-11e4-872e-1234567db123'
|
302 | */
|
303 | get stackId() {
|
304 | return new cfn_pseudo_1.ScopedAws(this).stackId;
|
305 | }
|
306 | /**
|
307 | * Returns the list of notification Amazon Resource Names (ARNs) for the current stack.
|
308 | */
|
309 | get notificationArns() {
|
310 | return new cfn_pseudo_1.ScopedAws(this).notificationArns;
|
311 | }
|
312 | /**
|
313 | * Indicates if this is a nested stack, in which case `parentStack` will include a reference to it's parent.
|
314 | */
|
315 | get nested() {
|
316 | return this.nestedStackResource !== undefined;
|
317 | }
|
318 | /**
|
319 | * Creates an ARN from components.
|
320 | *
|
321 | * If `partition`, `region` or `account` are not specified, the stack's
|
322 | * partition, region and account will be used.
|
323 | *
|
324 | * If any component is the empty string, an empty string will be inserted
|
325 | * into the generated ARN at the location that component corresponds to.
|
326 | *
|
327 | * The ARN will be formatted as follows:
|
328 | *
|
329 | * arn:{partition}:{service}:{region}:{account}:{resource}{sep}}{resource-name}
|
330 | *
|
331 | * The required ARN pieces that are omitted will be taken from the stack that
|
332 | * the 'scope' is attached to. If all ARN pieces are supplied, the supplied scope
|
333 | * can be 'undefined'.
|
334 | */
|
335 | formatArn(components) {
|
336 | try {
|
337 | jsiiDeprecationWarnings._aws_cdk_core_ArnComponents(components);
|
338 | }
|
339 | catch (error) {
|
340 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
341 | Error.captureStackTrace(error, this.formatArn);
|
342 | }
|
343 | throw error;
|
344 | }
|
345 | return arn_1.Arn.format(components, this);
|
346 | }
|
347 | /**
|
348 | * Given an ARN, parses it and returns components.
|
349 | *
|
350 | * IF THE ARN IS A CONCRETE STRING...
|
351 | *
|
352 | * ...it will be parsed and validated. The separator (`sep`) will be set to '/'
|
353 | * if the 6th component includes a '/', in which case, `resource` will be set
|
354 | * to the value before the '/' and `resourceName` will be the rest. In case
|
355 | * there is no '/', `resource` will be set to the 6th components and
|
356 | * `resourceName` will be set to the rest of the string.
|
357 | *
|
358 | * IF THE ARN IS A TOKEN...
|
359 | *
|
360 | * ...it cannot be validated, since we don't have the actual value yet at the
|
361 | * time of this function call. You will have to supply `sepIfToken` and
|
362 | * whether or not ARNs of the expected format usually have resource names
|
363 | * in order to parse it properly. The resulting `ArnComponents` object will
|
364 | * contain tokens for the subexpressions of the ARN, not string literals.
|
365 | *
|
366 | * If the resource name could possibly contain the separator char, the actual
|
367 | * resource name cannot be properly parsed. This only occurs if the separator
|
368 | * char is '/', and happens for example for S3 object ARNs, IAM Role ARNs,
|
369 | * IAM OIDC Provider ARNs, etc. To properly extract the resource name from a
|
370 | * Tokenized ARN, you must know the resource type and call
|
371 | * `Arn.extractResourceName`.
|
372 | *
|
373 | * @param arn The ARN string to parse
|
374 | * @param sepIfToken The separator used to separate resource from resourceName
|
375 | * @param hasName Whether there is a name component in the ARN at all. For
|
376 | * example, SNS Topics ARNs have the 'resource' component contain the topic
|
377 | * name, and no 'resourceName' component.
|
378 | *
|
379 | * @returns an ArnComponents object which allows access to the various
|
380 | * components of the ARN.
|
381 | *
|
382 | * @returns an ArnComponents object which allows access to the various
|
383 | * components of the ARN.
|
384 | *
|
385 | * @deprecated use splitArn instead
|
386 | */
|
387 | parseArn(arn, sepIfToken = '/', hasName = true) {
|
388 | try {
|
389 | jsiiDeprecationWarnings.print("@aws-cdk/core.Stack#parseArn", "use splitArn instead");
|
390 | }
|
391 | catch (error) {
|
392 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
393 | Error.captureStackTrace(error, this.parseArn);
|
394 | }
|
395 | throw error;
|
396 | }
|
397 | return arn_1.Arn.parse(arn, sepIfToken, hasName);
|
398 | }
|
399 | /**
|
400 | * Splits the provided ARN into its components.
|
401 | * Works both if 'arn' is a string like 'arn:aws:s3:::bucket',
|
402 | * and a Token representing a dynamic CloudFormation expression
|
403 | * (in which case the returned components will also be dynamic CloudFormation expressions,
|
404 | * encoded as Tokens).
|
405 | *
|
406 | * @param arn the ARN to split into its components
|
407 | * @param arnFormat the expected format of 'arn' - depends on what format the service 'arn' represents uses
|
408 | */
|
409 | splitArn(arn, arnFormat) {
|
410 | try {
|
411 | jsiiDeprecationWarnings._aws_cdk_core_ArnFormat(arnFormat);
|
412 | }
|
413 | catch (error) {
|
414 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
415 | Error.captureStackTrace(error, this.splitArn);
|
416 | }
|
417 | throw error;
|
418 | }
|
419 | return arn_1.Arn.split(arn, arnFormat);
|
420 | }
|
421 | /**
|
422 | * Returns the list of AZs that are available in the AWS environment
|
423 | * (account/region) associated with this stack.
|
424 | *
|
425 | * If the stack is environment-agnostic (either account and/or region are
|
426 | * tokens), this property will return an array with 2 tokens that will resolve
|
427 | * at deploy-time to the first two availability zones returned from CloudFormation's
|
428 | * `Fn::GetAZs` intrinsic function.
|
429 | *
|
430 | * If they are not available in the context, returns a set of dummy values and
|
431 | * reports them as missing, and let the CLI resolve them by calling EC2
|
432 | * `DescribeAvailabilityZones` on the target environment.
|
433 | *
|
434 | * To specify a different strategy for selecting availability zones override this method.
|
435 | */
|
436 | get availabilityZones() {
|
437 | // if account/region are tokens, we can't obtain AZs through the context
|
438 | // provider, so we fallback to use Fn::GetAZs. the current lowest common
|
439 | // denominator is 2 AZs across all AWS regions.
|
440 | const agnostic = token_1.Token.isUnresolved(this.account) || token_1.Token.isUnresolved(this.region);
|
441 | if (agnostic) {
|
442 | return this.node.tryGetContext(cxapi.AVAILABILITY_ZONE_FALLBACK_CONTEXT_KEY) || [
|
443 | cfn_fn_1.Fn.select(0, cfn_fn_1.Fn.getAzs()),
|
444 | cfn_fn_1.Fn.select(1, cfn_fn_1.Fn.getAzs()),
|
445 | ];
|
446 | }
|
447 | const value = context_provider_1.ContextProvider.getValue(this, {
|
448 | provider: cxschema.ContextProvider.AVAILABILITY_ZONE_PROVIDER,
|
449 | dummyValue: ['dummy1a', 'dummy1b', 'dummy1c'],
|
450 | }).value;
|
451 | if (!Array.isArray(value)) {
|
452 | throw new Error(`Provider ${cxschema.ContextProvider.AVAILABILITY_ZONE_PROVIDER} expects a list`);
|
453 | }
|
454 | return value;
|
455 | }
|
456 | /**
|
457 | * Register a file asset on this Stack
|
458 | *
|
459 | * @deprecated Use `stack.synthesizer.addFileAsset()` if you are calling,
|
460 | * and a different IStackSynthesizer class if you are implementing.
|
461 | */
|
462 | addFileAsset(asset) {
|
463 | try {
|
464 | jsiiDeprecationWarnings.print("@aws-cdk/core.Stack#addFileAsset", "Use `stack.synthesizer.addFileAsset()` if you are calling,\nand a different IStackSynthesizer class if you are implementing.");
|
465 | jsiiDeprecationWarnings._aws_cdk_core_FileAssetSource(asset);
|
466 | }
|
467 | catch (error) {
|
468 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
469 | Error.captureStackTrace(error, this.addFileAsset);
|
470 | }
|
471 | throw error;
|
472 | }
|
473 | return this.synthesizer.addFileAsset(asset);
|
474 | }
|
475 | /**
|
476 | * Register a docker image asset on this Stack
|
477 | *
|
478 | * @deprecated Use `stack.synthesizer.addDockerImageAsset()` if you are calling,
|
479 | * and a different `IStackSynthesizer` class if you are implementing.
|
480 | */
|
481 | addDockerImageAsset(asset) {
|
482 | try {
|
483 | jsiiDeprecationWarnings.print("@aws-cdk/core.Stack#addDockerImageAsset", "Use `stack.synthesizer.addDockerImageAsset()` if you are calling,\nand a different `IStackSynthesizer` class if you are implementing.");
|
484 | jsiiDeprecationWarnings._aws_cdk_core_DockerImageAssetSource(asset);
|
485 | }
|
486 | catch (error) {
|
487 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
488 | Error.captureStackTrace(error, this.addDockerImageAsset);
|
489 | }
|
490 | throw error;
|
491 | }
|
492 | return this.synthesizer.addDockerImageAsset(asset);
|
493 | }
|
494 | /**
|
495 | * If this is a nested stack, returns it's parent stack.
|
496 | */
|
497 | get nestedStackParent() {
|
498 | return this.nestedStackResource && Stack.of(this.nestedStackResource);
|
499 | }
|
500 | /**
|
501 | * Returns the parent of a nested stack.
|
502 | *
|
503 | * @deprecated use `nestedStackParent`
|
504 | */
|
505 | get parentStack() {
|
506 | try {
|
507 | jsiiDeprecationWarnings.print("@aws-cdk/core.Stack#parentStack", "use `nestedStackParent`");
|
508 | }
|
509 | catch (error) {
|
510 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
511 | Error.captureStackTrace(error, jsiiDeprecationWarnings.getPropertyDescriptor(this, "parentStack").get);
|
512 | }
|
513 | throw error;
|
514 | }
|
515 | return this.nestedStackParent;
|
516 | }
|
517 | /**
|
518 | * Add a Transform to this stack. A Transform is a macro that AWS
|
519 | * CloudFormation uses to process your template.
|
520 | *
|
521 | * Duplicate values are removed when stack is synthesized.
|
522 | *
|
523 | * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/transform-section-structure.html
|
524 | * @param transform The transform to add
|
525 | *
|
526 | * @example
|
527 | * declare const stack: Stack;
|
528 | *
|
529 | * stack.addTransform('AWS::Serverless-2016-10-31')
|
530 | */
|
531 | addTransform(transform) {
|
532 | if (!this.templateOptions.transforms) {
|
533 | this.templateOptions.transforms = [];
|
534 | }
|
535 | this.templateOptions.transforms.push(transform);
|
536 | }
|
537 | /**
|
538 | * Called implicitly by the `addDependency` helper function in order to
|
539 | * realize a dependency between two top-level stacks at the assembly level.
|
540 | *
|
541 | * Use `stack.addDependency` to define the dependency between any two stacks,
|
542 | * and take into account nested stack relationships.
|
543 | *
|
544 | * @internal
|
545 | */
|
546 | _addAssemblyDependency(target, reason) {
|
547 | // defensive: we should never get here for nested stacks
|
548 | if (this.nested || target.nested) {
|
549 | throw new Error('Cannot add assembly-level dependencies for nested stacks');
|
550 | }
|
551 | reason = reason || 'dependency added using stack.addDependency()';
|
552 | const cycle = target.stackDependencyReasons(this);
|
553 | if (cycle !== undefined) {
|
554 | // eslint-disable-next-line max-len
|
555 | throw new Error(`'${target.node.path}' depends on '${this.node.path}' (${cycle.join(', ')}). Adding this dependency (${reason}) would create a cyclic reference.`);
|
556 | }
|
557 | let dep = this._stackDependencies[names_1.Names.uniqueId(target)];
|
558 | if (!dep) {
|
559 | dep = this._stackDependencies[names_1.Names.uniqueId(target)] = {
|
560 | stack: target,
|
561 | reasons: [],
|
562 | };
|
563 | }
|
564 | dep.reasons.push(reason);
|
565 | if (process.env.CDK_DEBUG_DEPS) {
|
566 | // eslint-disable-next-line no-console
|
567 | console.error(`[CDK_DEBUG_DEPS] stack "${this.node.path}" depends on "${target.node.path}" because: ${reason}`);
|
568 | }
|
569 | }
|
570 | /**
|
571 | * Synthesizes the cloudformation template into a cloud assembly.
|
572 | * @internal
|
573 | */
|
574 | _synthesizeTemplate(session, lookupRoleArn) {
|
575 | // In principle, stack synthesis is delegated to the
|
576 | // StackSynthesis object.
|
577 | //
|
578 | // However, some parts of synthesis currently use some private
|
579 | // methods on Stack, and I don't really see the value in refactoring
|
580 | // this right now, so some parts still happen here.
|
581 | const builder = session.assembly;
|
582 | const template = this._toCloudFormation();
|
583 | // write the CloudFormation template as a JSON file
|
584 | const outPath = path.join(builder.outdir, this.templateFile);
|
585 | if (this.maxResources > 0) {
|
586 | const resources = template.Resources || {};
|
587 | const numberOfResources = Object.keys(resources).length;
|
588 | if (numberOfResources > this.maxResources) {
|
589 | const counts = Object.entries(count(Object.values(resources).map((r) => `${r?.Type}`))).map(([type, c]) => `${type} (${c})`).join(', ');
|
590 | throw new Error(`Number of resources in stack '${this.node.path}': ${numberOfResources} is greater than allowed maximum of ${this.maxResources}: ${counts}`);
|
591 | }
|
592 | else if (numberOfResources >= (this.maxResources * 0.8)) {
|
593 | annotations_1.Annotations.of(this).addInfo(`Number of resources: ${numberOfResources} is approaching allowed maximum of ${this.maxResources}`);
|
594 | }
|
595 | }
|
596 | fs.writeFileSync(outPath, JSON.stringify(template, undefined, 1));
|
597 | for (const ctx of this._missingContext) {
|
598 | if (lookupRoleArn != null) {
|
599 | builder.addMissing({ ...ctx, props: { ...ctx.props, lookupRoleArn } });
|
600 | }
|
601 | else {
|
602 | builder.addMissing(ctx);
|
603 | }
|
604 | }
|
605 | }
|
606 | /**
|
607 | * Look up a fact value for the given fact for the region of this stack
|
608 | *
|
609 | * Will return a definite value only if the region of the current stack is resolved.
|
610 | * If not, a lookup map will be added to the stack and the lookup will be done at
|
611 | * CDK deployment time.
|
612 | *
|
613 | * What regions will be included in the lookup map is controlled by the
|
614 | * `@aws-cdk/core:target-partitions` context value: it must be set to a list
|
615 | * of partitions, and only regions from the given partitions will be included.
|
616 | * If no such context key is set, all regions will be included.
|
617 | *
|
618 | * This function is intended to be used by construct library authors. Application
|
619 | * builders can rely on the abstractions offered by construct libraries and do
|
620 | * not have to worry about regional facts.
|
621 | *
|
622 | * If `defaultValue` is not given, it is an error if the fact is unknown for
|
623 | * the given region.
|
624 | */
|
625 | regionalFact(factName, defaultValue) {
|
626 | if (!token_1.Token.isUnresolved(this.region)) {
|
627 | const ret = region_info_1.Fact.find(this.region, factName) ?? defaultValue;
|
628 | if (ret === undefined) {
|
629 | throw new Error(`region-info: don't know ${factName} for region ${this.region}. Use 'Fact.register' to provide this value.`);
|
630 | }
|
631 | return ret;
|
632 | }
|
633 | const partitions = constructs_1.Node.of(this).tryGetContext(cxapi.TARGET_PARTITIONS);
|
634 | if (partitions !== undefined && !Array.isArray(partitions)) {
|
635 | throw new Error(`Context value '${cxapi.TARGET_PARTITIONS}' should be a list of strings, got: ${JSON.stringify(cxapi.TARGET_PARTITIONS)}`);
|
636 | }
|
637 | const lookupMap = partitions ? region_info_1.RegionInfo.limitedRegionMap(factName, partitions) : region_info_1.RegionInfo.regionMap(factName);
|
638 | return region_lookup_1.deployTimeLookup(this, factName, lookupMap, defaultValue);
|
639 | }
|
640 | /**
|
641 | * Create a CloudFormation Export for a value
|
642 | *
|
643 | * Returns a string representing the corresponding `Fn.importValue()`
|
644 | * expression for this Export. You can control the name for the export by
|
645 | * passing the `name` option.
|
646 | *
|
647 | * If you don't supply a value for `name`, the value you're exporting must be
|
648 | * a Resource attribute (for example: `bucket.bucketName`) and it will be
|
649 | * given the same name as the automatic cross-stack reference that would be created
|
650 | * if you used the attribute in another Stack.
|
651 | *
|
652 | * One of the uses for this method is to *remove* the relationship between
|
653 | * two Stacks established by automatic cross-stack references. It will
|
654 | * temporarily ensure that the CloudFormation Export still exists while you
|
655 | * remove the reference from the consuming stack. After that, you can remove
|
656 | * the resource and the manual export.
|
657 | *
|
658 | * ## Example
|
659 | *
|
660 | * Here is how the process works. Let's say there are two stacks,
|
661 | * `producerStack` and `consumerStack`, and `producerStack` has a bucket
|
662 | * called `bucket`, which is referenced by `consumerStack` (perhaps because
|
663 | * an AWS Lambda Function writes into it, or something like that).
|
664 | *
|
665 | * It is not safe to remove `producerStack.bucket` because as the bucket is being
|
666 | * deleted, `consumerStack` might still be using it.
|
667 | *
|
668 | * Instead, the process takes two deployments:
|
669 | *
|
670 | * ### Deployment 1: break the relationship
|
671 | *
|
672 | * - Make sure `consumerStack` no longer references `bucket.bucketName` (maybe the consumer
|
673 | * stack now uses its own bucket, or it writes to an AWS DynamoDB table, or maybe you just
|
674 | * remove the Lambda Function altogether).
|
675 | * - In the `ProducerStack` class, call `this.exportValue(this.bucket.bucketName)`. This
|
676 | * will make sure the CloudFormation Export continues to exist while the relationship
|
677 | * between the two stacks is being broken.
|
678 | * - Deploy (this will effectively only change the `consumerStack`, but it's safe to deploy both).
|
679 | *
|
680 | * ### Deployment 2: remove the bucket resource
|
681 | *
|
682 | * - You are now free to remove the `bucket` resource from `producerStack`.
|
683 | * - Don't forget to remove the `exportValue()` call as well.
|
684 | * - Deploy again (this time only the `producerStack` will be changed -- the bucket will be deleted).
|
685 | */
|
686 | exportValue(exportedValue, options = {}) {
|
687 | try {
|
688 | jsiiDeprecationWarnings._aws_cdk_core_ExportValueOptions(options);
|
689 | }
|
690 | catch (error) {
|
691 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
692 | Error.captureStackTrace(error, this.exportValue);
|
693 | }
|
694 | throw error;
|
695 | }
|
696 | if (options.name) {
|
697 | new cfn_output_1.CfnOutput(this, `Export${options.name}`, {
|
698 | value: exportedValue,
|
699 | exportName: options.name,
|
700 | });
|
701 | return cfn_fn_1.Fn.importValue(options.name);
|
702 | }
|
703 | const resolvable = token_1.Tokenization.reverse(exportedValue);
|
704 | if (!resolvable || !reference_1.Reference.isReference(resolvable)) {
|
705 | throw new Error('exportValue: either supply \'name\' or make sure to export a resource attribute (like \'bucket.bucketName\')');
|
706 | }
|
707 | // if exportValue is being called manually (which is pre onPrepare) then the logicalId
|
708 | // could potentially be changed by a call to overrideLogicalId. This would cause our Export/Import
|
709 | // to have an incorrect id. For a better user experience, lock the logicalId and throw an error
|
710 | // if the user tries to override the id _after_ calling exportValue
|
711 | if (cfn_element_1.CfnElement.isCfnElement(resolvable.target)) {
|
712 | resolvable.target._lockLogicalId();
|
713 | }
|
714 | // "teleport" the value here, in case it comes from a nested stack. This will also
|
715 | // ensure the value is from our own scope.
|
716 | const exportable = refs_1.referenceNestedStackValueInParent(resolvable, this);
|
717 | // Ensure a singleton "Exports" scoping Construct
|
718 | // This mostly exists to trigger LogicalID munging, which would be
|
719 | // disabled if we parented constructs directly under Stack.
|
720 | // Also it nicely prevents likely construct name clashes
|
721 | const exportsScope = getCreateExportsScope(this);
|
722 | // Ensure a singleton CfnOutput for this value
|
723 | const resolved = this.resolve(exportable);
|
724 | const id = 'Output' + JSON.stringify(resolved);
|
725 | const exportName = generateExportName(exportsScope, id);
|
726 | if (token_1.Token.isUnresolved(exportName)) {
|
727 | throw new Error(`unresolved token in generated export name: ${JSON.stringify(this.resolve(exportName))}`);
|
728 | }
|
729 | const output = exportsScope.node.tryFindChild(id);
|
730 | if (!output) {
|
731 | new cfn_output_1.CfnOutput(exportsScope, id, { value: token_1.Token.asString(exportable), exportName });
|
732 | }
|
733 | return cfn_fn_1.Fn.importValue(exportName);
|
734 | }
|
735 | /**
|
736 | * Returns the naming scheme used to allocate logical IDs. By default, uses
|
737 | * the `HashedAddressingScheme` but this method can be overridden to customize
|
738 | * this behavior.
|
739 | *
|
740 | * In order to make sure logical IDs are unique and stable, we hash the resource
|
741 | * construct tree path (i.e. toplevel/secondlevel/.../myresource) and add it as
|
742 | * a suffix to the path components joined without a separator (CloudFormation
|
743 | * IDs only allow alphanumeric characters).
|
744 | *
|
745 | * The result will be:
|
746 | *
|
747 | * <path.join('')><md5(path.join('/')>
|
748 | * "human" "hash"
|
749 | *
|
750 | * If the "human" part of the ID exceeds 240 characters, we simply trim it so
|
751 | * the total ID doesn't exceed CloudFormation's 255 character limit.
|
752 | *
|
753 | * We only take 8 characters from the md5 hash (0.000005 chance of collision).
|
754 | *
|
755 | * Special cases:
|
756 | *
|
757 | * - If the path only contains a single component (i.e. it's a top-level
|
758 | * resource), we won't add the hash to it. The hash is not needed for
|
759 | * disamiguation and also, it allows for a more straightforward migration an
|
760 | * existing CloudFormation template to a CDK stack without logical ID changes
|
761 | * (or renames).
|
762 | * - For aesthetic reasons, if the last components of the path are the same
|
763 | * (i.e. `L1/L2/Pipeline/Pipeline`), they will be de-duplicated to make the
|
764 | * resulting human portion of the ID more pleasing: `L1L2Pipeline<HASH>`
|
765 | * instead of `L1L2PipelinePipeline<HASH>`
|
766 | * - If a component is named "Default" it will be omitted from the path. This
|
767 | * allows refactoring higher level abstractions around constructs without affecting
|
768 | * the IDs of already deployed resources.
|
769 | * - If a component is named "Resource" it will be omitted from the user-visible
|
770 | * path, but included in the hash. This reduces visual noise in the human readable
|
771 | * part of the identifier.
|
772 | *
|
773 | * @param cfnElement The element for which the logical ID is allocated.
|
774 | */
|
775 | allocateLogicalId(cfnElement) {
|
776 | try {
|
777 | jsiiDeprecationWarnings._aws_cdk_core_CfnElement(cfnElement);
|
778 | }
|
779 | catch (error) {
|
780 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
781 | Error.captureStackTrace(error, this.allocateLogicalId);
|
782 | }
|
783 | throw error;
|
784 | }
|
785 | const scopes = cfnElement.node.scopes;
|
786 | const stackIndex = scopes.indexOf(cfnElement.stack);
|
787 | const pathComponents = scopes.slice(stackIndex + 1).map(x => x.node.id);
|
788 | return uniqueid_1.makeUniqueId(pathComponents);
|
789 | }
|
790 | /**
|
791 | * Validate stack name
|
792 | *
|
793 | * CloudFormation stack names can include dashes in addition to the regular identifier
|
794 | * character classes, and we don't allow one of the magic markers.
|
795 | *
|
796 | * @internal
|
797 | */
|
798 | _validateId(name) {
|
799 | if (name && !VALID_STACK_NAME_REGEX.test(name)) {
|
800 | throw new Error(`Stack name must match the regular expression: ${VALID_STACK_NAME_REGEX.toString()}, got '${name}'`);
|
801 | }
|
802 | }
|
803 | /**
|
804 | * Returns the CloudFormation template for this stack by traversing
|
805 | * the tree and invoking _toCloudFormation() on all Entity objects.
|
806 | *
|
807 | * @internal
|
808 | */
|
809 | _toCloudFormation() {
|
810 | let transform;
|
811 | if (this.templateOptions.transform) {
|
812 | // eslint-disable-next-line max-len
|
813 | annotations_1.Annotations.of(this).addWarning('This stack is using the deprecated `templateOptions.transform` property. Consider switching to `addTransform()`.');
|
814 | this.addTransform(this.templateOptions.transform);
|
815 | }
|
816 | if (this.templateOptions.transforms) {
|
817 | if (this.templateOptions.transforms.length === 1) { // Extract single value
|
818 | transform = this.templateOptions.transforms[0];
|
819 | }
|
820 | else { // Remove duplicate values
|
821 | transform = Array.from(new Set(this.templateOptions.transforms));
|
822 | }
|
823 | }
|
824 | const template = {
|
825 | Description: this.templateOptions.description,
|
826 | Transform: transform,
|
827 | AWSTemplateFormatVersion: this.templateOptions.templateFormatVersion,
|
828 | Metadata: this.templateOptions.metadata,
|
829 | };
|
830 | const elements = cfnElements(this);
|
831 | const fragments = elements.map(e => this.resolve(e._toCloudFormation()));
|
832 | // merge in all CloudFormation fragments collected from the tree
|
833 | for (const fragment of fragments) {
|
834 | merge(template, fragment);
|
835 | }
|
836 | // resolve all tokens and remove all empties
|
837 | const ret = this.resolve(template) || {};
|
838 | this._logicalIds.assertAllRenamesApplied();
|
839 | return ret;
|
840 | }
|
841 | /**
|
842 | * Deprecated.
|
843 | *
|
844 | * @see https://github.com/aws/aws-cdk/pull/7187
|
845 | * @returns reference itself without any change
|
846 | * @deprecated cross reference handling has been moved to `App.prepare()`.
|
847 | */
|
848 | prepareCrossReference(_sourceStack, reference) {
|
849 | try {
|
850 | jsiiDeprecationWarnings.print("@aws-cdk/core.Stack#prepareCrossReference", "cross reference handling has been moved to `App.prepare()`.");
|
851 | jsiiDeprecationWarnings._aws_cdk_core_Stack(_sourceStack);
|
852 | jsiiDeprecationWarnings._aws_cdk_core_Reference(reference);
|
853 | }
|
854 | catch (error) {
|
855 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
856 | Error.captureStackTrace(error, this.prepareCrossReference);
|
857 | }
|
858 | throw error;
|
859 | }
|
860 | return reference;
|
861 | }
|
862 | /**
|
863 | * Determine the various stack environment attributes.
|
864 | *
|
865 | */
|
866 | parseEnvironment(env = {}) {
|
867 | // if an environment property is explicitly specified when the stack is
|
868 | // created, it will be used. if not, use tokens for account and region.
|
869 | //
|
870 | // (They do not need to be anchored to any construct like resource attributes
|
871 | // are, because we'll never Export/Fn::ImportValue them -- the only situation
|
872 | // in which Export/Fn::ImportValue would work is if the value are the same
|
873 | // between producer and consumer anyway, so we can just assume that they are).
|
874 | const containingAssembly = stage_1.Stage.of(this);
|
875 | const account = env.account ?? containingAssembly?.account ?? cfn_pseudo_1.Aws.ACCOUNT_ID;
|
876 | const region = env.region ?? containingAssembly?.region ?? cfn_pseudo_1.Aws.REGION;
|
877 | // this is the "aws://" env specification that will be written to the cloud assembly
|
878 | // manifest. it will use "unknown-account" and "unknown-region" to indicate
|
879 | // environment-agnosticness.
|
880 | const envAccount = !token_1.Token.isUnresolved(account) ? account : cxapi.UNKNOWN_ACCOUNT;
|
881 | const envRegion = !token_1.Token.isUnresolved(region) ? region : cxapi.UNKNOWN_REGION;
|
882 | return {
|
883 | account,
|
884 | region,
|
885 | environment: cxapi.EnvironmentUtils.format(envAccount, envRegion),
|
886 | };
|
887 | }
|
888 | /**
|
889 | * Maximum number of resources in the stack
|
890 | *
|
891 | * Set to 0 to mean "unlimited".
|
892 | */
|
893 | get maxResources() {
|
894 | const contextLimit = this.node.tryGetContext(exports.STACK_RESOURCE_LIMIT_CONTEXT);
|
895 | return contextLimit !== undefined ? parseInt(contextLimit, 10) : MAX_RESOURCES;
|
896 | }
|
897 | /**
|
898 | * Check whether this stack has a (transitive) dependency on another stack
|
899 | *
|
900 | * Returns the list of reasons on the dependency path, or undefined
|
901 | * if there is no dependency.
|
902 | */
|
903 | stackDependencyReasons(other) {
|
904 | if (this === other) {
|
905 | return [];
|
906 | }
|
907 | for (const dep of Object.values(this._stackDependencies)) {
|
908 | const ret = dep.stack.stackDependencyReasons(other);
|
909 | if (ret !== undefined) {
|
910 | return [...dep.reasons, ...ret];
|
911 | }
|
912 | }
|
913 | return undefined;
|
914 | }
|
915 | /**
|
916 | * Calculate the stack name based on the construct path
|
917 | *
|
918 | * The stack name is the name under which we'll deploy the stack,
|
919 | * and incorporates containing Stage names by default.
|
920 | *
|
921 | * Generally this looks a lot like how logical IDs are calculated.
|
922 | * The stack name is calculated based on the construct root path,
|
923 | * as follows:
|
924 | *
|
925 | * - Path is calculated with respect to containing App or Stage (if any)
|
926 | * - If the path is one component long just use that component, otherwise
|
927 | * combine them with a hash.
|
928 | *
|
929 | * Since the hash is quite ugly and we'd like to avoid it if possible -- but
|
930 | * we can't anymore in the general case since it has been written into legacy
|
931 | * stacks. The introduction of Stages makes it possible to make this nicer however.
|
932 | * When a Stack is nested inside a Stage, we use the path components below the
|
933 | * Stage, and prefix the path components of the Stage before it.
|
934 | */
|
935 | generateStackName() {
|
936 | const assembly = stage_1.Stage.of(this);
|
937 | const prefix = (assembly && assembly.stageName) ? `${assembly.stageName}-` : '';
|
938 | return `${prefix}${this.generateStackId(assembly)}`;
|
939 | }
|
940 | /**
|
941 | * The artifact ID for this stack
|
942 | *
|
943 | * Stack artifact ID is unique within the App's Cloud Assembly.
|
944 | */
|
945 | generateStackArtifactId() {
|
946 | return this.generateStackId(this.node.root);
|
947 | }
|
948 | /**
|
949 | * Generate an ID with respect to the given container construct.
|
950 | */
|
951 | generateStackId(container) {
|
952 | const rootPath = rootPathTo(this, container);
|
953 | const ids = rootPath.map(c => constructs_1.Node.of(c).id);
|
954 | // In unit tests our Stack (which is the only component) may not have an
|
955 | // id, so in that case just pretend it's "Stack".
|
956 | if (ids.length === 1 && !ids[0]) {
|
957 | throw new Error('unexpected: stack id must always be defined');
|
958 | }
|
959 | return makeStackName(ids);
|
960 | }
|
961 | /**
|
962 | * Indicates whether the stack requires bundling or not
|
963 | */
|
964 | get bundlingRequired() {
|
965 | const bundlingStacks = this.node.tryGetContext(cxapi.BUNDLING_STACKS) ?? ['*'];
|
966 | // bundlingStacks is of the form `Stage/Stack`, convert it to `Stage-Stack` before comparing to stack name
|
967 | return bundlingStacks.some(pattern => minimatch(this.stackName, pattern.replace('/', '-')));
|
968 | }
|
969 | }
|
970 | exports.Stack = Stack;
|
971 | _a = JSII_RTTI_SYMBOL_1;
|
972 | Stack[_a] = { fqn: "@aws-cdk/core.Stack", version: "1.204.0" };
|
973 | function merge(template, fragment) {
|
974 | for (const section of Object.keys(fragment)) {
|
975 | const src = fragment[section];
|
976 | // create top-level section if it doesn't exist
|
977 | const dest = template[section];
|
978 | if (!dest) {
|
979 | template[section] = src;
|
980 | }
|
981 | else {
|
982 | template[section] = mergeSection(section, dest, src);
|
983 | }
|
984 | }
|
985 | }
|
986 | function mergeSection(section, val1, val2) {
|
987 | switch (section) {
|
988 | case 'Description':
|
989 | return `${val1}\n${val2}`;
|
990 | case 'AWSTemplateFormatVersion':
|
991 | if (val1 != null && val2 != null && val1 !== val2) {
|
992 | throw new Error(`Conflicting CloudFormation template versions provided: '${val1}' and '${val2}`);
|
993 | }
|
994 | return val1 ?? val2;
|
995 | case 'Transform':
|
996 | return mergeSets(val1, val2);
|
997 | default:
|
998 | return mergeObjectsWithoutDuplicates(section, val1, val2);
|
999 | }
|
1000 | }
|
1001 | function mergeSets(val1, val2) {
|
1002 | const array1 = val1 == null ? [] : (Array.isArray(val1) ? val1 : [val1]);
|
1003 | const array2 = val2 == null ? [] : (Array.isArray(val2) ? val2 : [val2]);
|
1004 | for (const value of array2) {
|
1005 | if (!array1.includes(value)) {
|
1006 | array1.push(value);
|
1007 | }
|
1008 | }
|
1009 | return array1.length === 1 ? array1[0] : array1;
|
1010 | }
|
1011 | function mergeObjectsWithoutDuplicates(section, dest, src) {
|
1012 | if (typeof dest !== 'object') {
|
1013 | throw new Error(`Expecting ${JSON.stringify(dest)} to be an object`);
|
1014 | }
|
1015 | if (typeof src !== 'object') {
|
1016 | throw new Error(`Expecting ${JSON.stringify(src)} to be an object`);
|
1017 | }
|
1018 | // add all entities from source section to destination section
|
1019 | for (const id of Object.keys(src)) {
|
1020 | if (id in dest) {
|
1021 | throw new Error(`section '${section}' already contains '${id}'`);
|
1022 | }
|
1023 | dest[id] = src[id];
|
1024 | }
|
1025 | return dest;
|
1026 | }
|
1027 | /**
|
1028 | * Collect all CfnElements from a Stack.
|
1029 | *
|
1030 | * @param node Root node to collect all CfnElements from
|
1031 | * @param into Array to append CfnElements to
|
1032 | * @returns The same array as is being collected into
|
1033 | */
|
1034 | function cfnElements(node, into = []) {
|
1035 | if (cfn_element_1.CfnElement.isCfnElement(node)) {
|
1036 | into.push(node);
|
1037 | }
|
1038 | for (const child of constructs_1.Node.of(node).children) {
|
1039 | // Don't recurse into a substack
|
1040 | if (Stack.isStack(child)) {
|
1041 | continue;
|
1042 | }
|
1043 | cfnElements(child, into);
|
1044 | }
|
1045 | return into;
|
1046 | }
|
1047 | /**
|
1048 | * Return the construct root path of the given construct relative to the given ancestor
|
1049 | *
|
1050 | * If no ancestor is given or the ancestor is not found, return the entire root path.
|
1051 | */
|
1052 | function rootPathTo(construct, ancestor) {
|
1053 | const scopes = constructs_1.Node.of(construct).scopes;
|
1054 | for (let i = scopes.length - 2; i >= 0; i--) {
|
1055 | if (scopes[i] === ancestor) {
|
1056 | return scopes.slice(i + 1);
|
1057 | }
|
1058 | }
|
1059 | return scopes;
|
1060 | }
|
1061 | exports.rootPathTo = rootPathTo;
|
1062 | /**
|
1063 | * makeUniqueId, specialized for Stack names
|
1064 | *
|
1065 | * Stack names may contain '-', so we allow that character if the stack name
|
1066 | * has only one component. Otherwise we fall back to the regular "makeUniqueId"
|
1067 | * behavior.
|
1068 | */
|
1069 | function makeStackName(components) {
|
1070 | if (components.length === 1) {
|
1071 | return components[0];
|
1072 | }
|
1073 | return uniqueid_1.makeUniqueId(components);
|
1074 | }
|
1075 | function getCreateExportsScope(stack) {
|
1076 | const exportsName = 'Exports';
|
1077 | let stackExports = stack.node.tryFindChild(exportsName);
|
1078 | if (stackExports === undefined) {
|
1079 | stackExports = new construct_compat_1.Construct(stack, exportsName);
|
1080 | }
|
1081 | return stackExports;
|
1082 | }
|
1083 | function generateExportName(stackExports, id) {
|
1084 | const stackRelativeExports = feature_flags_1.FeatureFlags.of(stackExports).isEnabled(cxapi.STACK_RELATIVE_EXPORTS_CONTEXT);
|
1085 | const stack = Stack.of(stackExports);
|
1086 | const components = [
|
1087 | ...stackExports.node.scopes
|
1088 | .slice(stackRelativeExports ? stack.node.scopes.length : 2)
|
1089 | .map(c => c.node.id),
|
1090 | id,
|
1091 | ];
|
1092 | const prefix = stack.stackName ? stack.stackName + ':' : '';
|
1093 | const localPart = uniqueid_1.makeUniqueId(components);
|
1094 | const maxLength = 255;
|
1095 | return prefix + localPart.slice(Math.max(0, localPart.length - maxLength + prefix.length));
|
1096 | }
|
1097 | function count(xs) {
|
1098 | const ret = {};
|
1099 | for (const x of xs) {
|
1100 | if (x in ret) {
|
1101 | ret[x] += 1;
|
1102 | }
|
1103 | else {
|
1104 | ret[x] = 1;
|
1105 | }
|
1106 | }
|
1107 | return ret;
|
1108 | }
|
1109 | // These imports have to be at the end to prevent circular imports
|
1110 | const cfn_output_1 = require("./cfn-output");
|
1111 | const deps_1 = require("./deps");
|
1112 | const fs_1 = require("./fs");
|
1113 | const names_1 = require("./names");
|
1114 | const reference_1 = require("./reference");
|
1115 | const stack_synthesizers_1 = require("./stack-synthesizers");
|
1116 | const stage_1 = require("./stage");
|
1117 | const tag_manager_1 = require("./tag-manager");
|
1118 | const token_1 = require("./token");
|
1119 | const refs_1 = require("./private/refs");
|
1120 | const region_info_1 = require("@aws-cdk/region-info");
|
1121 | const region_lookup_1 = require("./private/region-lookup");
|
1122 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhY2suanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJzdGFjay50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSx5QkFBeUI7QUFDekIsNkJBQTZCO0FBQzdCLDJEQUEyRDtBQUMzRCx5Q0FBeUM7QUFDekMsMkNBQXlEO0FBQ3pELHVDQUF1QztBQUN2QywrQ0FBNEM7QUFDNUMsK0JBQTRCO0FBQzVCLCtCQUFzRDtBQUV0RCwrQ0FBMkM7QUFDM0MscUNBQThCO0FBQzlCLDZDQUE4QztBQUM5QyxpREFBc0Q7QUFFdEQseURBQXFEO0FBRXJELG1EQUErQztBQUMvQyx1RUFBa0c7QUFDbEcscURBQWtEO0FBQ2xELCtDQUE0QztBQUM1QyxpREFBa0Q7QUFFbEQsZ0hBQWdIO0FBQ2hILDJCQUEyQjtBQUMzQix5REFBZ0U7QUFFaEUsTUFBTSxZQUFZLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO0FBQ3ZELE1BQU0sY0FBYyxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsNkJBQTZCLENBQUMsQ0FBQztBQUVwRCxRQUFBLDRCQUE0QixHQUFHLGtDQUFrQyxDQUFDO0FBRS9FLE1BQU0sc0JBQXNCLEdBQUcseUJBQXlCLENBQUM7QUFFekQsTUFBTSxhQUFhLEdBQUcsR0FBRyxDQUFDO0FBa0gxQjs7R0FFRztBQUNILE1BQWEsS0FBTSxTQUFRLDRCQUFhO0lBK0t0Qzs7Ozs7Ozs7T0FRRztJQUNILFlBQW1CLEtBQWlCLEVBQUUsRUFBVyxFQUFFLFFBQW9CLEVBQUU7Ozs7OzsrQ0F4TDlELEtBQUs7Ozs7UUF5TGQsK0VBQStFO1FBQy9FLG9FQUFvRTtRQUNwRSxLQUFLLEdBQUcsS0FBSyxJQUFJLElBQUksU0FBRyxDQUFDO1lBQ3ZCLFNBQVMsRUFBRSxLQUFLO1lBQ2hCLE1BQU0sRUFBRSxlQUFVLENBQUMsT0FBTyxDQUFDLGVBQWUsQ0FBQztTQUM1QyxDQUFDLENBQUM7UUFFSCxnRUFBZ0U7UUFDaEUsRUFBRSxHQUFH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O0lBQ0YsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLFNBQVMsR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUM1RCxNQUFNLFNBQVMsR0FBRyx1QkFBWSxDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQzNDLE1BQU0sU0FBUyxHQUFHLEdBQUcsQ0FBQztJQUN0QixPQUFPLE1BQU0sR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxNQUFNLEdBQUcsU0FBUyxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0FBQzdGLENBQUM7QUFtQkQsU0FBUyxLQUFLLENBQUMsRUFBWTtJQUN6QixNQUFNLEdBQUcsR0FBMkIsRUFBRSxDQUFDO0lBQ3ZDLEtBQUssTUFBTSxDQUFDLElBQUksRUFBRSxFQUFFO1FBQ2xCLElBQUksQ0FBQyxJQUFJLEdBQUcsRUFBRTtZQUNaLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7U0FDYjthQUFNO1lBQ0wsR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztTQUNaO0tBQ0Y7SUFDRCxPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUM7QUFFRCxrRUFBa0U7QUFDbEUsNkNBQXlDO0FBQ3pDLGlDQUF1QztBQUN2Qyw2QkFBa0M7QUFDbEMsbUNBQWdDO0FBQ2hDLDJDQUF3QztBQUV4Qyw2REFBMEc7QUFDMUcsbUNBQWdDO0FBQ2hDLCtDQUFzRDtBQUN0RCxtQ0FBOEM7QUFDOUMseUNBQW1FO0FBQ25FLHNEQUF3RDtBQUN4RCwyREFBMkQiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBmcyBmcm9tICdmcyc7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0ICogYXMgY3hzY2hlbWEgZnJvbSAnQGF3cy1jZGsvY2xvdWQtYXNzZW1ibHktc2NoZW1hJztcbmltcG9ydCAqIGFzIGN4YXBpIGZyb20gJ0Bhd3MtY2RrL2N4LWFwaSc7XG5pbXBvcnQgeyBJQ29uc3RydWN0LCBDb25zdHJ1Y3QsIE5vZGUgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCAqIGFzIG1pbmltYXRjaCBmcm9tICdtaW5pbWF0Y2gnO1xuaW1wb3J0IHsgQW5ub3RhdGlvbnMgfSBmcm9tICcuL2Fubm90YXRpb25zJztcbmltcG9ydCB7IEFwcCB9IGZyb20gJy4vYXBwJztcbmltcG9ydCB7IEFybiwgQXJuQ29tcG9uZW50cywgQXJuRm9ybWF0IH0gZnJvbSAnLi9hcm4nO1xuaW1wb3J0IHsgRG9ja2VySW1hZ2VBc3NldExvY2F0aW9uLCBEb2NrZXJJbWFnZUFzc2V0U291cmNlLCBGaWxlQXNzZXRMb2NhdGlvbiwgRmlsZUFzc2V0U291cmNlIH0gZnJvbSAnLi9hc3NldHMnO1xuaW1wb3J0IHsgQ2ZuRWxlbWVudCB9IGZyb20gJy4vY2ZuLWVsZW1lbnQnO1xuaW1wb3J0IHsgRm4gfSBmcm9tICcuL2Nmbi1mbic7XG5pbXBvcnQgeyBBd3MsIFNjb3BlZEF3cyB9IGZyb20gJy4vY2ZuLXBzZXVkbyc7XG5pbXBvcnQgeyBDZm5SZXNvdXJjZSwgVGFnVHlwZSB9IGZyb20gJy4vY2ZuLXJlc291cmNlJztcbmltcG9ydCB7IElTeW50aGVzaXNTZXNzaW9uIH0gZnJvbSAnLi9jb25zdHJ1Y3QtY29tcGF0JztcbmltcG9ydCB7IENvbnRleHRQcm92aWRlciB9IGZyb20gJy4vY29udGV4dC1wcm92aWRlcic7XG5pbXBvcnQgeyBFbnZpcm9ubWVudCB9IGZyb20gJy4vZW52aXJvbm1lbnQnO1xuaW1wb3J0IHsgRmVhdHVyZUZsYWdzIH0gZnJvbSAnLi9mZWF0dXJlLWZsYWdzJztcbmltcG9ydCB7IENMT1VERk9STUFUSU9OX1RPS0VOX1JFU09MVkVSLCBDbG91ZEZvcm1hdGlvbkxhbmcgfSBmcm9tICcuL3ByaXZhdGUvY2xvdWRmb3JtYXRpb24tbGFuZyc7XG5pbXBvcnQgeyBMb2dpY2FsSURzIH0gZnJvbSAnLi9wcml2YXRlL2xvZ2ljYWwtaWQnO1xuaW1wb3J0IHsgcmVzb2x2ZSB9IGZyb20gJy4vcHJpdmF0ZS9yZXNvbHZlJztcbmltcG9ydCB7IG1ha2VVbmlxdWVJZCB9IGZyb20gJy4vcHJpdmF0ZS91bmlxdWVpZCc7XG5cbi8vIHYyIC0ga2VlcCB0aGlzIGltcG9ydCBhcyBhIHNlcGFyYXRlIHNlY3Rpb24gdG8gcmVkdWNlIG1lcmdlIGNvbmZsaWN0IHdoZW4gZm9yd2FyZCBtZXJnaW5nIHdpdGggdGhlIHYyIGJyYW5jaC5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuaW1wb3J0IHsgQ29uc3RydWN0IGFzIENvcmVDb25zdHJ1Y3QgfSBmcm9tICcuL2NvbnN0cnVjdC1jb21wYXQnO1xuXG5jb25zdCBTVEFDS19TWU1CT0wgPSBTeW1ib2wuZm9yKCdAYXdzLWNkay9jb3JlLlN0YWNrJyk7XG5jb25zdCBNWV9TVEFDS19DQUNIRSA9IFN5bWJvbC5mb3IoJ0Bhd3MtY2RrL2NvcmUuU3RhY2subXlTdGFjaycpO1xuXG5leHBvcnQgY29uc3QgU1RBQ0tfUkVTT1VSQ0VfTElNSVRfQ09OVEVYVCA9ICdAYXdzLWNkay9jb3JlOnN0YWNrUmVzb3VyY2VMaW1pdCc7XG5cbmNvbnN0IFZBTElEX1NUQUNLX05BTUVfUkVHRVggPSAvXltBLVphLXpdW0EtWmEtejAtOS1dKiQvO1xuXG5jb25zdCBNQVhfUkVTT1VSQ0VTID0gNTAwO1xuXG5leHBvcnQgaW50ZXJmYWNlIFN0YWNrUHJvcHMge1xuICAvKipcbiAgICogQSBkZXNjcmlwdGlvbiBvZiB0aGUgc3RhY2suXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gZGVzY3JpcHRpb24uXG4gICAqL1xuICByZWFkb25seSBkZXNjcmlwdGlvbj86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIEFXUyBlbnZpcm9ubWVudCAoYWNjb3VudC9yZWdpb24pIHdoZXJlIHRoaXMgc3RhY2sgd2lsbCBiZSBkZXBsb3llZC5cbiAgICpcbiAgICogU2V0IHRoZSBgcmVnaW9uYC9gYWNjb3VudGAgZmllbGRzIG9mIGBlbnZgIHRvIGVpdGhlciBhIGNvbmNyZXRlIHZhbHVlIHRvXG4gICAqIHNlbGVjdCB0aGUgaW5kaWNhdGVkIGVudmlyb25tZW50IChyZWNvbW1lbmRlZCBmb3IgcHJvZHVjdGlvbiBzdGFja3MpLCBvciB0b1xuICAgKiB0aGUgdmFsdWVzIG9mIGVudmlyb25tZW50IHZhcmlhYmxlc1xuICAgKiBgQ0RLX0RFRkFVTFRfUkVHSU9OYC9gQ0RLX0RFRkFVTFRfQUNDT1VOVGAgdG8gbGV0IHRoZSB0YXJnZXQgZW52aXJvbm1lbnRcbiAgICogZGVwZW5kIG9uIHRoZSBBV1MgY3JlZGVudGlhbHMvY29uZmlndXJhdGlvbiB0aGF0IHRoZSBDREsgQ0xJIGlzIGV4ZWN1dGVkXG4gICAqIHVuZGVyIChyZWNvbW1lbmRlZCBmb3IgZGV2ZWxvcG1lbnQgc3RhY2tzKS5cbiAgICpcbiAgICogSWYgdGhlIGBTdGFja2AgaXMgaW5zdGFudGlhdGVkIGluc2lkZSBhIGBTdGFnZWAsIGFueSB1bmRlZmluZWRcbiAgICogYHJlZ2lvbmAvYGFjY291bnRgIGZpZWxkcyBmcm9tIGBlbnZgIHdpbGwgZGVmYXVsdCB0byB0aGUgc2FtZSBmaWVsZCBvbiB0aGVcbiAgICogZW5jb21wYXNzaW5nIGBTdGFnZWAsIGlmIGNvbmZpZ3VyZWQgdGhlcmUuXG4gICAqXG4gICAqIElmIGVpdGhlciBgcmVnaW9uYCBvciBgYWNjb3VudGAgYXJlIG5vdCBzZXQgbm9yIGluaGVyaXRlZCBmcm9tIGBTdGFnZWAsIHRoZVxuICAgKiBTdGFjayB3aWxsIGJlIGNvbnNpZGVyZWQgXCIqZW52aXJvbm1lbnQtYWdub3N0aWMqXCJcIi4gRW52aXJvbm1lbnQtYWdub3N0aWNcbiAgICogc3RhY2tzIGNhbiBiZSBkZXBsb3llZCB0byBhbnkgZW52aXJvbm1lbnQgYnV0IG1heSBub3QgYmUgYWJsZSB0byB0YWtlXG4gICAqIGFkdmFudGFnZSBvZiBhbGwgZmVhdHVyZXMgb2YgdGhlIENESy4gRm9yIGV4YW1wbGUsIHRoZXkgd2lsbCBub3QgYmUgYWJsZSB0b1xuICAgKiB1c2UgZW52aXJvbm1lbnRhbCBjb250ZXh0IGxvb2t1cHMgc3VjaCBhcyBgZWMyLlZwYy5mcm9tTG9va3VwYCBhbmQgd2lsbCBub3RcbiAgICogYXV0b21hdGljYWxseSB0cmFuc2xhdGUgU2VydmljZSBQcmluY2lwYWxzIHRvIHRoZSByaWdodCBmb3JtYXQgYmFzZWQgb24gdGhlXG4gICAqIGVudmlyb25tZW50J3MgQVdTIHBhcnRpdGlvbiwgYW5kIG90aGVyIHN1Y2ggZW5oYW5jZW1lbnRzLlxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKlxuICAgKiAvLyBVc2UgYSBjb25jcmV0ZSBhY2NvdW50IGFuZCByZWdpb24gdG8gZGVwbG95IHRoaXMgc3RhY2sgdG86XG4gICAqIC8vIGAuYWNjb3VudGAgYW5kIGAucmVnaW9uYCB3aWxsIHNpbXBseSByZXR1cm4gdGhlc2UgdmFsdWVzLlxuICAgKiBuZXcgU3RhY2soYXBwLCAnU3RhY2sxJywge1xuICAgKiAgIGVudjoge1xuICAgKiAgICAgYWNjb3VudDogJzEyMzQ1Njc4OTAxMicsXG4gICAqICAgICByZWdpb246ICd1cy1lYXN0LTEnXG4gICAqICAgfSxcbiAgICogfSk7XG4gICAqXG4gICAqIC8vIFVzZSB0aGUgQ0xJJ3MgY3VycmVudCBjcmVkZW50aWFscyB0byBkZXRlcm1pbmUgdGhlIHRhcmdldCBlbnZpcm9ubWVudDpcbiAgICogLy8gYC5hY2NvdW50YCBhbmQgYC5yZWdpb25gIHdpbGwgcmVmbGVjdCB0aGUgYWNjb3VudCtyZWdpb24gdGhlIENMSVxuICAgKiAvLyBpcyBjb25maWd1cmVkIHRvIHVzZSAoYmFzZWQgb24gdGhlIHVzZXIgQ0xJIGNyZWRlbnRpYWxzKVxuICAgKiBuZXcgU3RhY2soYXBwLCAnU3RhY2syJywge1xuICAgKiAgIGVudjoge1xuICAgKiAgICAgYWNjb3VudDogcHJvY2Vzcy5lbnYuQ0RLX0RFRkFVTFRfQUNDT1VOVCxcbiAgICogICAgIHJlZ2lvbjogcHJvY2Vzcy5lbnYuQ0RLX0RFRkFVTFRfUkVHSU9OXG4gICAqICAgfSxcbiAgICogfSk7XG4gICAqXG4gICAqIC8vIERlZmluZSBtdWx0aXBsZSBzdGFja3Mgc3RhZ2UgYXNzb2NpYXRlZCB3aXRoIGFuIGVudmlyb25tZW50XG4gICAqIGNvbnN0IG15U3RhZ2UgPSBuZXcgU3RhZ2UoYXBwLCAnTXlTdGFnZScsIHtcbiAgICogICBlbnY6IHtcbiAgICogICAgIGFjY291bnQ6ICcxMjM0NTY3ODkwMTInLFxuICAgKiAgICAgcmVnaW9uOiAndXMtZWFzdC0xJ1xuICAgKiAgIH1cbiAgICogfSk7XG4gICAqXG4gICAqIC8vIGJvdGggb2YgdGhlc2Ugc3RhY2tzIHdpbGwgdXNlIHRoZSBzdGFnZSdzIGFjY291bnQvcmVnaW9uOlxuICAgKiAvLyBgLmFjY291bnRgIGFuZCBgLnJlZ2lvbmAgd2lsbCByZXNvbHZlIHRvIHRoZSBjb25jcmV0ZSB2YWx1ZXMgYXMgYWJvdmVcbiAgICogbmV3IE15U3RhY2sobXlTdGFnZSwgJ1N0YWNrMScpO1xuICAgKiBuZXcgWW91clN0YWNrKG15U3RhZ2UsICdTdGFjazInKTtcbiAgICpcbiAgICogLy8gRGVmaW5lIGFuIGVudmlyb25tZW50LWFnbm9zdGljIHN0YWNrOlxuICAgKiAvLyBgLmFjY291bnRgIGFuZCBgLnJlZ2lvbmAgd2lsbCByZXNvbHZlIHRvIGB7IFwiUmVmXCI6IFwiQVdTOjpBY2NvdW50SWRcIiB9YCBhbmQgYHsgXCJSZWZcIjogXCJBV1M6OlJlZ2lvblwiIH1gIHJlc3BlY3RpdmVseS5cbiAgICogLy8gd2hpY2ggd2lsbCBvbmx5IHJlc29sdmUgdG8gYWN0dWFsIHZhbHVlcyBieSBDbG91ZEZvcm1hdGlvbiBkdXJpbmcgZGVwbG95bWVudC5cbiAgICogbmV3IE15U3RhY2soYXBwLCAnU3RhY2sxJyk7XG4gICAqXG4gICAqIEBkZWZhdWx0IC0gVGhlIGVudmlyb25tZW50IG9mIHRoZSBjb250YWluaW5nIGBTdGFnZWAgaWYgYXZhaWxhYmxlLFxuICAgKiBvdGhlcndpc2UgY3JlYXRlIHRoZSBzdGFjayB3aWxsIGJlIGVudmlyb25tZW50LWFnbm9zdGljLlxuICAgKi9cbiAgcmVhZG9ubHkgZW52PzogRW52aXJvbm1lbnQ7XG5cbiAgLyoqXG4gICAqIE5hbWUgdG8gZGVwbG95IHRoZSBzdGFjayB3aXRoXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gRGVyaXZlZCBmcm9tIGNvbnN0cnVjdCBwYXRoLlxuICAgKi9cbiAgcmVhZG9ubHkgc3RhY2tOYW1lPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBTdGFjayB0YWdzIHRoYXQgd2lsbCBiZSBhcHBsaWVkIHRvIGFsbCB0aGUgdGFnZ2FibGUgcmVzb3VyY2VzIGFuZCB0aGUgc3RhY2sgaXRzZWxmLlxuICAgKlxuICAgKiBAZGVmYXVsdCB7fVxuICAgKi9cbiAgcmVhZG9ubHkgdGFncz86IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH07XG5cbiAgLyoqXG4gICAqIFN5bnRoZXNpcyBtZXRob2QgdG8gdXNlIHdoaWxlIGRlcGxveWluZyB0aGlzIHN0YWNrXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gYERlZmF1bHRTdGFja1N5bnRoZXNpemVyYCBpZiB0aGUgYEBhd3MtY2RrL2NvcmU6bmV3U3R5bGVTdGFja1N5bnRoZXNpc2AgZmVhdHVyZSBmbGFnXG4gICAqIGlzIHNldCwgYExlZ2FjeVN0YWNrU3ludGhlc2l6ZXJgIG90aGVyd2lzZS5cbiAgICovXG4gIHJlYWRvbmx5IHN5bnRoZXNpemVyPzogSVN0YWNrU3ludGhlc2l6ZXI7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gZW5hYmxlIHRlcm1pbmF0aW9uIHByb3RlY3Rpb24gZm9yIHRoaXMgc3RhY2suXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSB0ZXJtaW5hdGlvblByb3RlY3Rpb24/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBJbmNsdWRlIHJ1bnRpbWUgdmVyc2lvbmluZyBpbmZvcm1hdGlvbiBpbiB0aGlzIFN0YWNrXG4gICAqXG4gICAqIEBkZWZhdWx0IGBhbmFseXRpY3NSZXBvcnRpbmdgIHNldHRpbmcgb2YgY29udGFpbmluZyBgQXBwYCwgb3IgdmFsdWUgb2ZcbiAgICogJ2F3czpjZGs6dmVyc2lvbi1yZXBvcnRpbmcnIGNvbnRleHQga2V5XG4gICAqL1xuICByZWFkb25seSBhbmFseXRpY3NSZXBvcnRpbmc/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIEEgcm9vdCBjb25zdHJ1Y3Qgd2hpY2ggcmVwcmVzZW50cyBhIHNpbmdsZSBDbG91ZEZvcm1hdGlvbiBzdGFjay5cbiAqL1xuZXhwb3J0IGNsYXNzIFN0YWNrIGV4dGVuZHMgQ29yZUNvbnN0cnVjdCBpbXBsZW1lbnRzIElUYWdnYWJsZSB7XG4gIC8qKlxuICAgKiBSZXR1cm4gd2hldGhlciB0aGUgZ2l2ZW4gb2JqZWN0IGlzIGEgU3RhY2suXG4gICAqXG4gICAqIFdlIGRvIGF0dHJpYnV0ZSBkZXRlY3Rpb24gc2luY2Ugd2UgY2FuJ3QgcmVsaWFibHkgdXNlICdpbnN0YW5jZW9mJy5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgaXNTdGFjayh4OiBhbnkpOiB4IGlzIFN0YWNrIHtcbiAgICByZXR1cm4geCAhPT0gbnVsbCAmJiB0eXBlb2YoeCkgPT09ICdvYmplY3QnICYmIFNUQUNLX1NZTUJPTCBpbiB4O1xuICB9XG5cbiAgLyoqXG4gICAqIExvb2tzIHVwIHRoZSBmaXJzdCBzdGFjayBzY29wZSBpbiB3aGljaCBgY29uc3RydWN0YCBpcyBkZWZpbmVkLiBGYWlscyBpZiB0aGVyZSBpcyBubyBzdGFjayB1cCB0aGUgdHJlZS5cbiAgICogQHBhcmFtIGNvbnN0cnVjdCBUaGUgY29uc3RydWN0IHRvIHN0YXJ0IHRoZSBzZWFyY2ggZnJvbS5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgb2YoY29uc3RydWN0OiBJQ29uc3RydWN0KTogU3RhY2sge1xuICAgIC8vIHdlIHdhbnQgdGhpcyB0byBiZSBhcyBjaGVhcCBhcyBwb3NzaWJsZS4gY2FjaGUgdGhpcyByZXN1bHQgYnkgbXV0YXRpbmdcbiAgICAvLyB0aGUgb2JqZWN0LiBhbmVjZG90YWxseSwgYXQgdGhlIHRpbWUgb2YgdGhpcyB3cml0aW5nLCBAYXdzLWNkay9jb3JlIHVuaXRcbiAgICAvLyB0ZXN0cyBoaXQgdGhpcyBjYWNoZSAxLDExMiB0aW1lcywgQGF3cy1jZGsvYXdzLWNsb3VkZm9ybWF0aW9uIHVuaXQgdGVzdHNcbiAgICAvLyBoaXQgdGhpcyAyLDQzNSB0aW1lcykuXG4gICAgY29uc3QgY2FjaGUgPSAoY29uc3RydWN0IGFzIGFueSlbTVlfU1RBQ0tfQ0FDSEVdIGFzIFN0YWNrIHwgdW5kZWZpbmVkO1xuICAgIGlmIChjYWNoZSkge1xuICAgICAgcmV0dXJuIGNhY2hlO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCB2YWx1ZSA9IF9sb29rdXAoY29uc3RydWN0KTtcbiAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShjb25zdHJ1Y3QsIE1ZX1NUQUNLX0NBQ0hFLCB7XG4gICAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogZmFsc2UsXG4gICAgICAgIHZhbHVlLFxuICAgICAgfSk7XG4gICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gX2xvb2t1cChjOiBJQ29uc3RydWN0KTogU3RhY2sge1xuICAgICAgaWYgKFN0YWNrLmlzU3RhY2soYykpIHtcbiAgICAgICAgcmV0dXJuIGM7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IF9zY29wZSA9IE5vZGUub2YoYykuc2NvcGU7XG4gICAgICBpZiAoU3RhZ2UuaXNTdGFnZShjKSB8fCAhX3Njb3BlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgJHtjb25zdHJ1Y3QuY29uc3RydWN0b3I/Lm5hbWUgPz8gJ0NvbnN0cnVjdCd9IGF0ICcke05vZGUub2YoY29uc3RydWN0KS5wYXRofScgc2hvdWxkIGJlIGNyZWF0ZWQgaW4gdGhlIHNjb3BlIG9mIGEgU3RhY2ssIGJ1dCBubyBTdGFjayBmb3VuZGApO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gX2xvb2t1cChfc2NvcGUpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUYWdzIHRvIGJlIGFwcGxpZWQgdG8gdGhlIHN0YWNrLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHRhZ3M6IFRhZ01hbmFnZXI7XG5cbiAgLyoqXG4gICAqIE9wdGlvbnMgZm9yIENsb3VkRm9ybWF0aW9uIHRlbXBsYXRlIChsaWtlIHZlcnNpb24sIHRyYW5zZm9ybSwgZGVzY3JpcHRpb24pLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHRlbXBsYXRlT3B0aW9uczogSVRlbXBsYXRlT3B0aW9ucztcblxuICAvKipcbiAgICogVGhlIEFXUyByZWdpb24gaW50byB3aGljaCB0aGlzIHN0YWNrIHdpbGwgYmUgZGVwbG95ZWQgKGUuZy4gYHVzLXdlc3QtMmApLlxuICAgKlxuICAgKiBUaGlzIHZhbHVlIGlzIHJlc29sdmVkIGFjY29yZGluZyB0byB0aGUgZm9sbG93aW5nIHJ1bGVzOlxuICAgKlxuICAgKiAxLiBUaGUgdmFsdWUgcHJvdmlkZWQgdG8gYGVudi5yZWdpb25gIHdoZW4gdGhlIHN0YWNrIGlzIGRlZmluZWQuIFRoaXMgY2FuXG4gICAqICAgIGVpdGhlciBiZSBhIGNvbmNlcmV0ZSByZWdpb24gKGUuZy4gYHVzLXdlc3QtMmApIG9yIHRoZSBgQXdzLnJlZ2lvbmBcbiAgICogICAgdG9rZW4uXG4gICAqIDMuIGBBd3MucmVnaW9uYCwgd2hpY2ggaXMgcmVwcmVzZW50cyB0aGUgQ2xvdWRGb3JtYXRpb24gaW50cmluc2ljIHJlZmVyZW5jZVxuICAgKiAgICBgeyBcIlJlZlwiOiBcIkFXUzo6UmVnaW9uXCIgfWAgZW5jb2RlZCBhcyBhIHN0cmluZyB0b2tlbi5cbiAgICpcbiAgICogUHJlZmVyYWJseSwgeW91IHNob3VsZCB1c2UgdGhlIHJldHVybiB2YWx1ZSBhcyBhbiBvcGFxdWUgc3RyaW5nIGFuZCBub3RcbiAgICogYXR0ZW1wdCB0byBwYXJzZSBpdCB0byBpbXBsZW1lbnQgeW91ciBsb2dpYy4gSWYgeW91IGRvLCB5b3UgbXVzdCBmaXJzdFxuICAgKiBjaGVjayB0aGF0IGl0IGlzIGEgY29uY2VyZXRlIHZhbHVlIGFuIG5vdCBhbiB1bnJlc29sdmVkIHRva2VuLiBJZiB0aGlzXG4gICAqIHZhbHVlIGlzIGFuIHVucmVzb2x2ZWQgdG9rZW4gKGBUb2tlbi5pc1VucmVzb2x2ZWQoc3RhY2sucmVnaW9uKWAgcmV0dXJuc1xuICAgKiBgdHJ1ZWApLCB0aGlzIGltcGxpZXMgdGhhdCB0aGUgdXNlciB3aXNoZXMgdGhhdCB0aGlzIHN0YWNrIHdpbGwgc3ludGhlc2l6ZVxuICAgKiBpbnRvIGEgKipyZWdpb24tYWdub3N0aWMgdGVtcGxhdGUqKi4gSW4gdGhpcyBjYXNlLCB5b3VyIGNvZGUgc2hvdWxkIGVpdGhlclxuICAgKiBmYWlsICh0aHJvdyBhbiBlcnJvciwgZW1pdCBhIHN5bnRoIGVycm9yIHVzaW5nIGBBbm5vdGF0aW9ucy5vZihjb25zdHJ1Y3QpLmFkZEVycm9yKClgKSBvclxuICAgKiBpbXBsZW1lbnQgc29tZSBvdGhlciByZWdpb24tYWdub3N0aWMgYmVoYXZpb3IuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgcmVnaW9uOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBBV1MgYWNjb3VudCBpbnRvIHdoaWNoIHRoaXMgc3RhY2sgd2lsbCBiZSBkZXBsb3llZC5cbiAgICpcbiAgICogVGhpcyB2YWx1ZSBpcyByZXNvbHZlZCBhY2NvcmRpbmcgdG8gdGhlIGZvbGxvd2luZyBydWxlczpcbiAgICpcbiAgICogMS4gVGhlIHZhbHVlIHByb3ZpZGVkIHRvIGBlbnYuYWNjb3VudGAgd2hlbiB0aGUgc3RhY2sgaXMgZGVmaW5lZC4gVGhpcyBjYW5cbiAgICogICAgZWl0aGVyIGJlIGEgY29uY2VyZXRlIGFjY291bnQgKGUuZy4gYDU4NTY5NTAzMTExMWApIG9yIHRoZVxuICAgKiAgICBgQXdzLmFjY291bnRJZGAgdG9rZW4uXG4gICAqIDMuIGBBd3MuYWNjb3VudElkYCwgd2hpY2ggcmVwcmVzZW50cyB0aGUgQ2xvdWRGb3JtYXRpb24gaW50cmluc2ljIHJlZmVyZW5jZVxuICAgKiAgICBgeyBcIlJlZlwiOiBcIkFXUzo6QWNjb3VudElkXCIgfWAgZW5jb2RlZCBhcyBhIHN0cmluZyB0b2tlbi5cbiAgICpcbiAgICogUHJlZmVyYWJseSwgeW91IHNob3VsZCB1c2UgdGhlIHJldHVybiB2YWx1ZSBhcyBhbiBvcGFxdWUgc3RyaW5nIGFuZCBub3RcbiAgICogYXR0ZW1wdCB0byBwYXJzZSBpdCB0byBpbXBsZW1lbnQgeW91ciBsb2dpYy4gSWYgeW91IGRvLCB5b3UgbXVzdCBmaXJzdFxuICAgKiBjaGVjayB0aGF0IGl0IGlzIGEgY29uY2VyZXRlIHZhbHVlIGFuIG5vdCBhbiB1bnJlc29sdmVkIHRva2VuLiBJZiB0aGlzXG4gICAqIHZhbHVlIGlzIGFuIHVucmVzb2x2ZWQgdG9rZW4gKGBUb2tlbi5pc1VucmVzb2x2ZWQoc3RhY2suYWNjb3VudClgIHJldHVybnNcbiAgICogYHRydWVgKSwgdGhpcyBpbXBsaWVzIHRoYXQgdGhlIHVzZXIgd2lzaGVzIHRoYXQgdGhpcyBzdGFjayB3aWxsIHN5bnRoZXNpemVcbiAgICogaW50byBhICoqYWNjb3VudC1hZ25vc3RpYyB0ZW1wbGF0ZSoqLiBJbiB0aGlzIGNhc2UsIHlvdXIgY29kZSBzaG91bGQgZWl0aGVyXG4gICAqIGZhaWwgKHRocm93IGFuIGVycm9yLCBlbWl0IGEgc3ludGggZXJyb3IgdXNpbmcgYEFubm90YXRpb25zLm9mKGNvbnN0cnVjdCkuYWRkRXJyb3IoKWApIG9yXG4gICAqIGltcGxlbWVudCBzb21lIG90aGVyIHJlZ2lvbi1hZ25vc3RpYyBiZWhhdmlvci5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBhY2NvdW50OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBlbnZpcm9ubWVudCBjb29yZGluYXRlcyBpbiB3aGljaCB0aGlzIHN0YWNrIGlzIGRlcGxveWVkLiBJbiB0aGUgZm9ybVxuICAgKiBgYXdzOi8vYWNjb3VudC9yZWdpb25gLiBVc2UgYHN0YWNrLmFjY291bnRgIGFuZCBgc3RhY2sucmVnaW9uYCB0byBvYnRhaW5cbiAgICogdGhlIHNwZWNpZmljIHZhbHVlcywgbm8gbmVlZCB0byBwYXJzZS5cbiAgICpcbiAgICogWW91IGNhbiB1c2UgdGhpcyB2YWx1ZSB0byBkZXRlcm1pbmUgaWYgdHdvIHN0YWNrcyBhcmUgdGFyZ2V0aW5nIHRoZSBzYW1lXG4gICAqIGVudmlyb25tZW50LlxuICAgKlxuICAgKiBJZiBlaXRoZXIgYHN0YWNrLmFjY291bnRgIG9yIGBzdGFjay5yZWdpb25gIGFyZSBub3QgY29uY3JldGUgdmFsdWVzIChlLmcuXG4gICAqIGBBd3MuYWNjb3VudGAgb3IgYEF3cy5yZWdpb25gKSB0aGUgc3BlY2lhbCBzdHJpbmdzIGB1bmtub3duLWFjY291bnRgIGFuZC9vclxuICAgKiBgdW5rbm93bi1yZWdpb25gIHdpbGwgYmUgdXNlZCByZXNwZWN0aXZlbHkgdG8gaW5kaWNhdGUgdGhpcyBzdGFjayBpc1xuICAgKiByZWdpb24vYWNjb3VudC1hZ25vc3RpYy5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBlbnZpcm9ubWVudDogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRlcm1pbmF0aW9uIHByb3RlY3Rpb24gaXMgZW5hYmxlZCBmb3IgdGhpcyBzdGFjay5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSB0ZXJtaW5hdGlvblByb3RlY3Rpb24/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBJZiB0aGlzIGlzIGEgbmVzdGVkIHN0YWNrLCB0aGlzIHJlcHJlc2VudHMgaXRzIGBBV1M6OkNsb3VkRm9ybWF0aW9uOjpTdGFja2BcbiAgICogcmVzb3VyY2UuIGB1bmRlZmluZWRgIGZvciB0b3AtbGV2ZWwgKG5vbi1uZXN0ZWQpIHN0YWNrcy5cbiAgICpcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBuZXN0ZWRTdGFja1Jlc291cmNlPzogQ2ZuUmVzb3VyY2U7XG5cbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIHRoZSBDbG91ZEZvcm1hdGlvbiB0ZW1wbGF0ZSBmaWxlIGVtaXR0ZWQgdG8gdGhlIG91dHB1dFxuICAgKiBkaXJlY3RvcnkgZHVyaW5nIHN5bnRoZXNpcy5cbiAgICpcbiAgICogRXhhbXBsZSB2YWx1ZTogYE15U3RhY2sudGVtcGxhdGUuanNvbmBcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSB0ZW1wbGF0ZUZpbGU6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIElEIG9mIHRoZSBjbG91ZCBhc3NlbWJseSBhcnRpZmFjdCBmb3IgdGhpcyBzdGFjay5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBhcnRpZmFjdElkOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFN5bnRoZXNpcyBtZXRob2QgZm9yIHRoaXMgc3RhY2tcbiAgICpcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBzeW50aGVzaXplcjogSVN0YWNrU3ludGhlc2l6ZXI7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdmVyc2lvbiByZXBvcnRpbmcgaXMgZW5hYmxlZCBmb3IgdGhpcyBzdGFja1xuICAgKlxuICAgKiBDb250cm9scyB3aGV0aGVyIHRoZSBDREsgTWV0YWRhdGEgcmVzb3VyY2UgaXMgaW5qZWN0ZWRcbiAgICpcbiAgICogQGludGVybmFsXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgX3ZlcnNpb25SZXBvcnRpbmdFbmFibGVkOiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBMb2dpY2FsIElEIGdlbmVyYXRpb24gc3RyYXRlZ3lcbiAgICovXG4gIHByaXZhdGUgcmVhZG9ubHkgX2xvZ2ljYWxJZHM6IExvZ2ljYWxJRHM7XG5cbiAgLyoqXG4gICAqIE90aGVyIHN0YWNrcyB0aGlzIHN0YWNrIGRlcGVuZHMgb25cbiAgICovXG4gIHByaXZhdGUgcmVhZG9ubHkgX3N0YWNrRGVwZW5kZW5jaWVzOiB7IFt1bmlxdWVJZDogc3RyaW5nXTogU3RhY2tEZXBlbmRlbmN5IH07XG5cbiAgLyoqXG4gICAqIExpc3RzIGFsbCBtaXNzaW5nIGNvbnRleHR1YWwgaW5mb3JtYXRpb24uXG4gICAqIFRoaXMgaXMgcmV0dXJuZWQgd2hlbiB0aGUgc3RhY2sgaXMgc3ludGhlc2l6ZWQgdW5kZXIgdGhlICdtaXNzaW5nJyBhdHRyaWJ1dGVcbiAgICogYW5kIGFsbG93cyB0b29saW5nIHRvIG9idGFpbiB0aGUgY29udGV4dCBhbmQgcmUtc3ludGhlc2l6ZS5cbiAgICovXG4gIHByaXZhdGUgcmVhZG9ubHkgX21pc3NpbmdDb250ZXh0OiBjeHNjaGVtYS5NaXNzaW5nQ29udGV4dFtdO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgX3N0YWNrTmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgbmV3IHN0YWNrLlxuICAgKlxuICAgKiBAcGFyYW0gc2NvcGUgUGFyZW50IG9mIHRoaXMgc3RhY2ssIHVzdWFsbHkgYW4gYEFwcGAgb3IgYSBgU3RhZ2VgLCBidXQgY291bGQgYmUgYW55IGNvbnN0cnVjdC5cbiAgICogQHBhcmFtIGlkIFRoZSBjb25zdHJ1Y3QgSUQgb2YgdGhpcyBzdGFjay4gSWYgYHN0YWNrTmFtZWAgaXMgbm90IGV4cGxpY2l0bHlcbiAgICogZGVmaW5lZCwgdGhpcyBpZCAoYW5kIGFueSBwYXJlbnQgSURzKSB3aWxsIGJlIHVzZWQgdG8gZGV0ZXJtaW5lIHRoZVxuICAgKiBwaHlzaWNhbCBJRCBvZiB0aGUgc3RhY2suXG4gICAqIEBwYXJhbSBwcm9wcyBTdGFjayBwcm9wZXJ0aWVzLlxuICAgKi9cbiAgcHVibGljIGNvbnN0cnVjdG9yKHNjb3BlPzogQ29uc3RydWN0LCBpZD86IHN0cmluZywgcHJvcHM6IFN0YWNrUHJvcHMgPSB7fSkge1xuICAgIC8vIEZvciB1bml0IHRlc3Qgc2NvcGUgYW5kIGlkIGFyZSBvcHRpb25hbCBmb3Igc3RhY2tzLCBidXQgd2Ugc3RpbGwgd2FudCBhbiBBcHBcbiAgICAvLyBhcyB0aGUgcGFyZW50IGJlY2F1c2UgYXBwcyBpbXBsZW1lbnQgbXVjaCBvZiB0aGUgc3ludGhlc2lzIGxvZ2ljLlxuICAgIHNjb3BlID0gc2NvcGUgPz8gbmV3IEFwcCh7XG4gICAgICBhdXRvU3ludGg6IGZhbHNlLFxuICAgICAgb3V0ZGlyOiBGaWxlU3lzdGVtLm1rZHRlbXAoJ2Nkay10ZXN0LWFwcC0nKSxcbiAgICB9KTtcblxuICAgIC8vIFwiRGVmYXVsdFwiIGlzIGEgXCJoaWRkZW4gaWRcIiBmcm9tIGEgYG5vZGUudW5pcXVlSWRgIHBlcnNwZWN0aXZlXG4gICAgaWQgPSBpZCA/PyAnRGVmYXVsdCc7XG5cbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgdGhpcy5fbWlzc2luZ0NvbnRleHQgPSBuZXcgQXJyYXk8Y3hzY2hlbWEuTWlzc2luZ0NvbnRleHQ+KCk7XG4gICAgdGhpcy5fc3RhY2tEZXBlbmRlbmNpZXMgPSB7IH07XG4gICAgdGhpcy50ZW1wbGF0ZU9wdGlvbnMgPSB7IH07XG5cbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcywgU1RBQ0tfU1lNQk9MLCB7IHZhbHVlOiB0cnVlIH0pO1xuXG4gICAgdGhpcy5fbG9naWNhbElkcyA9IG5ldyBMb2dpY2FsSURzKCk7XG5cbiAgICBjb25zdCB7IGFjY291bnQsIHJlZ2lvbiwgZW52aXJvbm1lbnQgfSA9IHRoaXMucGFyc2VFbnZpcm9ubWVudChwcm9wcy5lbnYpO1xuXG4gICAgdGhpcy5hY2NvdW50ID0gYWNjb3VudDtcbiAgICB0aGlzLnJlZ2lvbiA9IHJlZ2lvbjtcbiAgICB0aGlzLmVudmlyb25tZW50ID0gZW52aXJvbm1lbnQ7XG4gICAgdGhpcy50ZXJtaW5hdGlvblByb3RlY3Rpb24gPSBwcm9wcy50ZXJtaW5hdGlvblByb3RlY3Rpb247XG5cbiAgICBpZiAocHJvcHMuZGVzY3JpcHRpb24gIT09IHVuZGVmaW5lZCkge1xuICAgICAgLy8gTWF4IGxlbmd0aCAxMDI0IGJ5dGVzXG4gICAgICAvLyBUeXBpY2FsbHkgMiBieXRlcyBwZXIgY2hhcmFjdGVyLCBtYXkgYmUgbW9yZSBmb3IgbW9yZSBleG90aWMgY2hhcmFjdGVyc1xuICAgICAgaWYgKHByb3BzLmRlc2NyaXB0aW9uLmxlbmd0aCA+IDUxMikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFN0YWNrIGRlc2NyaXB0aW9uIG11c3QgYmUgPD0gMTAyNCBieXRlcy4gUmVjZWl2ZWQgZGVzY3JpcHRpb246ICcke3Byb3BzLmRlc2NyaXB0aW9ufSdgKTtcbiAgICAgIH1cbiAgICAgIHRoaXMudGVtcGxhdGVPcHRpb25zLmRlc2NyaXB0aW9uID0gcHJvcHMuZGVzY3JpcHRpb247XG4gICAgfVxuXG4gICAgdGhpcy5fc3RhY2tOYW1lID0gcHJvcHMuc3RhY2tOYW1lID8/IHRoaXMuZ2VuZXJhdGVTdGFja05hbWUoKTtcbiAgICBpZiAodGhpcy5fc3RhY2tOYW1lLmxlbmd0aCA+IDEyOCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBTdGFjayBuYW1lIG11c3QgYmUgPD0gMTI4IGNoYXJhY3RlcnMuIFN0YWNrIG5hbWU6ICcke3RoaXMuX3N0YWNrTmFtZX0nYCk7XG4gICAgfVxuICAgIHRoaXMudGFncyA9IG5ldyBUYWdNYW5hZ2VyKFRhZ1R5cGUuS0VZX1ZBTFVFLCAnYXdzOmNkazpzdGFjaycsIHByb3BzLnRhZ3MpO1xuXG4gICAgaWYgKCFWQUxJRF9TVEFDS19OQU1FX1JFR0VYLnRlc3QodGhpcy5zdGFja05hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFN0YWNrIG5hbWUgbXVzdCBtYXRjaCB0aGUgcmVndWxhciBleHByZXNzaW9uOiAke1ZBTElEX1NUQUNLX05BTUVfUkVHRVgudG9TdHJpbmcoKX0sIGdvdCAnJHt0aGlzLnN0YWNrTmFtZX0nYCk7XG4gICAgfVxuXG4gICAgLy8gdGhlIHByZWZlcnJlZCBiZWhhdmlvciBpcyB0byBnZW5lcmF0ZSBhIHVuaXF1ZSBpZCBmb3IgdGhpcyBzdGFjayBhbmQgdXNlXG4gICAgLy8gaXQgYXMgdGhlIGFydGlmYWN0IElEIGluIHRoZSBhc3NlbWJseS4gdGhpcyBhbGxvd3MgbXVsdGlwbGUgc3RhY2tzIHRvIHVzZVxuICAgIC8vIHRoZSBzYW1lIG5hbWUuIGhvd2V2ZXIsIHRoaXMgYmVoYXZpb3IgaXMgYnJlYWtpbmcgZm9yIDEueCBzbyBpdCdzIG9ubHlcbiAgICAvLyBhcHBsaWVkIHVuZGVyIGEgZmVhdHVyZSBmbGFnIHdoaWNoIGlzIGFwcGxpZWQgYXV0b21hdGljYWxseSBmb3IgbmV3XG4gICAgLy8gcHJvamVjdHMgY3JlYXRlZCB1c2luZyBgY2RrIGluaXRgLlxuICAgIC8vXG4gICAgLy8gQWxzbyB1c2UgdGhlIG5ldyBiZWhhdmlvciBpZiB3ZSBhcmUgdXNpbmcgdGhlIG5ldyBDSS9DRC1yZWFkeSBzeW50aGVzaXplcjsgdGhhdCB3YXlcbiAgICAvLyBwZW9wbGUgb25seSBoYXZlIHRvIGZsaXAgb25lIGZsYWcuXG4gICAgY29uc3QgZmVhdHVyZUZsYWdzID0gRmVhdHVyZUZsYWdzLm9mKHRoaXMpO1xuICAgIGNvbnN0IHN0YWNrTmFtZUR1cGVDb250ZXh0ID0gZmVhdHVyZUZsYWdzLmlzRW5hYmxlZChjeGFwaS5FTkFCTEVfU1RBQ0tfTkFNRV9EVVBMSUNBVEVTX0NPTlRFWFQpO1xuICAgIGNvbnN0IG5ld1N0eWxlU3ludGhlc2lzQ29udGV4dCA9IGZlYXR1cmVGbGFncy5pc0VuYWJsZWQoY3hhcGkuTkVXX1NUWUxFX1NUQUNLX1NZTlRIRVNJU19DT05URVhUKTtcbiAgICB0aGlzLmFydGlmYWN0SWQgPSAoc3RhY2tOYW1lRHVwZUNvbnRleHQgfHwgbmV3U3R5bGVTeW50aGVzaXNDb250ZXh0KVxuICAgICAgPyB0aGlzLmdlbmVyYXRlU3RhY2tBcnRpZmFjdElkKClcbiAgICAgIDogdGhpcy5zdGFja05hbWU7XG5cbiAgICB0aGlzLnRlbXBsYXRlRmlsZSA9IGAke3RoaXMuYXJ0aWZhY3RJZH0udGVtcGxhdGUuanNvbmA7XG5cbiAgICAvLyBOb3QgZm9yIG5lc3RlZCBzdGFja3NcbiAgICB0aGlzLl92ZXJzaW9uUmVwb3J0aW5nRW5hYmxlZCA9IChwcm9wcy5hbmFseXRpY3NSZXBvcnRpbmcgPz8gdGhpcy5ub2RlLnRyeUdldENvbnRleHQoY3hhcGkuQU5BTFlUSUNTX1JFUE9SVElOR19FTkFCTEVEX0NPTlRFWFQpKVxuICAgICAgJiYgIXRoaXMubmVzdGVkU3RhY2tQYXJlbnQ7XG5cbiAgICB0aGlzLnN5bnRoZXNpemVyID0gcHJvcHMuc3ludGhlc2l6ZXIgPz8gKG5ld1N0eWxlU3ludGhlc2lzQ29udGV4dFxuICAgICAgPyBuZXcgRGVmYXVsdFN0YWNrU3ludGhlc2l6ZXIoKVxuICAgICAgOiBuZXcgTGVnYWN5U3RhY2tTeW50aGVzaXplcigpKTtcbiAgICB0aGlzLnN5bnRoZXNpemVyLmJpbmQodGhpcyk7XG4gIH1cblxuICAvKipcbiAgICogUmVzb2x2ZSBhIHRva2VuaXplZCB2YWx1ZSBpbiB0aGUgY29udGV4dCBvZiB0aGUgY3VycmVudCBzdGFjay5cbiAgICovXG4gIHB1YmxpYyByZXNvbHZlKG9iajogYW55KTogYW55IHtcbiAgICByZXR1cm4gcmVzb2x2ZShvYmosIHtcbiAgICAgIHNjb3BlOiB0aGlzLFxuICAgICAgcHJlZml4OiBbXSxcbiAgICAgIHJlc29sdmVyOiBDTE9VREZPUk1BVElPTl9UT0tFTl9SRVNPTFZFUixcbiAgICAgIHByZXBhcmluZzogZmFsc2UsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydCBhbiBvYmplY3QsIHBvdGVudGlhbGx5IGNvbnRhaW5pbmcgdG9rZW5zLCB0byBhIEpTT04gc3RyaW5nXG4gICAqL1xuICBwdWJsaWMgdG9Kc29uU3RyaW5nKG9iajogYW55LCBzcGFjZT86IG51bWJlcik6IHN0cmluZyB7XG4gICAgcmV0dXJuIENsb3VkRm9ybWF0aW9uTGFuZy50b0pTT04ob2JqLCBzcGFjZSkudG9TdHJpbmcoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBERVBSRUNBVEVEXG4gICAqIEBkZXByZWNhdGVkIHVzZSBgcmVwb3J0TWlzc2luZ0NvbnRleHRLZXkoKWBcbiAgICovXG4gIHB1YmxpYyByZXBvcnRNaXNzaW5nQ29udGV4dChyZXBvcnQ6IGN4YXBpLk1pc3NpbmdDb250ZXh0KSB7XG4gICAgaWYgKCFPYmplY3QudmFsdWVzKGN4c2NoZW1hLkNvbnRleHRQcm92aWRlcikuaW5jbHVkZXMocmVwb3J0LnByb3ZpZGVyIGFzIGN4c2NoZW1hLkNvbnRleHRQcm92aWRlcikpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVW5rbm93biBjb250ZXh0IHByb3ZpZGVyIHJlcXVlc3RlZCBpbjogJHtKU09OLnN0cmluZ2lmeShyZXBvcnQpfWApO1xuICAgIH1cbiAgICB0aGlzLnJlcG9ydE1pc3NpbmdDb250ZXh0S2V5KHJlcG9ydCBhcyBjeHNjaGVtYS5NaXNzaW5nQ29udGV4dCk7XG4gIH1cblxuICAvKipcbiAgICogSW5kaWNhdGUgdGhhdCBhIGNvbnRleHQga2V5IHdhcyBleHBlY3RlZFxuICAgKlxuICAgKiBDb250YWlucyBpbnN0cnVjdGlvbnMgd2hpY2ggd2lsbCBiZSBlbWl0dGVkIGludG8gdGhlIGNsb3VkIGFzc2VtYmx5IG9uIGhvd1xuICAgKiB0aGUga2V5IHNob3VsZCBiZSBzdXBwbGllZC5cbiAgICpcbiAgICogQHBhcmFtIHJlcG9ydCBUaGUgc2V0IG9mIHBhcmFtZXRlcnMgbmVlZGVkIHRvIG9idGFpbiB0aGUgY29udGV4dFxuICAgKi9cbiAgcHVibGljIHJlcG9ydE1pc3NpbmdDb250ZXh0S2V5KHJlcG9ydDogY3hzY2hlbWEuTWlzc2luZ0NvbnRleHQpIHtcbiAgICB0aGlzLl9taXNzaW5nQ29udGV4dC5wdXNoKHJlcG9ydCk7XG4gIH1cblxuICAvKipcbiAgICogUmVuYW1lIGEgZ2VuZXJhdGVkIGxvZ2ljYWwgaWRlbnRpdGllc1xuICAgKlxuICAgKiBUbyBtb2RpZnkgdGhlIG5hbWluZyBzY2hlbWUgc3RyYXRlZ3ksIGV4dGVuZCB0aGUgYFN0YWNrYCBjbGFzcyBhbmRcbiAgICogb3ZlcnJpZGUgdGhlIGBhbGxvY2F0ZUxvZ2ljYWxJZGAgbWV0aG9kLlxuICAgKi9cbiAgcHVibGljIHJlbmFtZUxvZ2ljYWxJZChvbGRJZDogc3RyaW5nLCBuZXdJZDogc3RyaW5nKSB7XG4gICAgdGhpcy5fbG9naWNhbElkcy5hZGRSZW5hbWUob2xkSWQsIG5ld0lkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBbGxvY2F0ZXMgYSBzdGFjay11bmlxdWUgQ2xvdWRGb3JtYXRpb24tY29tcGF0aWJsZSBsb2dpY2FsIGlkZW50aXR5IGZvciBhXG4gICAqIHNwZWNpZmljIHJlc291cmNlLlxuICAgKlxuICAgKiBUaGlzIG1ldGhvZCBpcyBjYWxsZWQgd2hlbiBhIGBDZm5FbGVtZW50YCBpcyBjcmVhdGVkIGFuZCB1c2VkIHRvIHJlbmRlciB0aGVcbiAgICogaW5pdGlhbCBsb2dpY2FsIGlkZW50aXR5IG9mIHJlc291cmNlcy4gTG9naWNhbCBJRCByZW5hbWVzIGFyZSBhcHBsaWVkIGF0XG4gICAqIHRoaXMgc3RhZ2UuXG4gICAqXG4gICAqIFRoaXMgbWV0aG9kIHVzZXMgdGhlIHByb3RlY3RlZCBtZXRob2QgYGFsbG9jYXRlTG9naWNhbElkYCB0byByZW5kZXIgdGhlXG4gICAqIGxvZ2ljYWwgSUQgZm9yIGFuIGVsZW1lbnQuIFRvIG1vZGlmeSB0aGUgbmFtaW5nIHNjaGVtZSwgZXh0ZW5kIHRoZSBgU3RhY2tgXG4gICAqIGNsYXNzIGFuZCBvdmVycmlkZSB0aGlzIG1ldGhvZC5cbiAgICpcbiAgICogQHBhcmFtIGVsZW1lbnQgVGhlIENsb3VkRm9ybWF0aW9uIGVsZW1lbnQgZm9yIHdoaWNoIGEgbG9naWNhbCBpZGVudGl0eSBpc1xuICAgKiBuZWVkZWQuXG4gICAqL1xuICBwdWJsaWMgZ2V0TG9naWNhbElkKGVsZW1lbnQ6IENmbkVsZW1lbnQpOiBzdHJpbmcge1xuICAgIGNvbnN0IGxvZ2ljYWxJZCA9IHRoaXMuYWxsb2NhdGVMb2dpY2FsSWQoZWxlbWVudCk7XG4gICAgcmV0dXJuIHRoaXMuX2xvZ2ljYWxJZHMuYXBwbHlSZW5hbWUobG9naWNhbElkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgYSBkZXBlbmRlbmN5IGJldHdlZW4gdGhpcyBzdGFjayBhbmQgYW5vdGhlciBzdGFjay5cbiAgICpcbiAgICogVGhpcyBjYW4gYmUgdXNlZCB0byBkZWZpbmUgZGVwZW5kZW5jaWVzIGJldHdlZW4gYW55IHR3byBzdGFja3Mgd2l0aGluIGFuXG4gICAqIGFwcCwgYW5kIGFsc28gc3VwcG9ydHMgbmVzdGVkIHN0YWNrcy5cbiAgICovXG4gIHB1YmxpYyBhZGREZXBlbmRlbmN5KHRhcmdldDogU3RhY2ssIHJlYXNvbj86IHN0cmluZykge1xuICAgIGFkZERlcGVuZGVuY3kodGhpcywgdGFyZ2V0LCByZWFzb24pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiB0aGUgc3RhY2tzIHRoaXMgc3RhY2sgZGVwZW5kcyBvblxuICAgKi9cbiAgcHVibGljIGdldCBkZXBlbmRlbmNpZXMoKTogU3RhY2tbXSB7XG4gICAgcmV0dXJuIE9iamVjdC52YWx1ZXModGhpcy5fc3RhY2tEZXBlbmRlbmNpZXMpLm1hcCh4ID0+IHguc3RhY2spO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBjb25jcmV0ZSBDbG91ZEZvcm1hdGlvbiBwaHlzaWNhbCBzdGFjayBuYW1lLlxuICAgKlxuICAgKiBUaGlzIGlzIGVpdGhlciB0aGUgbmFtZSBkZWZpbmVkIGV4cGxpY2l0bHkgaW4gdGhlIGBzdGFja05hbWVgIHByb3Agb3JcbiAgICogYWxsb2NhdGVkIGJhc2VkIG9uIHRoZSBzdGFjaydzIGxvY2F0aW9uIGluIHRoZSBjb25zdHJ1Y3QgdHJlZS4gU3RhY2tzIHRoYXRcbiAgICogYXJlIGRpcmVjdGx5IGRlZmluZWQgdW5kZXIgdGhlIGFwcCB1c2UgdGhlaXIgY29uc3RydWN0IGBpZGAgYXMgdGhlaXIgc3RhY2tcbiAgICogbmFtZS4gU3RhY2tzIHRoYXQgYXJlIGRlZmluZWQgZGVlcGVyIHdpdGhpbiB0aGUgdHJlZSB3aWxsIHVzZSBhIGhhc2hlZCBuYW1pbmdcbiAgICogc2NoZW1lIGJhc2VkIG9uIHRoZSBjb25zdHJ1Y3QgcGF0aCB0byBlbnN1cmUgdW5pcXVlbmVzcy5cbiAgICpcbiAgICogSWYgeW91IHdpc2ggdG8gb2J0YWluIHRoZSBkZXBsb3ktdGltZSBBV1M6OlN0YWNrTmFtZSBpbnRyaW5zaWMsXG4gICAqIHlvdSBjYW4gdXNlIGBBd3Muc3RhY2tOYW1lYCBkaXJlY3RseS5cbiAgICovXG4gIHB1YmxpYyBnZXQgc3RhY2tOYW1lKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuX3N0YWNrTmFtZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgcGFydGl0aW9uIGluIHdoaWNoIHRoaXMgc3RhY2sgaXMgZGVmaW5lZFxuICAgKi9cbiAgcHVibGljIGdldCBwYXJ0aXRpb24oKTogc3RyaW5nIHtcbiAgICAvLyBBbHdheXMgcmV0dXJuIGEgbm9uLXNjb3BlZCBwYXJ0aXRpb24gaW50cmluc2ljLiBUaGVzZSB3aWxsIHVzdWFsbHlcbiAgICAvLyBiZSB1c2VkIHRvIGNvbnN0cnVjdCBhbiBBUk4sIGJ1dCB0aGVyZSBhcmUgbm8gY3Jvc3MtcGFydGl0aW9uXG4gICAgLy8gY2FsbHMgYW55d2F5LlxuICAgIHJldHVybiBBd3MuUEFSVElUSU9OO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBBbWF6b24gZG9tYWluIHN1ZmZpeCBmb3IgdGhlIHJlZ2lvbiBpbiB3aGljaCB0aGlzIHN0YWNrIGlzIGRlZmluZWRcbiAgICovXG4gIHB1YmxpYyBnZXQgdXJsU3VmZml4KCk6IHN0cmluZyB7XG4gICAgLy8gU2luY2UgVVJMIFN1ZmZpeCBhbHdheXMgZm9sbG93cyBwYXJ0aXRpb24sIGl0IGlzIHVuc2NvcGVkIGxpa2UgcGFydGl0aW9uIGlzLlxuICAgIHJldHVybiBBd3MuVVJMX1NVRkZJWDtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgSUQgb2YgdGhlIHN0YWNrXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIC8vIEFmdGVyIHJlc29sdmluZywgbG9va3MgbGlrZVxuICAgKiAnYXJuOmF3czpjbG91ZGZvcm1hdGlvbjp1cy13ZXN0LTI6MTIzNDU2Nzg5MDEyOnN0YWNrL3Rlc3RzdGFjay81MWFmM2RjMC1kYTc3LTExZTQtODcyZS0xMjM0NTY3ZGIxMjMnXG4gICAqL1xuICBwdWJsaWMgZ2V0IHN0YWNrSWQoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gbmV3IFNjb3BlZEF3cyh0aGlzKS5zdGFja0lkO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGxpc3Qgb2Ygbm90aWZpY2F0aW9uIEFtYXpvbiBSZXNvdXJjZSBOYW1lcyAoQVJOcykgZm9yIHRoZSBjdXJyZW50IHN0YWNrLlxuICAgKi9cbiAgcHVibGljIGdldCBub3RpZmljYXRpb25Bcm5zKCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gbmV3IFNjb3BlZEF3cyh0aGlzKS5ub3RpZmljYXRpb25Bcm5zO1xuICB9XG5cbiAgLyoqXG4gICAqIEluZGljYXRlcyBpZiB0aGlzIGlzIGEgbmVzdGVkIHN0YWNrLCBpbiB3aGljaCBjYXNlIGBwYXJlbnRTdGFja2Agd2lsbCBpbmNsdWRlIGEgcmVmZXJlbmNlIHRvIGl0J3MgcGFyZW50LlxuICAgKi9cbiAgcHVibGljIGdldCBuZXN0ZWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMubmVzdGVkU3RhY2tSZXNvdXJjZSAhPT0gdW5kZWZpbmVkO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYW4gQVJOIGZyb20gY29tcG9uZW50cy5cbiAgICpcbiAgICogSWYgYHBhcnRpdGlvbmAsIGByZWdpb25gIG9yIGBhY2NvdW50YCBhcmUgbm90IHNwZWNpZmllZCwgdGhlIHN0YWNrJ3NcbiAgICogcGFydGl0aW9uLCByZWdpb24gYW5kIGFjY291bnQgd2lsbCBiZSB1c2VkLlxuICAgKlxuICAgKiBJZiBhbnkgY29tcG9uZW50IGlzIHRoZSBlbXB0eSBzdHJpbmcsIGFuIGVtcHR5IHN0cmluZyB3aWxsIGJlIGluc2VydGVkXG4gICAqIGludG8gdGhlIGdlbmVyYXRlZCBBUk4gYXQgdGhlIGxvY2F0aW9uIHRoYXQgY29tcG9uZW50IGNvcnJlc3BvbmRzIHRvLlxuICAgKlxuICAgKiBUaGUgQVJOIHdpbGwgYmUgZm9ybWF0dGVkIGFzIGZvbGxvd3M6XG4gICAqXG4gICAqICAgYXJuOntwYXJ0aXRpb259OntzZXJ2aWNlfTp7cmVnaW9ufTp7YWNjb3VudH06e3Jlc291cmNlfXtzZXB9fXtyZXNvdXJjZS1uYW1lfVxuICAgKlxuICAgKiBUaGUgcmVxdWlyZWQgQVJOIHBpZWNlcyB0aGF0IGFyZSBvbWl0dGVkIHdpbGwgYmUgdGFrZW4gZnJvbSB0aGUgc3RhY2sgdGhhdFxuICAgKiB0aGUgJ3Njb3BlJyBpcyBhdHRhY2hlZCB0by4gSWYgYWxsIEFSTiBwaWVjZXMgYXJlIHN1cHBsaWVkLCB0aGUgc3VwcGxpZWQgc2NvcGVcbiAgICogY2FuIGJlICd1bmRlZmluZWQnLlxuICAgKi9cbiAgcHVibGljIGZvcm1hdEFybihjb21wb25lbnRzOiBBcm5Db21wb25lbnRzKTogc3RyaW5nIHtcbiAgICByZXR1cm4gQXJuLmZvcm1hdChjb21wb25lbnRzLCB0aGlzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHaXZlbiBhbiBBUk4sIHBhcnNlcyBpdCBhbmQgcmV0dXJucyBjb21wb25lbnRzLlxuICAgKlxuICAgKiBJRiBUSEUgQVJOIElTIEEgQ09OQ1JFVEUgU1RSSU5HLi4uXG4gICAqXG4gICAqIC4uLml0IHdpbGwgYmUgcGFyc2VkIGFuZCB2YWxpZGF0ZWQuIFRoZSBzZXBhcmF0b3IgKGBzZXBgKSB3aWxsIGJlIHNldCB0byAnLydcbiAgICogaWYgdGhlIDZ0aCBjb21wb25lbnQgaW5jbHVkZXMgYSAnLycsIGluIHdoaWNoIGNhc2UsIGByZXNvdXJjZWAgd2lsbCBiZSBzZXRcbiAgICogdG8gdGhlIHZhbHVlIGJlZm9yZSB0aGUgJy8nIGFuZCBgcmVzb3VyY2VOYW1lYCB3aWxsIGJlIHRoZSByZXN0LiBJbiBjYXNlXG4gICAqIHRoZXJlIGlzIG5vICcvJywgYHJlc291cmNlYCB3aWxsIGJlIHNldCB0byB0aGUgNnRoIGNvbXBvbmVudHMgYW5kXG4gICAqIGByZXNvdXJjZU5hbWVgIHdpbGwgYmUgc2V0IHRvIHRoZSByZXN0IG9mIHRoZSBzdHJpbmcuXG4gICAqXG4gICAqIElGIFRIRSBBUk4gSVMgQSBUT0tFTi4uLlxuICAgKlxuICAgKiAuLi5pdCBjYW5ub3QgYmUgdmFsaWRhdGVkLCBzaW5jZSB3ZSBkb24ndCBoYXZlIHRoZSBhY3R1YWwgdmFsdWUgeWV0IGF0IHRoZVxuICAgKiB0aW1lIG9mIHRoaXMgZnVuY3Rpb24gY2FsbC4gWW91IHdpbGwgaGF2ZSB0byBzdXBwbHkgYHNlcElmVG9rZW5gIGFuZFxuICAgKiB3aGV0aGVyIG9yIG5vdCBBUk5zIG9mIHRoZSBleHBlY3RlZCBmb3JtYXQgdXN1YWxseSBoYXZlIHJlc291cmNlIG5hbWVzXG4gICAqIGluIG9yZGVyIHRvIHBhcnNlIGl0IHByb3Blcmx5LiBUaGUgcmVzdWx0aW5nIGBBcm5Db21wb25lbnRzYCBvYmplY3Qgd2lsbFxuICAgKiBjb250YWluIHRva2VucyBmb3IgdGhlIHN1YmV4cHJlc3Npb25zIG9mIHRoZSBBUk4sIG5vdCBzdHJpbmcgbGl0ZXJhbHMuXG4gICAqXG4gICAqIElmIHRoZSByZXNvdXJjZSBuYW1lIGNvdWxkIHBvc3NpYmx5IGNvbnRhaW4gdGhlIHNlcGFyYXRvciBjaGFyLCB0aGUgYWN0dWFsXG4gICAqIHJlc291cmNlIG5hbWUgY2Fubm90IGJlIHByb3Blcmx5IHBhcnNlZC4gVGhpcyBvbmx5IG9jY3VycyBpZiB0aGUgc2VwYXJhdG9yXG4gICAqIGNoYXIgaXMgJy8nLCBhbmQgaGFwcGVucyBmb3IgZXhhbXBsZSBmb3IgUzMgb2JqZWN0IEFSTnMsIElBTSBSb2xlIEFSTnMsXG4gICAqIElBTSBPSURDIFByb3ZpZGVyIEFSTnMsIGV0Yy4gVG8gcHJvcGVybHkgZXh0cmFjdCB0aGUgcmVzb3VyY2UgbmFtZSBmcm9tIGFcbiAgICogVG9rZW5pemVkIEFSTiwgeW91IG11c3Qga25vdyB0aGUgcmVzb3VyY2UgdHlwZSBhbmQgY2FsbFxuICAgKiBgQXJuLmV4dHJhY3RSZXNvdXJjZU5hbWVgLlxuICAgKlxuICAgKiBAcGFyYW0gYXJuIFRoZSBBUk4gc3RyaW5nIHRvIHBhcnNlXG4gICAqIEBwYXJhbSBzZXBJZlRva2VuIFRoZSBzZXBhcmF0b3IgdXNlZCB0byBzZXBhcmF0ZSByZXNvdXJjZSBmcm9tIHJlc291cmNlTmFtZVxuICAgKiBAcGFyYW0gaGFzTmFtZSBXaGV0aGVyIHRoZXJlIGlzIGEgbmFtZSBjb21wb25lbnQgaW4gdGhlIEFSTiBhdCBhbGwuIEZvclxuICAgKiBleGFtcGxlLCBTTlMgVG9waWNzIEFSTnMgaGF2ZSB0aGUgJ3Jlc291cmNlJyBjb21wb25lbnQgY29udGFpbiB0aGUgdG9waWNcbiAgICogbmFtZSwgYW5kIG5vICdyZXNvdXJjZU5hbWUnIGNvbXBvbmVudC5cbiAgICpcbiAgICogQHJldHVybnMgYW4gQXJuQ29tcG9uZW50cyBvYmplY3Qgd2hpY2ggYWxsb3dzIGFjY2VzcyB0byB0aGUgdmFyaW91c1xuICAgKiBjb21wb25lbnRzIG9mIHRoZSBBUk4uXG4gICAqXG4gICAqIEByZXR1cm5zIGFuIEFybkNvbXBvbmVudHMgb2JqZWN0IHdoaWNoIGFsbG93cyBhY2Nlc3MgdG8gdGhlIHZhcmlvdXNcbiAgICogICAgICBjb21wb25lbnRzIG9mIHRoZSBBUk4uXG4gICAqXG4gICAqIEBkZXByZWNhdGVkIHVzZSBzcGxpdEFybiBpbnN0ZWFkXG4gICAqL1xuICBwdWJsaWMgcGFyc2VBcm4oYXJuOiBzdHJpbmcsIHNlcElmVG9rZW46IHN0cmluZyA9ICcvJywgaGFzTmFtZTogYm9vbGVhbiA9IHRydWUpOiBBcm5Db21wb25lbnRzIHtcbiAgICByZXR1cm4gQXJuLnBhcnNlKGFybiwgc2VwSWZUb2tlbiwgaGFzTmFtZSk7XG4gIH1cblxuICAvKipcbiAgICogU3BsaXRzIHRoZSBwcm92aWRlZCBBUk4gaW50byBpdHMgY29tcG9uZW50cy5cbiAgICogV29ya3MgYm90aCBpZiAnYXJuJyBpcyBhIHN0cmluZyBsaWtlICdhcm46YXdzOnMzOjo6YnVja2V0JyxcbiAgICogYW5kIGEgVG9rZW4gcmVwcmVzZW50aW5nIGEgZHluYW1pYyBDbG91ZEZvcm1hdGlvbiBleHByZXNzaW9uXG4gICAqIChpbiB3aGljaCBjYXNlIHRoZSByZXR1cm5lZCBjb21wb25lbnRzIHdpbGwgYWxzbyBiZSBkeW5hbWljIENsb3VkRm9ybWF0aW9uIGV4cHJlc3Npb25zLFxuICAgKiBlbmNvZGVkIGFzIFRva2VucykuXG4gICAqXG4gICAqIEBwYXJhbSBhcm4gdGhlIEFSTiB0byBzcGxpdCBpbnRvIGl0cyBjb21wb25lbnRzXG4gICAqIEBwYXJhbSBhcm5Gb3JtYXQgdGhlIGV4cGVjdGVkIGZvcm1hdCBvZiAnYXJuJyAtIGRlcGVuZHMgb24gd2hhdCBmb3JtYXQgdGhlIHNlcnZpY2UgJ2FybicgcmVwcmVzZW50cyB1c2VzXG4gICAqL1xuICBwdWJsaWMgc3BsaXRBcm4oYXJuOiBzdHJpbmcsIGFybkZvcm1hdDogQXJuRm9ybWF0KTogQXJuQ29tcG9uZW50cyB7XG4gICAgcmV0dXJuIEFybi5zcGxpdChhcm4sIGFybkZvcm1hdCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgbGlzdCBvZiBBWnMgdGhhdCBhcmUgYXZhaWxhYmxlIGluIHRoZSBBV1MgZW52aXJvbm1lbnRcbiAgICogKGFjY291bnQvcmVnaW9uKSBhc3NvY2lhdGVkIHdpdGggdGhpcyBzdGFjay5cbiAgICpcbiAgICogSWYgdGhlIHN0YWNrIGlzIGVudmlyb25tZW50LWFnbm9zdGljIChlaXRoZXIgYWNjb3VudCBhbmQvb3IgcmVnaW9uIGFyZVxuICAgKiB0b2tlbnMpLCB0aGlzIHByb3BlcnR5IHdpbGwgcmV0dXJuIGFuIGFycmF5IHdpdGggMiB0b2tlbnMgdGhhdCB3aWxsIHJlc29sdmVcbiAgICogYXQgZGVwbG95LXRpbWUgdG8gdGhlIGZpcnN0IHR3byBhdmFpbGFiaWxpdHkgem9uZXMgcmV0dXJuZWQgZnJvbSBDbG91ZEZvcm1hdGlvbidzXG4gICAqIGBGbjo6R2V0QVpzYCBpbnRyaW5zaWMgZnVuY3Rpb24uXG4gICAqXG4gICAqIElmIHRoZXkgYXJlIG5vdCBhdmFpbGFibGUgaW4gdGhlIGNvbnRleHQsIHJldHVybnMgYSBzZXQgb2YgZHVtbXkgdmFsdWVzIGFuZFxuICAgKiByZXBvcnRzIHRoZW0gYXMgbWlzc2luZywgYW5kIGxldCB0aGUgQ0xJIHJlc29sdmUgdGhlbSBieSBjYWxsaW5nIEVDMlxuICAgKiBgRGVzY3JpYmVBdmFpbGFiaWxpdHlab25lc2Agb24gdGhlIHRhcmdldCBlbnZpcm9ubWVudC5cbiAgICpcbiAgICogVG8gc3BlY2lmeSBhIGRpZmZlcmVudCBzdHJhdGVneSBmb3Igc2VsZWN0aW5nIGF2YWlsYWJpbGl0eSB6b25lcyBvdmVycmlkZSB0aGlzIG1ldGhvZC5cbiAgICovXG4gIHB1YmxpYyBnZXQgYXZhaWxhYmlsaXR5Wm9uZXMoKTogc3RyaW5nW10ge1xuICAgIC8vIGlmIGFjY291bnQvcmVnaW9uIGFyZSB0b2tlbnMsIHdlIGNhbid0IG9idGFpbiBBWnMgdGhyb3VnaCB0aGUgY29udGV4dFxuICAgIC8vIHByb3ZpZGVyLCBzbyB3ZSBmYWxsYmFjayB0byB1c2UgRm46OkdldEFacy4gdGhlIGN1cnJlbnQgbG93ZXN0IGNvbW1vblxuICAgIC8vIGRlbm9taW5hdG9yIGlzIDIgQVpzIGFjcm9zcyBhbGwgQVdTIHJlZ2lvbnMuXG4gICAgY29uc3QgYWdub3N0aWMgPSBUb2tlbi5pc1VucmVzb2x2ZWQodGhpcy5hY2NvdW50KSB8fCBUb2tlbi5pc1VucmVzb2x2ZWQodGhpcy5yZWdpb24pO1xuICAgIGlmIChhZ25vc3RpYykge1xuICAgICAgcmV0dXJuIHRoaXMubm9kZS50cnlHZXRDb250ZXh0KGN4YXBpLkFWQUlMQUJJTElUWV9aT05FX0ZBTExCQUNLX0NPTlRFWFRfS0VZKSB8fCBbXG4gICAgICAgIEZuLnNlbGVjdCgwLCBGbi5nZXRBenMoKSksXG4gICAgICAgIEZuLnNlbGVjdCgxLCBGbi5nZXRBenMoKSksXG4gICAgICBdO1xuICAgIH1cblxuICAgIGNvbnN0IHZhbHVlID0gQ29udGV4dFByb3ZpZGVyLmdldFZhbHVlKHRoaXMsIHtcbiAgICAgIHByb3ZpZGVyOiBjeHNjaGVtYS5Db250ZXh0UHJvdmlkZXIuQVZBSUxBQklMSVRZX1pPTkVfUFJPVklERVIsXG4gICAgICBkdW1teVZhbHVlOiBbJ2R1bW15MWEnLCAnZHVtbXkxYicsICdkdW1teTFjJ10sXG4gICAgfSkudmFsdWU7XG5cbiAgICBpZiAoIUFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFByb3ZpZGVyICR7Y3hzY2hlbWEuQ29udGV4dFByb3ZpZGVyLkFWQUlMQUJJTElUWV9aT05FX1BST1ZJREVSfSBleHBlY3RzIGEgbGlzdGApO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlciBhIGZpbGUgYXNzZXQgb24gdGhpcyBTdGFja1xuICAgKlxuICAgKiBAZGVwcmVjYXRlZCBVc2UgYHN0YWNrLnN5bnRoZXNpemVyLmFkZEZpbGVBc3NldCgpYCBpZiB5b3UgYXJlIGNhbGxpbmcsXG4gICAqIGFuZCBhIGRpZmZlcmVudCBJU3RhY2tTeW50aGVzaXplciBjbGFzcyBpZiB5b3UgYXJlIGltcGxlbWVudGluZy5cbiAgICovXG4gIHB1YmxpYyBhZGRGaWxlQXNzZXQoYXNzZXQ6IEZpbGVBc3NldFNvdXJjZSk6IEZpbGVBc3NldExvY2F0aW9uIHtcbiAgICByZXR1cm4gdGhpcy5zeW50aGVzaXplci5hZGRGaWxlQXNzZXQoYXNzZXQpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlZ2lzdGVyIGEgZG9ja2VyIGltYWdlIGFzc2V0IG9uIHRoaXMgU3RhY2tcbiAgICpcbiAgICogQGRlcHJlY2F0ZWQgVXNlIGBzdGFjay5zeW50aGVzaXplci5hZGREb2NrZXJJbWFnZUFzc2V0KClgIGlmIHlvdSBhcmUgY2FsbGluZyxcbiAgICogYW5kIGEgZGlmZmVyZW50IGBJU3RhY2tTeW50aGVzaXplcmAgY2xhc3MgaWYgeW91IGFyZSBpbXBsZW1lbnRpbmcuXG4gICAqL1xuICBwdWJsaWMgYWRkRG9ja2VySW1hZ2VBc3NldChhc3NldDogRG9ja2VySW1hZ2VBc3NldFNvdXJjZSk6IERvY2tlckltYWdlQXNzZXRMb2NhdGlvbiB7XG4gICAgcmV0dXJuIHRoaXMuc3ludGhlc2l6ZXIuYWRkRG9ja2VySW1hZ2VBc3NldChhc3NldCk7XG4gIH1cblxuICAvKipcbiAgICogSWYgdGhpcyBpcyBhIG5lc3RlZCBzdGFjaywgcmV0dXJucyBpdCdzIHBhcmVudCBzdGFjay5cbiAgICovXG4gIHB1YmxpYyBnZXQgbmVzdGVkU3RhY2tQYXJlbnQoKSB7XG4gICAgcmV0dXJuIHRoaXMubmVzdGVkU3RhY2tSZXNvdXJjZSAmJiBTdGFjay5vZih0aGlzLm5lc3RlZFN0YWNrUmVzb3VyY2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHBhcmVudCBvZiBhIG5lc3RlZCBzdGFjay5cbiAgICpcbiAgICogQGRlcHJlY2F0ZWQgdXNlIGBuZXN0ZWRTdGFja1BhcmVudGBcbiAgICovXG4gIHB1YmxpYyBnZXQgcGFyZW50U3RhY2soKSB7XG4gICAgcmV0dXJuIHRoaXMubmVzdGVkU3RhY2tQYXJlbnQ7XG4gIH1cblxuICAvKipcbiAgICogQWRkIGEgVHJhbnNmb3JtIHRvIHRoaXMgc3RhY2suIEEgVHJhbnNmb3JtIGlzIGEgbWFjcm8gdGhhdCBBV1NcbiAgICogQ2xvdWRGb3JtYXRpb24gdXNlcyB0byBwcm9jZXNzIHlvdXIgdGVtcGxhdGUuXG4gICAqXG4gICAqIER1cGxpY2F0ZSB2YWx1ZXMgYXJlIHJlbW92ZWQgd2hlbiBzdGFjayBpcyBzeW50aGVzaXplZC5cbiAgICpcbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS90cmFuc2Zvcm0tc2VjdGlvbi1zdHJ1Y3R1cmUuaHRtbFxuICAgKiBAcGFyYW0gdHJhbnNmb3JtIFRoZSB0cmFuc2Zvcm0gdG8gYWRkXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIGRlY2xhcmUgY29uc3Qgc3RhY2s6IFN0YWNrO1xuICAgKlxuICAgKiBzdGFjay5hZGRUcmFuc2Zvcm0oJ0FXUzo6U2VydmVybGVzcy0yMDE2LTEwLTMxJylcbiAgICovXG4gIHB1YmxpYyBhZGRUcmFuc2Zvcm0odHJhbnNmb3JtOiBzdHJpbmcpIHtcbiAgICBpZiAoIXRoaXMudGVtcGxhdGVPcHRpb25zLnRyYW5zZm9ybXMpIHtcbiAgICAgIHRoaXMudGVtcGxhdGVPcHRpb25zLnRyYW5zZm9ybXMgPSBbXTtcbiAgICB9XG4gICAgdGhpcy50ZW1wbGF0ZU9wdGlvbnMudHJhbnNmb3Jtcy5wdXNoKHRyYW5zZm9ybSk7XG4gIH1cblxuICAvKipcbiAgICogQ2FsbGVkIGltcGxpY2l0bHkgYnkgdGhlIGBhZGREZXBlbmRlbmN5YCBoZWxwZXIgZnVuY3Rpb24gaW4gb3JkZXIgdG9cbiAgICogcmVhbGl6ZSBhIGRlcGVuZGVuY3kgYmV0d2VlbiB0d28gdG9wLWxldmVsIHN0YWNrcyBhdCB0aGUgYXNzZW1ibHkgbGV2ZWwuXG4gICAqXG4gICAqIFVzZSBgc3RhY2suYWRkRGVwZW5kZW5jeWAgdG8gZGVmaW5lIHRoZSBkZXBlbmRlbmN5IGJldHdlZW4gYW55IHR3byBzdGFja3MsXG4gICAqIGFuZCB0YWtlIGludG8gYWNjb3VudCBuZXN0ZWQgc3RhY2sgcmVsYXRpb25zaGlwcy5cbiAgICpcbiAgICogQGludGVybmFsXG4gICAqL1xuICBwdWJsaWMgX2FkZEFzc2VtYmx5RGVwZW5kZW5jeSh0YXJnZXQ6IFN0YWNrLCByZWFzb24/OiBzdHJpbmcpIHtcbiAgICAvLyBkZWZlbnNpdmU6IHdlIHNob3VsZCBuZXZlciBnZXQgaGVyZSBmb3IgbmVzdGVkIHN0YWNrc1xuICAgIGlmICh0aGlzLm5lc3RlZCB8fCB0YXJnZXQubmVzdGVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBhZGQgYXNzZW1ibHktbGV2ZWwgZGVwZW5kZW5jaWVzIGZvciBuZXN0ZWQgc3RhY2tzJyk7XG4gICAgfVxuXG4gICAgcmVhc29uID0gcmVhc29uIHx8ICdkZXBlbmRlbmN5IGFkZGVkIHVzaW5nIHN0YWNrLmFkZERlcGVuZGVuY3koKSc7XG4gICAgY29uc3QgY3ljbGUgPSB0YXJnZXQuc3RhY2tEZXBlbmRlbmN5UmVhc29ucyh0aGlzKTtcbiAgICBpZiAoY3ljbGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG1heC1sZW5cbiAgICAgIHRocm93IG5ldyBFcnJvcihgJyR7dGFyZ2V0Lm5vZGUucGF0aH0nIGRlcGVuZHMgb24gJyR7dGhpcy5ub2RlLnBhdGh9JyAoJHtjeWNsZS5qb2luKCcsICcpfSkuIEFkZGluZyB0aGlzIGRlcGVuZGVuY3kgKCR7cmVhc29ufSkgd291bGQgY3JlYXRlIGEgY3ljbGljIHJlZmVyZW5jZS5gKTtcbiAgICB9XG5cbiAgICBsZXQgZGVwID0gdGhpcy5fc3RhY2tEZXBlbmRlbmNpZXNbTmFtZXMudW5pcXVlSWQodGFyZ2V0KV07XG4gICAgaWYgKCFkZXApIHtcbiAgICAgIGRlcCA9IHRoaXMuX3N0YWNrRGVwZW5kZW5jaWVzW05hbWVzLnVuaXF1ZUlkKHRhcmdldCldID0ge1xuICAgICAgICBzdGFjazogdGFyZ2V0LFxuICAgICAgICByZWFzb25zOiBbXSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgZGVwLnJlYXNvbnMucHVzaChyZWFzb24pO1xuXG4gICAgaWYgKHByb2Nlc3MuZW52LkNES19ERUJVR19ERVBTKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZVxuICAgICAgY29uc29sZS5lcnJvcihgW0NES19ERUJVR19ERVBTXSBzdGFjayBcIiR7dGhpcy5ub2RlLnBhdGh9XCIgZGVwZW5kcyBvbiBcIiR7dGFyZ2V0Lm5vZGUucGF0aH1cIiBiZWNhdXNlOiAke3JlYXNvbn1gKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU3ludGhlc2l6ZXMgdGhlIGNsb3VkZm9ybWF0aW9uIHRlbXBsYXRlIGludG8gYSBjbG91ZCBhc3NlbWJseS5cbiAgICogQGludGVybmFsXG4gICAqL1xuICBwdWJsaWMgX3N5bnRoZXNpemVUZW1wbGF0ZShzZXNzaW9uOiBJU3ludGhlc2lzU2Vzc2lvbiwgbG9va3VwUm9sZUFybj86IHN0cmluZyk6IHZvaWQge1xuICAgIC8vIEluIHByaW5jaXBsZSwgc3RhY2sgc3ludGhlc2lzIGlzIGRlbGVnYXRlZCB0byB0aGVcbiAgICAvLyBTdGFja1N5bnRoZXNpcyBvYmplY3QuXG4gICAgLy9cbiAgICAvLyBIb3dldmVyLCBzb21lIHBhcnRzIG9mIHN5bnRoZXNpcyBjdXJyZW50bHkgdXNlIHNvbWUgcHJpdmF0ZVxuICAgIC8vIG1ldGhvZHMgb24gU3RhY2ssIGFuZCBJIGRvbid0IHJlYWxseSBzZWUgdGhlIHZhbHVlIGluIHJlZmFjdG9yaW5nXG4gICAgLy8gdGhpcyByaWdodCBub3csIHNvIHNvbWUgcGFydHMgc3RpbGwgaGFwcGVuIGhlcmUuXG4gICAgY29uc3QgYnVpbGRlciA9IHNlc3Npb24uYXNzZW1ibHk7XG5cbiAgICBjb25zdCB0ZW1wbGF0ZSA9IHRoaXMuX3RvQ2xvdWRGb3JtYXRpb24oKTtcblxuICAgIC8vIHdyaXRlIHRoZSBDbG91ZEZvcm1hdGlvbiB0ZW1wbGF0ZSBhcyBhIEpTT04gZmlsZVxuICAgIGNvbnN0IG91dFBhdGggPSBwYXRoLmpvaW4oYnVpbGRlci5vdXRkaXIsIHRoaXMudGVtcGxhdGVGaWxlKTtcblxuICAgIGlmICh0aGlzLm1heFJlc291cmNlcyA+IDApIHtcbiAgICAgIGNvbnN0IHJlc291cmNlcyA9IHRlbXBsYXRlLlJlc291cmNlcyB8fCB7fTtcbiAgICAgIGNvbnN0IG51bWJlck9mUmVzb3VyY2VzID0gT2JqZWN0LmtleXMocmVzb3VyY2VzKS5sZW5ndGg7XG5cbiAgICAgIGlmIChudW1iZXJPZlJlc291cmNlcyA+IHRoaXMubWF4UmVzb3VyY2VzKSB7XG4gICAgICAgIGNvbnN0IGNvdW50cyA9IE9iamVjdC5lbnRyaWVzKGNvdW50KE9iamVjdC52YWx1ZXMocmVzb3VyY2VzKS5tYXAoKHI6IGFueSkgPT4gYCR7cj8uVHlwZX1gKSkpLm1hcCgoW3R5cGUsIGNdKSA9PiBgJHt0eXBlfSAoJHtjfSlgKS5qb2luKCcsICcpO1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYE51bWJlciBvZiByZXNvdXJjZXMgaW4gc3RhY2sgJyR7dGhpcy5ub2RlLnBhdGh9JzogJHtudW1iZXJPZlJlc291cmNlc30gaXMgZ3JlYXRlciB0aGFuIGFsbG93ZWQgbWF4aW11bSBvZiAke3RoaXMubWF4UmVzb3VyY2VzfTogJHtjb3VudHN9YCk7XG4gICAgICB9IGVsc2UgaWYgKG51bWJlck9mUmVzb3VyY2VzID49ICh0aGlzLm1heFJlc291cmNlcyAqIDAuOCkpIHtcbiAgICAgICAgQW5ub3RhdGlvbnMub2YodGhpcykuYWRkSW5mbyhgTnVtYmVyIG9mIHJlc291cmNlczogJHtudW1iZXJPZlJlc291cmNlc30gaXMgYXBwcm9hY2hpbmcgYWxsb3dlZCBtYXhpbXVtIG9mICR7dGhpcy5tYXhSZXNvdXJjZXN9YCk7XG4gICAgICB9XG4gICAgfVxuICAgIGZzLndyaXRlRmlsZVN5bmMob3V0UGF0aCwgSlNPTi5zdHJpbmdpZnkodGVtcGxhdGUsIHVuZGVmaW5lZCwgMSkpO1xuXG4gICAgZm9yIChjb25zdCBjdHggb2YgdGhpcy5fbWlzc2luZ0NvbnRleHQpIHtcbiAgICAgIGlmIChsb29rdXBSb2xlQXJuICE9IG51bGwpIHtcbiAgICAgICAgYnVpbGRlci5hZGRNaXNzaW5nKHsgLi4uY3R4LCBwcm9wczogeyAuLi5jdHgucHJvcHMsIGxvb2t1cFJvbGVBcm4gfSB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGJ1aWxkZXIuYWRkTWlzc2luZyhjdHgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBMb29rIHVwIGEgZmFjdCB2YWx1ZSBmb3IgdGhlIGdpdmVuIGZhY3QgZm9yIHRoZSByZWdpb24gb2YgdGhpcyBzdGFja1xuICAgKlxuICAgKiBXaWxsIHJldHVybiBhIGRlZmluaXRlIHZhbHVlIG9ubHkgaWYgdGhlIHJlZ2lvbiBvZiB0aGUgY3VycmVudCBzdGFjayBpcyByZXNvbHZlZC5cbiAgICogSWYgbm90LCBhIGxvb2t1cCBtYXAgd2lsbCBiZSBhZGRlZCB0byB0aGUgc3RhY2sgYW5kIHRoZSBsb29rdXAgd2lsbCBiZSBkb25lIGF0XG4gICAqIENESyBkZXBsb3ltZW50IHRpbWUuXG4gICAqXG4gICAqIFdoYXQgcmVnaW9ucyB3aWxsIGJlIGluY2x1ZGVkIGluIHRoZSBsb29rdXAgbWFwIGlzIGNvbnRyb2xsZWQgYnkgdGhlXG4gICAqIGBAYXdzLWNkay9jb3JlOnRhcmdldC1wYXJ0aXRpb25zYCBjb250ZXh0IHZhbHVlOiBpdCBtdXN0IGJlIHNldCB0byBhIGxpc3RcbiAgICogb2YgcGFydGl0aW9ucywgYW5kIG9ubHkgcmVnaW9ucyBmcm9tIHRoZSBnaXZlbiBwYXJ0aXRpb25zIHdpbGwgYmUgaW5jbHVkZWQuXG4gICAqIElmIG5vIHN1Y2ggY29udGV4dCBrZXkgaXMgc2V0LCBhbGwgcmVnaW9ucyB3aWxsIGJlIGluY2x1ZGVkLlxuICAgKlxuICAgKiBUaGlzIGZ1bmN0aW9uIGlzIGludGVuZGVkIHRvIGJlIHVzZWQgYnkgY29uc3RydWN0IGxpYnJhcnkgYXV0aG9ycy4gQXBwbGljYXRpb25cbiAgICogYnVpbGRlcnMgY2FuIHJlbHkgb24gdGhlIGFic3RyYWN0aW9ucyBvZmZlcmVkIGJ5IGNvbnN0cnVjdCBsaWJyYXJpZXMgYW5kIGRvXG4gICAqIG5vdCBoYXZlIHRvIHdvcnJ5IGFib3V0IHJlZ2lvbmFsIGZhY3RzLlxuICAgKlxuICAgKiBJZiBgZGVmYXVsdFZhbHVlYCBpcyBub3QgZ2l2ZW4sIGl0IGlzIGFuIGVycm9yIGlmIHRoZSBmYWN0IGlzIHVua25vd24gZm9yXG4gICAqIHRoZSBnaXZlbiByZWdpb24uXG4gICAqL1xuICBwdWJsaWMgcmVnaW9uYWxGYWN0KGZhY3ROYW1lOiBzdHJpbmcsIGRlZmF1bHRWYWx1ZT86IHN0cmluZyk6IHN0cmluZyB7XG4gICAgaWYgKCFUb2tlbi5pc1VucmVzb2x2ZWQodGhpcy5yZWdpb24pKSB7XG4gICAgICBjb25zdCByZXQgPSBGYWN0LmZpbmQodGhpcy5yZWdpb24sIGZhY3ROYW1lKSA/PyBkZWZhdWx0VmFsdWU7XG4gICAgICBpZiAocmV0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGByZWdpb24taW5mbzogZG9uJ3Qga25vdyAke2ZhY3ROYW1lfSBmb3IgcmVnaW9uICR7dGhpcy5yZWdpb259LiBVc2UgJ0ZhY3QucmVnaXN0ZXInIHRvIHByb3ZpZGUgdGhpcyB2YWx1ZS5gKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXQ7XG4gICAgfVxuXG4gICAgY29uc3QgcGFydGl0aW9ucyA9IE5vZGUub2YodGhpcykudHJ5R2V0Q29udGV4dChjeGFwaS5UQVJHRVRfUEFSVElUSU9OUyk7XG4gICAgaWYgKHBhcnRpdGlvbnMgIT09IHVuZGVmaW5lZCAmJiAhQXJyYXkuaXNBcnJheShwYXJ0aXRpb25zKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBDb250ZXh0IHZhbHVlICcke2N4YXBpLlRBUkdFVF9QQVJUSVRJT05TfScgc2hvdWxkIGJlIGEgbGlzdCBvZiBzdHJpbmdzLCBnb3Q6ICR7SlNPTi5zdHJpbmdpZnkoY3hhcGkuVEFSR0VUX1BBUlRJVElPTlMpfWApO1xuICAgIH1cblxuICAgIGNvbnN0IGxvb2t1cE1hcCA9IHBhcnRpdGlvbnMgPyBSZWdpb25JbmZvLmxpbWl0ZWRSZWdpb25NYXAoZmFjdE5hbWUsIHBhcnRpdGlvbnMpIDogUmVnaW9uSW5mby5yZWdpb25NYXAoZmFjdE5hbWUpO1xuXG4gICAgcmV0dXJuIGRlcGxveVRpbWVMb29rdXAodGhpcywgZmFjdE5hbWUsIGxvb2t1cE1hcCwgZGVmYXVsdFZhbHVlKTtcbiAgfVxuXG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIENsb3VkRm9ybWF0aW9uIEV4cG9ydCBmb3IgYSB2YWx1ZVxuICAgKlxuICAgKiBSZXR1cm5zIGEgc3RyaW5nIHJlcHJlc2VudGluZyB0aGUgY29ycmVzcG9uZGluZyBgRm4uaW1wb3J0VmFsdWUoKWBcbiAgICogZXhwcmVzc2lvbiBmb3IgdGhpcyBFeHBvcnQuIFlvdSBjYW4gY29udHJvbCB0aGUgbmFtZSBmb3IgdGhlIGV4cG9ydCBieVxuICAgKiBwYXNzaW5nIHRoZSBgbmFtZWAgb3B0aW9uLlxuICAgKlxuICAgKiBJZiB5b3UgZG9uJ3Qgc3VwcGx5IGEgdmFsdWUgZm9yIGBuYW1lYCwgdGhlIHZhbHVlIHlvdSdyZSBleHBvcnRpbmcgbXVzdCBiZVxuICAgKiBhIFJlc291cmNlIGF0dHJpYnV0ZSAoZm9yIGV4YW1wbGU6IGBidWNrZXQuYnVja2V0TmFtZWApIGFuZCBpdCB3aWxsIGJlXG4gICAqIGdpdmVuIHRoZSBzYW1lIG5hbWUgYXMgdGhlIGF1dG9tYXRpYyBjcm9zcy1zdGFjayByZWZlcmVuY2UgdGhhdCB3b3VsZCBiZSBjcmVhdGVkXG4gICAqIGlmIHlvdSB1c2VkIHRoZSBhdHRyaWJ1dGUgaW4gYW5vdGhlciBTdGFjay5cbiAgICpcbiAgICogT25lIG9mIHRoZSB1c2VzIGZvciB0aGlzIG1ldGhvZCBpcyB0byAqcmVtb3ZlKiB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW5cbiAgICogdHdvIFN0YWNrcyBlc3RhYmxpc2hlZCBieSBhdXRvbWF0aWMgY3Jvc3Mtc3RhY2sgcmVmZXJlbmNlcy4gSXQgd2lsbFxuICAgKiB0ZW1wb3JhcmlseSBlbnN1cmUgdGhhdCB0aGUgQ2xvdWRGb3JtYXRpb24gRXhwb3J0IHN0aWxsIGV4aXN0cyB3aGlsZSB5b3VcbiAgICogcmVtb3ZlIHRoZSByZWZlcmVuY2UgZnJvbSB0aGUgY29uc3VtaW5nIHN0YWNrLiBBZnRlciB0aGF0LCB5b3UgY2FuIHJlbW92ZVxuICAgKiB0aGUgcmVzb3VyY2UgYW5kIHRoZSBtYW51YWwgZXhwb3J0LlxuICAgKlxuICAgKiAjIyBFeGFtcGxlXG4gICAqXG4gICAqIEhlcmUgaXMgaG93IHRoZSBwcm9jZXNzIHdvcmtzLiBMZXQncyBzYXkgdGhlcmUgYXJlIHR3byBzdGFja3MsXG4gICAqIGBwcm9kdWNlclN0YWNrYCBhbmQgYGNvbnN1bWVyU3RhY2tgLCBhbmQgYHByb2R1Y2VyU3RhY2tgIGhhcyBhIGJ1Y2tldFxuICAgKiBjYWxsZWQgYGJ1Y2tldGAsIHdoaWNoIGlzIHJlZmVyZW5jZWQgYnkgYGNvbnN1bWVyU3RhY2tgIChwZXJoYXBzIGJlY2F1c2VcbiAgICogYW4gQVdTIExhbWJkYSBGdW5jdGlvbiB3cml0ZXMgaW50byBpdCwgb3Igc29tZXRoaW5nIGxpa2UgdGhhdCkuXG4gICAqXG4gICAqIEl0IGlzIG5vdCBzYWZlIHRvIHJlbW92ZSBgcHJvZHVjZXJTdGFjay5idWNrZXRgIGJlY2F1c2UgYXMgdGhlIGJ1Y2tldCBpcyBiZWluZ1xuICAgKiBkZWxldGVkLCBgY29uc3VtZXJTdGFja2AgbWlnaHQgc3RpbGwgYmUgdXNpbmcgaXQuXG4gICAqXG4gICAqIEluc3RlYWQsIHRoZSBwcm9jZXNzIHRha2VzIHR3byBkZXBsb3ltZW50czpcbiAgICpcbiAgICogIyMjIERlcGxveW1lbnQgMTogYnJlYWsgdGhlIHJlbGF0aW9uc2hpcFxuICAgKlxuICAgKiAtIE1ha2Ugc3VyZSBgY29uc3VtZXJTdGFja2Agbm8gbG9uZ2VyIHJlZmVyZW5jZXMgYGJ1Y2tldC5idWNrZXROYW1lYCAobWF5YmUgdGhlIGNvbnN1bWVyXG4gICAqICAgc3RhY2sgbm93IHVzZXMgaXRzIG93biBidWNrZXQsIG9yIGl0IHdyaXRlcyB0byBhbiBBV1MgRHluYW1vREIgdGFibGUsIG9yIG1heWJlIHlvdSBqdXN0XG4gICAqICAgcmVtb3ZlIHRoZSBMYW1iZGEgRnVuY3Rpb24gYWx0b2dldGhlcikuXG4gICAqIC0gSW4gdGhlIGBQcm9kdWNlclN0YWNrYCBjbGFzcywgY2FsbCBgdGhpcy5leHBvcnRWYWx1ZSh0aGlzLmJ1Y2tldC5idWNrZXROYW1lKWAuIFRoaXNcbiAgICogICB3aWxsIG1ha2Ugc3VyZSB0aGUgQ2xvdWRGb3JtYXRpb24gRXhwb3J0IGNvbnRpbnVlcyB0byBleGlzdCB3aGlsZSB0aGUgcmVsYXRpb25zaGlwXG4gICAqICAgYmV0d2VlbiB0aGUgdHdvIHN0YWNrcyBpcyBiZWluZyBicm9rZW4uXG4gICAqIC0gRGVwbG95ICh0aGlzIHdpbGwgZWZmZWN0aXZlbHkgb25seSBjaGFuZ2UgdGhlIGBjb25zdW1lclN0YWNrYCwgYnV0IGl0J3Mgc2FmZSB0byBkZXBsb3kgYm90aCkuXG4gICAqXG4gICAqICMjIyBEZXBsb3ltZW50IDI6IHJlbW92ZSB0aGUgYnVja2V0IHJlc291cmNlXG4gICAqXG4gICAqIC0gWW91IGFyZSBub3cgZnJlZSB0byByZW1vdmUgdGhlIGBidWNrZXRgIHJlc291cmNlIGZyb20gYHByb2R1Y2VyU3RhY2tgLlxuICAgKiAtIERvbid0IGZvcmdldCB0byByZW1vdmUgdGhlIGBleHBvcnRWYWx1ZSgpYCBjYWxsIGFzIHdlbGwuXG4gICAqIC0gRGVwbG95IGFnYWluICh0aGlzIHRpbWUgb25seSB0aGUgYHByb2R1Y2VyU3RhY2tgIHdpbGwgYmUgY2hhbmdlZCAtLSB0aGUgYnVja2V0IHdpbGwgYmUgZGVsZXRlZCkuXG4gICAqL1xuICBwdWJsaWMgZXhwb3J0VmFsdWUoZXhwb3J0ZWRWYWx1ZTogYW55LCBvcHRpb25zOiBFeHBvcnRWYWx1ZU9wdGlvbnMgPSB7fSkge1xuICAgIGlmIChvcHRpb25zLm5hbWUpIHtcbiAgICAgIG5ldyBDZm5PdXRwdXQodGhpcywgYEV4cG9ydCR7b3B0aW9ucy5uYW1lfWAsIHtcbiAgICAgICAgdmFsdWU6IGV4cG9ydGVkVmFsdWUsXG4gICAgICAgIGV4cG9ydE5hbWU6IG9wdGlvbnMubmFtZSxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIEZuLmltcG9ydFZhbHVlKG9wdGlvbnMubmFtZSk7XG4gICAgfVxuXG4gICAgY29uc3QgcmVzb2x2YWJsZSA9IFRva2VuaXphdGlvbi5yZXZlcnNlKGV4cG9ydGVkVmFsdWUpO1xuICAgIGlmICghcmVzb2x2YWJsZSB8fCAhUmVmZXJlbmNlLmlzUmVmZXJlbmNlKHJlc29sdmFibGUpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2V4cG9ydFZhbHVlOiBlaXRoZXIgc3VwcGx5IFxcJ25hbWVcXCcgb3IgbWFrZSBzdXJlIHRvIGV4cG9ydCBhIHJlc291cmNlIGF0dHJpYnV0ZSAobGlrZSBcXCdidWNrZXQuYnVja2V0TmFtZVxcJyknKTtcbiAgICB9XG5cbiAgICAvLyBpZiBleHBvcnRWYWx1ZSBpcyBiZWluZyBjYWxsZWQgbWFudWFsbHkgKHdoaWNoIGlzIHByZSBvblByZXBhcmUpIHRoZW4gdGhlIGxvZ2ljYWxJZFxuICAgIC8vIGNvdWxkIHBvdGVudGlhbGx5IGJlIGNoYW5nZWQgYnkgYSBjYWxsIHRvIG92ZXJyaWRlTG9naWNhbElkLiBUaGlzIHdvdWxkIGNhdXNlIG91ciBFeHBvcnQvSW1wb3J0XG4gICAgLy8gdG8gaGF2ZSBhbiBpbmNvcnJlY3QgaWQuIEZvciBhIGJldHRlciB1c2VyIGV4cGVyaWVuY2UsIGxvY2sgdGhlIGxvZ2ljYWxJZCBhbmQgdGhyb3cgYW4gZXJyb3JcbiAgICAvLyBpZiB0aGUgdXNlciB0cmllcyB0byBvdmVycmlkZSB0aGUgaWQgX2FmdGVyXyBjYWxsaW5nIGV4cG9ydFZhbHVlXG4gICAgaWYgKENmbkVsZW1lbnQuaXNDZm5FbGVtZW50KHJlc29sdmFibGUudGFyZ2V0KSkge1xuICAgICAgcmVzb2x2YWJsZS50YXJnZXQuX2xvY2tMb2dpY2FsSWQoKTtcbiAgICB9XG5cbiAgICAvLyBcInRlbGVwb3J0XCIgdGhlIHZhbHVlIGhlcmUsIGluIGNhc2UgaXQgY29tZXMgZnJvbSBhIG5lc3RlZCBzdGFjay4gVGhpcyB3aWxsIGFsc29cbiAgICAvLyBlbnN1cmUgdGhlIHZhbHVlIGlzIGZyb20gb3VyIG93biBzY29wZS5cbiAgICBjb25zdCBleHBvcnRhYmxlID0gcmVmZXJlbmNlTmVzdGVkU3RhY2tWYWx1ZUluUGFyZW50KHJlc29sdmFibGUsIHRoaXMpO1xuXG4gICAgLy8gRW5zdXJlIGEgc2luZ2xldG9uIFwiRXhwb3J0c1wiIHNjb3BpbmcgQ29uc3RydWN0XG4gICAgLy8gVGhpcyBtb3N0bHkgZXhpc3RzIHRvIHRyaWdnZXIgTG9naWNhbElEIG11bmdpbmcsIHdoaWNoIHdvdWxkIGJlXG4gICAgLy8gZGlzYWJsZWQgaWYgd2UgcGFyZW50ZWQgY29uc3RydWN0cyBkaXJlY3RseSB1bmRlciBTdGFjay5cbiAgICAvLyBBbHNvIGl0IG5pY2VseSBwcmV2ZW50cyBsaWtlbHkgY29uc3RydWN0IG5hbWUgY2xhc2hlc1xuICAgIGNvbnN0IGV4cG9ydHNTY29wZSA9IGdldENyZWF0ZUV4cG9ydHNTY29wZSh0aGlzKTtcblxuICAgIC8vIEVuc3VyZSBhIHNpbmdsZXRvbiBDZm5PdXRwdXQgZm9yIHRoaXMgdmFsdWVcbiAgICBjb25zdCByZXNvbHZlZCA9IHRoaXMucmVzb2x2ZShleHBvcnRhYmxlKTtcbiAgICBjb25zdCBpZCA9ICdPdXRwdXQnICsgSlNPTi5zdHJpbmdpZnkocmVzb2x2ZWQpO1xuICAgIGNvbnN0IGV4cG9ydE5hbWUgPSBnZW5lcmF0ZUV4cG9ydE5hbWUoZXhwb3J0c1Njb3BlLCBpZCk7XG5cbiAgICBpZiAoVG9rZW4uaXNVbnJlc29sdmVkKGV4cG9ydE5hbWUpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYHVucmVzb2x2ZWQgdG9rZW4gaW4gZ2VuZXJhdGVkIGV4cG9ydCBuYW1lOiAke0pTT04uc3RyaW5naWZ5KHRoaXMucmVzb2x2ZShleHBvcnROYW1lKSl9YCk7XG4gICAgfVxuXG4gICAgY29uc3Qgb3V0cHV0ID0gZXhwb3J0c1Njb3BlLm5vZGUudHJ5RmluZENoaWxkKGlkKSBhcyBDZm5PdXRwdXQ7XG4gICAgaWYgKCFvdXRwdXQpIHtcbiAgICAgIG5ldyBDZm5PdXRwdXQoZXhwb3J0c1Njb3BlLCBpZCwgeyB2YWx1ZTogVG9rZW4uYXNTdHJpbmcoZXhwb3J0YWJsZSksIGV4cG9ydE5hbWUgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIEZuLmltcG9ydFZhbHVlKGV4cG9ydE5hbWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIG5hbWluZyBzY2hlbWUgdXNlZCB0byBhbGxvY2F0ZSBsb2dpY2FsIElEcy4gQnkgZGVmYXVsdCwgdXNlc1xuICAgKiB0aGUgYEhhc2hlZEFkZHJlc3NpbmdTY2hlbWVgIGJ1dCB0aGlzIG1ldGhvZCBjYW4gYmUgb3ZlcnJpZGRlbiB0byBjdXN0b21pemVcbiAgICogdGhpcyBiZWhhdmlvci5cbiAgICpcbiAgICogSW4gb3JkZXIgdG8gbWFrZSBzdXJlIGxvZ2ljYWwgSURzIGFyZSB1bmlxdWUgYW5kIHN0YWJsZSwgd2UgaGFzaCB0aGUgcmVzb3VyY2VcbiAgICogY29uc3RydWN0IHRyZWUgcGF0aCAoaS5lLiB0b3BsZXZlbC9zZWNvbmRsZXZlbC8uLi4vbXlyZXNvdXJjZSkgYW5kIGFkZCBpdCBhc1xuICAgKiBhIHN1ZmZpeCB0byB0aGUgcGF0aCBjb21wb25lbnRzIGpvaW5lZCB3aXRob3V0IGEgc2VwYXJhdG9yIChDbG91ZEZvcm1hdGlvblxuICAgKiBJRHMgb25seSBhbGxvdyBhbHBoYW51bWVyaWMgY2hhcmFjdGVycykuXG4gICAqXG4gICAqIFRoZSByZXN1bHQgd2lsbCBiZTpcbiAgICpcbiAgICogICA8cGF0aC5qb2luKCcnKT48bWQ1KHBhdGguam9pbignLycpPlxuICAgKiAgICAgXCJodW1hblwiICAgICAgXCJoYXNoXCJcbiAgICpcbiAgICogSWYgdGhlIFwiaHVtYW5cIiBwYXJ0IG9mIHRoZSBJRCBleGNlZWRzIDI0MCBjaGFyYWN0ZXJzLCB3ZSBzaW1wbHkgdHJpbSBpdCBzb1xuICAgKiB0aGUgdG90YWwgSUQgZG9lc24ndCBleGNlZWQgQ2xvdWRGb3JtYXRpb24ncyAyNTUgY2hhcmFjdGVyIGxpbWl0LlxuICAgKlxuICAgKiBXZSBvbmx5IHRha2UgOCBjaGFyYWN0ZXJzIGZyb20gdGhlIG1kNSBoYXNoICgwLjAwMDAwNSBjaGFuY2Ugb2YgY29sbGlzaW9uKS5cbiAgICpcbiAgICogU3BlY2lhbCBjYXNlczpcbiAgICpcbiAgICogLSBJZiB0aGUgcGF0aCBvbmx5IGNvbnRhaW5zIGEgc2luZ2xlIGNvbXBvbmVudCAoaS5lLiBpdCdzIGEgdG9wLWxldmVsXG4gICAqICAgcmVzb3VyY2UpLCB3ZSB3b24ndCBhZGQgdGhlIGhhc2ggdG8gaXQuIFRoZSBoYXNoIGlzIG5vdCBuZWVkZWQgZm9yXG4gICAqICAgZGlzYW1pZ3VhdGlvbiBhbmQgYWxzbywgaXQgYWxsb3dzIGZvciBhIG1vcmUgc3RyYWlnaHRmb3J3YXJkIG1pZ3JhdGlvbiBhblxuICAgKiAgIGV4aXN0aW5nIENsb3VkRm9ybWF0aW9uIHRlbXBsYXRlIHRvIGEgQ0RLIHN0YWNrIHdpdGhvdXQgbG9naWNhbCBJRCBjaGFuZ2VzXG4gICAqICAgKG9yIHJlbmFtZXMpLlxuICAgKiAtIEZvciBhZXN0aGV0aWMgcmVhc29ucywgaWYgdGhlIGxhc3QgY29tcG9uZW50cyBvZiB0aGUgcGF0aCBhcmUgdGhlIHNhbWVcbiAgICogICAoaS5lLiBgTDEvTDIvUGlwZWxpbmUvUGlwZWxpbmVgKSwgdGhleSB3aWxsIGJlIGRlLWR1cGxpY2F0ZWQgdG8gbWFrZSB0aGVcbiAgICogICByZXN1bHRpbmcgaHVtYW4gcG9ydGlvbiBvZiB0aGUgSUQgbW9yZSBwbGVhc2luZzogYEwxTDJQaXBlbGluZTxIQVNIPmBcbiAgICogICBpbnN0ZWFkIG9mIGBMMUwyUGlwZWxpbmVQaXBlbGluZTxIQVNIPmBcbiAgICogLSBJZiBhIGNvbXBvbmVudCBpcyBuYW1lZCBcIkRlZmF1bHRcIiBpdCB3aWxsIGJlIG9taXR0ZWQgZnJvbSB0aGUgcGF0aC4gVGhpc1xuICAgKiAgIGFsbG93cyByZWZhY3RvcmluZyBoaWdoZXIgbGV2ZWwgYWJzdHJhY3Rpb25zIGFyb3VuZCBjb25zdHJ1Y3RzIHdpdGhvdXQgYWZmZWN0aW5nXG4gICAqICAgdGhlIElEcyBvZiBhbHJlYWR5IGRlcGxveWVkIHJlc291cmNlcy5cbiAgICogLSBJZiBhIGNvbXBvbmVudCBpcyBuYW1lZCBcIlJlc291cmNlXCIgaXQgd2lsbCBiZSBvbWl0dGVkIGZyb20gdGhlIHVzZXItdmlzaWJsZVxuICAgKiAgIHBhdGgsIGJ1dCBpbmNsdWRlZCBpbiB0aGUgaGFzaC4gVGhpcyByZWR1Y2VzIHZpc3VhbCBub2lzZSBpbiB0aGUgaHVtYW4gcmVhZGFibGVcbiAgICogICBwYXJ0IG9mIHRoZSBpZGVudGlmaWVyLlxuICAgKlxuICAgKiBAcGFyYW0gY2ZuRWxlbWVudCBUaGUgZWxlbWVudCBmb3Igd2hpY2ggdGhlIGxvZ2ljYWwgSUQgaXMgYWxsb2NhdGVkLlxuICAgKi9cbiAgcHJvdGVjdGVkIGFsbG9jYXRlTG9naWNhbElkKGNmbkVsZW1lbnQ6IENmbkVsZW1lbnQpOiBzdHJpbmcge1xuICAgIGNvbnN0IHNjb3BlcyA9IGNmbkVsZW1lbnQubm9kZS5zY29wZXM7XG4gICAgY29uc3Qgc3RhY2tJbmRleCA9IHNjb3Blcy5pbmRleE9mKGNmbkVsZW1lbnQuc3RhY2spO1xuICAgIGNvbnN0IHBhdGhDb21wb25lbnRzID0gc2NvcGVzLnNsaWNlKHN0YWNrSW5kZXggKyAxKS5tYXAoeCA9PiB4Lm5vZGUuaWQpO1xuICAgIHJldHVybiBtYWtlVW5pcXVlSWQocGF0aENvbXBvbmVudHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlIHN0YWNrIG5hbWVcbiAgICpcbiAgICogQ2xvdWRGb3JtYXRpb24gc3RhY2sgbmFtZXMgY2FuIGluY2x1ZGUgZGFzaGVzIGluIGFkZGl0aW9uIHRvIHRoZSByZWd1bGFyIGlkZW50aWZpZXJcbiAgICogY2hhcmFjdGVyIGNsYXNzZXMsIGFuZCB3ZSBkb24ndCBhbGxvdyBvbmUgb2YgdGhlIG1hZ2ljIG1hcmtlcnMuXG4gICAqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHJvdGVjdGVkIF92YWxpZGF0ZUlkKG5hbWU6IHN0cmluZykge1xuICAgIGlmIChuYW1lICYmICFWQUxJRF9TVEFDS19OQU1FX1JFR0VYLnRlc3QobmFtZSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgU3RhY2sgbmFtZSBtdXN0IG1hdGNoIHRoZSByZWd1bGFyIGV4cHJlc3Npb246ICR7VkFMSURfU1RBQ0tfTkFNRV9SRUdFWC50b1N0cmluZygpfSwgZ290ICcke25hbWV9J2ApO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBDbG91ZEZvcm1hdGlvbiB0ZW1wbGF0ZSBmb3IgdGhpcyBzdGFjayBieSB0cmF2ZXJzaW5nXG4gICAqIHRoZSB0cmVlIGFuZCBpbnZva2luZyBfdG9DbG91ZEZvcm1hdGlvbigpIG9uIGFsbCBFbnRpdHkgb2JqZWN0cy5cbiAgICpcbiAgICogQGludGVybmFsXG4gICAqL1xuICBwcm90ZWN0ZWQgX3RvQ2xvdWRGb3JtYXRpb24oKSB7XG4gICAgbGV0IHRyYW5zZm9ybTogc3RyaW5nIHwgc3RyaW5nW10gfCB1bmRlZmluZWQ7XG5cbiAgICBpZiAodGhpcy50ZW1wbGF0ZU9wdGlvbnMudHJhbnNmb3JtKSB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbWF4LWxlblxuICAgICAgQW5ub3RhdGlvbnMub2YodGhpcykuYWRkV2FybmluZygnVGhpcyBzdGFjayBpcyB1c2luZyB0aGUgZGVwcmVjYXRlZCBgdGVtcGxhdGVPcHRpb25zLnRyYW5zZm9ybWAgcHJvcGVydHkuIENvbnNpZGVyIHN3aXRjaGluZyB0byBgYWRkVHJhbnNmb3JtKClgLicpO1xuICAgICAgdGhpcy5hZGRUcmFuc2Zvcm0odGhpcy50ZW1wbGF0ZU9wdGlvbnMudHJhbnNmb3JtKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy50ZW1wbGF0ZU9wdGlvbnMudHJhbnNmb3Jtcykge1xuICAgICAgaWYgKHRoaXMudGVtcGxhdGVPcHRpb25zLnRyYW5zZm9ybXMubGVuZ3RoID09PSAxKSB7IC8vIEV4dHJhY3Qgc2luZ2xlIHZhbHVlXG4gICAgICAgIHRyYW5zZm9ybSA9IHRoaXMudGVtcGxhdGVPcHRpb25zLnRyYW5zZm9ybXNbMF07XG4gICAgICB9IGVsc2UgeyAvLyBSZW1vdmUgZHVwbGljYXRlIHZhbHVlc1xuICAgICAgICB0cmFuc2Zvcm0gPSBBcnJheS5mcm9tKG5ldyBTZXQodGhpcy50ZW1wbGF0ZU9wdGlvbnMudHJhbnNmb3JtcykpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IHRlbXBsYXRlOiBhbnkgPSB7XG4gICAgICBEZXNjcmlwdGlvbjogdGhpcy50ZW1wbGF0ZU9wdGlvbnMuZGVzY3JpcHRpb24sXG4gICAgICBUcmFuc2Zvcm06IHRyYW5zZm9ybSxcbiAgICAgIEFXU1RlbXBsYXRlRm9ybWF0VmVyc2lvbjogdGhpcy50ZW1wbGF0ZU9wdGlvbnMudGVtcGxhdGVGb3JtYXRWZXJzaW9uLFxuICAgICAgTWV0YWRhdGE6IHRoaXMudGVtcGxhdGVPcHRpb25zLm1ldGFkYXRhLFxuICAgIH07XG5cbiAgICBjb25zdCBlbGVtZW50cyA9IGNmbkVsZW1lbnRzKHRoaXMpO1xuICAgIGNvbnN0IGZyYWdtZW50cyA9IGVsZW1lbnRzLm1hcChlID0+IHRoaXMucmVzb2x2ZShlLl90b0Nsb3VkRm9ybWF0aW9uKCkpKTtcblxuICAgIC8vIG1lcmdlIGluIGFsbCBDbG91ZEZvcm1hdGlvbiBmcmFnbWVudHMgY29sbGVjdGVkIGZyb20gdGhlIHRyZWVcbiAgICBmb3IgKGNvbnN0IGZyYWdtZW50IG9mIGZyYWdtZW50cykge1xuICAgICAgbWVyZ2UodGVtcGxhdGUsIGZyYWdtZW50KTtcbiAgICB9XG5cbiAgICAvLyByZXNvbHZlIGFsbCB0b2tlbnMgYW5kIHJlbW92ZSBhbGwgZW1wdGllc1xuICAgIGNvbnN0IHJldCA9IHRoaXMucmVzb2x2ZSh0ZW1wbGF0ZSkgfHwge307XG5cbiAgICB0aGlzLl9sb2dpY2FsSWRzLmFzc2VydEFsbFJlbmFtZXNBcHBsaWVkKCk7XG5cbiAgICByZXR1cm4gcmV0O1xuICB9XG5cbiAgLyoqXG4gICAqIERlcHJlY2F0ZWQuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9naXRodWIuY29tL2F3cy9hd3MtY2RrL3B1bGwvNzE4N1xuICAgKiBAcmV0dXJucyByZWZlcmVuY2UgaXRzZWxmIHdpdGhvdXQgYW55IGNoYW5nZVxuICAgKiBAZGVwcmVjYXRlZCBjcm9zcyByZWZlcmVuY2UgaGFuZGxpbmcgaGFzIGJlZW4gbW92ZWQgdG8gYEFwcC5wcmVwYXJlKClgLlxuICAgKi9cbiAgcHJvdGVjdGVkIHByZXBhcmVDcm9zc1JlZmVyZW5jZShfc291cmNlU3RhY2s6IFN0YWNrLCByZWZlcmVuY2U6IFJlZmVyZW5jZSk6IElSZXNvbHZhYmxlIHtcbiAgICByZXR1cm4gcmVmZXJlbmNlO1xuICB9XG5cbiAgLyoqXG4gICAqIERldGVybWluZSB0aGUgdmFyaW91cyBzdGFjayBlbnZpcm9ubWVudCBhdHRyaWJ1dGVzLlxuICAgKlxuICAgKi9cbiAgcHJpdmF0ZSBwYXJzZUVudmlyb25tZW50KGVudjogRW52aXJvbm1lbnQgPSB7fSkge1xuICAgIC8vIGlmIGFuIGVudmlyb25tZW50IHByb3BlcnR5IGlzIGV4cGxpY2l0bHkgc3BlY2lmaWVkIHdoZW4gdGhlIHN0YWNrIGlzXG4gICAgLy8gY3JlYXRlZCwgaXQgd2lsbCBiZSB1c2VkLiBpZiBub3QsIHVzZSB0b2tlbnMgZm9yIGFjY291bnQgYW5kIHJlZ2lvbi5cbiAgICAvL1xuICAgIC8vIChUaGV5IGRvIG5vdCBuZWVkIHRvIGJlIGFuY2hvcmVkIHRvIGFueSBjb25zdHJ1Y3QgbGlrZSByZXNvdXJjZSBhdHRyaWJ1dGVzXG4gICAgLy8gYXJlLCBiZWNhdXNlIHdlJ2xsIG5ldmVyIEV4cG9ydC9Gbjo6SW1wb3J0VmFsdWUgdGhlbSAtLSB0aGUgb25seSBzaXR1YXRpb25cbiAgICAvLyBpbiB3aGljaCBFeHBvcnQvRm46OkltcG9ydFZhbHVlIHdvdWxkIHdvcmsgaXMgaWYgdGhlIHZhbHVlIGFyZSB0aGUgc2FtZVxuICAgIC8vIGJldHdlZW4gcHJvZHVjZXIgYW5kIGNvbnN1bWVyIGFueXdheSwgc28gd2UgY2FuIGp1c3QgYXNzdW1lIHRoYXQgdGhleSBhcmUpLlxuICAgIGNvbnN0IGNvbnRhaW5pbmdBc3NlbWJseSA9IFN0YWdlLm9mKHRoaXMpO1xuICAgIGNvbnN0IGFjY291bnQgPSBlbnYuYWNjb3VudCA/PyBjb250YWluaW5nQXNzZW1ibHk/LmFjY291bnQgPz8gQXdzLkFDQ09VTlRfSUQ7XG4gICAgY29uc3QgcmVnaW9uID0gZW52LnJlZ2lvbiA/PyBjb250YWluaW5nQXNzZW1ibHk/LnJlZ2lvbiA/PyBBd3MuUkVHSU9OO1xuXG4gICAgLy8gdGhpcyBpcyB0aGUgXCJhd3M6Ly9cIiBlbnYgc3BlY2lmaWNhdGlvbiB0aGF0IHdpbGwgYmUgd3JpdHRlbiB0byB0aGUgY2xvdWQgYXNzZW1ibHlcbiAgICAvLyBtYW5pZmVzdC4gaXQgd2lsbCB1c2UgXCJ1bmtub3duLWFjY291bnRcIiBhbmQgXCJ1bmtub3duLXJlZ2lvblwiIHRvIGluZGljYXRlXG4gICAgLy8gZW52aXJvbm1lbnQtYWdub3N0aWNuZXNzLlxuICAgIGNvbnN0IGVudkFjY291bnQgPSAhVG9rZW4uaXNVbnJlc29sdmVkKGFjY291bnQpID8gYWNjb3VudCA6IGN4YXBpLlVOS05PV05fQUNDT1VOVDtcbiAgICBjb25zdCBlbnZSZWdpb24gPSAhVG9rZW4uaXNVbnJlc29sdmVkKHJlZ2lvbikgPyByZWdpb24gOiBjeGFwaS5VTktOT1dOX1JFR0lPTjtcblxuICAgIHJldHVybiB7XG4gICAgICBhY2NvdW50LFxuICAgICAgcmVnaW9uLFxuICAgICAgZW52aXJvbm1lbnQ6IGN4YXBpLkVudmlyb25tZW50VXRpbHMuZm9ybWF0KGVudkFjY291bnQsIGVudlJlZ2lvbiksXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNYXhpbXVtIG51bWJlciBvZiByZXNvdXJjZXMgaW4gdGhlIHN0YWNrXG4gICAqXG4gICAqIFNldCB0byAwIHRvIG1lYW4gXCJ1bmxpbWl0ZWRcIi5cbiAgICovXG4gIHByaXZhdGUgZ2V0IG1heFJlc291cmNlcygpOiBudW1iZXIge1xuICAgIGNvbnN0IGNvbnRleHRMaW1pdCA9IHRoaXMubm9kZS50cnlHZXRDb250ZXh0KFNUQUNLX1JFU09VUkNFX0xJTUlUX0NPTlRFWFQpO1xuICAgIHJldHVybiBjb250ZXh0TGltaXQgIT09IHVuZGVmaW5lZCA/IHBhcnNlSW50KGNvbnRleHRMaW1pdCwgMTApIDogTUFYX1JFU09VUkNFUztcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayB3aGV0aGVyIHRoaXMgc3RhY2sgaGFzIGEgKHRyYW5zaXRpdmUpIGRlcGVuZGVuY3kgb24gYW5vdGhlciBzdGFja1xuICAgKlxuICAgKiBSZXR1cm5zIHRoZSBsaXN0IG9mIHJlYXNvbnMgb24gdGhlIGRlcGVuZGVuY3kgcGF0aCwgb3IgdW5kZWZpbmVkXG4gICAqIGlmIHRoZXJlIGlzIG5vIGRlcGVuZGVuY3kuXG4gICAqL1xuICBwcml2YXRlIHN0YWNrRGVwZW5kZW5jeVJlYXNvbnMob3RoZXI6IFN0YWNrKTogc3RyaW5nW10gfCB1bmRlZmluZWQge1xuICAgIGlmICh0aGlzID09PSBvdGhlcikgeyByZXR1cm4gW107IH1cbiAgICBmb3IgKGNvbnN0IGRlcCBvZiBPYmplY3QudmFsdWVzKHRoaXMuX3N0YWNrRGVwZW5kZW5jaWVzKSkge1xuICAgICAgY29uc3QgcmV0ID0gZGVwLnN0YWNrLnN0YWNrRGVwZW5kZW5jeVJlYXNvbnMob3RoZXIpO1xuICAgICAgaWYgKHJldCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiBbLi4uZGVwLnJlYXNvbnMsIC4uLnJldF07XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICAvKipcbiAgICogQ2FsY3VsYXRlIHRoZSBzdGFjayBuYW1lIGJhc2VkIG9uIHRoZSBjb25zdHJ1Y3QgcGF0aFxuICAgKlxuICAgKiBUaGUgc3RhY2sgbmFtZSBpcyB0aGUgbmFtZSB1bmRlciB3aGljaCB3ZSdsbCBkZXBsb3kgdGhlIHN0YWNrLFxuICAgKiBhbmQgaW5jb3Jwb3JhdGVzIGNvbnRhaW5pbmcgU3RhZ2UgbmFtZXMgYnkgZGVmYXVsdC5cbiAgICpcbiAgICogR2VuZXJhbGx5IHRoaXMgbG9va3MgYSBsb3QgbGlrZSBob3cgbG9naWNhbCBJRHMgYXJlIGNhbGN1bGF0ZWQuXG4gICAqIFRoZSBzdGFjayBuYW1lIGlzIGNhbGN1bGF0ZWQgYmFzZWQgb24gdGhlIGNvbnN0cnVjdCByb290IHBhdGgsXG4gICAqIGFzIGZvbGxvd3M6XG4gICAqXG4gICAqIC0gUGF0aCBpcyBjYWxjdWxhdGVkIHdpdGggcmVzcGVjdCB0byBjb250YWluaW5nIEFwcCBvciBTdGFnZSAoaWYgYW55KVxuICAgKiAtIElmIHRoZSBwYXRoIGlzIG9uZSBjb21wb25lbnQgbG9uZyBqdXN0IHVzZSB0aGF0IGNvbXBvbmVudCwgb3RoZXJ3aXNlXG4gICAqICAgY29tYmluZSB0aGVtIHdpdGggYSBoYXNoLlxuICAgKlxuICAgKiBTaW5jZSB0aGUgaGFzaCBpcyBxdWl0ZSB1Z2x5IGFuZCB3ZSdkIGxpa2UgdG8gYXZvaWQgaXQgaWYgcG9zc2libGUgLS0gYnV0XG4gICAqIHdlIGNhbid0IGFueW1vcmUgaW4gdGhlIGdlbmVyYWwgY2FzZSBzaW5jZSBpdCBoYXMgYmVlbiB3cml0dGVuIGludG8gbGVnYWN5XG4gICAqIHN0YWNrcy4gVGhlIGludHJvZHVjdGlvbiBvZiBTdGFnZXMgbWFrZXMgaXQgcG9zc2libGUgdG8gbWFrZSB0aGlzIG5pY2VyIGhvd2V2ZXIuXG4gICAqIFdoZW4gYSBTdGFjayBpcyBuZXN0ZWQgaW5zaWRlIGEgU3RhZ2UsIHdlIHVzZSB0aGUgcGF0aCBjb21wb25lbnRzIGJlbG93IHRoZVxuICAgKiBTdGFnZSwgYW5kIHByZWZpeCB0aGUgcGF0aCBjb21wb25lbnRzIG9mIHRoZSBTdGFnZSBiZWZvcmUgaXQuXG4gICAqL1xuICBwcml2YXRlIGdlbmVyYXRlU3RhY2tOYW1lKCkge1xuICAgIGNvbnN0IGFzc2VtYmx5ID0gU3RhZ2Uub2YodGhpcyk7XG4gICAgY29uc3QgcHJlZml4ID0gKGFzc2VtYmx5ICYmIGFzc2VtYmx5LnN0YWdlTmFtZSkgPyBgJHthc3NlbWJseS5zdGFnZU5hbWV9LWAgOiAnJztcbiAgICByZXR1cm4gYCR7cHJlZml4fSR7dGhpcy5nZW5lcmF0ZVN0YWNrSWQoYXNzZW1ibHkpfWA7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGFydGlmYWN0IElEIGZvciB0aGlzIHN0YWNrXG4gICAqXG4gICAqIFN0YWNrIGFydGlmYWN0IElEIGlzIHVuaXF1ZSB3aXRoaW4gdGhlIEFwcCdzIENsb3VkIEFzc2VtYmx5LlxuICAgKi9cbiAgcHJpdmF0ZSBnZW5lcmF0ZVN0YWNrQXJ0aWZhY3RJZCgpIHtcbiAgICByZXR1cm4gdGhpcy5nZW5lcmF0ZVN0YWNrSWQodGhpcy5ub2RlLnJvb3QpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdlbmVyYXRlIGFuIElEIHdpdGggcmVzcGVjdCB0byB0aGUgZ2l2ZW4gY29udGFpbmVyIGNvbnN0cnVjdC5cbiAgICovXG4gIHByaXZhdGUgZ2VuZXJhdGVTdGFja0lkKGNvbnRhaW5lcjogSUNvbnN0cnVjdCB8IHVuZGVmaW5lZCkge1xuICAgIGNvbnN0IHJvb3RQYXRoID0gcm9vdFBhdGhUbyh0aGlzLCBjb250YWluZXIpO1xuICAgIGNvbnN0IGlkcyA9IHJvb3RQYXRoLm1hcChjID0+IE5vZGUub2YoYykuaWQpO1xuXG4gICAgLy8gSW4gdW5pdCB0ZXN0cyBvdXIgU3RhY2sgKHdoaWNoIGlzIHRoZSBvbmx5IGNvbXBvbmVudCkgbWF5IG5vdCBoYXZlIGFuXG4gICAgLy8gaWQsIHNvIGluIHRoYXQgY2FzZSBqdXN0IHByZXRlbmQgaXQncyBcIlN0YWNrXCIuXG4gICAgaWYgKGlkcy5sZW5ndGggPT09IDEgJiYgIWlkc1swXSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCd1bmV4cGVjdGVkOiBzdGFjayBpZCBtdXN0IGFsd2F5cyBiZSBkZWZpbmVkJyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG1ha2VTdGFja05hbWUoaWRzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbmRpY2F0ZXMgd2hldGhlciB0aGUgc3RhY2sgcmVxdWlyZXMgYnVuZGxpbmcgb3Igbm90XG4gICAqL1xuICBwdWJsaWMgZ2V0IGJ1bmRsaW5nUmVxdWlyZWQoKSB7XG4gICAgY29uc3QgYnVuZGxpbmdTdGFja3M6IHN0cmluZ1tdID0gdGhpcy5ub2RlLnRyeUdldENvbnRleHQoY3hhcGkuQlVORExJTkdfU1RBQ0tTKSA/PyBbJyonXTtcblxuICAgIC8vIGJ1bmRsaW5nU3RhY2tzIGlzIG9mIHRoZSBmb3JtIGBTdGFnZS9TdGFja2AsIGNvbnZlcnQgaXQgdG8gYFN0YWdlLVN0YWNrYCBiZWZvcmUgY29tcGFyaW5nIHRvIHN0YWNrIG5hbWVcbiAgICByZXR1cm4gYnVuZGxpbmdTdGFja3Muc29tZShwYXR0ZXJuID0+IG1pbmltYXRjaChcbiAgICAgIHRoaXMuc3RhY2tOYW1lLFxuICAgICAgcGF0dGVybi5yZXBsYWNlKCcvJywgJy0nKSxcbiAgICApKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBtZXJnZSh0ZW1wbGF0ZTogYW55LCBmcmFnbWVudDogYW55KTogdm9pZCB7XG4gIGZvciAoY29uc3Qgc2VjdGlvbiBvZiBPYmplY3Qua2V5cyhmcmFnbWVudCkpIHtcbiAgICBjb25zdCBzcmMgPSBmcmFnbWVudFtzZWN0aW9uXTtcblxuICAgIC8vIGNyZWF0ZSB0b3AtbGV2ZWwgc2VjdGlvbiBpZiBpdCBkb2Vzbid0IGV4aXN0XG4gICAgY29uc3QgZGVzdCA9IHRlbXBsYXRlW3NlY3Rpb25dO1xuICAgIGlmICghZGVzdCkge1xuICAgICAgdGVtcGxhdGVbc2VjdGlvbl0gPSBzcmM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRlbXBsYXRlW3NlY3Rpb25dID0gbWVyZ2VTZWN0aW9uKHNlY3Rpb24sIGRlc3QsIHNyYyk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIG1lcmdlU2VjdGlvbihzZWN0aW9uOiBzdHJpbmcsIHZhbDE6IGFueSwgdmFsMjogYW55KTogYW55IHtcbiAgc3dpdGNoIChzZWN0aW9uKSB7XG4gICAgY2FzZSAnRGVzY3JpcHRpb24nOlxuICAgICAgcmV0dXJuIGAke3ZhbDF9XFxuJHt2YWwyfWA7XG4gICAgY2FzZSAnQVdTVGVtcGxhdGVGb3JtYXRWZXJzaW9uJzpcbiAgICAgIGlmICh2YWwxICE9IG51bGwgJiYgdmFsMiAhPSBudWxsICYmIHZhbDEgIT09IHZhbDIpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDb25mbGljdGluZyBDbG91ZEZvcm1hdGlvbiB0ZW1wbGF0ZSB2ZXJzaW9ucyBwcm92aWRlZDogJyR7dmFsMX0nIGFuZCAnJHt2YWwyfWApO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHZhbDEgPz8gdmFsMjtcbiAgICBjYXNlICdUcmFuc2Zvcm0nOlxuICAgICAgcmV0dXJuIG1lcmdlU2V0cyh2YWwxLCB2YWwyKTtcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIG1lcmdlT2JqZWN0c1dpdGhvdXREdXBsaWNhdGVzKHNlY3Rpb24sIHZhbDEsIHZhbDIpO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1lcmdlU2V0cyh2YWwxOiBhbnksIHZhbDI6IGFueSk6IGFueSB7XG4gIGNvbnN0IGFycmF5MSA9IHZhbDEgPT0gbnVsbCA/IFtdIDogKEFycmF5LmlzQXJyYXkodmFsMSkgPyB2YWwxIDogW3ZhbDFdKTtcbiAgY29uc3QgYXJyYXkyID0gdmFsMiA9PSBudWxsID8gW10gOiAoQXJyYXkuaXNBcnJheSh2YWwyKSA/IHZhbDIgOiBbdmFsMl0pO1xuICBmb3IgKGNvbnN0IHZhbHVlIG9mIGFycmF5Mikge1xuICAgIGlmICghYXJyYXkxLmluY2x1ZGVzKHZhbHVlKSkge1xuICAgICAgYXJyYXkxLnB1c2godmFsdWUpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gYXJyYXkxLmxlbmd0aCA9PT0gMSA/IGFycmF5MVswXSA6IGFycmF5MTtcbn1cblxuZnVuY3Rpb24gbWVyZ2VPYmplY3RzV2l0aG91dER1cGxpY2F0ZXMoc2VjdGlvbjogc3RyaW5nLCBkZXN0OiBhbnksIHNyYzogYW55KTogYW55IHtcbiAgaWYgKHR5cGVvZiBkZXN0ICE9PSAnb2JqZWN0Jykge1xuICAgIHRocm93IG5ldyBFcnJvcihgRXhwZWN0aW5nICR7SlNPTi5zdHJpbmdpZnkoZGVzdCl9IHRvIGJlIGFuIG9iamVjdGApO1xuICB9XG4gIGlmICh0eXBlb2Ygc3JjICE9PSAnb2JqZWN0Jykge1xuICAgIHRocm93IG5ldyBFcnJvcihgRXhwZWN0aW5nICR7SlNPTi5zdHJpbmdpZnkoc3JjKX0gdG8gYmUgYW4gb2JqZWN0YCk7XG4gIH1cblxuICAvLyBhZGQgYWxsIGVudGl0aWVzIGZyb20gc291cmNlIHNlY3Rpb24gdG8gZGVzdGluYXRpb24gc2VjdGlvblxuICBmb3IgKGNvbnN0IGlkIG9mIE9iamVjdC5rZXlzKHNyYykpIHtcbiAgICBpZiAoaWQgaW4gZGVzdCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBzZWN0aW9uICcke3NlY3Rpb259JyBhbHJlYWR5IGNvbnRhaW5zICcke2lkfSdgKTtcbiAgICB9XG4gICAgZGVzdFtpZF0gPSBzcmNbaWRdO1xuICB9XG5cbiAgcmV0dXJuIGRlc3Q7XG59XG5cbi8qKlxuICogQ2xvdWRGb3JtYXRpb24gdGVtcGxhdGUgb3B0aW9ucyBmb3IgYSBzdGFjay5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJVGVtcGxhdGVPcHRpb25zIHtcbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgZGVzY3JpcHRpb24gb2YgdGhpcyBzdGFjay5cbiAgICogSWYgcHJvdmlkZWQsIGl0IHdpbGwgYmUgaW5jbHVkZWQgaW4gdGhlIENsb3VkRm9ybWF0aW9uIHRlbXBsYXRlJ3MgXCJEZXNjcmlwdGlvblwiIGF0dHJpYnV0ZS5cbiAgICovXG4gIGRlc2NyaXB0aW9uPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBHZXRzIG9yIHNldHMgdGhlIEFXU1RlbXBsYXRlRm9ybWF0VmVyc2lvbiBmaWVsZCBvZiB0aGUgQ2xvdWRGb3JtYXRpb24gdGVtcGxhdGUuXG4gICAqL1xuICB0ZW1wbGF0ZUZvcm1hdFZlcnNpb24/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgdG9wLWxldmVsIHRlbXBsYXRlIHRyYW5zZm9ybSBmb3IgdGhpcyBzdGFjayAoZS5nLiBcIkFXUzo6U2VydmVybGVzcy0yMDE2LTEwLTMxXCIpLlxuICAgKlxuICAgKiBAZGVwcmVjYXRlZCB1c2UgYHRyYW5zZm9ybXNgIGluc3RlYWQuXG4gICAqL1xuICB0cmFuc2Zvcm0/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEdldHMgb3Igc2V0cyB0aGUgdG9wLWxldmVsIHRlbXBsYXRlIHRyYW5zZm9ybShzKSBmb3IgdGhpcyBzdGFjayAoZS5nLiBgW1wiQVdTOjpTZXJ2ZXJsZXNzLTIwMTYtMTAtMzFcIl1gKS5cbiAgICovXG4gIHRyYW5zZm9ybXM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogTWV0YWRhdGEgYXNzb2NpYXRlZCB3aXRoIHRoZSBDbG91ZEZvcm1hdGlvbiB0ZW1wbGF0ZS5cbiAgICovXG4gIG1ldGFkYXRhPzogeyBba2V5OiBzdHJpbmddOiBhbnkgfTtcbn1cblxuLyoqXG4gKiBDb2xsZWN0IGFsbCBDZm5FbGVtZW50cyBmcm9tIGEgU3RhY2suXG4gKlxuICogQHBhcmFtIG5vZGUgUm9vdCBub2RlIHRvIGNvbGxlY3QgYWxsIENmbkVsZW1lbnRzIGZyb21cbiAqIEBwYXJhbSBpbnRvIEFycmF5IHRvIGFwcGVuZCBDZm5FbGVtZW50cyB0b1xuICogQHJldHVybnMgVGhlIHNhbWUgYXJyYXkgYXMgaXMgYmVpbmcgY29sbGVjdGVkIGludG9cbiAqL1xuZnVuY3Rpb24gY2ZuRWxlbWVudHMobm9kZTogSUNvbnN0cnVjdCwgaW50bzogQ2ZuRWxlbWVudFtdID0gW10pOiBDZm5FbGVtZW50W10ge1xuICBpZiAoQ2ZuRWxlbWVudC5pc0NmbkVsZW1lbnQobm9kZSkpIHtcbiAgICBpbnRvLnB1c2gobm9kZSk7XG4gIH1cblxuICBmb3IgKGNvbnN0IGNoaWxkIG9mIE5vZGUub2Yobm9kZSkuY2hpbGRyZW4pIHtcbiAgICAvLyBEb24ndCByZWN1cnNlIGludG8gYSBzdWJzdGFja1xuICAgIGlmIChTdGFjay5pc1N0YWNrKGNoaWxkKSkgeyBjb250aW51ZTsgfVxuXG4gICAgY2ZuRWxlbWVudHMoY2hpbGQsIGludG8pO1xuICB9XG5cbiAgcmV0dXJuIGludG87XG59XG5cbi8qKlxuICogUmV0dXJuIHRoZSBjb25zdHJ1Y3Qgcm9vdCBwYXRoIG9mIHRoZSBnaXZlbiBjb25zdHJ1Y3QgcmVsYXRpdmUgdG8gdGhlIGdpdmVuIGFuY2VzdG9yXG4gKlxuICogSWYgbm8gYW5jZXN0b3IgaXMgZ2l2ZW4gb3IgdGhlIGFuY2VzdG9yIGlzIG5vdCBmb3VuZCwgcmV0dXJuIHRoZSBlbnRpcmUgcm9vdCBwYXRoLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcm9vdFBhdGhUbyhjb25zdHJ1Y3Q6IElDb25zdHJ1Y3QsIGFuY2VzdG9yPzogSUNvbnN0cnVjdCk6IElDb25zdHJ1Y3RbXSB7XG4gIGNvbnN0IHNjb3BlcyA9IE5vZGUub2YoY29uc3RydWN0KS5zY29wZXM7XG4gIGZvciAobGV0IGkgPSBzY29wZXMubGVuZ3RoIC0gMjsgaSA+PSAwOyBpLS0pIHtcbiAgICBpZiAoc2NvcGVzW2ldID09PSBhbmNlc3Rvcikge1xuICAgICAgcmV0dXJuIHNjb3Blcy5zbGljZShpICsgMSk7XG4gICAgfVxuICB9XG4gIHJldHVybiBzY29wZXM7XG59XG5cbi8qKlxuICogbWFrZVVuaXF1ZUlkLCBzcGVjaWFsaXplZCBmb3IgU3RhY2sgbmFtZXNcbiAqXG4gKiBTdGFjayBuYW1lcyBtYXkgY29udGFpbiAnLScsIHNvIHdlIGFsbG93IHRoYXQgY2hhcmFjdGVyIGlmIHRoZSBzdGFjayBuYW1lXG4gKiBoYXMgb25seSBvbmUgY29tcG9uZW50LiBPdGhlcndpc2Ugd2UgZmFsbCBiYWNrIHRvIHRoZSByZWd1bGFyIFwibWFrZVVuaXF1ZUlkXCJcbiAqIGJlaGF2aW9yLlxuICovXG5mdW5jdGlvbiBtYWtlU3RhY2tOYW1lKGNvbXBvbmVudHM6IHN0cmluZ1tdKSB7XG4gIGlmIChjb21wb25lbnRzLmxlbmd0aCA9PT0gMSkgeyByZXR1cm4gY29tcG9uZW50c1swXTsgfVxuICByZXR1cm4gbWFrZVVuaXF1ZUlkKGNvbXBvbmVudHMpO1xufVxuXG5mdW5jdGlvbiBnZXRDcmVhdGVFeHBvcnRzU2NvcGUoc3RhY2s6IFN0YWNrKSB7XG4gIGNvbnN0IGV4cG9ydHNOYW1lID0gJ0V4cG9ydHMnO1xuICBsZXQgc3RhY2tFeHBvcnRzID0gc3RhY2subm9kZS50cnlGaW5kQ2hpbGQoZXhwb3J0c05hbWUpIGFzIENvcmVDb25zdHJ1Y3Q7XG4gIGlmIChzdGFja0V4cG9ydHMgPT09IHVuZGVmaW5lZCkge1xuICAgIHN0YWNrRXhwb3J0cyA9IG5ldyBDb3JlQ29uc3RydWN0KHN0YWNrLCBleHBvcnRzTmFtZSk7XG4gIH1cblxuICByZXR1cm4gc3RhY2tFeHBvcnRzO1xufVxuXG5mdW5jdGlvbiBnZW5lcmF0ZUV4cG9ydE5hbWUoc3RhY2tFeHBvcnRzOiBDb3JlQ29uc3RydWN0LCBpZDogc3RyaW5nKSB7XG4gIGNvbnN0IHN0YWNrUmVsYXRpdmVFeHBvcnRzID0gRmVhdHVyZUZsYWdzLm9mKHN0YWNrRXhwb3J0cykuaXNFbmFibGVkKGN4YXBpLlNUQUNLX1JFTEFUSVZFX0VYUE9SVFNfQ09OVEVYVCk7XG4gIGNvbnN0IHN0YWNrID0gU3RhY2sub2Yoc3RhY2tFeHBvcnRzKTtcblxuICBjb25zdCBjb21wb25lbnRzID0gW1xuICAgIC4uLnN0YWNrRXhwb3J0cy5ub2RlLnNjb3Blc1xuICAgICAgLnNsaWNlKHN0YWNrUmVsYXRpdmVFeHBvcnRzID8gc3RhY2subm9kZS5zY29wZXMubGVuZ3RoIDogMilcbiAgICAgIC5tYXAoYyA9PiBjLm5vZGUuaWQpLFxuICAgIGlkLFxuICBdO1xuICBjb25zdCBwcmVmaXggPSBzdGFjay5zdGFja05hbWUgPyBzdGFjay5zdGFja05hbWUgKyAnOicgOiAnJztcbiAgY29uc3QgbG9jYWxQYXJ0ID0gbWFrZVVuaXF1ZUlkKGNvbXBvbmVudHMpO1xuICBjb25zdCBtYXhMZW5ndGggPSAyNTU7XG4gIHJldHVybiBwcmVmaXggKyBsb2NhbFBhcnQuc2xpY2UoTWF0aC5tYXgoMCwgbG9jYWxQYXJ0Lmxlbmd0aCAtIG1heExlbmd0aCArIHByZWZpeC5sZW5ndGgpKTtcbn1cblxuaW50ZXJmYWNlIFN0YWNrRGVwZW5kZW5jeSB7XG4gIHN0YWNrOiBTdGFjaztcbiAgcmVhc29uczogc3RyaW5nW107XG59XG5cbi8qKlxuICogT3B0aW9ucyBmb3IgdGhlIGBzdGFjay5leHBvcnRWYWx1ZSgpYCBtZXRob2RcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBFeHBvcnRWYWx1ZU9wdGlvbnMge1xuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIGV4cG9ydCB0byBjcmVhdGVcbiAgICpcbiAgICogQGRlZmF1bHQgLSBBIG5hbWUgaXMgYXV0b21hdGljYWxseSBjaG9zZW5cbiAgICovXG4gIHJlYWRvbmx5IG5hbWU/OiBzdHJpbmc7XG59XG5cbmZ1bmN0aW9uIGNvdW50KHhzOiBzdHJpbmdbXSk6IFJlY29yZDxzdHJpbmcsIG51bWJlcj4ge1xuICBjb25zdCByZXQ6IFJlY29yZDxzdHJpbmcsIG51bWJlcj4gPSB7fTtcbiAgZm9yIChjb25zdCB4IG9mIHhzKSB7XG4gICAgaWYgKHggaW4gcmV0KSB7XG4gICAgICByZXRbeF0gKz0gMTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0W3hdID0gMTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJldDtcbn1cblxuLy8gVGhlc2UgaW1wb3J0cyBoYXZlIHRvIGJlIGF0IHRoZSBlbmQgdG8gcHJldmVudCBjaXJjdWxhciBpbXBvcnRzXG5pbXBvcnQgeyBDZm5PdXRwdXQgfSBmcm9tICcuL2Nmbi1vdXRwdXQnO1xuaW1wb3J0IHsgYWRkRGVwZW5kZW5jeSB9IGZyb20gJy4vZGVwcyc7XG5pbXBvcnQgeyBGaWxlU3lzdGVtIH0gZnJvbSAnLi9mcyc7XG5pbXBvcnQgeyBOYW1lcyB9IGZyb20gJy4vbmFtZXMnO1xuaW1wb3J0IHsgUmVmZXJlbmNlIH0gZnJvbSAnLi9yZWZlcmVuY2UnO1xuaW1wb3J0IHsgSVJlc29sdmFibGUgfSBmcm9tICcuL3Jlc29sdmFibGUnO1xuaW1wb3J0IHsgRGVmYXVsdFN0YWNrU3ludGhlc2l6ZXIsIElTdGFja1N5bnRoZXNpemVyLCBMZWdhY3lTdGFja1N5bnRoZXNpemVyIH0gZnJvbSAnLi9zdGFjay1zeW50aGVzaXplcnMnO1xuaW1wb3J0IHsgU3RhZ2UgfSBmcm9tICcuL3N0YWdlJztcbmltcG9ydCB7IElUYWdnYWJsZSwgVGFnTWFuYWdlciB9IGZyb20gJy4vdGFnLW1hbmFnZXInO1xuaW1wb3J0IHsgVG9rZW4sIFRva2VuaXphdGlvbiB9IGZyb20gJy4vdG9rZW4nO1xuaW1wb3J0IHsgcmVmZXJlbmNlTmVzdGVkU3RhY2tWYWx1ZUluUGFyZW50IH0gZnJvbSAnLi9wcml2YXRlL3JlZnMnO1xuaW1wb3J0IHsgRmFjdCwgUmVnaW9uSW5mbyB9IGZyb20gJ0Bhd3MtY2RrL3JlZ2lvbi1pbmZvJztcbmltcG9ydCB7IGRlcGxveVRpbWVMb29rdXAgfSBmcm9tICcuL3ByaXZhdGUvcmVnaW9uLWxvb2t1cCc7XG5cbiJdfQ== |
\ | No newline at end of file |