1 | ;
|
2 | var _a;
|
3 | Object.defineProperty(exports, "__esModule", { value: true });
|
4 | exports.Effect = exports.PolicyStatement = void 0;
|
5 | const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
|
6 | const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
7 | const cdk = require("@aws-cdk/core");
|
8 | const group_1 = require("./group");
|
9 | const principals_1 = require("./principals");
|
10 | const postprocess_policy_document_1 = require("./private/postprocess-policy-document");
|
11 | const util_1 = require("./util");
|
12 | const ensureArrayOrUndefined = (field) => {
|
13 | if (field === undefined) {
|
14 | return undefined;
|
15 | }
|
16 | if (typeof (field) !== 'string' && !Array.isArray(field)) {
|
17 | throw new Error('Fields must be either a string or an array of strings');
|
18 | }
|
19 | if (Array.isArray(field) && !!field.find((f) => typeof (f) !== 'string')) {
|
20 | throw new Error('Fields must be either a string or an array of strings');
|
21 | }
|
22 | return Array.isArray(field) ? field : [field];
|
23 | };
|
24 | /**
|
25 | * Represents a statement in an IAM policy document.
|
26 | */
|
27 | class PolicyStatement {
|
28 | constructor(props = {}) {
|
29 | this.action = new Array();
|
30 | this.notAction = new Array();
|
31 | this.principal = {};
|
32 | this.notPrincipal = {};
|
33 | this.resource = new Array();
|
34 | this.notResource = new Array();
|
35 | this.condition = {};
|
36 | // Hold on to those principals
|
37 | this._principals = new Array();
|
38 | try {
|
39 | jsiiDeprecationWarnings._aws_cdk_aws_iam_PolicyStatementProps(props);
|
40 | }
|
41 | catch (error) {
|
42 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
43 | Error.captureStackTrace(error, this.constructor);
|
44 | }
|
45 | throw error;
|
46 | }
|
47 | // Validate actions
|
48 | for (const action of [...props.actions || [], ...props.notActions || []]) {
|
49 | if (!/^(\*|[a-zA-Z0-9-]+:[a-zA-Z0-9*]+)$/.test(action) && !cdk.Token.isUnresolved(action)) {
|
50 | throw new Error(`Action '${action}' is invalid. An action string consists of a service namespace, a colon, and the name of an action. Action names can include wildcards.`);
|
51 | }
|
52 | }
|
53 | this.sid = props.sid;
|
54 | this.effect = props.effect || Effect.ALLOW;
|
55 | this.addActions(...props.actions || []);
|
56 | this.addNotActions(...props.notActions || []);
|
57 | this.addPrincipals(...props.principals || []);
|
58 | this.addNotPrincipals(...props.notPrincipals || []);
|
59 | this.addResources(...props.resources || []);
|
60 | this.addNotResources(...props.notResources || []);
|
61 | if (props.conditions !== undefined) {
|
62 | this.addConditions(props.conditions);
|
63 | }
|
64 | }
|
65 | /**
|
66 | * Creates a new PolicyStatement based on the object provided.
|
67 | * This will accept an object created from the `.toJSON()` call
|
68 | * @param obj the PolicyStatement in object form.
|
69 | */
|
70 | static fromJson(obj) {
|
71 | const ret = new PolicyStatement({
|
72 | sid: obj.Sid,
|
73 | actions: ensureArrayOrUndefined(obj.Action),
|
74 | resources: ensureArrayOrUndefined(obj.Resource),
|
75 | conditions: obj.Condition,
|
76 | effect: obj.Effect,
|
77 | notActions: ensureArrayOrUndefined(obj.NotAction),
|
78 | notResources: ensureArrayOrUndefined(obj.NotResource),
|
79 | principals: obj.Principal ? [new JsonPrincipal(obj.Principal)] : undefined,
|
80 | notPrincipals: obj.NotPrincipal ? [new JsonPrincipal(obj.NotPrincipal)] : undefined,
|
81 | });
|
82 | // validate that the PolicyStatement has the correct shape
|
83 | const errors = ret.validateForAnyPolicy();
|
84 | if (errors.length > 0) {
|
85 | throw new Error('Incorrect Policy Statement: ' + errors.join('\n'));
|
86 | }
|
87 | return ret;
|
88 | }
|
89 | //
|
90 | // Actions
|
91 | //
|
92 | /**
|
93 | * Specify allowed actions into the "Action" section of the policy statement.
|
94 | *
|
95 | * @see https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_action.html
|
96 | *
|
97 | * @param actions actions that will be allowed.
|
98 | */
|
99 | addActions(...actions) {
|
100 | if (actions.length > 0 && this.notAction.length > 0) {
|
101 | throw new Error('Cannot add \'Actions\' to policy statement if \'NotActions\' have been added');
|
102 | }
|
103 | this.action.push(...actions);
|
104 | }
|
105 | /**
|
106 | * Explicitly allow all actions except the specified list of actions into the "NotAction" section
|
107 | * of the policy document.
|
108 | *
|
109 | * @see https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notaction.html
|
110 | *
|
111 | * @param notActions actions that will be denied. All other actions will be permitted.
|
112 | */
|
113 | addNotActions(...notActions) {
|
114 | if (notActions.length > 0 && this.action.length > 0) {
|
115 | throw new Error('Cannot add \'NotActions\' to policy statement if \'Actions\' have been added');
|
116 | }
|
117 | this.notAction.push(...notActions);
|
118 | }
|
119 | //
|
120 | // Principal
|
121 | //
|
122 | /**
|
123 | * Indicates if this permission has a "Principal" section.
|
124 | */
|
125 | get hasPrincipal() {
|
126 | return Object.keys(this.principal).length > 0 || Object.keys(this.notPrincipal).length > 0;
|
127 | }
|
128 | /**
|
129 | * Adds principals to the "Principal" section of a policy statement.
|
130 | *
|
131 | * @see https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_principal.html
|
132 | *
|
133 | * @param principals IAM principals that will be added
|
134 | */
|
135 | addPrincipals(...principals) {
|
136 | try {
|
137 | jsiiDeprecationWarnings._aws_cdk_aws_iam_IPrincipal(principals);
|
138 | }
|
139 | catch (error) {
|
140 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
141 | Error.captureStackTrace(error, this.addPrincipals);
|
142 | }
|
143 | throw error;
|
144 | }
|
145 | this._principals.push(...principals);
|
146 | if (Object.keys(principals).length > 0 && Object.keys(this.notPrincipal).length > 0) {
|
147 | throw new Error('Cannot add \'Principals\' to policy statement if \'NotPrincipals\' have been added');
|
148 | }
|
149 | for (const principal of principals) {
|
150 | this.validatePolicyPrincipal(principal);
|
151 | const fragment = principal.policyFragment;
|
152 | util_1.mergePrincipal(this.principal, fragment.principalJson);
|
153 | this.addPrincipalConditions(fragment.conditions);
|
154 | }
|
155 | }
|
156 | /**
|
157 | * Expose principals to allow their ARNs to be replaced by account ID strings
|
158 | * in policy statements for resources policies that don't allow full account ARNs,
|
159 | * such as AWS::Logs::ResourcePolicy.
|
160 | */
|
161 | get principals() {
|
162 | return [...this._principals];
|
163 | }
|
164 | /**
|
165 | * Specify principals that is not allowed or denied access to the "NotPrincipal" section of
|
166 | * a policy statement.
|
167 | *
|
168 | * @see https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notprincipal.html
|
169 | *
|
170 | * @param notPrincipals IAM principals that will be denied access
|
171 | */
|
172 | addNotPrincipals(...notPrincipals) {
|
173 | try {
|
174 | jsiiDeprecationWarnings._aws_cdk_aws_iam_IPrincipal(notPrincipals);
|
175 | }
|
176 | catch (error) {
|
177 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
178 | Error.captureStackTrace(error, this.addNotPrincipals);
|
179 | }
|
180 | throw error;
|
181 | }
|
182 | if (Object.keys(notPrincipals).length > 0 && Object.keys(this.principal).length > 0) {
|
183 | throw new Error('Cannot add \'NotPrincipals\' to policy statement if \'Principals\' have been added');
|
184 | }
|
185 | for (const notPrincipal of notPrincipals) {
|
186 | this.validatePolicyPrincipal(notPrincipal);
|
187 | const fragment = notPrincipal.policyFragment;
|
188 | util_1.mergePrincipal(this.notPrincipal, fragment.principalJson);
|
189 | this.addPrincipalConditions(fragment.conditions);
|
190 | }
|
191 | }
|
192 | validatePolicyPrincipal(principal) {
|
193 | if (principal instanceof group_1.Group) {
|
194 | throw new Error('Cannot use an IAM Group as the \'Principal\' or \'NotPrincipal\' in an IAM Policy');
|
195 | }
|
196 | }
|
197 | /**
|
198 | * Specify AWS account ID as the principal entity to the "Principal" section of a policy statement.
|
199 | */
|
200 | addAwsAccountPrincipal(accountId) {
|
201 | this.addPrincipals(new principals_1.AccountPrincipal(accountId));
|
202 | }
|
203 | /**
|
204 | * Specify a principal using the ARN identifier of the principal.
|
205 | * You cannot specify IAM groups and instance profiles as principals.
|
206 | *
|
207 | * @param arn ARN identifier of AWS account, IAM user, or IAM role (i.e. arn:aws:iam::123456789012:user/user-name)
|
208 | */
|
209 | addArnPrincipal(arn) {
|
210 | this.addPrincipals(new principals_1.ArnPrincipal(arn));
|
211 | }
|
212 | /**
|
213 | * Adds a service principal to this policy statement.
|
214 | *
|
215 | * @param service the service name for which a service principal is requested (e.g: `s3.amazonaws.com`).
|
216 | * @param opts options for adding the service principal (such as specifying a principal in a different region)
|
217 | */
|
218 | addServicePrincipal(service, opts) {
|
219 | try {
|
220 | jsiiDeprecationWarnings._aws_cdk_aws_iam_ServicePrincipalOpts(opts);
|
221 | }
|
222 | catch (error) {
|
223 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
224 | Error.captureStackTrace(error, this.addServicePrincipal);
|
225 | }
|
226 | throw error;
|
227 | }
|
228 | this.addPrincipals(new principals_1.ServicePrincipal(service, opts));
|
229 | }
|
230 | /**
|
231 | * Adds a federated identity provider such as Amazon Cognito to this policy statement.
|
232 | *
|
233 | * @param federated federated identity provider (i.e. 'cognito-identity.amazonaws.com')
|
234 | * @param conditions The conditions under which the policy is in effect.
|
235 | * See [the IAM documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition.html).
|
236 | */
|
237 | addFederatedPrincipal(federated, conditions) {
|
238 | this.addPrincipals(new principals_1.FederatedPrincipal(federated, conditions));
|
239 | }
|
240 | /**
|
241 | * Adds an AWS account root user principal to this policy statement
|
242 | */
|
243 | addAccountRootPrincipal() {
|
244 | this.addPrincipals(new principals_1.AccountRootPrincipal());
|
245 | }
|
246 | /**
|
247 | * Adds a canonical user ID principal to this policy document
|
248 | *
|
249 | * @param canonicalUserId unique identifier assigned by AWS for every account
|
250 | */
|
251 | addCanonicalUserPrincipal(canonicalUserId) {
|
252 | this.addPrincipals(new principals_1.CanonicalUserPrincipal(canonicalUserId));
|
253 | }
|
254 | /**
|
255 | * Adds all identities in all accounts ("*") to this policy statement
|
256 | */
|
257 | addAnyPrincipal() {
|
258 | this.addPrincipals(new principals_1.AnyPrincipal());
|
259 | }
|
260 | //
|
261 | // Resources
|
262 | //
|
263 | /**
|
264 | * Specify resources that this policy statement applies into the "Resource" section of
|
265 | * this policy statement.
|
266 | *
|
267 | * @see https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_resource.html
|
268 | *
|
269 | * @param arns Amazon Resource Names (ARNs) of the resources that this policy statement applies to
|
270 | */
|
271 | addResources(...arns) {
|
272 | if (arns.length > 0 && this.notResource.length > 0) {
|
273 | throw new Error('Cannot add \'Resources\' to policy statement if \'NotResources\' have been added');
|
274 | }
|
275 | this.resource.push(...arns);
|
276 | }
|
277 | /**
|
278 | * Specify resources that this policy statement will not apply to in the "NotResource" section
|
279 | * of this policy statement. All resources except the specified list will be matched.
|
280 | *
|
281 | * @see https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_notresource.html
|
282 | *
|
283 | * @param arns Amazon Resource Names (ARNs) of the resources that this policy statement does not apply to
|
284 | */
|
285 | addNotResources(...arns) {
|
286 | if (arns.length > 0 && this.resource.length > 0) {
|
287 | throw new Error('Cannot add \'NotResources\' to policy statement if \'Resources\' have been added');
|
288 | }
|
289 | this.notResource.push(...arns);
|
290 | }
|
291 | /**
|
292 | * Adds a ``"*"`` resource to this statement.
|
293 | */
|
294 | addAllResources() {
|
295 | this.addResources('*');
|
296 | }
|
297 | /**
|
298 | * Indicates if this permission has at least one resource associated with it.
|
299 | */
|
300 | get hasResource() {
|
301 | return this.resource && this.resource.length > 0;
|
302 | }
|
303 | //
|
304 | // Condition
|
305 | //
|
306 | /**
|
307 | * Add a condition to the Policy
|
308 | *
|
309 | * If multiple calls are made to add a condition with the same operator and field, only
|
310 | * the last one wins. For example:
|
311 | *
|
312 | * ```ts
|
313 | * declare const stmt: iam.PolicyStatement;
|
314 | *
|
315 | * stmt.addCondition('StringEquals', { 'aws:SomeField': '1' });
|
316 | * stmt.addCondition('StringEquals', { 'aws:SomeField': '2' });
|
317 | * ```
|
318 | *
|
319 | * Will end up with the single condition `StringEquals: { 'aws:SomeField': '2' }`.
|
320 | *
|
321 | * If you meant to add a condition to say that the field can be *either* `1` or `2`, write
|
322 | * this:
|
323 | *
|
324 | * ```ts
|
325 | * declare const stmt: iam.PolicyStatement;
|
326 | *
|
327 | * stmt.addCondition('StringEquals', { 'aws:SomeField': ['1', '2'] });
|
328 | * ```
|
329 | */
|
330 | addCondition(key, value) {
|
331 | const existingValue = this.condition[key];
|
332 | this.condition[key] = existingValue ? { ...existingValue, ...value } : value;
|
333 | }
|
334 | /**
|
335 | * Add multiple conditions to the Policy
|
336 | *
|
337 | * See the `addCondition` function for a caveat on calling this method multiple times.
|
338 | */
|
339 | addConditions(conditions) {
|
340 | Object.keys(conditions).map(key => {
|
341 | this.addCondition(key, conditions[key]);
|
342 | });
|
343 | }
|
344 | /**
|
345 | * Add a condition that limits to a given account
|
346 | *
|
347 | * This method can only be called once: subsequent calls will overwrite earlier calls.
|
348 | */
|
349 | addAccountCondition(accountId) {
|
350 | this.addCondition('StringEquals', { 'sts:ExternalId': accountId });
|
351 | }
|
352 | /**
|
353 | * Create a new `PolicyStatement` with the same exact properties
|
354 | * as this one, except for the overrides
|
355 | */
|
356 | copy(overrides = {}) {
|
357 | var _b, _c, _d, _e, _f, _g;
|
358 | try {
|
359 | jsiiDeprecationWarnings._aws_cdk_aws_iam_PolicyStatementProps(overrides);
|
360 | }
|
361 | catch (error) {
|
362 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
363 | Error.captureStackTrace(error, this.copy);
|
364 | }
|
365 | throw error;
|
366 | }
|
367 | return new PolicyStatement({
|
368 | sid: (_b = overrides.sid) !== null && _b !== void 0 ? _b : this.sid,
|
369 | effect: (_c = overrides.effect) !== null && _c !== void 0 ? _c : this.effect,
|
370 | actions: (_d = overrides.actions) !== null && _d !== void 0 ? _d : this.action,
|
371 | notActions: (_e = overrides.notActions) !== null && _e !== void 0 ? _e : this.notAction,
|
372 | principals: overrides.principals,
|
373 | notPrincipals: overrides.notPrincipals,
|
374 | resources: (_f = overrides.resources) !== null && _f !== void 0 ? _f : this.resource,
|
375 | notResources: (_g = overrides.notResources) !== null && _g !== void 0 ? _g : this.notResource,
|
376 | });
|
377 | }
|
378 | /**
|
379 | * JSON-ify the policy statement
|
380 | *
|
381 | * Used when JSON.stringify() is called
|
382 | */
|
383 | toStatementJson() {
|
384 | return postprocess_policy_document_1.normalizeStatement({
|
385 | Action: this.action,
|
386 | NotAction: this.notAction,
|
387 | Condition: this.condition,
|
388 | Effect: this.effect,
|
389 | Principal: this.principal,
|
390 | NotPrincipal: this.notPrincipal,
|
391 | Resource: this.resource,
|
392 | NotResource: this.notResource,
|
393 | Sid: this.sid,
|
394 | });
|
395 | }
|
396 | /**
|
397 | * String representation of this policy statement
|
398 | */
|
399 | toString() {
|
400 | return cdk.Token.asString(this, {
|
401 | displayHint: 'PolicyStatement',
|
402 | });
|
403 | }
|
404 | /**
|
405 | * JSON-ify the statement
|
406 | *
|
407 | * Used when JSON.stringify() is called
|
408 | */
|
409 | toJSON() {
|
410 | return this.toStatementJson();
|
411 | }
|
412 | /**
|
413 | * Add a principal's conditions
|
414 | *
|
415 | * For convenience, principals have been modeled as both a principal
|
416 | * and a set of conditions. This makes it possible to have a single
|
417 | * object represent e.g. an "SNS Topic" (SNS service principal + aws:SourcArn
|
418 | * condition) or an Organization member (* + aws:OrgId condition).
|
419 | *
|
420 | * However, when using multiple principals in the same policy statement,
|
421 | * they must all have the same conditions or the OR samentics
|
422 | * implied by a list of principals cannot be guaranteed (user needs to
|
423 | * add multiple statements in that case).
|
424 | */
|
425 | addPrincipalConditions(conditions) {
|
426 | // Stringifying the conditions is an easy way to do deep equality
|
427 | const theseConditions = JSON.stringify(conditions);
|
428 | if (this.principalConditionsJson === undefined) {
|
429 | // First principal, anything goes
|
430 | this.principalConditionsJson = theseConditions;
|
431 | }
|
432 | else {
|
433 | if (this.principalConditionsJson !== theseConditions) {
|
434 | throw new Error(`All principals in a PolicyStatement must have the same Conditions (got '${this.principalConditionsJson}' and '${theseConditions}'). Use multiple statements instead.`);
|
435 | }
|
436 | }
|
437 | this.addConditions(conditions);
|
438 | }
|
439 | /**
|
440 | * Validate that the policy statement satisfies base requirements for a policy.
|
441 | */
|
442 | validateForAnyPolicy() {
|
443 | const errors = new Array();
|
444 | if (this.action.length === 0 && this.notAction.length === 0) {
|
445 | errors.push('A PolicyStatement must specify at least one \'action\' or \'notAction\'.');
|
446 | }
|
447 | return errors;
|
448 | }
|
449 | /**
|
450 | * Validate that the policy statement satisfies all requirements for a resource-based policy.
|
451 | */
|
452 | validateForResourcePolicy() {
|
453 | const errors = this.validateForAnyPolicy();
|
454 | if (Object.keys(this.principal).length === 0 && Object.keys(this.notPrincipal).length === 0) {
|
455 | errors.push('A PolicyStatement used in a resource-based policy must specify at least one IAM principal.');
|
456 | }
|
457 | return errors;
|
458 | }
|
459 | /**
|
460 | * Validate that the policy statement satisfies all requirements for an identity-based policy.
|
461 | */
|
462 | validateForIdentityPolicy() {
|
463 | const errors = this.validateForAnyPolicy();
|
464 | if (Object.keys(this.principal).length > 0 || Object.keys(this.notPrincipal).length > 0) {
|
465 | errors.push('A PolicyStatement used in an identity-based policy cannot specify any IAM principals.');
|
466 | }
|
467 | if (Object.keys(this.resource).length === 0 && Object.keys(this.notResource).length === 0) {
|
468 | errors.push('A PolicyStatement used in an identity-based policy must specify at least one resource.');
|
469 | }
|
470 | return errors;
|
471 | }
|
472 | }
|
473 | exports.PolicyStatement = PolicyStatement;
|
474 | _a = JSII_RTTI_SYMBOL_1;
|
475 | PolicyStatement[_a] = { fqn: "@aws-cdk/aws-iam.PolicyStatement", version: "1.156.1" };
|
476 | /**
|
477 | * The Effect element of an IAM policy
|
478 | *
|
479 | * @see https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_effect.html
|
480 | */
|
481 | var Effect;
|
482 | (function (Effect) {
|
483 | /**
|
484 | * Allows access to a resource in an IAM policy statement. By default, access to resources are denied.
|
485 | */
|
486 | Effect["ALLOW"] = "Allow";
|
487 | /**
|
488 | * Explicitly deny access to a resource. By default, all requests are denied implicitly.
|
489 | *
|
490 | * @see https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic.html
|
491 | */
|
492 | Effect["DENY"] = "Deny";
|
493 | })(Effect = exports.Effect || (exports.Effect = {}));
|
494 | class JsonPrincipal extends principals_1.PrincipalBase {
|
495 | constructor(json = {}) {
|
496 | super();
|
497 | // special case: if principal is a string, turn it into a "LiteralString" principal,
|
498 | // so we render the exact same string back out.
|
499 | if (typeof (json) === 'string') {
|
500 | json = { [util_1.LITERAL_STRING_KEY]: [json] };
|
501 | }
|
502 | if (typeof (json) !== 'object') {
|
503 | throw new Error(`JSON IAM principal should be an object, got ${JSON.stringify(json)}`);
|
504 | }
|
505 | this.policyFragment = {
|
506 | principalJson: json,
|
507 | conditions: {},
|
508 | };
|
509 | }
|
510 | }
|
511 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9saWN5LXN0YXRlbWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInBvbGljeS1zdGF0ZW1lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEscUNBQXFDO0FBQ3JDLG1DQUFnQztBQUNoQyw2Q0FHc0I7QUFDdEIsdUZBQTJFO0FBQzNFLGlDQUE0RDtBQUU1RCxNQUFNLHNCQUFzQixHQUFHLENBQUMsS0FBVSxFQUFFLEVBQUU7SUFDNUMsSUFBSSxLQUFLLEtBQUssU0FBUyxFQUFFO1FBQ3ZCLE9BQU8sU0FBUyxDQUFDO0tBQ2xCO0lBQ0QsSUFBSSxPQUFPLENBQUMsS0FBSyxDQUFDLEtBQUssUUFBUSxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsRUFBRTtRQUN4RCxNQUFNLElBQUksS0FBSyxDQUFDLHVEQUF1RCxDQUFDLENBQUM7S0FDMUU7SUFDRCxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFNLEVBQUUsRUFBRSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsS0FBSyxRQUFRLENBQUMsRUFBRTtRQUM3RSxNQUFNLElBQUksS0FBSyxDQUFDLHVEQUF1RCxDQUFDLENBQUM7S0FDMUU7SUFDRCxPQUFPLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUNoRCxDQUFDLENBQUM7QUFFRjs7R0FFRztBQUNILE1BQWEsZUFBZTtJQWtEMUIsWUFBWSxRQUE4QixFQUFFO1FBWjNCLFdBQU0sR0FBRyxJQUFJLEtBQUssRUFBTyxDQUFDO1FBQzFCLGNBQVMsR0FBRyxJQUFJLEtBQUssRUFBTyxDQUFDO1FBQzdCLGNBQVMsR0FBNkIsRUFBRSxDQUFDO1FBQ3pDLGlCQUFZLEdBQTZCLEVBQUUsQ0FBQztRQUM1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LE9BQU8sTUFBTSxDQUFDO0tBQ2Y7O0FBbmNILDBDQW9jQzs7O0FBRUQ7Ozs7R0FJRztBQUNILElBQVksTUFZWDtBQVpELFdBQVksTUFBTTtJQUNoQjs7T0FFRztJQUNILHlCQUFlLENBQUE7SUFFZjs7OztPQUlHO0lBQ0gsdUJBQWEsQ0FBQTtBQUNmLENBQUMsRUFaVyxNQUFNLEdBQU4sY0FBTSxLQUFOLGNBQU0sUUFZakI7QUF3R0QsTUFBTSxhQUFjLFNBQVEsMEJBQWE7SUFHdkMsWUFBWSxPQUFZLEVBQUc7UUFDekIsS0FBSyxFQUFFLENBQUM7UUFFUixvRkFBb0Y7UUFDcEYsK0NBQStDO1FBQy9DLElBQUksT0FBTSxDQUFDLElBQUksQ0FBQyxLQUFLLFFBQVEsRUFBRTtZQUM3QixJQUFJLEdBQUcsRUFBRSxDQUFDLHlCQUFrQixDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1NBQ3pDO1FBQ0QsSUFBSSxPQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssUUFBUSxFQUFFO1lBQzdCLE1BQU0sSUFBSSxLQUFLLENBQUMsK0NBQStDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1NBQ3hGO1FBRUQsSUFBSSxDQUFDLGNBQWMsR0FBRztZQUNwQixhQUFhLEVBQUUsSUFBSTtZQUNuQixVQUFVLEVBQUUsRUFBRTtTQUNmLENBQUM7S0FDSDtDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgY2RrIGZyb20gJ0Bhd3MtY2RrL2NvcmUnO1xuaW1wb3J0IHsgR3JvdXAgfSBmcm9tICcuL2dyb3VwJztcbmltcG9ydCB7XG4gIEFjY291bnRQcmluY2lwYWwsIEFjY291bnRSb290UHJpbmNpcGFsLCBBbnlQcmluY2lwYWwsIEFyblByaW5jaXBhbCwgQ2Fub25pY2FsVXNlclByaW5jaXBhbCxcbiAgRmVkZXJhdGVkUHJpbmNpcGFsLCBJUHJpbmNpcGFsLCBQcmluY2lwYWxCYXNlLCBQcmluY2lwYWxQb2xpY3lGcmFnbWVudCwgU2VydmljZVByaW5jaXBhbCwgU2VydmljZVByaW5jaXBhbE9wdHMsXG59IGZyb20gJy4vcHJpbmNpcGFscyc7XG5pbXBvcnQgeyBub3JtYWxpemVTdGF0ZW1lbnQgfSBmcm9tICcuL3ByaXZhdGUvcG9zdHByb2Nlc3MtcG9saWN5LWRvY3VtZW50JztcbmltcG9ydCB7IExJVEVSQUxfU1RSSU5HX0tFWSwgbWVyZ2VQcmluY2lwYWwgfSBmcm9tICcuL3V0aWwnO1xuXG5jb25zdCBlbnN1cmVBcnJheU9yVW5kZWZpbmVkID0gKGZpZWxkOiBhbnkpID0+IHtcbiAgaWYgKGZpZWxkID09PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG4gIGlmICh0eXBlb2YgKGZpZWxkKSAhPT0gJ3N0cmluZycgJiYgIUFycmF5LmlzQXJyYXkoZmllbGQpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdGaWVsZHMgbXVzdCBiZSBlaXRoZXIgYSBzdHJpbmcgb3IgYW4gYXJyYXkgb2Ygc3RyaW5ncycpO1xuICB9XG4gIGlmIChBcnJheS5pc0FycmF5KGZpZWxkKSAmJiAhIWZpZWxkLmZpbmQoKGY6IGFueSkgPT4gdHlwZW9mIChmKSAhPT0gJ3N0cmluZycpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdGaWVsZHMgbXVzdCBiZSBlaXRoZXIgYSBzdHJpbmcgb3IgYW4gYXJyYXkgb2Ygc3RyaW5ncycpO1xuICB9XG4gIHJldHVybiBBcnJheS5pc0FycmF5KGZpZWxkKSA/IGZpZWxkIDogW2ZpZWxkXTtcbn07XG5cbi8qKlxuICogUmVwcmVzZW50cyBhIHN0YXRlbWVudCBpbiBhbiBJQU0gcG9saWN5IGRvY3VtZW50LlxuICovXG5leHBvcnQgY2xhc3MgUG9saWN5U3RhdGVtZW50IHtcblxuICAvKipcbiAgICogQ3JlYXRlcyBhIG5ldyBQb2xpY3lTdGF0ZW1lbnQgYmFzZWQgb24gdGhlIG9iamVjdCBwcm92aWRlZC5cbiAgICogVGhpcyB3aWxsIGFjY2VwdCBhbiBvYmplY3QgY3JlYXRlZCBmcm9tIHRoZSBgLnRvSlNPTigpYCBjYWxsXG4gICAqIEBwYXJhbSBvYmogdGhlIFBvbGljeVN0YXRlbWVudCBpbiBvYmplY3QgZm9ybS5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZnJvbUpzb24ob2JqOiBhbnkpIHtcbiAgICBjb25zdCByZXQgPSBuZXcgUG9saWN5U3RhdGVtZW50KHtcbiAgICAgIHNpZDogb2JqLlNpZCxcbiAgICAgIGFjdGlvbnM6IGVuc3VyZUFycmF5T3JVbmRlZmluZWQob2JqLkFjdGlvbiksXG4gICAgICByZXNvdXJjZXM6IGVuc3VyZUFycmF5T3JVbmRlZmluZWQob2JqLlJlc291cmNlKSxcbiAgICAgIGNvbmRpdGlvbnM6IG9iai5Db25kaXRpb24sXG4gICAgICBlZmZlY3Q6IG9iai5FZmZlY3QsXG4gICAgICBub3RBY3Rpb25zOiBlbnN1cmVBcnJheU9yVW5kZWZpbmVkKG9iai5Ob3RBY3Rpb24pLFxuICAgICAgbm90UmVzb3VyY2VzOiBlbnN1cmVBcnJheU9yVW5kZWZpbmVkKG9iai5Ob3RSZXNvdXJjZSksXG4gICAgICBwcmluY2lwYWxzOiBvYmouUHJpbmNpcGFsID8gW25ldyBKc29uUHJpbmNpcGFsKG9iai5QcmluY2lwYWwpXSA6IHVuZGVmaW5lZCxcbiAgICAgIG5vdFByaW5jaXBhbHM6IG9iai5Ob3RQcmluY2lwYWwgPyBbbmV3IEpzb25QcmluY2lwYWwob2JqLk5vdFByaW5jaXBhbCldIDogdW5kZWZpbmVkLFxuICAgIH0pO1xuXG4gICAgLy8gdmFsaWRhdGUgdGhhdCB0aGUgUG9saWN5U3RhdGVtZW50IGhhcyB0aGUgY29ycmVjdCBzaGFwZVxuICAgIGNvbnN0IGVycm9ycyA9IHJldC52YWxpZGF0ZUZvckFueVBvbGljeSgpO1xuICAgIGlmIChlcnJvcnMubGVuZ3RoID4gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbmNvcnJlY3QgUG9saWN5IFN0YXRlbWVudDogJyArIGVycm9ycy5qb2luKCdcXG4nKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHJldDtcbiAgfVxuXG4gIC8qKlxuICAgKiBTdGF0ZW1lbnQgSUQgZm9yIHRoaXMgc3RhdGVtZW50XG4gICAqL1xuICBwdWJsaWMgc2lkPzogc3RyaW5nO1xuICAvKipcbiAgICogV2hldGhlciB0byBhbGxvdyBvciBkZW55IHRoZSBhY3Rpb25zIGluIHRoaXMgc3RhdGVtZW50XG4gICAqL1xuICBwdWJsaWMgZWZmZWN0OiBFZmZlY3Q7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBhY3Rpb24gPSBuZXcgQXJyYXk8YW55PigpO1xuICBwcml2YXRlIHJlYWRvbmx5IG5vdEFjdGlvbiA9IG5ldyBBcnJheTxhbnk+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgcHJpbmNpcGFsOiB7IFtrZXk6IHN0cmluZ106IGFueVtdIH0gPSB7fTtcbiAgcHJpdmF0ZSByZWFkb25seSBub3RQcmluY2lwYWw6IHsgW2tleTogc3RyaW5nXTogYW55W10gfSA9IHt9O1xuICBwcml2YXRlIHJlYWRvbmx5IHJlc291cmNlID0gbmV3IEFycmF5PGFueT4oKTtcbiAgcHJpdmF0ZSByZWFkb25seSBub3RSZXNvdXJjZSA9IG5ldyBBcnJheTxhbnk+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgY29uZGl0aW9uOiB7IFtrZXk6IHN0cmluZ106IGFueSB9ID0geyB9O1xuICBwcml2YXRlIHByaW5jaXBhbENvbmRpdGlvbnNKc29uPzogc3RyaW5nO1xuXG4gIC8vIEhvbGQgb24gdG8gdGhvc2UgcHJpbmNpcGFsc1xuICBwcml2YXRlIHJlYWRvbmx5IF9wcmluY2lwYWxzID0gbmV3IEFycmF5PElQcmluY2lwYWw+KCk7XG5cbiAgY29uc3RydWN0b3IocHJvcHM6IFBvbGljeVN0YXRlbWVudFByb3BzID0ge30pIHtcbiAgICAvLyBWYWxpZGF0ZSBhY3Rpb25zXG4gICAgZm9yIChjb25zdCBhY3Rpb24gb2YgWy4uLnByb3BzLmFjdGlvbnMgfHwgW10sIC4uLnByb3BzLm5vdEFjdGlvbnMgfHwgW11dKSB7XG5cbiAgICAgIGlmICghL14oXFwqfFthLXpBLVowLTktXSs6W2EtekEtWjAtOSpdKykkLy50ZXN0KGFjdGlvbikgJiYgIWNkay5Ub2tlbi5pc1VucmVzb2x2ZWQoYWN0aW9uKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEFjdGlvbiAnJHthY3Rpb259JyBpcyBpbnZhbGlkLiBBbiBhY3Rpb24gc3RyaW5nIGNvbnNpc3RzIG9mIGEgc2VydmljZSBuYW1lc3BhY2UsIGEgY29sb24sIGFuZCB0aGUgbmFtZSBvZiBhbiBhY3Rpb24uIEFjdGlvbiBuYW1lcyBjYW4gaW5jbHVkZSB3aWxkY2FyZHMuYCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5zaWQgPSBwcm9wcy5zaWQ7XG4gICAgdGhpcy5lZmZlY3QgPSBwcm9wcy5lZmZlY3QgfHwgRWZmZWN0LkFMTE9XO1xuXG4gICAgdGhpcy5hZGRBY3Rpb25zKC4uLnByb3BzLmFjdGlvbnMgfHwgW10pO1xuICAgIHRoaXMuYWRkTm90QWN0aW9ucyguLi5wcm9wcy5ub3RBY3Rpb25zIHx8IFtdKTtcbiAgICB0aGlzLmFkZFByaW5jaXBhbHMoLi4ucHJvcHMucHJpbmNpcGFscyB8fCBbXSk7XG4gICAgdGhpcy5hZGROb3RQcmluY2lwYWxzKC4uLnByb3BzLm5vdFByaW5jaXBhbHMgfHwgW10pO1xuICAgIHRoaXMuYWRkUmVzb3VyY2VzKC4uLnByb3BzLnJlc291cmNlcyB8fCBbXSk7XG4gICAgdGhpcy5hZGROb3RSZXNvdXJjZXMoLi4ucHJvcHMubm90UmVzb3VyY2VzIHx8IFtdKTtcbiAgICBpZiAocHJvcHMuY29uZGl0aW9ucyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmFkZENvbmRpdGlvbnMocHJvcHMuY29uZGl0aW9ucyk7XG4gICAgfVxuICB9XG5cbiAgLy9cbiAgLy8gQWN0aW9uc1xuICAvL1xuXG4gIC8qKlxuICAgKiBTcGVjaWZ5IGFsbG93ZWQgYWN0aW9ucyBpbnRvIHRoZSBcIkFjdGlvblwiIHNlY3Rpb24gb2YgdGhlIHBvbGljeSBzdGF0ZW1lbnQuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0lBTS9sYXRlc3QvVXNlckd1aWRlL3JlZmVyZW5jZV9wb2xpY2llc19lbGVtZW50c19hY3Rpb24uaHRtbFxuICAgKlxuICAgKiBAcGFyYW0gYWN0aW9ucyBhY3Rpb25zIHRoYXQgd2lsbCBiZSBhbGxvd2VkLlxuICAgKi9cbiAgcHVibGljIGFkZEFjdGlvbnMoLi4uYWN0aW9uczogc3RyaW5nW10pIHtcbiAgICBpZiAoYWN0aW9ucy5sZW5ndGggPiAwICYmIHRoaXMubm90QWN0aW9uLmxlbmd0aCA+IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGFkZCBcXCdBY3Rpb25zXFwnIHRvIHBvbGljeSBzdGF0ZW1lbnQgaWYgXFwnTm90QWN0aW9uc1xcJyBoYXZlIGJlZW4gYWRkZWQnKTtcbiAgICB9XG4gICAgdGhpcy5hY3Rpb24ucHVzaCguLi5hY3Rpb25zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFeHBsaWNpdGx5IGFsbG93IGFsbCBhY3Rpb25zIGV4Y2VwdCB0aGUgc3BlY2lmaWVkIGxpc3Qgb2YgYWN0aW9ucyBpbnRvIHRoZSBcIk5vdEFjdGlvblwiIHNlY3Rpb25cbiAgICogb2YgdGhlIHBvbGljeSBkb2N1bWVudC5cbiAgICpcbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vSUFNL2xhdGVzdC9Vc2VyR3VpZGUvcmVmZXJlbmNlX3BvbGljaWVzX2VsZW1lbnRzX25vdGFjdGlvbi5odG1sXG4gICAqXG4gICAqIEBwYXJhbSBub3RBY3Rpb25zIGFjdGlvbnMgdGhhdCB3aWxsIGJlIGRlbmllZC4gQWxsIG90aGVyIGFjdGlvbnMgd2lsbCBiZSBwZXJtaXR0ZWQuXG4gICAqL1xuICBwdWJsaWMgYWRkTm90QWN0aW9ucyguLi5ub3RBY3Rpb25zOiBzdHJpbmdbXSkge1xuICAgIGlmIChub3RBY3Rpb25zLmxlbmd0aCA+IDAgJiYgdGhpcy5hY3Rpb24ubGVuZ3RoID4gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgYWRkIFxcJ05vdEFjdGlvbnNcXCcgdG8gcG9saWN5IHN0YXRlbWVudCBpZiBcXCdBY3Rpb25zXFwnIGhhdmUgYmVlbiBhZGRlZCcpO1xuICAgIH1cbiAgICB0aGlzLm5vdEFjdGlvbi5wdXNoKC4uLm5vdEFjdGlvbnMpO1xuICB9XG5cbiAgLy9cbiAgLy8gUHJpbmNpcGFsXG4gIC8vXG5cbiAgLyoqXG4gICAqIEluZGljYXRlcyBpZiB0aGlzIHBlcm1pc3Npb24gaGFzIGEgXCJQcmluY2lwYWxcIiBzZWN0aW9uLlxuICAgKi9cbiAgcHVibGljIGdldCBoYXNQcmluY2lwYWwoKSB7XG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKHRoaXMucHJpbmNpcGFsKS5sZW5ndGggPiAwIHx8IE9iamVjdC5rZXlzKHRoaXMubm90UHJpbmNpcGFsKS5sZW5ndGggPiAwO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgcHJpbmNpcGFscyB0byB0aGUgXCJQcmluY2lwYWxcIiBzZWN0aW9uIG9mIGEgcG9saWN5IHN0YXRlbWVudC5cbiAgICpcbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vSUFNL2xhdGVzdC9Vc2VyR3VpZGUvcmVmZXJlbmNlX3BvbGljaWVzX2VsZW1lbnRzX3ByaW5jaXBhbC5odG1sXG4gICAqXG4gICAqIEBwYXJhbSBwcmluY2lwYWxzIElBTSBwcmluY2lwYWxzIHRoYXQgd2lsbCBiZSBhZGRlZFxuICAgKi9cbiAgcHVibGljIGFkZFByaW5jaXBhbHMoLi4ucHJpbmNpcGFsczogSVByaW5jaXBhbFtdKSB7XG4gICAgdGhpcy5fcHJpbmNpcGFscy5wdXNoKC4uLnByaW5jaXBhbHMpO1xuICAgIGlmIChPYmplY3Qua2V5cyhwcmluY2lwYWxzKS5sZW5ndGggPiAwICYmIE9iamVjdC5rZXlzKHRoaXMubm90UHJpbmNpcGFsKS5sZW5ndGggPiAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBhZGQgXFwnUHJpbmNpcGFsc1xcJyB0byBwb2xpY3kgc3RhdGVtZW50IGlmIFxcJ05vdFByaW5jaXBhbHNcXCcgaGF2ZSBiZWVuIGFkZGVkJyk7XG4gICAgfVxuICAgIGZvciAoY29uc3QgcHJpbmNpcGFsIG9mIHByaW5jaXBhbHMpIHtcbiAgICAgIHRoaXMudmFsaWRhdGVQb2xpY3lQcmluY2lwYWwocHJpbmNpcGFsKTtcbiAgICAgIGNvbnN0IGZyYWdtZW50ID0gcHJpbmNpcGFsLnBvbGljeUZyYWdtZW50O1xuICAgICAgbWVyZ2VQcmluY2lwYWwodGhpcy5wcmluY2lwYWwsIGZyYWdtZW50LnByaW5jaXBhbEpzb24pO1xuICAgICAgdGhpcy5hZGRQcmluY2lwYWxDb25kaXRpb25zKGZyYWdtZW50LmNvbmRpdGlvbnMpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBFeHBvc2UgcHJpbmNpcGFscyB0byBhbGxvdyB0aGVpciBBUk5zIHRvIGJlIHJlcGxhY2VkIGJ5IGFjY291bnQgSUQgc3RyaW5nc1xuICAgKiBpbiBwb2xpY3kgc3RhdGVtZW50cyBmb3IgcmVzb3VyY2VzIHBvbGljaWVzIHRoYXQgZG9uJ3QgYWxsb3cgZnVsbCBhY2NvdW50IEFSTnMsXG4gICAqIHN1Y2ggYXMgQVdTOjpMb2dzOjpSZXNvdXJjZVBvbGljeS5cbiAgICovXG4gIHB1YmxpYyBnZXQgcHJpbmNpcGFscygpOiBJUHJpbmNpcGFsW10ge1xuICAgIHJldHVybiBbLi4udGhpcy5fcHJpbmNpcGFsc107XG4gIH1cblxuICAvKipcbiAgICogU3BlY2lmeSBwcmluY2lwYWxzIHRoYXQgaXMgbm90IGFsbG93ZWQgb3IgZGVuaWVkIGFjY2VzcyB0byB0aGUgXCJOb3RQcmluY2lwYWxcIiBzZWN0aW9uIG9mXG4gICAqIGEgcG9saWN5IHN0YXRlbWVudC5cbiAgICpcbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vSUFNL2xhdGVzdC9Vc2VyR3VpZGUvcmVmZXJlbmNlX3BvbGljaWVzX2VsZW1lbnRzX25vdHByaW5jaXBhbC5odG1sXG4gICAqXG4gICAqIEBwYXJhbSBub3RQcmluY2lwYWxzIElBTSBwcmluY2lwYWxzIHRoYXQgd2lsbCBiZSBkZW5pZWQgYWNjZXNzXG4gICAqL1xuICBwdWJsaWMgYWRkTm90UHJpbmNpcGFscyguLi5ub3RQcmluY2lwYWxzOiBJUHJpbmNpcGFsW10pIHtcbiAgICBpZiAoT2JqZWN0LmtleXMobm90UHJpbmNpcGFscykubGVuZ3RoID4gMCAmJiBPYmplY3Qua2V5cyh0aGlzLnByaW5jaXBhbCkubGVuZ3RoID4gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgYWRkIFxcJ05vdFByaW5jaXBhbHNcXCcgdG8gcG9saWN5IHN0YXRlbWVudCBpZiBcXCdQcmluY2lwYWxzXFwnIGhhdmUgYmVlbiBhZGRlZCcpO1xuICAgIH1cbiAgICBmb3IgKGNvbnN0IG5vdFByaW5jaXBhbCBvZiBub3RQcmluY2lwYWxzKSB7XG4gICAgICB0aGlzLnZhbGlkYXRlUG9saWN5UHJpbmNpcGFsKG5vdFByaW5jaXBhbCk7XG4gICAgICBjb25zdCBmcmFnbWVudCA9IG5vdFByaW5jaXBhbC5wb2xpY3lGcmFnbWVudDtcbiAgICAgIG1lcmdlUHJpbmNpcGFsKHRoaXMubm90UHJpbmNpcGFsLCBmcmFnbWVudC5wcmluY2lwYWxKc29uKTtcbiAgICAgIHRoaXMuYWRkUHJpbmNpcGFsQ29uZGl0aW9ucyhmcmFnbWVudC5jb25kaXRpb25zKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHZhbGlkYXRlUG9saWN5UHJpbmNpcGFsKHByaW5jaXBhbDogSVByaW5jaXBhbCkge1xuICAgIGlmIChwcmluY2lwYWwgaW5zdGFuY2VvZiBHcm91cCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgdXNlIGFuIElBTSBHcm91cCBhcyB0aGUgXFwnUHJpbmNpcGFsXFwnIG9yIFxcJ05vdFByaW5jaXBhbFxcJyBpbiBhbiBJQU0gUG9saWN5Jyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNwZWNpZnkgQVdTIGFjY291bnQgSUQgYXMgdGhlIHByaW5jaXBhbCBlbnRpdHkgdG8gdGhlIFwiUHJpbmNpcGFsXCIgc2VjdGlvbiBvZiBhIHBvbGljeSBzdGF0ZW1lbnQuXG4gICAqL1xuICBwdWJsaWMgYWRkQXdzQWNjb3VudFByaW5jaXBhbChhY2NvdW50SWQ6IHN0cmluZykge1xuICAgIHRoaXMuYWRkUHJpbmNpcGFscyhuZXcgQWNjb3VudFByaW5jaXBhbChhY2NvdW50SWQpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTcGVjaWZ5IGEgcHJpbmNpcGFsIHVzaW5nIHRoZSBBUk4gIGlkZW50aWZpZXIgb2YgdGhlIHByaW5jaXBhbC5cbiAgICogWW91IGNhbm5vdCBzcGVjaWZ5IElBTSBncm91cHMgYW5kIGluc3RhbmNlIHByb2ZpbGVzIGFzIHByaW5jaXBhbHMuXG4gICAqXG4gICAqIEBwYXJhbSBhcm4gQVJOIGlkZW50aWZpZXIgb2YgQVdTIGFjY291bnQsIElBTSB1c2VyLCBvciBJQU0gcm9sZSAoaS5lLiBhcm46YXdzOmlhbTo6MTIzNDU2Nzg5MDEyOnVzZXIvdXNlci1uYW1lKVxuICAgKi9cbiAgcHVibGljIGFkZEFyblByaW5jaXBhbChhcm46IHN0cmluZykge1xuICAgIHRoaXMuYWRkUHJpbmNpcGFscyhuZXcgQXJuUHJpbmNpcGFsKGFybikpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYSBzZXJ2aWNlIHByaW5jaXBhbCB0byB0aGlzIHBvbGljeSBzdGF0ZW1lbnQuXG4gICAqXG4gICAqIEBwYXJhbSBzZXJ2aWNlIHRoZSBzZXJ2aWNlIG5hbWUgZm9yIHdoaWNoIGEgc2VydmljZSBwcmluY2lwYWwgaXMgcmVxdWVzdGVkIChlLmc6IGBzMy5hbWF6b25hd3MuY29tYCkuXG4gICAqIEBwYXJhbSBvcHRzICAgIG9wdGlvbnMgZm9yIGFkZGluZyB0aGUgc2VydmljZSBwcmluY2lwYWwgKHN1Y2ggYXMgc3BlY2lmeWluZyBhIHByaW5jaXBhbCBpbiBhIGRpZmZlcmVudCByZWdpb24pXG4gICAqL1xuICBwdWJsaWMgYWRkU2VydmljZVByaW5jaXBhbChzZXJ2aWNlOiBzdHJpbmcsIG9wdHM/OiBTZXJ2aWNlUHJpbmNpcGFsT3B0cykge1xuICAgIHRoaXMuYWRkUHJpbmNpcGFscyhuZXcgU2VydmljZVByaW5jaXBhbChzZXJ2aWNlLCBvcHRzKSk7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhIGZlZGVyYXRlZCBpZGVudGl0eSBwcm92aWRlciBzdWNoIGFzIEFtYXpvbiBDb2duaXRvIHRvIHRoaXMgcG9saWN5IHN0YXRlbWVudC5cbiAgICpcbiAgICogQHBhcmFtIGZlZGVyYXRlZCBmZWRlcmF0ZWQgaWRlbnRpdHkgcHJvdmlkZXIgKGkuZS4gJ2NvZ25pdG8taWRlbnRpdHkuYW1hem9uYXdzLmNvbScpXG4gICAqIEBwYXJhbSBjb25kaXRpb25zIFRoZSBjb25kaXRpb25zIHVuZGVyIHdoaWNoIHRoZSBwb2xpY3kgaXMgaW4gZWZmZWN0LlxuICAgKiAgIFNlZSBbdGhlIElBTSBkb2N1bWVudGF0aW9uXShodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vSUFNL2xhdGVzdC9Vc2VyR3VpZGUvcmVmZXJlbmNlX3BvbGljaWVzX2VsZW1lbnRzX2NvbmRpdGlvbi5odG1sKS5cbiAgICovXG4gIHB1YmxpYyBhZGRGZWRlcmF0ZWRQcmluY2lwYWwoZmVkZXJhdGVkOiBhbnksIGNvbmRpdGlvbnM6IENvbmRpdGlvbnMpIHtcbiAgICB0aGlzLmFkZFByaW5jaXBhbHMobmV3IEZlZGVyYXRlZFByaW5jaXBhbChmZWRlcmF0ZWQsIGNvbmRpdGlvbnMpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGFuIEFXUyBhY2NvdW50IHJvb3QgdXNlciBwcmluY2lwYWwgdG8gdGhpcyBwb2xpY3kgc3RhdGVtZW50XG4gICAqL1xuICBwdWJsaWMgYWRkQWNjb3VudFJvb3RQcmluY2lwYWwoKSB7XG4gICAgdGhpcy5hZGRQcmluY2lwYWxzKG5ldyBBY2NvdW50Um9vdFByaW5jaXBhbCgpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGEgY2Fub25pY2FsIHVzZXIgSUQgcHJpbmNpcGFsIHRvIHRoaXMgcG9saWN5IGRvY3VtZW50XG4gICAqXG4gICAqIEBwYXJhbSBjYW5vbmljYWxVc2VySWQgdW5pcXVlIGlkZW50aWZpZXIgYXNzaWduZWQgYnkgQVdTIGZvciBldmVyeSBhY2NvdW50XG4gICAqL1xuICBwdWJsaWMgYWRkQ2Fub25pY2FsVXNlclByaW5jaXBhbChjYW5vbmljYWxVc2VySWQ6IHN0cmluZykge1xuICAgIHRoaXMuYWRkUHJpbmNpcGFscyhuZXcgQ2Fub25pY2FsVXNlclByaW5jaXBhbChjYW5vbmljYWxVc2VySWQpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGFsbCBpZGVudGl0aWVzIGluIGFsbCBhY2NvdW50cyAoXCIqXCIpIHRvIHRoaXMgcG9saWN5IHN0YXRlbWVudFxuICAgKi9cbiAgcHVibGljIGFkZEFueVByaW5jaXBhbCgpIHtcbiAgICB0aGlzLmFkZFByaW5jaXBhbHMobmV3IEFueVByaW5jaXBhbCgpKTtcbiAgfVxuXG4gIC8vXG4gIC8vIFJlc291cmNlc1xuICAvL1xuXG4gIC8qKlxuICAgKiBTcGVjaWZ5IHJlc291cmNlcyB0aGF0IHRoaXMgcG9saWN5IHN0YXRlbWVudCBhcHBsaWVzIGludG8gdGhlIFwiUmVzb3VyY2VcIiBzZWN0aW9uIG9mXG4gICAqIHRoaXMgcG9saWN5IHN0YXRlbWVudC5cbiAgICpcbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vSUFNL2xhdGVzdC9Vc2VyR3VpZGUvcmVmZXJlbmNlX3BvbGljaWVzX2VsZW1lbnRzX3Jlc291cmNlLmh0bWxcbiAgICpcbiAgICogQHBhcmFtIGFybnMgQW1hem9uIFJlc291cmNlIE5hbWVzIChBUk5zKSBvZiB0aGUgcmVzb3VyY2VzIHRoYXQgdGhpcyBwb2xpY3kgc3RhdGVtZW50IGFwcGxpZXMgdG9cbiAgICovXG4gIHB1YmxpYyBhZGRSZXNvdXJjZXMoLi4uYXJuczogc3RyaW5nW10pIHtcbiAgICBpZiAoYXJucy5sZW5ndGggPiAwICYmIHRoaXMubm90UmVzb3VyY2UubGVuZ3RoID4gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgYWRkIFxcJ1Jlc291cmNlc1xcJyB0byBwb2xpY3kgc3RhdGVtZW50IGlmIFxcJ05vdFJlc291cmNlc1xcJyBoYXZlIGJlZW4gYWRkZWQnKTtcbiAgICB9XG4gICAgdGhpcy5yZXNvdXJjZS5wdXNoKC4uLmFybnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNwZWNpZnkgcmVzb3VyY2VzIHRoYXQgdGhpcyBwb2xpY3kgc3RhdGVtZW50IHdpbGwgbm90IGFwcGx5IHRvIGluIHRoZSBcIk5vdFJlc291cmNlXCIgc2VjdGlvblxuICAgKiBvZiB0aGlzIHBvbGljeSBzdGF0ZW1lbnQuIEFsbCByZXNvdXJjZXMgZXhjZXB0IHRoZSBzcGVjaWZpZWQgbGlzdCB3aWxsIGJlIG1hdGNoZWQuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0lBTS9sYXRlc3QvVXNlckd1aWRlL3JlZmVyZW5jZV9wb2xpY2llc19lbGVtZW50c19ub3RyZXNvdXJjZS5odG1sXG4gICAqXG4gICAqIEBwYXJhbSBhcm5zIEFtYXpvbiBSZXNvdXJjZSBOYW1lcyAoQVJOcykgb2YgdGhlIHJlc291cmNlcyB0aGF0IHRoaXMgcG9saWN5IHN0YXRlbWVudCBkb2VzIG5vdCBhcHBseSB0b1xuICAgKi9cbiAgcHVibGljIGFkZE5vdFJlc291cmNlcyguLi5hcm5zOiBzdHJpbmdbXSkge1xuICAgIGlmIChhcm5zLmxlbmd0aCA+IDAgJiYgdGhpcy5yZXNvdXJjZS5sZW5ndGggPiAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBhZGQgXFwnTm90UmVzb3VyY2VzXFwnIHRvIHBvbGljeSBzdGF0ZW1lbnQgaWYgXFwnUmVzb3VyY2VzXFwnIGhhdmUgYmVlbiBhZGRlZCcpO1xuICAgIH1cbiAgICB0aGlzLm5vdFJlc291cmNlLnB1c2goLi4uYXJucyk7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhIGBgXCIqXCJgYCByZXNvdXJjZSB0byB0aGlzIHN0YXRlbWVudC5cbiAgICovXG4gIHB1YmxpYyBhZGRBbGxSZXNvdXJjZXMoKSB7XG4gICAgdGhpcy5hZGRSZXNvdXJjZXMoJyonKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbmRpY2F0ZXMgaWYgdGhpcyBwZXJtaXNzaW9uIGhhcyBhdCBsZWFzdCBvbmUgcmVzb3VyY2UgYXNzb2NpYXRlZCB3aXRoIGl0LlxuICAgKi9cbiAgcHVibGljIGdldCBoYXNSZXNvdXJjZSgpIHtcbiAgICByZXR1cm4gdGhpcy5yZXNvdXJjZSAmJiB0aGlzLnJlc291cmNlLmxlbmd0aCA+IDA7XG4gIH1cblxuICAvL1xuICAvLyBDb25kaXRpb25cbiAgLy9cblxuICAvKipcbiAgICogQWRkIGEgY29uZGl0aW9uIHRvIHRoZSBQb2xpY3lcbiAgICpcbiAgICogSWYgbXVsdGlwbGUgY2FsbHMgYXJlIG1hZGUgdG8gYWRkIGEgY29uZGl0aW9uIHdpdGggdGhlIHNhbWUgb3BlcmF0b3IgYW5kIGZpZWxkLCBvbmx5XG4gICAqIHRoZSBsYXN0IG9uZSB3aW5zLiBGb3IgZXhhbXBsZTpcbiAgICpcbiAgICogYGBgdHNcbiAgICogZGVjbGFyZSBjb25zdCBzdG10OiBpYW0uUG9saWN5U3RhdGVtZW50O1xuICAgKlxuICAgKiBzdG10LmFkZENvbmRpdGlvbignU3RyaW5nRXF1YWxzJywgeyAnYXdzOlNvbWVGaWVsZCc6ICcxJyB9KTtcbiAgICogc3RtdC5hZGRDb25kaXRpb24oJ1N0cmluZ0VxdWFscycsIHsgJ2F3czpTb21lRmllbGQnOiAnMicgfSk7XG4gICAqIGBgYFxuICAgKlxuICAgKiBXaWxsIGVuZCB1cCB3aXRoIHRoZSBzaW5nbGUgY29uZGl0aW9uIGBTdHJpbmdFcXVhbHM6IHsgJ2F3czpTb21lRmllbGQnOiAnMicgfWAuXG4gICAqXG4gICAqIElmIHlvdSBtZWFudCB0byBhZGQgYSBjb25kaXRpb24gdG8gc2F5IHRoYXQgdGhlIGZpZWxkIGNhbiBiZSAqZWl0aGVyKiBgMWAgb3IgYDJgLCB3cml0ZVxuICAgKiB0aGlzOlxuICAgKlxuICAgKiBgYGB0c1xuICAgKiBkZWNsYXJlIGNvbnN0IHN0bXQ6IGlhbS5Qb2xpY3lTdGF0ZW1lbnQ7XG4gICAqXG4gICAqIHN0bXQuYWRkQ29uZGl0aW9uKCdTdHJpbmdFcXVhbHMnLCB7ICdhd3M6U29tZUZpZWxkJzogWycxJywgJzInXSB9KTtcbiAgICogYGBgXG4gICAqL1xuICBwdWJsaWMgYWRkQ29uZGl0aW9uKGtleTogc3RyaW5nLCB2YWx1ZTogQ29uZGl0aW9uKSB7XG4gICAgY29uc3QgZXhpc3RpbmdWYWx1ZSA9IHRoaXMuY29uZGl0aW9uW2tleV07XG4gICAgdGhpcy5jb25kaXRpb25ba2V5XSA9IGV4aXN0aW5nVmFsdWUgPyB7IC4uLmV4aXN0aW5nVmFsdWUsIC4uLnZhbHVlIH0gOiB2YWx1ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgbXVsdGlwbGUgY29uZGl0aW9ucyB0byB0aGUgUG9saWN5XG4gICAqXG4gICAqIFNlZSB0aGUgYGFkZENvbmRpdGlvbmAgZnVuY3Rpb24gZm9yIGEgY2F2ZWF0IG9uIGNhbGxpbmcgdGhpcyBtZXRob2QgbXVsdGlwbGUgdGltZXMuXG4gICAqL1xuICBwdWJsaWMgYWRkQ29uZGl0aW9ucyhjb25kaXRpb25zOiBDb25kaXRpb25zKSB7XG4gICAgT2JqZWN0LmtleXMoY29uZGl0aW9ucykubWFwKGtleSA9PiB7XG4gICAgICB0aGlzLmFkZENvbmRpdGlvbihrZXksIGNvbmRpdGlvbnNba2V5XSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQWRkIGEgY29uZGl0aW9uIHRoYXQgbGltaXRzIHRvIGEgZ2l2ZW4gYWNjb3VudFxuICAgKlxuICAgKiBUaGlzIG1ldGhvZCBjYW4gb25seSBiZSBjYWxsZWQgb25jZTogc3Vic2VxdWVudCBjYWxscyB3aWxsIG92ZXJ3cml0ZSBlYXJsaWVyIGNhbGxzLlxuICAgKi9cbiAgcHVibGljIGFkZEFjY291bnRDb25kaXRpb24oYWNjb3VudElkOiBzdHJpbmcpIHtcbiAgICB0aGlzLmFkZENvbmRpdGlvbignU3RyaW5nRXF1YWxzJywgeyAnc3RzOkV4dGVybmFsSWQnOiBhY2NvdW50SWQgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgbmV3IGBQb2xpY3lTdGF0ZW1lbnRgIHdpdGggdGhlIHNhbWUgZXhhY3QgcHJvcGVydGllc1xuICAgKiBhcyB0aGlzIG9uZSwgZXhjZXB0IGZvciB0aGUgb3ZlcnJpZGVzXG4gICAqL1xuICBwdWJsaWMgY29weShvdmVycmlkZXM6IFBvbGljeVN0YXRlbWVudFByb3BzID0ge30pIHtcbiAgICByZXR1cm4gbmV3IFBvbGljeVN0YXRlbWVudCh7XG4gICAgICBzaWQ6IG92ZXJyaWRlcy5zaWQgPz8gdGhpcy5zaWQsXG4gICAgICBlZmZlY3Q6IG92ZXJyaWRlcy5lZmZlY3QgPz8gdGhpcy5lZmZlY3QsXG4gICAgICBhY3Rpb25zOiBvdmVycmlkZXMuYWN0aW9ucyA/PyB0aGlzLmFjdGlvbixcbiAgICAgIG5vdEFjdGlvbnM6IG92ZXJyaWRlcy5ub3RBY3Rpb25zID8/IHRoaXMubm90QWN0aW9uLFxuXG4gICAgICBwcmluY2lwYWxzOiBvdmVycmlkZXMucHJpbmNpcGFscyxcbiAgICAgIG5vdFByaW5jaXBhbHM6IG92ZXJyaWRlcy5ub3RQcmluY2lwYWxzLFxuXG4gICAgICByZXNvdXJjZXM6IG92ZXJyaWRlcy5yZXNvdXJjZXMgPz8gdGhpcy5yZXNvdXJjZSxcbiAgICAgIG5vdFJlc291cmNlczogb3ZlcnJpZGVzLm5vdFJlc291cmNlcyA/PyB0aGlzLm5vdFJlc291cmNlLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEpTT04taWZ5IHRoZSBwb2xpY3kgc3RhdGVtZW50XG4gICAqXG4gICAqIFVzZWQgd2hlbiBKU09OLnN0cmluZ2lmeSgpIGlzIGNhbGxlZFxuICAgKi9cbiAgcHVibGljIHRvU3RhdGVtZW50SnNvbigpOiBhbnkge1xuICAgIHJldHVybiBub3JtYWxpemVTdGF0ZW1lbnQoe1xuICAgICAgQWN0aW9uOiB0aGlzLmFjdGlvbixcbiAgICAgIE5vdEFjdGlvbjogdGhpcy5ub3RBY3Rpb24sXG4gICAgICBDb25kaXRpb246IHRoaXMuY29uZGl0aW9uLFxuICAgICAgRWZmZWN0OiB0aGlzLmVmZmVjdCxcbiAgICAgIFByaW5jaXBhbDogdGhpcy5wcmluY2lwYWwsXG4gICAgICBOb3RQcmluY2lwYWw6IHRoaXMubm90UHJpbmNpcGFsLFxuICAgICAgUmVzb3VyY2U6IHRoaXMucmVzb3VyY2UsXG4gICAgICBOb3RSZXNvdXJjZTogdGhpcy5ub3RSZXNvdXJjZSxcbiAgICAgIFNpZDogdGhpcy5zaWQsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogU3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoaXMgcG9saWN5IHN0YXRlbWVudFxuICAgKi9cbiAgcHVibGljIHRvU3RyaW5nKCkge1xuICAgIHJldHVybiBjZGsuVG9rZW4uYXNTdHJpbmcodGhpcywge1xuICAgICAgZGlzcGxheUhpbnQ6ICdQb2xpY3lTdGF0ZW1lbnQnLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEpTT04taWZ5IHRoZSBzdGF0ZW1lbnRcbiAgICpcbiAgICogVXNlZCB3aGVuIEpTT04uc3RyaW5naWZ5KCkgaXMgY2FsbGVkXG4gICAqL1xuICBwdWJsaWMgdG9KU09OKCkge1xuICAgIHJldHVybiB0aGlzLnRvU3RhdGVtZW50SnNvbigpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBhIHByaW5jaXBhbCdzIGNvbmRpdGlvbnNcbiAgICpcbiAgICogRm9yIGNvbnZlbmllbmNlLCBwcmluY2lwYWxzIGhhdmUgYmVlbiBtb2RlbGVkIGFzIGJvdGggYSBwcmluY2lwYWxcbiAgICogYW5kIGEgc2V0IG9mIGNvbmRpdGlvbnMuIFRoaXMgbWFrZXMgaXQgcG9zc2libGUgdG8gaGF2ZSBhIHNpbmdsZVxuICAgKiBvYmplY3QgcmVwcmVzZW50IGUuZy4gYW4gXCJTTlMgVG9waWNcIiAoU05TIHNlcnZpY2UgcHJpbmNpcGFsICsgYXdzOlNvdXJjQXJuXG4gICAqIGNvbmRpdGlvbikgb3IgYW4gT3JnYW5pemF0aW9uIG1lbWJlciAoKiArIGF3czpPcmdJZCBjb25kaXRpb24pLlxuICAgKlxuICAgKiBIb3dldmVyLCB3aGVuIHVzaW5nIG11bHRpcGxlIHByaW5jaXBhbHMgaW4gdGhlIHNhbWUgcG9saWN5IHN0YXRlbWVudCxcbiAgICogdGhleSBtdXN0IGFsbCBoYXZlIHRoZSBzYW1lIGNvbmRpdGlvbnMgb3IgdGhlIE9SIHNhbWVudGljc1xuICAgKiBpbXBsaWVkIGJ5IGEgbGlzdCBvZiBwcmluY2lwYWxzIGNhbm5vdCBiZSBndWFyYW50ZWVkICh1c2VyIG5lZWRzIHRvXG4gICAqIGFkZCBtdWx0aXBsZSBzdGF0ZW1lbnRzIGluIHRoYXQgY2FzZSkuXG4gICAqL1xuICBwcml2YXRlIGFkZFByaW5jaXBhbENvbmRpdGlvbnMoY29uZGl0aW9uczogQ29uZGl0aW9ucykge1xuICAgIC8vIFN0cmluZ2lmeWluZyB0aGUgY29uZGl0aW9ucyBpcyBhbiBlYXN5IHdheSB0byBkbyBkZWVwIGVxdWFsaXR5XG4gICAgY29uc3QgdGhlc2VDb25kaXRpb25zID0gSlNPTi5zdHJpbmdpZnkoY29uZGl0aW9ucyk7XG4gICAgaWYgKHRoaXMucHJpbmNpcGFsQ29uZGl0aW9uc0pzb24gPT09IHVuZGVmaW5lZCkge1xuICAgICAgLy8gRmlyc3QgcHJpbmNpcGFsLCBhbnl0aGluZyBnb2VzXG4gICAgICB0aGlzLnByaW5jaXBhbENvbmRpdGlvbnNKc29uID0gdGhlc2VDb25kaXRpb25zO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAodGhpcy5wcmluY2lwYWxDb25kaXRpb25zSnNvbiAhPT0gdGhlc2VDb25kaXRpb25zKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgQWxsIHByaW5jaXBhbHMgaW4gYSBQb2xpY3lTdGF0ZW1lbnQgbXVzdCBoYXZlIHRoZSBzYW1lIENvbmRpdGlvbnMgKGdvdCAnJHt0aGlzLnByaW5jaXBhbENvbmRpdGlvbnNKc29ufScgYW5kICcke3RoZXNlQ29uZGl0aW9uc30nKS4gVXNlIG11bHRpcGxlIHN0YXRlbWVudHMgaW5zdGVhZC5gKTtcbiAgICAgIH1cbiAgICB9XG4gICAgdGhpcy5hZGRDb25kaXRpb25zKGNvbmRpdGlvbnMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlIHRoYXQgdGhlIHBvbGljeSBzdGF0ZW1lbnQgc2F0aXNmaWVzIGJhc2UgcmVxdWlyZW1lbnRzIGZvciBhIHBvbGljeS5cbiAgICovXG4gIHB1YmxpYyB2YWxpZGF0ZUZvckFueVBvbGljeSgpOiBzdHJpbmdbXSB7XG4gICAgY29uc3QgZXJyb3JzID0gbmV3IEFycmF5PHN0cmluZz4oKTtcbiAgICBpZiAodGhpcy5hY3Rpb24ubGVuZ3RoID09PSAwICYmIHRoaXMubm90QWN0aW9uLmxlbmd0aCA9PT0gMCkge1xuICAgICAgZXJyb3JzLnB1c2goJ0EgUG9saWN5U3RhdGVtZW50IG11c3Qgc3BlY2lmeSBhdCBsZWFzdCBvbmUgXFwnYWN0aW9uXFwnIG9yIFxcJ25vdEFjdGlvblxcJy4nKTtcbiAgICB9XG4gICAgcmV0dXJuIGVycm9ycztcbiAgfVxuXG4gIC8qKlxuICAgKiBWYWxpZGF0ZSB0aGF0IHRoZSBwb2xpY3kgc3RhdGVtZW50IHNhdGlzZmllcyBhbGwgcmVxdWlyZW1lbnRzIGZvciBhIHJlc291cmNlLWJhc2VkIHBvbGljeS5cbiAgICovXG4gIHB1YmxpYyB2YWxpZGF0ZUZvclJlc291cmNlUG9saWN5KCk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCBlcnJvcnMgPSB0aGlzLnZhbGlkYXRlRm9yQW55UG9saWN5KCk7XG4gICAgaWYgKE9iamVjdC5rZXlzKHRoaXMucHJpbmNpcGFsKS5sZW5ndGggPT09IDAgJiYgT2JqZWN0LmtleXModGhpcy5ub3RQcmluY2lwYWwpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgZXJyb3JzLnB1c2goJ0EgUG9saWN5U3RhdGVtZW50IHVzZWQgaW4gYSByZXNvdXJjZS1iYXNlZCBwb2xpY3kgbXVzdCBzcGVjaWZ5IGF0IGxlYXN0IG9uZSBJQU0gcHJpbmNpcGFsLicpO1xuICAgIH1cbiAgICByZXR1cm4gZXJyb3JzO1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlIHRoYXQgdGhlIHBvbGljeSBzdGF0ZW1lbnQgc2F0aXNmaWVzIGFsbCByZXF1aXJlbWVudHMgZm9yIGFuIGlkZW50aXR5LWJhc2VkIHBvbGljeS5cbiAgICovXG4gIHB1YmxpYyB2YWxpZGF0ZUZvcklkZW50aXR5UG9saWN5KCk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCBlcnJvcnMgPSB0aGlzLnZhbGlkYXRlRm9yQW55UG9saWN5KCk7XG4gICAgaWYgKE9iamVjdC5rZXlzKHRoaXMucHJpbmNpcGFsKS5sZW5ndGggPiAwIHx8IE9iamVjdC5rZXlzKHRoaXMubm90UHJpbmNpcGFsKS5sZW5ndGggPiAwKSB7XG4gICAgICBlcnJvcnMucHVzaCgnQSBQb2xpY3lTdGF0ZW1lbnQgdXNlZCBpbiBhbiBpZGVudGl0eS1iYXNlZCBwb2xpY3kgY2Fubm90IHNwZWNpZnkgYW55IElBTSBwcmluY2lwYWxzLicpO1xuICAgIH1cbiAgICBpZiAoT2JqZWN0LmtleXModGhpcy5yZXNvdXJjZSkubGVuZ3RoID09PSAwICYmIE9iamVjdC5rZXlzKHRoaXMubm90UmVzb3VyY2UpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgZXJyb3JzLnB1c2goJ0EgUG9saWN5U3RhdGVtZW50IHVzZWQgaW4gYW4gaWRlbnRpdHktYmFzZWQgcG9saWN5IG11c3Qgc3BlY2lmeSBhdCBsZWFzdCBvbmUgcmVzb3VyY2UuJyk7XG4gICAgfVxuICAgIHJldHVybiBlcnJvcnM7XG4gIH1cbn1cblxuLyoqXG4gKiBUaGUgRWZmZWN0IGVsZW1lbnQgb2YgYW4gSUFNIHBvbGljeVxuICpcbiAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0lBTS9sYXRlc3QvVXNlckd1aWRlL3JlZmVyZW5jZV9wb2xpY2llc19lbGVtZW50c19lZmZlY3QuaHRtbFxuICovXG5leHBvcnQgZW51bSBFZmZlY3Qge1xuICAvKipcbiAgICogQWxsb3dzIGFjY2VzcyB0byBhIHJlc291cmNlIGluIGFuIElBTSBwb2xpY3kgc3RhdGVtZW50LiBCeSBkZWZhdWx0LCBhY2Nlc3MgdG8gcmVzb3VyY2VzIGFyZSBkZW5pZWQuXG4gICAqL1xuICBBTExPVyA9ICdBbGxvdycsXG5cbiAgLyoqXG4gICAqIEV4cGxpY2l0bHkgZGVueSBhY2Nlc3MgdG8gYSByZXNvdXJjZS4gQnkgZGVmYXVsdCwgYWxsIHJlcXVlc3RzIGFyZSBkZW5pZWQgaW1wbGljaXRseS5cbiAgICpcbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vSUFNL2xhdGVzdC9Vc2VyR3VpZGUvcmVmZXJlbmNlX3BvbGljaWVzX2V2YWx1YXRpb24tbG9naWMuaHRtbFxuICAgKi9cbiAgREVOWSA9ICdEZW55Jyxcbn1cblxuLyoqXG4gKiBDb25kaXRpb24gZm9yIHdoZW4gYW4gSUFNIHBvbGljeSBpcyBpbiBlZmZlY3QuIE1hcHMgZnJvbSB0aGUga2V5cyBpbiBhIHJlcXVlc3QncyBjb250ZXh0IHRvXG4gKiBhIHN0cmluZyB2YWx1ZSBvciBhcnJheSBvZiBzdHJpbmcgdmFsdWVzLiBTZWUgdGhlIENvbmRpdGlvbnMgaW50ZXJmYWNlIGZvciBtb3JlIGRldGFpbHMuXG4gKi9cbmV4cG9ydCB0eXBlIENvbmRpdGlvbiA9IGFueTtcblxuLy8gTk9URSEgV2UnZCBpZGVhbGx5IGxpa2UgdG8gdHlwZSB0aGlzIGFzIGBSZWNvcmQ8c3RyaW5nLCBhbnk+YCwgYmVjYXVzZSB0aGVcbi8vIEFQSSBleHBlY3RzIGEgbWFwIHdoaWNoIGNhbiB0YWtlIGVpdGhlciBzdHJpbmdzIG9yIGxpc3RzIG9mIHN0cmluZ3MuXG4vL1xuLy8gSG93ZXZlciwgaWYgd2Ugd2VyZSB0byBjaGFuZ2UgdGhpcyByaWdodCBub3csIHRoZSBKYXZhIGJpbmRpbmdzIGZvciBDREsgd291bGRcbi8vIGVtaXQgYSB0eXBlIG9mIGBNYXA8U3RyaW5nLCBPYmplY3Q+YCwgYnV0IHRoZSBtb3N0IGNvbW1vbiB0eXBlcyBwZW9wbGUgd291bGRcbi8vIGluc3RhbnRpYXRlIHdvdWxkIGJlIGFuIGBJbW11dGFibGVNYXA8U3RyaW5nLCBTdHJpbmc+YCB3aGljaCB3b3VsZCBub3QgYmVcbi8vIGFzc2lnbmFibGUgdG8gYE1hcDxTdHJpbmcsIE9iamVjdD5gLiBUaGUgdHlwZXMgZG9uJ3QgaGF2ZSBhIGJ1aWx0LWluIG5vdGlvblxuLy8gb2YgY28tY29udHJhdmFyaWFuY2UsIHlvdSBoYXZlIHRvIGluZGljYXRlIHRoYXQgb24gdGhlIHR5cGUuIFNvIGpzaWkgd291bGQgZmlyc3Rcbi8vIG5lZWQgdG8gZW1pdCB0aGUgdHlwZSBhcyBgTWFwPFN0cmluZywgPyBleHRlbmRzIE9iamVjdD5gLlxuLy9cbi8vIEZlYXR1cmUgcmVxdWVzdCBpbiBodHRwczovL2dpdGh1Yi5jb20vYXdzL2pzaWkvaXNzdWVzLzE1MTdcblxuLyoqXG4gKiBDb25kaXRpb25zIGZvciB3aGVuIGFuIElBTSBQb2xpY3kgaXMgaW4gZWZmZWN0LCBzcGVjaWZpZWQgaW4gdGhlIGZvbGxvd2luZyBzdHJ1Y3R1cmU6XG4gKlxuICogYHsgXCJPcGVyYXRvclwiOiB7IFwia2V5SW5SZXF1ZXN0Q29udGV4dFwiOiBcInZhbHVlXCIgfSB9YFxuICpcbiAqIFRoZSB2YWx1ZSBjYW4gYmUgZWl0aGVyIGEgc2luZ2xlIHN0cmluZyB2YWx1ZSBvciBhbiBhcnJheSBvZiBzdHJpbmcgdmFsdWVzLlxuICpcbiAqIEZvciBtb3JlIGluZm9ybWF0aW9uLCBpbmNsdWRpbmcgd2hpY2ggb3BlcmF0b3JzIGFyZSBzdXBwb3J0ZWQsIHNlZSBbdGhlIElBTVxuICogZG9jdW1lbnRhdGlvbl0oaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0lBTS9sYXRlc3QvVXNlckd1aWRlL3JlZmVyZW5jZV9wb2xpY2llc19lbGVtZW50c19jb25kaXRpb24uaHRtbCkuXG4gKi9cbmV4cG9ydCB0eXBlIENvbmRpdGlvbnMgPSBSZWNvcmQ8c3RyaW5nLCBDb25kaXRpb24+O1xuXG4vKipcbiAqIEludGVyZmFjZSBmb3IgY3JlYXRpbmcgYSBwb2xpY3kgc3RhdGVtZW50XG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUG9saWN5U3RhdGVtZW50UHJvcHMge1xuICAvKipcbiAgICogVGhlIFNpZCAoc3RhdGVtZW50IElEKSBpcyBhbiBvcHRpb25hbCBpZGVudGlmaWVyIHRoYXQgeW91IHByb3ZpZGUgZm9yIHRoZVxuICAgKiBwb2xpY3kgc3RhdGVtZW50LiBZb3UgY2FuIGFzc2lnbiBhIFNpZCB2YWx1ZSB0byBlYWNoIHN0YXRlbWVudCBpbiBhXG4gICAqIHN0YXRlbWVudCBhcnJheS4gSW4gc2VydmljZXMgdGhhdCBsZXQgeW91IHNwZWNpZnkgYW4gSUQgZWxlbWVudCwgc3VjaCBhc1xuICAgKiBTUVMgYW5kIFNOUywgdGhlIFNpZCB2YWx1ZSBpcyBqdXN0IGEgc3ViLUlEIG9mIHRoZSBwb2xpY3kgZG9jdW1lbnQncyBJRC4gSW5cbiAgICogSUFNLCB0aGUgU2lkIHZhbHVlIG11c3QgYmUgdW5pcXVlIHdpdGhpbiBhIEpTT04gcG9saWN5LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIHNpZFxuICAgKi9cbiAgcmVhZG9ubHkgc2lkPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBMaXN0IG9mIGFjdGlvbnMgdG8gYWRkIHRvIHRoZSBzdGF0ZW1lbnRcbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBhY3Rpb25zXG4gICAqL1xuICByZWFkb25seSBhY3Rpb25zPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIExpc3Qgb2Ygbm90IGFjdGlvbnMgdG8gYWRkIHRvIHRoZSBzdGF0ZW1lbnRcbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBub3QtYWN0aW9uc1xuICAgKi9cbiAgcmVhZG9ubHkgbm90QWN0aW9ucz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBMaXN0IG9mIHByaW5jaXBhbHMgdG8gYWRkIHRvIHRoZSBzdGF0ZW1lbnRcbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBwcmluY2lwYWxzXG4gICAqL1xuICByZWFkb25seSBwcmluY2lwYWxzPzogSVByaW5jaXBhbFtdO1xuXG4gIC8qKlxuICAgKiBMaXN0IG9mIG5vdCBwcmluY2lwYWxzIHRvIGFkZCB0byB0aGUgc3RhdGVtZW50XG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm8gbm90IHByaW5jaXBhbHNcbiAgICovXG4gIHJlYWRvbmx5IG5vdFByaW5jaXBhbHM/OiBJUHJpbmNpcGFsW107XG5cbiAgLyoqXG4gICAqIFJlc291cmNlIEFSTnMgdG8gYWRkIHRvIHRoZSBzdGF0ZW1lbnRcbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyByZXNvdXJjZXNcbiAgICovXG4gIHJlYWRvbmx5IHJlc291cmNlcz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBOb3RSZXNvdXJjZSBBUk5zIHRvIGFkZCB0byB0aGUgc3RhdGVtZW50XG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm8gbm90LXJlc291cmNlc1xuICAgKi9cbiAgcmVhZG9ubHkgbm90UmVzb3VyY2VzPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIENvbmRpdGlvbnMgdG8gYWRkIHRvIHRoZSBzdGF0ZW1lbnRcbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBjb25kaXRpb25cbiAgICovXG4gIHJlYWRvbmx5IGNvbmRpdGlvbnM/OiB7W2tleTogc3RyaW5nXTogYW55fTtcblxuICAvKipcbiAgICogV2hldGhlciB0byBhbGxvdyBvciBkZW55IHRoZSBhY3Rpb25zIGluIHRoaXMgc3RhdGVtZW50XG4gICAqXG4gICAqIEBkZWZhdWx0IEVmZmVjdC5BTExPV1xuICAgKi9cbiAgcmVhZG9ubHkgZWZmZWN0PzogRWZmZWN0O1xufVxuXG5jbGFzcyBKc29uUHJpbmNpcGFsIGV4dGVuZHMgUHJpbmNpcGFsQmFzZSB7XG4gIHB1YmxpYyByZWFkb25seSBwb2xpY3lGcmFnbWVudDogUHJpbmNpcGFsUG9saWN5RnJhZ21lbnQ7XG5cbiAgY29uc3RydWN0b3IoanNvbjogYW55ID0geyB9KSB7XG4gICAgc3VwZXIoKTtcblxuICAgIC8vIHNwZWNpYWwgY2FzZTogaWYgcHJpbmNpcGFsIGlzIGEgc3RyaW5nLCB0dXJuIGl0IGludG8gYSBcIkxpdGVyYWxTdHJpbmdcIiBwcmluY2lwYWwsXG4gICAgLy8gc28gd2UgcmVuZGVyIHRoZSBleGFjdCBzYW1lIHN0cmluZyBiYWNrIG91dC5cbiAgICBpZiAodHlwZW9mKGpzb24pID09PSAnc3RyaW5nJykge1xuICAgICAganNvbiA9IHsgW0xJVEVSQUxfU1RSSU5HX0tFWV06IFtqc29uXSB9O1xuICAgIH1cbiAgICBpZiAodHlwZW9mKGpzb24pICE9PSAnb2JqZWN0Jykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBKU09OIElBTSBwcmluY2lwYWwgc2hvdWxkIGJlIGFuIG9iamVjdCwgZ290ICR7SlNPTi5zdHJpbmdpZnkoanNvbil9YCk7XG4gICAgfVxuXG4gICAgdGhpcy5wb2xpY3lGcmFnbWVudCA9IHtcbiAgICAgIHByaW5jaXBhbEpzb246IGpzb24sXG4gICAgICBjb25kaXRpb25zOiB7fSxcbiAgICB9O1xuICB9XG59XG4iXX0= |
\ | No newline at end of file |