1 | ;
|
2 | var _a;
|
3 | Object.defineProperty(exports, "__esModule", { value: true });
|
4 | exports.Rule = void 0;
|
5 | const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
|
6 | const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
7 | const aws_iam_1 = require("@aws-cdk/aws-iam");
|
8 | const core_1 = require("@aws-cdk/core");
|
9 | const constructs_1 = require("constructs");
|
10 | const events_generated_1 = require("./events.generated");
|
11 | const schedule_1 = require("./schedule");
|
12 | const util_1 = require("./util");
|
13 | /**
|
14 | * Defines an EventBridge Rule in this stack.
|
15 | *
|
16 | * @resource AWS::Events::Rule
|
17 | */
|
18 | class Rule extends core_1.Resource {
|
19 | constructor(scope, id, props = {}) {
|
20 | var _b, _c;
|
21 | super(scope, id, {
|
22 | physicalName: props.ruleName,
|
23 | });
|
24 | this.targets = new Array();
|
25 | this.eventPattern = {};
|
26 | /** Set to keep track of what target accounts and regions we've already created event buses for */
|
27 | this._xEnvTargetsAdded = new Set();
|
28 | try {
|
29 | jsiiDeprecationWarnings._aws_cdk_aws_events_RuleProps(props);
|
30 | }
|
31 | catch (error) {
|
32 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
33 | Error.captureStackTrace(error, this.constructor);
|
34 | }
|
35 | throw error;
|
36 | }
|
37 | if (props.eventBus && props.schedule) {
|
38 | throw new Error('Cannot associate rule with \'eventBus\' when using \'schedule\'');
|
39 | }
|
40 | this.description = props.description;
|
41 | this.scheduleExpression = (_b = props.schedule) === null || _b === void 0 ? void 0 : _b.expressionString;
|
42 | // add a warning on synth when minute is not defined in a cron schedule
|
43 | (_c = props.schedule) === null || _c === void 0 ? void 0 : _c._bind(this);
|
44 | const resource = new events_generated_1.CfnRule(this, 'Resource', {
|
45 | name: this.physicalName,
|
46 | description: this.description,
|
47 | state: props.enabled == null ? 'ENABLED' : (props.enabled ? 'ENABLED' : 'DISABLED'),
|
48 | scheduleExpression: this.scheduleExpression,
|
49 | eventPattern: core_1.Lazy.any({ produce: () => this._renderEventPattern() }),
|
50 | targets: core_1.Lazy.any({ produce: () => this.renderTargets() }),
|
51 | eventBusName: props.eventBus && props.eventBus.eventBusName,
|
52 | });
|
53 | this.ruleArn = this.getResourceArnAttribute(resource.attrArn, {
|
54 | service: 'events',
|
55 | resource: 'rule',
|
56 | resourceName: this.physicalName,
|
57 | });
|
58 | this.ruleName = this.getResourceNameAttribute(resource.ref);
|
59 | this.addEventPattern(props.eventPattern);
|
60 | for (const target of props.targets || []) {
|
61 | this.addTarget(target);
|
62 | }
|
63 | }
|
64 | /**
|
65 | * Import an existing EventBridge Rule provided an ARN
|
66 | *
|
67 | * @param scope The parent creating construct (usually `this`).
|
68 | * @param id The construct's name.
|
69 | * @param eventRuleArn Event Rule ARN (i.e. arn:aws:events:<region>:<account-id>:rule/MyScheduledRule).
|
70 | */
|
71 | static fromEventRuleArn(scope, id, eventRuleArn) {
|
72 | const parts = core_1.Stack.of(scope).splitArn(eventRuleArn, core_1.ArnFormat.SLASH_RESOURCE_NAME);
|
73 | class Import extends core_1.Resource {
|
74 | constructor() {
|
75 | super(...arguments);
|
76 | this.ruleArn = eventRuleArn;
|
77 | this.ruleName = parts.resourceName || '';
|
78 | }
|
79 | }
|
80 | return new Import(scope, id);
|
81 | }
|
82 | /**
|
83 | * Adds a target to the rule. The abstract class RuleTarget can be extended to define new
|
84 | * targets.
|
85 | *
|
86 | * No-op if target is undefined.
|
87 | */
|
88 | addTarget(target) {
|
89 | var _b, _c, _d;
|
90 | try {
|
91 | jsiiDeprecationWarnings._aws_cdk_aws_events_IRuleTarget(target);
|
92 | }
|
93 | catch (error) {
|
94 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
95 | Error.captureStackTrace(error, this.addTarget);
|
96 | }
|
97 | throw error;
|
98 | }
|
99 | if (!target) {
|
100 | return;
|
101 | }
|
102 | // Simply increment id for each `addTarget` call. This is guaranteed to be unique.
|
103 | const autoGeneratedId = `Target${this.targets.length}`;
|
104 | const targetProps = target.bind(this, autoGeneratedId);
|
105 | const inputProps = targetProps.input && targetProps.input.bind(this);
|
106 | const roleArn = (_b = targetProps.role) === null || _b === void 0 ? void 0 : _b.roleArn;
|
107 | const id = targetProps.id || autoGeneratedId;
|
108 | if (targetProps.targetResource) {
|
109 | const targetStack = core_1.Stack.of(targetProps.targetResource);
|
110 | const targetAccount = ((_c = targetProps.targetResource.env) === null || _c === void 0 ? void 0 : _c.account) || targetStack.account;
|
111 | const targetRegion = ((_d = targetProps.targetResource.env) === null || _d === void 0 ? void 0 : _d.region) || targetStack.region;
|
112 | const sourceStack = core_1.Stack.of(this);
|
113 | const sourceAccount = sourceStack.account;
|
114 | const sourceRegion = sourceStack.region;
|
115 | // if the target is in a different account or region and is defined in this CDK App
|
116 | // we can generate all the needed components:
|
117 | // - forwarding rule in the source stack (target: default event bus of the receiver region)
|
118 | // - eventbus permissions policy (creating an extra stack)
|
119 | // - receiver rule in the target stack (target: the actual target)
|
120 | if (!util_1.sameEnvDimension(sourceAccount, targetAccount) || !util_1.sameEnvDimension(sourceRegion, targetRegion)) {
|
121 | // cross-account and/or cross-region event - strap in, this works differently than regular events!
|
122 | // based on:
|
123 | // https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-cross-account.html
|
124 | // for cross-account or cross-region events, we require a concrete target account and region
|
125 | if (!targetAccount || core_1.Token.isUnresolved(targetAccount)) {
|
126 | throw new Error('You need to provide a concrete account for the target stack when using cross-account or cross-region events');
|
127 | }
|
128 | if (!targetRegion || core_1.Token.isUnresolved(targetRegion)) {
|
129 | throw new Error('You need to provide a concrete region for the target stack when using cross-account or cross-region events');
|
130 | }
|
131 | if (core_1.Token.isUnresolved(sourceAccount)) {
|
132 | throw new Error('You need to provide a concrete account for the source stack when using cross-account or cross-region events');
|
133 | }
|
134 | // Don't exactly understand why this code was here (seems unlikely this rule would be violated), but
|
135 | // let's leave it in nonetheless.
|
136 | const sourceApp = this.node.root;
|
137 | if (!sourceApp || !core_1.App.isApp(sourceApp)) {
|
138 | throw new Error('Event stack which uses cross-account or cross-region targets must be part of a CDK app');
|
139 | }
|
140 | const targetApp = constructs_1.Node.of(targetProps.targetResource).root;
|
141 | if (!targetApp || !core_1.App.isApp(targetApp)) {
|
142 | throw new Error('Target stack which uses cross-account or cross-region event targets must be part of a CDK app');
|
143 | }
|
144 | if (sourceApp !== targetApp) {
|
145 | throw new Error('Event stack and target stack must belong to the same CDK app');
|
146 | }
|
147 | // The target of this Rule will be the default event bus of the target environment
|
148 | this.ensureXEnvTargetEventBus(targetStack, targetAccount, targetRegion, id);
|
149 | // The actual rule lives in the target stack. Other than the account, it's identical to this one,
|
150 | // but only evaluated at render time (via a special subclass).
|
151 | //
|
152 | // FIXME: the MirrorRule is a bit silly, forwarding the exact same event to another event bus
|
153 | // and trigger on it there (there will be issues with construct references, for example). Especially
|
154 | // in the case of scheduled events, we will just trigger both rules in parallel in both environments.
|
155 | //
|
156 | // A better solution would be to have the source rule add a unique token to the the event,
|
157 | // and have the mirror rule trigger on that token only (thereby properly separating triggering, which
|
158 | // happens in the source env; and activating, which happens in the target env).
|
159 | //
|
160 | // Don't have time to do that right now.
|
161 | const mirrorRuleScope = this.obtainMirrorRuleScope(targetStack, targetAccount, targetRegion);
|
162 | new MirrorRule(mirrorRuleScope, `${core_1.Names.uniqueId(this)}-${id}`, {
|
163 | targets: [target],
|
164 | eventPattern: this.eventPattern,
|
165 | schedule: this.scheduleExpression ? schedule_1.Schedule.expression(this.scheduleExpression) : undefined,
|
166 | description: this.description,
|
167 | }, this);
|
168 | return;
|
169 | }
|
170 | }
|
171 | // Here only if the target does not have a targetResource defined.
|
172 | // In such case we don't have to generate any extra component.
|
173 | // Note that this can also be an imported resource (i.e: EventBus target)
|
174 | this.targets.push({
|
175 | id,
|
176 | arn: targetProps.arn,
|
177 | roleArn,
|
178 | ecsParameters: targetProps.ecsParameters,
|
179 | httpParameters: targetProps.httpParameters,
|
180 | kinesisParameters: targetProps.kinesisParameters,
|
181 | runCommandParameters: targetProps.runCommandParameters,
|
182 | batchParameters: targetProps.batchParameters,
|
183 | deadLetterConfig: targetProps.deadLetterConfig,
|
184 | retryPolicy: targetProps.retryPolicy,
|
185 | sqsParameters: targetProps.sqsParameters,
|
186 | input: inputProps && inputProps.input,
|
187 | inputPath: inputProps && inputProps.inputPath,
|
188 | inputTransformer: (inputProps === null || inputProps === void 0 ? void 0 : inputProps.inputTemplate) !== undefined ? {
|
189 | inputTemplate: inputProps.inputTemplate,
|
190 | inputPathsMap: inputProps.inputPathsMap,
|
191 | } : undefined,
|
192 | });
|
193 | }
|
194 | /**
|
195 | * Adds an event pattern filter to this rule. If a pattern was already specified,
|
196 | * these values are merged into the existing pattern.
|
197 | *
|
198 | * For example, if the rule already contains the pattern:
|
199 | *
|
200 | * {
|
201 | * "resources": [ "r1" ],
|
202 | * "detail": {
|
203 | * "hello": [ 1 ]
|
204 | * }
|
205 | * }
|
206 | *
|
207 | * And `addEventPattern` is called with the pattern:
|
208 | *
|
209 | * {
|
210 | * "resources": [ "r2" ],
|
211 | * "detail": {
|
212 | * "foo": [ "bar" ]
|
213 | * }
|
214 | * }
|
215 | *
|
216 | * The resulting event pattern will be:
|
217 | *
|
218 | * {
|
219 | * "resources": [ "r1", "r2" ],
|
220 | * "detail": {
|
221 | * "hello": [ 1 ],
|
222 | * "foo": [ "bar" ]
|
223 | * }
|
224 | * }
|
225 | *
|
226 | */
|
227 | addEventPattern(eventPattern) {
|
228 | try {
|
229 | jsiiDeprecationWarnings._aws_cdk_aws_events_EventPattern(eventPattern);
|
230 | }
|
231 | catch (error) {
|
232 | if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
233 | Error.captureStackTrace(error, this.addEventPattern);
|
234 | }
|
235 | throw error;
|
236 | }
|
237 | if (!eventPattern) {
|
238 | return;
|
239 | }
|
240 | util_1.mergeEventPattern(this.eventPattern, eventPattern);
|
241 | }
|
242 | /**
|
243 | * Not private only to be overrideen in CopyRule.
|
244 | *
|
245 | * @internal
|
246 | */
|
247 | _renderEventPattern() {
|
248 | return util_1.renderEventPattern(this.eventPattern);
|
249 | }
|
250 | validate() {
|
251 | if (Object.keys(this.eventPattern).length === 0 && !this.scheduleExpression) {
|
252 | return ['Either \'eventPattern\' or \'schedule\' must be defined'];
|
253 | }
|
254 | return [];
|
255 | }
|
256 | renderTargets() {
|
257 | if (this.targets.length === 0) {
|
258 | return undefined;
|
259 | }
|
260 | return this.targets;
|
261 | }
|
262 | /**
|
263 | * Make sure we add the target environments event bus as a target, and the target has permissions set up to receive our events
|
264 | *
|
265 | * For cross-account rules, uses a support stack to set up a policy on the target event bus.
|
266 | */
|
267 | ensureXEnvTargetEventBus(targetStack, targetAccount, targetRegion, id) {
|
268 | // the _actual_ target is just the event bus of the target's account
|
269 | // make sure we only add it once per account per region
|
270 | const key = `${targetAccount}:${targetRegion}`;
|
271 | if (this._xEnvTargetsAdded.has(key)) {
|
272 | return;
|
273 | }
|
274 | this._xEnvTargetsAdded.add(key);
|
275 | const eventBusArn = targetStack.formatArn({
|
276 | service: 'events',
|
277 | resource: 'event-bus',
|
278 | resourceName: 'default',
|
279 | region: targetRegion,
|
280 | account: targetAccount,
|
281 | });
|
282 | // For some reason, cross-region requires a Role (with `PutEvents` on the
|
283 | // target event bus) while cross-account doesn't
|
284 | const roleArn = !util_1.sameEnvDimension(targetRegion, core_1.Stack.of(this).region)
|
285 | ? this.crossRegionPutEventsRole(eventBusArn).roleArn
|
286 | : undefined;
|
287 | this.targets.push({
|
288 | id,
|
289 | arn: eventBusArn,
|
290 | roleArn,
|
291 | });
|
292 | // Add a policy to the target Event Bus to allow the source account/region to publish into it.
|
293 | //
|
294 | // Since this Event Bus permission needs to be deployed before the stack containing the Rule is deployed
|
295 | // (as EventBridge verifies whether you have permissions to the targets on rule creation), this needs
|
296 | // to be in a support stack.
|
297 | const sourceApp = this.node.root;
|
298 | const sourceAccount = core_1.Stack.of(this).account;
|
299 | // If different accounts, we need to add the permissions to the target eventbus
|
300 | //
|
301 | // For different region, no need for a policy on the target event bus (but a need
|
302 | // for a role).
|
303 | if (!util_1.sameEnvDimension(sourceAccount, targetAccount)) {
|
304 | const stackId = `EventBusPolicy-${sourceAccount}-${targetRegion}-${targetAccount}`;
|
305 | let eventBusPolicyStack = sourceApp.node.tryFindChild(stackId);
|
306 | if (!eventBusPolicyStack) {
|
307 | eventBusPolicyStack = new core_1.Stack(sourceApp, stackId, {
|
308 | env: {
|
309 | account: targetAccount,
|
310 | region: targetRegion,
|
311 | },
|
312 | // The region in the stack name is rather redundant (it will always be the target region)
|
313 | // Leaving it in for backwards compatibility.
|
314 | stackName: `${targetStack.stackName}-EventBusPolicy-support-${targetRegion}-${sourceAccount}`,
|
315 | });
|
316 | new events_generated_1.CfnEventBusPolicy(eventBusPolicyStack, 'GivePermToOtherAccount', {
|
317 | action: 'events:PutEvents',
|
318 | statementId: `Allow-account-${sourceAccount}-${this.node.addr}`,
|
319 | principal: sourceAccount,
|
320 | });
|
321 | }
|
322 | // deploy the event bus permissions before the source stack
|
323 | core_1.Stack.of(this).addDependency(eventBusPolicyStack);
|
324 | }
|
325 | }
|
326 | /**
|
327 | * Return the scope where the mirror rule should be created for x-env event targets
|
328 | *
|
329 | * This is the target resource's containing stack if it shares the same region (owned
|
330 | * resources), or should be a fresh support stack for imported resources.
|
331 | *
|
332 | * We don't implement the second yet, as I have to think long and hard on whether we
|
333 | * can reuse the existing support stack or not, and I don't have time for that right now.
|
334 | */
|
335 | obtainMirrorRuleScope(targetStack, targetAccount, targetRegion) {
|
336 | // for cross-account or cross-region events, we cannot create new components for an imported resource
|
337 | // because we don't have the target stack
|
338 | if (util_1.sameEnvDimension(targetStack.account, targetAccount) && util_1.sameEnvDimension(targetStack.region, targetRegion)) {
|
339 | return targetStack;
|
340 | }
|
341 | // For now, we don't do the work for the support stack yet
|
342 | throw new Error('Cannot create a cross-account or cross-region rule for an imported resource (create a stack with the right environment for the imported resource)');
|
343 | }
|
344 | /**
|
345 | * Obtain the Role for the EventBridge event
|
346 | *
|
347 | * If a role already exists, it will be returned. This ensures that if multiple
|
348 | * events have the same target, they will share a role.
|
349 | * @internal
|
350 | */
|
351 | crossRegionPutEventsRole(eventBusArn) {
|
352 | const id = 'EventsRole';
|
353 | let role = this.node.tryFindChild(id);
|
354 | if (!role) {
|
355 | role = new aws_iam_1.Role(this, id, {
|
356 | roleName: core_1.PhysicalName.GENERATE_IF_NEEDED,
|
357 | assumedBy: new aws_iam_1.ServicePrincipal('events.amazonaws.com'),
|
358 | });
|
359 | }
|
360 | role.addToPrincipalPolicy(new aws_iam_1.PolicyStatement({
|
361 | actions: ['events:PutEvents'],
|
362 | resources: [eventBusArn],
|
363 | }));
|
364 | return role;
|
365 | }
|
366 | }
|
367 | exports.Rule = Rule;
|
368 | _a = JSII_RTTI_SYMBOL_1;
|
369 | Rule[_a] = { fqn: "@aws-cdk/aws-events.Rule", version: "1.155.0" };
|
370 | /**
|
371 | * A rule that mirrors another rule
|
372 | */
|
373 | class MirrorRule extends Rule {
|
374 | constructor(scope, id, props, source) {
|
375 | super(scope, id, props);
|
376 | this.source = source;
|
377 | }
|
378 | _renderEventPattern() {
|
379 | return this.source._renderEventPattern();
|
380 | }
|
381 | /**
|
382 | * Override validate to be a no-op
|
383 | *
|
384 | * The rules are never stored on this object so there's nothing to validate.
|
385 | *
|
386 | * Instead, we mirror the other rule at render time.
|
387 | */
|
388 | validate() {
|
389 | return [];
|
390 | }
|
391 | }
|
392 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVsZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInJ1bGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsOENBQWtGO0FBQ2xGLHdDQUE2RztBQUM3RywyQ0FBNkM7QUFHN0MseURBQWdFO0FBRWhFLHlDQUFzQztBQUV0QyxpQ0FBaUY7QUE0RWpGOzs7O0dBSUc7QUFDSCxNQUFhLElBQUssU0FBUSxlQUFRO0lBOEJoQyxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLFFBQW1CLEVBQUc7O1FBQzlELEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFO1lBQ2YsWUFBWSxFQUFFLEtBQUssQ0FBQyxRQUFRO1NBQzdCLENBQUMsQ0FBQztRQVhZLFlBQU8sR0FBRyxJQUFJLEtBQUssRUFBMEIsQ0FBQztRQUM5QyxpQkFBWSxHQUFpQixFQUFHLENBQUM7UUFJbEQsa0dBQWtHO1FBQ2pGLHNCQUFpQixHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7Ozs7Ozs7Ozs7UUFPckQsSUFBSSxLQUFLLENBQUMsUUFBUSxJQUFJLEtBQUssQ0FBQyxRQUFRLEVBQUU7WUFDcEMsTUFBTSxJQUFJLEtBQUssQ0FBQyxpRUFBaUUsQ0FBQyxDQUFDO1NBQ3BGO1FBRUQsSUFBSSxDQUFDLFdBQVcsR0FBRyxLQUFLLENBQUMsV0FBVyxDQUFDO1FBQ3JDLElBQUksQ0FBQyxrQkFBa0IsU0FBRyxLQUFLLENBQUMsUUFBUSwwQ0FBRSxnQkFBZ0IsQ0FBQztRQUUzRCx1RUFBdUU7UUFDdkUsTUFBQSxLQUFLLENBQUMsUUFBUSwwQ0FBRSxLQUFLLENBQUMsSUFBSSxFQUFFO1FBRTVCLE1BQU0sUUFBUSxHQUFHLElBQUksMEJBQU8sQ0FBQyxJQUFJLEVBQUUsVUFBVSxFQUFFO1lBQzdDLElBQUksRUFBRSxJQUFJLENBQUMsWUFBWTtZQUN2QixXQUFXLEVBQUUsSUFBSSxDQUFDLFdBQVc7WUFDN0IsS0FBSyxFQUFFLEtBQUssQ0FBQyxPQUFPLElBQUksSUFBSSxDQUFD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LEVBQUUsQ0FBQyxXQUFXLENBQUM7U0FDekIsQ0FBQyxDQUFDLENBQUM7UUFFSixPQUFPLElBQUksQ0FBQztLQUNiOztBQXpXSCxvQkEwV0M7OztBQUVEOztHQUVHO0FBQ0gsTUFBTSxVQUFXLFNBQVEsSUFBSTtJQUMzQixZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQWdCLEVBQW1CLE1BQVk7UUFDdkYsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFEbUQsV0FBTSxHQUFOLE1BQU0sQ0FBTTtLQUV4RjtJQUVNLG1CQUFtQjtRQUN4QixPQUFPLElBQUksQ0FBQyxNQUFNLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztLQUMxQztJQUVEOzs7Ozs7T0FNRztJQUNPLFFBQVE7UUFDaEIsT0FBTyxFQUFFLENBQUM7S0FDWDtDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSVJvbGUsIFBvbGljeVN0YXRlbWVudCwgUm9sZSwgU2VydmljZVByaW5jaXBhbCB9IGZyb20gJ0Bhd3MtY2RrL2F3cy1pYW0nO1xuaW1wb3J0IHsgQXBwLCBJUmVzb3VyY2UsIExhenksIE5hbWVzLCBSZXNvdXJjZSwgU3RhY2ssIFRva2VuLCBQaHlzaWNhbE5hbWUsIEFybkZvcm1hdCB9IGZyb20gJ0Bhd3MtY2RrL2NvcmUnO1xuaW1wb3J0IHsgTm9kZSwgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBJRXZlbnRCdXMgfSBmcm9tICcuL2V2ZW50LWJ1cyc7XG5pbXBvcnQgeyBFdmVudFBhdHRlcm4gfSBmcm9tICcuL2V2ZW50LXBhdHRlcm4nO1xuaW1wb3J0IHsgQ2ZuRXZlbnRCdXNQb2xpY3ksIENmblJ1bGUgfSBmcm9tICcuL2V2ZW50cy5nZW5lcmF0ZWQnO1xuaW1wb3J0IHsgSVJ1bGUgfSBmcm9tICcuL3J1bGUtcmVmJztcbmltcG9ydCB7IFNjaGVkdWxlIH0gZnJvbSAnLi9zY2hlZHVsZSc7XG5pbXBvcnQgeyBJUnVsZVRhcmdldCB9IGZyb20gJy4vdGFyZ2V0JztcbmltcG9ydCB7IG1lcmdlRXZlbnRQYXR0ZXJuLCByZW5kZXJFdmVudFBhdHRlcm4sIHNhbWVFbnZEaW1lbnNpb24gfSBmcm9tICcuL3V0aWwnO1xuXG4vKipcbiAqIFByb3BlcnRpZXMgZm9yIGRlZmluaW5nIGFuIEV2ZW50QnJpZGdlIFJ1bGVcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSdWxlUHJvcHMge1xuICAvKipcbiAgICogQSBkZXNjcmlwdGlvbiBvZiB0aGUgcnVsZSdzIHB1cnBvc2UuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gZGVzY3JpcHRpb24uXG4gICAqL1xuICByZWFkb25seSBkZXNjcmlwdGlvbj86IHN0cmluZztcblxuICAvKipcbiAgICogQSBuYW1lIGZvciB0aGUgcnVsZS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBBV1MgQ2xvdWRGb3JtYXRpb24gZ2VuZXJhdGVzIGEgdW5pcXVlIHBoeXNpY2FsIElEIGFuZCB1c2VzIHRoYXQgSURcbiAgICogZm9yIHRoZSBydWxlIG5hbWUuIEZvciBtb3JlIGluZm9ybWF0aW9uLCBzZWUgTmFtZSBUeXBlLlxuICAgKi9cbiAgcmVhZG9ubHkgcnVsZU5hbWU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEluZGljYXRlcyB3aGV0aGVyIHRoZSBydWxlIGlzIGVuYWJsZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIHJlYWRvbmx5IGVuYWJsZWQ/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBUaGUgc2NoZWR1bGUgb3IgcmF0ZSAoZnJlcXVlbmN5KSB0aGF0IGRldGVybWluZXMgd2hlbiBFdmVudEJyaWRnZVxuICAgKiBydW5zIHRoZSBydWxlLiBGb3IgbW9yZSBpbmZvcm1hdGlvbiwgc2VlIFNjaGVkdWxlIEV4cHJlc3Npb24gU3ludGF4IGZvclxuICAgKiBSdWxlcyBpbiB0aGUgQW1hem9uIEV2ZW50QnJpZGdlIFVzZXIgR3VpZGUuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2V2ZW50YnJpZGdlL2xhdGVzdC91c2VyZ3VpZGUvc2NoZWR1bGVkLWV2ZW50cy5odG1sXG4gICAqXG4gICAqIFlvdSBtdXN0IHNwZWNpZnkgdGhpcyBwcm9wZXJ0eSwgdGhlIGBldmVudFBhdHRlcm5gIHByb3BlcnR5LCBvciBib3RoLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vbmUuXG4gICAqL1xuICByZWFkb25seSBzY2hlZHVsZT86IFNjaGVkdWxlO1xuXG4gIC8qKlxuICAgKiBEZXNjcmliZXMgd2hpY2ggZXZlbnRzIEV2ZW50QnJpZGdlIHJvdXRlcyB0byB0aGUgc3BlY2lmaWVkIHRhcmdldC5cbiAgICogVGhlc2Ugcm91dGVkIGV2ZW50cyBhcmUgbWF0Y2hlZCBldmVudHMuIEZvciBtb3JlIGluZm9ybWF0aW9uLCBzZWUgRXZlbnRzXG4gICAqIGFuZCBFdmVudCBQYXR0ZXJucyBpbiB0aGUgQW1hem9uIEV2ZW50QnJpZGdlIFVzZXIgR3VpZGUuXG4gICAqXG4gICAqIEBzZWVcbiAgICogaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2V2ZW50YnJpZGdlL2xhdGVzdC91c2VyZ3VpZGUvZXZlbnRicmlkZ2UtYW5kLWV2ZW50LXBhdHRlcm5zLmh0bWxcbiAgICpcbiAgICogWW91IG11c3Qgc3BlY2lmeSB0aGlzIHByb3BlcnR5IChlaXRoZXIgdmlhIHByb3BzIG9yIHZpYVxuICAgKiBgYWRkRXZlbnRQYXR0ZXJuYCksIHRoZSBgc2NoZWR1bGVFeHByZXNzaW9uYCBwcm9wZXJ0eSwgb3IgYm90aC4gVGhlXG4gICAqIG1ldGhvZCBgYWRkRXZlbnRQYXR0ZXJuYCBjYW4gYmUgdXNlZCB0byBhZGQgZmlsdGVyIHZhbHVlcyB0byB0aGUgZXZlbnRcbiAgICogcGF0dGVybi5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBOb25lLlxuICAgKi9cbiAgcmVhZG9ubHkgZXZlbnRQYXR0ZXJuPzogRXZlbnRQYXR0ZXJuO1xuXG4gIC8qKlxuICAgKiBUYXJnZXRzIHRvIGludm9rZSB3aGVuIHRoaXMgcnVsZSBtYXRjaGVzIGFuIGV2ZW50LlxuICAgKlxuICAgKiBJbnB1dCB3aWxsIGJlIHRoZSBmdWxsIG1hdGNoZWQgZXZlbnQuIElmIHlvdSB3aXNoIHRvIHNwZWNpZnkgY3VzdG9tXG4gICAqIHRhcmdldCBpbnB1dCwgdXNlIGBhZGRUYXJnZXQodGFyZ2V0WywgaW5wdXRPcHRpb25zXSlgLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIHRhcmdldHMuXG4gICAqL1xuICByZWFkb25seSB0YXJnZXRzPzogSVJ1bGVUYXJnZXRbXTtcblxuICAvKipcbiAgICogVGhlIGV2ZW50IGJ1cyB0byBhc3NvY2lhdGUgd2l0aCB0aGlzIHJ1bGUuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gVGhlIGRlZmF1bHQgZXZlbnQgYnVzLlxuICAgKi9cbiAgcmVhZG9ubHkgZXZlbnRCdXM/OiBJRXZlbnRCdXM7XG59XG5cbi8qKlxuICogRGVmaW5lcyBhbiBFdmVudEJyaWRnZSBSdWxlIGluIHRoaXMgc3RhY2suXG4gKlxuICogQHJlc291cmNlIEFXUzo6RXZlbnRzOjpSdWxlXG4gKi9cbmV4cG9ydCBjbGFzcyBSdWxlIGV4dGVuZHMgUmVzb3VyY2UgaW1wbGVtZW50cyBJUnVsZSB7XG5cbiAgLyoqXG4gICAqIEltcG9ydCBhbiBleGlzdGluZyBFdmVudEJyaWRnZSBSdWxlIHByb3ZpZGVkIGFuIEFSTlxuICAgKlxuICAgKiBAcGFyYW0gc2NvcGUgVGhlIHBhcmVudCBjcmVhdGluZyBjb25zdHJ1Y3QgKHVzdWFsbHkgYHRoaXNgKS5cbiAgICogQHBhcmFtIGlkIFRoZSBjb25zdHJ1Y3QncyBuYW1lLlxuICAgKiBAcGFyYW0gZXZlbnRSdWxlQXJuIEV2ZW50IFJ1bGUgQVJOIChpLmUuIGFybjphd3M6ZXZlbnRzOjxyZWdpb24+OjxhY2NvdW50LWlkPjpydWxlL015U2NoZWR1bGVkUnVsZSkuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGZyb21FdmVudFJ1bGVBcm4oc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgZXZlbnRSdWxlQXJuOiBzdHJpbmcpOiBJUnVsZSB7XG4gICAgY29uc3QgcGFydHMgPSBTdGFjay5vZihzY29wZSkuc3BsaXRBcm4oZXZlbnRSdWxlQXJuLCBBcm5Gb3JtYXQuU0xBU0hfUkVTT1VSQ0VfTkFNRSk7XG5cbiAgICBjbGFzcyBJbXBvcnQgZXh0ZW5kcyBSZXNvdXJjZSBpbXBsZW1lbnRzIElSdWxlIHtcbiAgICAgIHB1YmxpYyBydWxlQXJuID0gZXZlbnRSdWxlQXJuO1xuICAgICAgcHVibGljIHJ1bGVOYW1lID0gcGFydHMucmVzb3VyY2VOYW1lIHx8ICcnO1xuICAgIH1cbiAgICByZXR1cm4gbmV3IEltcG9ydChzY29wZSwgaWQpO1xuICB9XG5cbiAgcHVibGljIHJlYWRvbmx5IHJ1bGVBcm46IHN0cmluZztcbiAgcHVibGljIHJlYWRvbmx5IHJ1bGVOYW1lOiBzdHJpbmc7XG5cbiAgcHJpdmF0ZSByZWFkb25seSB0YXJnZXRzID0gbmV3IEFycmF5PENmblJ1bGUuVGFyZ2V0UHJvcGVydHk+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgZXZlbnRQYXR0ZXJuOiBFdmVudFBhdHRlcm4gPSB7IH07XG4gIHByaXZhdGUgcmVhZG9ubHkgc2NoZWR1bGVFeHByZXNzaW9uPzogc3RyaW5nO1xuICBwcml2YXRlIHJlYWRvbmx5IGRlc2NyaXB0aW9uPzogc3RyaW5nO1xuXG4gIC8qKiBTZXQgdG8ga2VlcCB0cmFjayBvZiB3aGF0IHRhcmdldCBhY2NvdW50cyBhbmQgcmVnaW9ucyB3ZSd2ZSBhbHJlYWR5IGNyZWF0ZWQgZXZlbnQgYnVzZXMgZm9yICovXG4gIHByaXZhdGUgcmVhZG9ubHkgX3hFbnZUYXJnZXRzQWRkZWQgPSBuZXcgU2V0PHN0cmluZz4oKTtcblxuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogUnVsZVByb3BzID0geyB9KSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkLCB7XG4gICAgICBwaHlzaWNhbE5hbWU6IHByb3BzLnJ1bGVOYW1lLFxuICAgIH0pO1xuXG4gICAgaWYgKHByb3BzLmV2ZW50QnVzICYmIHByb3BzLnNjaGVkdWxlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBhc3NvY2lhdGUgcnVsZSB3aXRoIFxcJ2V2ZW50QnVzXFwnIHdoZW4gdXNpbmcgXFwnc2NoZWR1bGVcXCcnKTtcbiAgICB9XG5cbiAgICB0aGlzLmRlc2NyaXB0aW9uID0gcHJvcHMuZGVzY3JpcHRpb247XG4gICAgdGhpcy5zY2hlZHVsZUV4cHJlc3Npb24gPSBwcm9wcy5zY2hlZHVsZT8uZXhwcmVzc2lvblN0cmluZztcblxuICAgIC8vIGFkZCBhIHdhcm5pbmcgb24gc3ludGggd2hlbiBtaW51dGUgaXMgbm90IGRlZmluZWQgaW4gYSBjcm9uIHNjaGVkdWxlXG4gICAgcHJvcHMuc2NoZWR1bGU/Ll9iaW5kKHRoaXMpO1xuXG4gICAgY29uc3QgcmVzb3VyY2UgPSBuZXcgQ2ZuUnVsZSh0aGlzLCAnUmVzb3VyY2UnLCB7XG4gICAgICBuYW1lOiB0aGlzLnBoeXNpY2FsTmFtZSxcbiAgICAgIGRlc2NyaXB0aW9uOiB0aGlzLmRlc2NyaXB0aW9uLFxuICAgICAgc3RhdGU6IHByb3BzLmVuYWJsZWQgPT0gbnVsbCA/ICdFTkFCTEVEJyA6IChwcm9wcy5lbmFibGVkID8gJ0VOQUJMRUQnIDogJ0RJU0FCTEVEJyksXG4gICAgICBzY2hlZHVsZUV4cHJlc3Npb246IHRoaXMuc2NoZWR1bGVFeHByZXNzaW9uLFxuICAgICAgZXZlbnRQYXR0ZXJuOiBMYXp5LmFueSh7IHByb2R1Y2U6ICgpID0+IHRoaXMuX3JlbmRlckV2ZW50UGF0dGVybigpIH0pLFxuICAgICAgdGFyZ2V0czogTGF6eS5hbnkoeyBwcm9kdWNlOiAoKSA9PiB0aGlzLnJlbmRlclRhcmdldHMoKSB9KSxcbiAgICAgIGV2ZW50QnVzTmFtZTogcHJvcHMuZXZlbnRCdXMgJiYgcHJvcHMuZXZlbnRCdXMuZXZlbnRCdXNOYW1lLFxuICAgIH0pO1xuXG4gICAgdGhpcy5ydWxlQXJuID0gdGhpcy5nZXRSZXNvdXJjZUFybkF0dHJpYnV0ZShyZXNvdXJjZS5hdHRyQXJuLCB7XG4gICAgICBzZXJ2aWNlOiAnZXZlbnRzJyxcbiAgICAgIHJlc291cmNlOiAncnVsZScsXG4gICAgICByZXNvdXJjZU5hbWU6IHRoaXMucGh5c2ljYWxOYW1lLFxuICAgIH0pO1xuICAgIHRoaXMucnVsZU5hbWUgPSB0aGlzLmdldFJlc291cmNlTmFtZUF0dHJpYnV0ZShyZXNvdXJjZS5yZWYpO1xuXG4gICAgdGhpcy5hZGRFdmVudFBhdHRlcm4ocHJvcHMuZXZlbnRQYXR0ZXJuKTtcblxuICAgIGZvciAoY29uc3QgdGFyZ2V0IG9mIHByb3BzLnRhcmdldHMgfHwgW10pIHtcbiAgICAgIHRoaXMuYWRkVGFyZ2V0KHRhcmdldCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYSB0YXJnZXQgdG8gdGhlIHJ1bGUuIFRoZSBhYnN0cmFjdCBjbGFzcyBSdWxlVGFyZ2V0IGNhbiBiZSBleHRlbmRlZCB0byBkZWZpbmUgbmV3XG4gICAqIHRhcmdldHMuXG4gICAqXG4gICAqIE5vLW9wIGlmIHRhcmdldCBpcyB1bmRlZmluZWQuXG4gICAqL1xuICBwdWJsaWMgYWRkVGFyZ2V0KHRhcmdldD86IElSdWxlVGFyZ2V0KTogdm9pZCB7XG4gICAgaWYgKCF0YXJnZXQpIHsgcmV0dXJuOyB9XG5cbiAgICAvLyBTaW1wbHkgaW5jcmVtZW50IGlkIGZvciBlYWNoIGBhZGRUYXJnZXRgIGNhbGwuIFRoaXMgaXMgZ3VhcmFudGVlZCB0byBiZSB1bmlxdWUuXG4gICAgY29uc3QgYXV0b0dlbmVyYXRlZElkID0gYFRhcmdldCR7dGhpcy50YXJnZXRzLmxlbmd0aH1gO1xuXG4gICAgY29uc3QgdGFyZ2V0UHJvcHMgPSB0YXJnZXQuYmluZCh0aGlzLCBhdXRvR2VuZXJhdGVkSWQpO1xuICAgIGNvbnN0IGlucHV0UHJvcHMgPSB0YXJnZXRQcm9wcy5pbnB1dCAmJiB0YXJnZXRQcm9wcy5pbnB1dC5iaW5kKHRoaXMpO1xuXG4gICAgY29uc3Qgcm9sZUFybiA9IHRhcmdldFByb3BzLnJvbGU/LnJvbGVBcm47XG4gICAgY29uc3QgaWQgPSB0YXJnZXRQcm9wcy5pZCB8fCBhdXRvR2VuZXJhdGVkSWQ7XG5cbiAgICBpZiAodGFyZ2V0UHJvcHMudGFyZ2V0UmVzb3VyY2UpIHtcbiAgICAgIGNvbnN0IHRhcmdldFN0YWNrID0gU3RhY2sub2YodGFyZ2V0UHJvcHMudGFyZ2V0UmVzb3VyY2UpO1xuXG4gICAgICBjb25zdCB0YXJnZXRBY2NvdW50ID0gKHRhcmdldFByb3BzLnRhcmdldFJlc291cmNlIGFzIElSZXNvdXJjZSkuZW52Py5hY2NvdW50IHx8IHRhcmdldFN0YWNrLmFjY291bnQ7XG4gICAgICBjb25zdCB0YXJnZXRSZWdpb24gPSAodGFyZ2V0UHJvcHMudGFyZ2V0UmVzb3VyY2UgYXMgSVJlc291cmNlKS5lbnY/LnJlZ2lvbiB8fCB0YXJnZXRTdGFjay5yZWdpb247XG5cbiAgICAgIGNvbnN0IHNvdXJjZVN0YWNrID0gU3RhY2sub2YodGhpcyk7XG4gICAgICBjb25zdCBzb3VyY2VBY2NvdW50ID0gc291cmNlU3RhY2suYWNjb3VudDtcbiAgICAgIGNvbnN0IHNvdXJjZVJlZ2lvbiA9IHNvdXJjZVN0YWNrLnJlZ2lvbjtcblxuICAgICAgLy8gaWYgdGhlIHRhcmdldCBpcyBpbiBhIGRpZmZlcmVudCBhY2NvdW50IG9yIHJlZ2lvbiBhbmQgaXMgZGVmaW5lZCBpbiB0aGlzIENESyBBcHBcbiAgICAgIC8vIHdlIGNhbiBnZW5lcmF0ZSBhbGwgdGhlIG5lZWRlZCBjb21wb25lbnRzOlxuICAgICAgLy8gLSBmb3J3YXJkaW5nIHJ1bGUgaW4gdGhlIHNvdXJjZSBzdGFjayAodGFyZ2V0OiBkZWZhdWx0IGV2ZW50IGJ1cyBvZiB0aGUgcmVjZWl2ZXIgcmVnaW9uKVxuICAgICAgLy8gLSBldmVudGJ1cyBwZXJtaXNzaW9ucyBwb2xpY3kgKGNyZWF0aW5nIGFuIGV4dHJhIHN0YWNrKVxuICAgICAgLy8gLSByZWNlaXZlciBydWxlIGluIHRoZSB0YXJnZXQgc3RhY2sgKHRhcmdldDogdGhlIGFjdHVhbCB0YXJnZXQpXG4gICAgICBpZiAoIXNhbWVFbnZEaW1lbnNpb24oc291cmNlQWNjb3VudCwgdGFyZ2V0QWNjb3VudCkgfHwgIXNhbWVFbnZEaW1lbnNpb24oc291cmNlUmVnaW9uLCB0YXJnZXRSZWdpb24pKSB7XG4gICAgICAgIC8vIGNyb3NzLWFjY291bnQgYW5kL29yIGNyb3NzLXJlZ2lvbiBldmVudCAtIHN0cmFwIGluLCB0aGlzIHdvcmtzIGRpZmZlcmVudGx5IHRoYW4gcmVndWxhciBldmVudHMhXG4gICAgICAgIC8vIGJhc2VkIG9uOlxuICAgICAgICAvLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vZXZlbnRicmlkZ2UvbGF0ZXN0L3VzZXJndWlkZS9lYi1jcm9zcy1hY2NvdW50Lmh0bWxcblxuICAgICAgICAvLyBmb3IgY3Jvc3MtYWNjb3VudCBvciBjcm9zcy1yZWdpb24gZXZlbnRzLCB3ZSByZXF1aXJlIGEgY29uY3JldGUgdGFyZ2V0IGFjY291bnQgYW5kIHJlZ2lvblxuICAgICAgICBpZiAoIXRhcmdldEFjY291bnQgfHwgVG9rZW4uaXNVbnJlc29sdmVkKHRhcmdldEFjY291bnQpKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdZb3UgbmVlZCB0byBwcm92aWRlIGEgY29uY3JldGUgYWNjb3VudCBmb3IgdGhlIHRhcmdldCBzdGFjayB3aGVuIHVzaW5nIGNyb3NzLWFjY291bnQgb3IgY3Jvc3MtcmVnaW9uIGV2ZW50cycpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGFyZ2V0UmVnaW9uIHx8IFRva2VuLmlzVW5yZXNvbHZlZCh0YXJnZXRSZWdpb24pKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdZb3UgbmVlZCB0byBwcm92aWRlIGEgY29uY3JldGUgcmVnaW9uIGZvciB0aGUgdGFyZ2V0IHN0YWNrIHdoZW4gdXNpbmcgY3Jvc3MtYWNjb3VudCBvciBjcm9zcy1yZWdpb24gZXZlbnRzJyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKFRva2VuLmlzVW5yZXNvbHZlZChzb3VyY2VBY2NvdW50KSkge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignWW91IG5lZWQgdG8gcHJvdmlkZSBhIGNvbmNyZXRlIGFjY291bnQgZm9yIHRoZSBzb3VyY2Ugc3RhY2sgd2hlbiB1c2luZyBjcm9zcy1hY2NvdW50IG9yIGNyb3NzLXJlZ2lvbiBldmVudHMnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIERvbid0IGV4YWN0bHkgdW5kZXJzdGFuZCB3aHkgdGhpcyBjb2RlIHdhcyBoZXJlIChzZWVtcyB1bmxpa2VseSB0aGlzIHJ1bGUgd291bGQgYmUgdmlvbGF0ZWQpLCBidXRcbiAgICAgICAgLy8gbGV0J3MgbGVhdmUgaXQgaW4gbm9uZXRoZWxlc3MuXG4gICAgICAgIGNvbnN0IHNvdXJjZUFwcCA9IHRoaXMubm9kZS5yb290O1xuICAgICAgICBpZiAoIXNvdXJjZUFwcCB8fCAhQXBwLmlzQXBwKHNvdXJjZUFwcCkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0V2ZW50IHN0YWNrIHdoaWNoIHVzZXMgY3Jvc3MtYWNjb3VudCBvciBjcm9zcy1yZWdpb24gdGFyZ2V0cyBtdXN0IGJlIHBhcnQgb2YgYSBDREsgYXBwJyk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgdGFyZ2V0QXBwID0gTm9kZS5vZih0YXJnZXRQcm9wcy50YXJnZXRSZXNvdXJjZSkucm9vdDtcbiAgICAgICAgaWYgKCF0YXJnZXRBcHAgfHwgIUFwcC5pc0FwcCh0YXJnZXRBcHApKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdUYXJnZXQgc3RhY2sgd2hpY2ggdXNlcyBjcm9zcy1hY2NvdW50IG9yIGNyb3NzLXJlZ2lvbiBldmVudCB0YXJnZXRzIG11c3QgYmUgcGFydCBvZiBhIENESyBhcHAnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc291cmNlQXBwICE9PSB0YXJnZXRBcHApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0V2ZW50IHN0YWNrIGFuZCB0YXJnZXQgc3RhY2sgbXVzdCBiZWxvbmcgdG8gdGhlIHNhbWUgQ0RLIGFwcCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVGhlIHRhcmdldCBvZiB0aGlzIFJ1bGUgd2lsbCBiZSB0aGUgZGVmYXVsdCBldmVudCBidXMgb2YgdGhlIHRhcmdldCBlbnZpcm9ubWVudFxuICAgICAgICB0aGlzLmVuc3VyZVhFbnZUYXJnZXRFdmVudEJ1cyh0YXJnZXRTdGFjaywgdGFyZ2V0QWNjb3VudCwgdGFyZ2V0UmVnaW9uLCBpZCk7XG5cbiAgICAgICAgLy8gVGhlIGFjdHVhbCBydWxlIGxpdmVzIGluIHRoZSB0YXJnZXQgc3RhY2suIE90aGVyIHRoYW4gdGhlIGFjY291bnQsIGl0J3MgaWRlbnRpY2FsIHRvIHRoaXMgb25lLFxuICAgICAgICAvLyBidXQgb25seSBldmFsdWF0ZWQgYXQgcmVuZGVyIHRpbWUgKHZpYSBhIHNwZWNpYWwgc3ViY2xhc3MpLlxuICAgICAgICAvL1xuICAgICAgICAvLyBGSVhNRTogdGhlIE1pcnJvclJ1bGUgaXMgYSBiaXQgc2lsbHksIGZvcndhcmRpbmcgdGhlIGV4YWN0IHNhbWUgZXZlbnQgdG8gYW5vdGhlciBldmVudCBidXNcbiAgICAgICAgLy8gYW5kIHRyaWdnZXIgb24gaXQgdGhlcmUgKHRoZXJlIHdpbGwgYmUgaXNzdWVzIHdpdGggY29uc3RydWN0IHJlZmVyZW5jZXMsIGZvciBleGFtcGxlKS4gRXNwZWNpYWxseVxuICAgICAgICAvLyBpbiB0aGUgY2FzZSBvZiBzY2hlZHVsZWQgZXZlbnRzLCB3ZSB3aWxsIGp1c3QgdHJpZ2dlciBib3RoIHJ1bGVzIGluIHBhcmFsbGVsIGluIGJvdGggZW52aXJvbm1lbnRzLlxuICAgICAgICAvL1xuICAgICAgICAvLyBBIGJldHRlciBzb2x1dGlvbiB3b3VsZCBiZSB0byBoYXZlIHRoZSBzb3VyY2UgcnVsZSBhZGQgYSB1bmlxdWUgdG9rZW4gdG8gdGhlIHRoZSBldmVudCxcbiAgICAgICAgLy8gYW5kIGhhdmUgdGhlIG1pcnJvciBydWxlIHRyaWdnZXIgb24gdGhhdCB0b2tlbiBvbmx5ICh0aGVyZWJ5IHByb3Blcmx5IHNlcGFyYXRpbmcgdHJpZ2dlcmluZywgd2hpY2hcbiAgICAgICAgLy8gaGFwcGVucyBpbiB0aGUgc291cmNlIGVudjsgYW5kIGFjdGl2YXRpbmcsIHdoaWNoIGhhcHBlbnMgaW4gdGhlIHRhcmdldCBlbnYpLlxuICAgICAgICAvL1xuICAgICAgICAvLyBEb24ndCBoYXZlIHRpbWUgdG8gZG8gdGhhdCByaWdodCBub3cuXG4gICAgICAgIGNvbnN0IG1pcnJvclJ1bGVTY29wZSA9IHRoaXMub2J0YWluTWlycm9yUnVsZVNjb3BlKHRhcmdldFN0YWNrLCB0YXJnZXRBY2NvdW50LCB0YXJnZXRSZWdpb24pO1xuICAgICAgICBuZXcgTWlycm9yUnVsZShtaXJyb3JSdWxlU2NvcGUsIGAke05hbWVzLnVuaXF1ZUlkKHRoaXMpfS0ke2lkfWAsIHtcbiAgICAgICAgICB0YXJnZXRzOiBbdGFyZ2V0XSxcbiAgICAgICAgICBldmVudFBhdHRlcm46IHRoaXMuZXZlbnRQYXR0ZXJuLFxuICAgICAgICAgIHNjaGVkdWxlOiB0aGlzLnNjaGVkdWxlRXhwcmVzc2lvbiA/IFNjaGVkdWxlLmV4cHJlc3Npb24odGhpcy5zY2hlZHVsZUV4cHJlc3Npb24pIDogdW5kZWZpbmVkLFxuICAgICAgICAgIGRlc2NyaXB0aW9uOiB0aGlzLmRlc2NyaXB0aW9uLFxuICAgICAgICB9LCB0aGlzKTtcblxuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gSGVyZSBvbmx5IGlmIHRoZSB0YXJnZXQgZG9lcyBub3QgaGF2ZSBhIHRhcmdldFJlc291cmNlIGRlZmluZWQuXG4gICAgLy8gSW4gc3VjaCBjYXNlIHdlIGRvbid0IGhhdmUgdG8gZ2VuZXJhdGUgYW55IGV4dHJhIGNvbXBvbmVudC5cbiAgICAvLyBOb3RlIHRoYXQgdGhpcyBjYW4gYWxzbyBiZSBhbiBpbXBvcnRlZCByZXNvdXJjZSAoaS5lOiBFdmVudEJ1cyB0YXJnZXQpXG5cbiAgICB0aGlzLnRhcmdldHMucHVzaCh7XG4gICAgICBpZCxcbiAgICAgIGFybjogdGFyZ2V0UHJvcHMuYXJuLFxuICAgICAgcm9sZUFybixcbiAgICAgIGVjc1BhcmFtZXRlcnM6IHRhcmdldFByb3BzLmVjc1BhcmFtZXRlcnMsXG4gICAgICBodHRwUGFyYW1ldGVyczogdGFyZ2V0UHJvcHMuaHR0cFBhcmFtZXRlcnMsXG4gICAgICBraW5lc2lzUGFyYW1ldGVyczogdGFyZ2V0UHJvcHMua2luZXNpc1BhcmFtZXRlcnMsXG4gICAgICBydW5Db21tYW5kUGFyYW1ldGVyczogdGFyZ2V0UHJvcHMucnVuQ29tbWFuZFBhcmFtZXRlcnMsXG4gICAgICBiYXRjaFBhcmFtZXRlcnM6IHRhcmdldFByb3BzLmJhdGNoUGFyYW1ldGVycyxcbiAgICAgIGRlYWRMZXR0ZXJDb25maWc6IHRhcmdldFByb3BzLmRlYWRMZXR0ZXJDb25maWcsXG4gICAgICByZXRyeVBvbGljeTogdGFyZ2V0UHJvcHMucmV0cnlQb2xpY3ksXG4gICAgICBzcXNQYXJhbWV0ZXJzOiB0YXJnZXRQcm9wcy5zcXNQYXJhbWV0ZXJzLFxuICAgICAgaW5wdXQ6IGlucHV0UHJvcHMgJiYgaW5wdXRQcm9wcy5pbnB1dCxcbiAgICAgIGlucHV0UGF0aDogaW5wdXRQcm9wcyAmJiBpbnB1dFByb3BzLmlucHV0UGF0aCxcbiAgICAgIGlucHV0VHJhbnNmb3JtZXI6IGlucHV0UHJvcHM/LmlucHV0VGVtcGxhdGUgIT09IHVuZGVmaW5lZCA/IHtcbiAgICAgICAgaW5wdXRUZW1wbGF0ZTogaW5wdXRQcm9wcy5pbnB1dFRlbXBsYXRlLFxuICAgICAgICBpbnB1dFBhdGhzTWFwOiBpbnB1dFByb3BzLmlucHV0UGF0aHNNYXAsXG4gICAgICB9IDogdW5kZWZpbmVkLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYW4gZXZlbnQgcGF0dGVybiBmaWx0ZXIgdG8gdGhpcyBydWxlLiBJZiBhIHBhdHRlcm4gd2FzIGFscmVhZHkgc3BlY2lmaWVkLFxuICAgKiB0aGVzZSB2YWx1ZXMgYXJlIG1lcmdlZCBpbnRvIHRoZSBleGlzdGluZyBwYXR0ZXJuLlxuICAgKlxuICAgKiBGb3IgZXhhbXBsZSwgaWYgdGhlIHJ1bGUgYWxyZWFkeSBjb250YWlucyB0aGUgcGF0dGVybjpcbiAgICpcbiAgICogICAge1xuICAgKiAgICAgIFwicmVzb3VyY2VzXCI6IFsgXCJyMVwiIF0sXG4gICAqICAgICAgXCJkZXRhaWxcIjoge1xuICAgKiAgICAgICAgXCJoZWxsb1wiOiBbIDEgXVxuICAgKiAgICAgIH1cbiAgICogICAgfVxuICAgKlxuICAgKiBBbmQgYGFkZEV2ZW50UGF0dGVybmAgaXMgY2FsbGVkIHdpdGggdGhlIHBhdHRlcm46XG4gICAqXG4gICAqICAgIHtcbiAgICogICAgICBcInJlc291cmNlc1wiOiBbIFwicjJcIiBdLFxuICAgKiAgICAgIFwiZGV0YWlsXCI6IHtcbiAgICogICAgICAgIFwiZm9vXCI6IFsgXCJiYXJcIiBdXG4gICAqICAgICAgfVxuICAgKiAgICB9XG4gICAqXG4gICAqIFRoZSByZXN1bHRpbmcgZXZlbnQgcGF0dGVybiB3aWxsIGJlOlxuICAgKlxuICAgKiAgICB7XG4gICAqICAgICAgXCJyZXNvdXJjZXNcIjogWyBcInIxXCIsIFwicjJcIiBdLFxuICAgKiAgICAgIFwiZGV0YWlsXCI6IHtcbiAgICogICAgICAgIFwiaGVsbG9cIjogWyAxIF0sXG4gICAqICAgICAgICBcImZvb1wiOiBbIFwiYmFyXCIgXVxuICAgKiAgICAgIH1cbiAgICogICAgfVxuICAgKlxuICAgKi9cbiAgcHVibGljIGFkZEV2ZW50UGF0dGVybihldmVudFBhdHRlcm4/OiBFdmVudFBhdHRlcm4pIHtcbiAgICBpZiAoIWV2ZW50UGF0dGVybikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBtZXJnZUV2ZW50UGF0dGVybih0aGlzLmV2ZW50UGF0dGVybiwgZXZlbnRQYXR0ZXJuKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBOb3QgcHJpdmF0ZSBvbmx5IHRvIGJlIG92ZXJyaWRlZW4gaW4gQ29weVJ1bGUuXG4gICAqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHVibGljIF9yZW5kZXJFdmVudFBhdHRlcm4oKTogYW55IHtcbiAgICByZXR1cm4gcmVuZGVyRXZlbnRQYXR0ZXJuKHRoaXMuZXZlbnRQYXR0ZXJuKTtcbiAgfVxuXG4gIHByb3RlY3RlZCB2YWxpZGF0ZSgpIHtcbiAgICBpZiAoT2JqZWN0LmtleXModGhpcy5ldmVudFBhdHRlcm4pLmxlbmd0aCA9PT0gMCAmJiAhdGhpcy5zY2hlZHVsZUV4cHJlc3Npb24pIHtcbiAgICAgIHJldHVybiBbJ0VpdGhlciBcXCdldmVudFBhdHRlcm5cXCcgb3IgXFwnc2NoZWR1bGVcXCcgbXVzdCBiZSBkZWZpbmVkJ107XG4gICAgfVxuXG4gICAgcmV0dXJuIFtdO1xuICB9XG5cbiAgcHJpdmF0ZSByZW5kZXJUYXJnZXRzKCkge1xuICAgIGlmICh0aGlzLnRhcmdldHMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnRhcmdldHM7XG4gIH1cblxuICAvKipcbiAgICogTWFrZSBzdXJlIHdlIGFkZCB0aGUgdGFyZ2V0IGVudmlyb25tZW50cyBldmVudCBidXMgYXMgYSB0YXJnZXQsIGFuZCB0aGUgdGFyZ2V0IGhhcyBwZXJtaXNzaW9ucyBzZXQgdXAgdG8gcmVjZWl2ZSBvdXIgZXZlbnRzXG4gICAqXG4gICAqIEZvciBjcm9zcy1hY2NvdW50IHJ1bGVzLCB1c2VzIGEgc3VwcG9ydCBzdGFjayB0byBzZXQgdXAgYSBwb2xpY3kgb24gdGhlIHRhcmdldCBldmVudCBidXMuXG4gICAqL1xuICBwcml2YXRlIGVuc3VyZVhFbnZUYXJnZXRFdmVudEJ1cyh0YXJnZXRTdGFjazogU3RhY2ssIHRhcmdldEFjY291bnQ6IHN0cmluZywgdGFyZ2V0UmVnaW9uOiBzdHJpbmcsIGlkOiBzdHJpbmcpIHtcbiAgICAvLyB0aGUgX2FjdHVhbF8gdGFyZ2V0IGlzIGp1c3QgdGhlIGV2ZW50IGJ1cyBvZiB0aGUgdGFyZ2V0J3MgYWNjb3VudFxuICAgIC8vIG1ha2Ugc3VyZSB3ZSBvbmx5IGFkZCBpdCBvbmNlIHBlciBhY2NvdW50IHBlciByZWdpb25cbiAgICBjb25zdCBrZXkgPSBgJHt0YXJnZXRBY2NvdW50fToke3RhcmdldFJlZ2lvbn1gO1xuICAgIGlmICh0aGlzLl94RW52VGFyZ2V0c0FkZGVkLmhhcyhrZXkpKSB7IHJldHVybjsgfVxuICAgIHRoaXMuX3hFbnZUYXJnZXRzQWRkZWQuYWRkKGtleSk7XG5cbiAgICBjb25zdCBldmVudEJ1c0FybiA9IHRhcmdldFN0YWNrLmZvcm1hdEFybih7XG4gICAgICBzZXJ2aWNlOiAnZXZlbnRzJyxcbiAgICAgIHJlc291cmNlOiAnZXZlbnQtYnVzJyxcbiAgICAgIHJlc291cmNlTmFtZTogJ2RlZmF1bHQnLFxuICAgICAgcmVnaW9uOiB0YXJnZXRSZWdpb24sXG4gICAgICBhY2NvdW50OiB0YXJnZXRBY2NvdW50LFxuICAgIH0pO1xuXG4gICAgLy8gRm9yIHNvbWUgcmVhc29uLCBjcm9zcy1yZWdpb24gcmVxdWlyZXMgYSBSb2xlICh3aXRoIGBQdXRFdmVudHNgIG9uIHRoZVxuICAgIC8vIHRhcmdldCBldmVudCBidXMpIHdoaWxlIGNyb3NzLWFjY291bnQgZG9lc24ndFxuICAgIGNvbnN0IHJvbGVBcm4gPSAhc2FtZUVudkRpbWVuc2lvbih0YXJnZXRSZWdpb24sIFN0YWNrLm9mKHRoaXMpLnJlZ2lvbilcbiAgICAgID8gdGhpcy5jcm9zc1JlZ2lvblB1dEV2ZW50c1JvbGUoZXZlbnRCdXNBcm4pLnJvbGVBcm5cbiAgICAgIDogdW5kZWZpbmVkO1xuXG4gICAgdGhpcy50YXJnZXRzLnB1c2goe1xuICAgICAgaWQsXG4gICAgICBhcm46IGV2ZW50QnVzQXJuLFxuICAgICAgcm9sZUFybixcbiAgICB9KTtcblxuICAgIC8vIEFkZCBhIHBvbGljeSB0byB0aGUgdGFyZ2V0IEV2ZW50IEJ1cyB0byBhbGxvdyB0aGUgc291cmNlIGFjY291bnQvcmVnaW9uIHRvIHB1Ymxpc2ggaW50byBpdC5cbiAgICAvL1xuICAgIC8vIFNpbmNlIHRoaXMgRXZlbnQgQnVzIHBlcm1pc3Npb24gbmVlZHMgdG8gYmUgZGVwbG95ZWQgYmVmb3JlIHRoZSBzdGFjayBjb250YWluaW5nIHRoZSBSdWxlIGlzIGRlcGxveWVkXG4gICAgLy8gKGFzIEV2ZW50QnJpZGdlIHZlcmlmaWVzIHdoZXRoZXIgeW91IGhhdmUgcGVybWlzc2lvbnMgdG8gdGhlIHRhcmdldHMgb24gcnVsZSBjcmVhdGlvbiksIHRoaXMgbmVlZHNcbiAgICAvLyB0byBiZSBpbiBhIHN1cHBvcnQgc3RhY2suXG5cbiAgICBjb25zdCBzb3VyY2VBcHAgPSB0aGlzLm5vZGUucm9vdCBhcyBBcHA7XG4gICAgY29uc3Qgc291cmNlQWNjb3VudCA9IFN0YWNrLm9mKHRoaXMpLmFjY291bnQ7XG5cbiAgICAvLyBJZiBkaWZmZXJlbnQgYWNjb3VudHMsIHdlIG5lZWQgdG8gYWRkIHRoZSBwZXJtaXNzaW9ucyB0byB0aGUgdGFyZ2V0IGV2ZW50YnVzXG4gICAgLy9cbiAgICAvLyBGb3IgZGlmZmVyZW50IHJlZ2lvbiwgbm8gbmVlZCBmb3IgYSBwb2xpY3kgb24gdGhlIHRhcmdldCBldmVudCBidXMgKGJ1dCBhIG5lZWRcbiAgICAvLyBmb3IgYSByb2xlKS5cbiAgICBpZiAoIXNhbWVFbnZEaW1lbnNpb24oc291cmNlQWNjb3VudCwgdGFyZ2V0QWNjb3VudCkpIHtcbiAgICAgIGNvbnN0IHN0YWNrSWQgPSBgRXZlbnRCdXNQb2xpY3ktJHtzb3VyY2VBY2NvdW50fS0ke3RhcmdldFJlZ2lvbn0tJHt0YXJnZXRBY2NvdW50fWA7XG4gICAgICBsZXQgZXZlbnRCdXNQb2xpY3lTdGFjazogU3RhY2sgPSBzb3VyY2VBcHAubm9kZS50cnlGaW5kQ2hpbGQoc3RhY2tJZCkgYXMgU3RhY2s7XG4gICAgICBpZiAoIWV2ZW50QnVzUG9saWN5U3RhY2spIHtcbiAgICAgICAgZXZlbnRCdXNQb2xpY3lTdGFjayA9IG5ldyBTdGFjayhzb3VyY2VBcHAsIHN0YWNrSWQsIHtcbiAgICAgICAgICBlbnY6IHtcbiAgICAgICAgICAgIGFjY291bnQ6IHRhcmdldEFjY291bnQsXG4gICAgICAgICAgICByZWdpb246IHRhcmdldFJlZ2lvbixcbiAgICAgICAgICB9LFxuICAgICAgICAgIC8vIFRoZSByZWdpb24gaW4gdGhlIHN0YWNrIG5hbWUgaXMgcmF0aGVyIHJlZHVuZGFudCAoaXQgd2lsbCBhbHdheXMgYmUgdGhlIHRhcmdldCByZWdpb24pXG4gICAgICAgICAgLy8gTGVhdmluZyBpdCBpbiBmb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHkuXG4gICAgICAgICAgc3RhY2tOYW1lOiBgJHt0YXJnZXRTdGFjay5zdGFja05hbWV9LUV2ZW50QnVzUG9saWN5LXN1cHBvcnQtJHt0YXJnZXRSZWdpb259LSR7c291cmNlQWNjb3VudH1gLFxuICAgICAgICB9KTtcbiAgICAgICAgbmV3IENmbkV2ZW50QnVzUG9saWN5KGV2ZW50QnVzUG9saWN5U3RhY2ssICdHaXZlUGVybVRvT3RoZXJBY2NvdW50Jywge1xuICAgICAgICAgIGFjdGlvbjogJ2V2ZW50czpQdXRFdmVudHMnLFxuICAgICAgICAgIHN0YXRlbWVudElkOiBgQWxsb3ctYWNjb3VudC0ke3NvdXJjZUFjY291bnR9LSR7dGhpcy5ub2RlLmFkZHJ9YCxcbiAgICAgICAgICBwcmluY2lwYWw6IHNvdXJjZUFjY291bnQsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgICAgLy8gZGVwbG95IHRoZSBldmVudCBidXMgcGVybWlzc2lvbnMgYmVmb3JlIHRoZSBzb3VyY2Ugc3RhY2tcbiAgICAgIFN0YWNrLm9mKHRoaXMpLmFkZERlcGVuZGVuY3koZXZlbnRCdXNQb2xpY3lTdGFjayk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiB0aGUgc2NvcGUgd2hlcmUgdGhlIG1pcnJvciBydWxlIHNob3VsZCBiZSBjcmVhdGVkIGZvciB4LWVudiBldmVudCB0YXJnZXRzXG4gICAqXG4gICAqIFRoaXMgaXMgdGhlIHRhcmdldCByZXNvdXJjZSdzIGNvbnRhaW5pbmcgc3RhY2sgaWYgaXQgc2hhcmVzIHRoZSBzYW1lIHJlZ2lvbiAob3duZWRcbiAgICogcmVzb3VyY2VzKSwgb3Igc2hvdWxkIGJlIGEgZnJlc2ggc3VwcG9ydCBzdGFjayBmb3IgaW1wb3J0ZWQgcmVzb3VyY2VzLlxuICAgKlxuICAgKiBXZSBkb24ndCBpbXBsZW1lbnQgdGhlIHNlY29uZCB5ZXQsIGFzIEkgaGF2ZSB0byB0aGluayBsb25nIGFuZCBoYXJkIG9uIHdoZXRoZXIgd2VcbiAgICogY2FuIHJldXNlIHRoZSBleGlzdGluZyBzdXBwb3J0IHN0YWNrIG9yIG5vdCwgYW5kIEkgZG9uJ3QgaGF2ZSB0aW1lIGZvciB0aGF0IHJpZ2h0IG5vdy5cbiAgICovXG4gIHByaXZhdGUgb2J0YWluTWlycm9yUnVsZVNjb3BlKHRhcmdldFN0YWNrOiBTdGFjaywgdGFyZ2V0QWNjb3VudDogc3RyaW5nLCB0YXJnZXRSZWdpb246IHN0cmluZyk6IENvbnN0cnVjdCB7XG4gICAgLy8gZm9yIGNyb3NzLWFjY291bnQgb3IgY3Jvc3MtcmVnaW9uIGV2ZW50cywgd2UgY2Fubm90IGNyZWF0ZSBuZXcgY29tcG9uZW50cyBmb3IgYW4gaW1wb3J0ZWQgcmVzb3VyY2VcbiAgICAvLyBiZWNhdXNlIHdlIGRvbid0IGhhdmUgdGhlIHRhcmdldCBzdGFja1xuICAgIGlmIChzYW1lRW52RGltZW5zaW9uKHRhcmdldFN0YWNrLmFjY291bnQsIHRhcmdldEFjY291bnQpICYmIHNhbWVFbnZEaW1lbnNpb24odGFyZ2V0U3RhY2sucmVnaW9uLCB0YXJnZXRSZWdpb24pKSB7XG4gICAgICByZXR1cm4gdGFyZ2V0U3RhY2s7XG4gICAgfVxuXG4gICAgLy8gRm9yIG5vdywgd2UgZG9uJ3QgZG8gdGhlIHdvcmsgZm9yIHRoZSBzdXBwb3J0IHN0YWNrIHlldFxuICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGNyZWF0ZSBhIGNyb3NzLWFjY291bnQgb3IgY3Jvc3MtcmVnaW9uIHJ1bGUgZm9yIGFuIGltcG9ydGVkIHJlc291cmNlIChjcmVhdGUgYSBzdGFjayB3aXRoIHRoZSByaWdodCBlbnZpcm9ubWVudCBmb3IgdGhlIGltcG9ydGVkIHJlc291cmNlKScpO1xuICB9XG5cbiAgLyoqXG4gICAqIE9idGFpbiB0aGUgUm9sZSBmb3IgdGhlIEV2ZW50QnJpZGdlIGV2ZW50XG4gICAqXG4gICAqIElmIGEgcm9sZSBhbHJlYWR5IGV4aXN0cywgaXQgd2lsbCBiZSByZXR1cm5lZC4gVGhpcyBlbnN1cmVzIHRoYXQgaWYgbXVsdGlwbGVcbiAgICogZXZlbnRzIGhhdmUgdGhlIHNhbWUgdGFyZ2V0LCB0aGV5IHdpbGwgc2hhcmUgYSByb2xlLlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIHByaXZhdGUgY3Jvc3NSZWdpb25QdXRFdmVudHNSb2xlKGV2ZW50QnVzQXJuOiBzdHJpbmcpOiBJUm9sZSB7XG4gICAgY29uc3QgaWQgPSAnRXZlbnRzUm9sZSc7XG4gICAgbGV0IHJvbGUgPSB0aGlzLm5vZGUudHJ5RmluZENoaWxkKGlkKSBhcyBJUm9sZTtcbiAgICBpZiAoIXJvbGUpIHtcbiAgICAgIHJvbGUgPSBuZXcgUm9sZSh0aGlzLCBpZCwge1xuICAgICAgICByb2xlTmFtZTogUGh5c2ljYWxOYW1lLkdFTkVSQVRFX0lGX05FRURFRCxcbiAgICAgICAgYXNzdW1lZEJ5OiBuZXcgU2VydmljZVByaW5jaXBhbCgnZXZlbnRzLmFtYXpvbmF3cy5jb20nKSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJvbGUuYWRkVG9QcmluY2lwYWxQb2xpY3kobmV3IFBvbGljeVN0YXRlbWVudCh7XG4gICAgICBhY3Rpb25zOiBbJ2V2ZW50czpQdXRFdmVudHMnXSxcbiAgICAgIHJlc291cmNlczogW2V2ZW50QnVzQXJuXSxcbiAgICB9KSk7XG5cbiAgICByZXR1cm4gcm9sZTtcbiAgfVxufVxuXG4vKipcbiAqIEEgcnVsZSB0aGF0IG1pcnJvcnMgYW5vdGhlciBydWxlXG4gKi9cbmNsYXNzIE1pcnJvclJ1bGUgZXh0ZW5kcyBSdWxlIHtcbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IFJ1bGVQcm9wcywgcHJpdmF0ZSByZWFkb25seSBzb3VyY2U6IFJ1bGUpIHtcbiAgICBzdXBlcihzY29wZSwgaWQsIHByb3BzKTtcbiAgfVxuXG4gIHB1YmxpYyBfcmVuZGVyRXZlbnRQYXR0ZXJuKCk6IGFueSB7XG4gICAgcmV0dXJuIHRoaXMuc291cmNlLl9yZW5kZXJFdmVudFBhdHRlcm4oKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBPdmVycmlkZSB2YWxpZGF0ZSB0byBiZSBhIG5vLW9wXG4gICAqXG4gICAqIFRoZSBydWxlcyBhcmUgbmV2ZXIgc3RvcmVkIG9uIHRoaXMgb2JqZWN0IHNvIHRoZXJlJ3Mgbm90aGluZyB0byB2YWxpZGF0ZS5cbiAgICpcbiAgICogSW5zdGVhZCwgd2UgbWlycm9yIHRoZSBvdGhlciBydWxlIGF0IHJlbmRlciB0aW1lLlxuICAgKi9cbiAgcHJvdGVjdGVkIHZhbGlkYXRlKCk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gW107XG4gIH1cbn1cbiJdfQ== |
\ | No newline at end of file |