@pipeline-builder/pipeline-data 4.1.0 → 4.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,223 +1,21 @@
1
1
  // Copyright 2026 Pipeline Builder Contributors
2
2
  // SPDX-License-Identifier: Apache-2.0
3
- import { createCacheService, createLogger, errorMessage, REPORT_INTERVALS, scrubAwsIdentifiers, scrubAwsIdentifiersFromString } from '@pipeline-builder/api-core';
3
+ import { createLogger, errorMessage, scrubAwsIdentifiers, scrubAwsIdentifiersFromString } from '@pipeline-builder/api-core';
4
4
  import { inArray, sql } from 'drizzle-orm';
5
5
  import { drizzleRows } from './crud-service.js';
6
6
  import { schema } from '../database/drizzle-schema.js';
7
7
  import { withTenantTx, runWithTenantContext } from '../database/tenancy.js';
8
+ // Extracted for size — see ./reporting/. Everything public is re-exported below
9
+ // so `@pipeline-builder/pipeline-data`'s surface is unchanged by the split.
10
+ import { inventoryCache, timeseriesCache } from './reporting/caches.js';
11
+ import { DORA_INCIDENT_WINDOW_HOURS, resolveIncidentWindowHours } from './reporting/dora-scoring.js';
12
+ import { getDoraMetrics as doraMetrics, getDoraTrend as doraTrend, getBuildHealth as buildHealth, } from './reporting/dora.js';
13
+ import { orgScope, runReport } from './reporting/query-scope.js';
14
+ // Aliased: the module functions and the delegating methods below share names.
15
+ import { REPORTING_EVENT_RETENTION_DAYS, REPORTING_DORA_RETENTION_DAYS, resolveEventRetentionDays, resolveDoraRetentionDays, retentionCutoff, } from './reporting/retention.js';
16
+ import { assertReportInterval, scrubOptional, optionalStartedAtRange } from './reporting/sql-helpers.js';
17
+ export { resolveDoraRetentionDays, resolveEventRetentionDays, retentionCutoff } from './reporting/retention.js';
8
18
  const logger = createLogger('reporting-service');
9
- /**
10
- * Defense-in-depth guard for the `DATE_TRUNC(${interval}, …)` bucket argument.
11
- * The route layer (`parseReportInterval`) is the security boundary and already
12
- * rejects unknown intervals; this assert makes an invalid value fail fast at the
13
- * service boundary with a clear error instead of surfacing a raw Postgres error
14
- * if a caller ever bypasses the route validation. Shares api-core's
15
- * REPORT_INTERVALS allow-list so the two can't drift.
16
- */
17
- function assertReportInterval(interval) {
18
- if (!REPORT_INTERVALS.includes(interval)) {
19
- throw new Error(`Invalid report interval: ${interval}. Expected one of: ${REPORT_INTERVALS.join(', ')}`);
20
- }
21
- }
22
- /**
23
- * Scrub AWS identifiers from an optional free-form string, preserving `undefined`
24
- * (so an absent field stays absent rather than becoming an empty scrubbed string).
25
- * The DURABLE persistence boundary for the ingest paths — every user/AWS-derived
26
- * string field is funneled through this before insert.
27
- */
28
- function scrubOptional(value) {
29
- return value !== undefined ? scrubAwsIdentifiersFromString(value) : undefined;
30
- }
31
- /**
32
- * Cache for reporting aggregations. Two tiers:
33
- * - Inventory queries (plugin summary/distribution/versions): 5 min TTL — changes on plugin CRUD
34
- * - Execution/build queries with date ranges: 2 min TTL — new events arrive continuously
35
- */
36
- const inventoryCache = createCacheService('report:inv:', parseInt(process.env.CACHE_TTL_REPORT_INVENTORY || '300', 10));
37
- const timeseriesCache = createCacheService('report:ts:', parseInt(process.env.CACHE_TTL_REPORT_TIMESERIES || '120', 10));
38
- /**
39
- * The DORA headline environment. Deployment to this literal env name is the
40
- * industry-standard DORA signal; MTTR is measured production-only, and this
41
- * environment's card is the summary shown at the top of the panel.
42
- */
43
- const HEADLINE_ENV = 'production';
44
- /**
45
- * Incident→deploy correlation window (Phase 5). An incident is attributed to the
46
- * most recent SUCCESSFUL deploy to its environment whose `completed_at` is within
47
- * this many hours before the incident's `opened_at`. Default 24h; override via
48
- * `DORA_INCIDENT_WINDOW_HOURS`. Guarded to a positive finite number.
49
- */
50
- const DORA_INCIDENT_WINDOW_HOURS = (() => {
51
- const raw = Number(process.env.DORA_INCIDENT_WINDOW_HOURS);
52
- return Number.isFinite(raw) && raw > 0 ? raw : 24;
53
- })();
54
- /**
55
- * Resolve the effective incident→deploy correlation window (Phase 5b). A per-org
56
- * override (from `dora_settings.incident_window_hours`, surfaced through the
57
- * settings endpoint and threaded into {@link DoraOptions.incidentWindowHours})
58
- * wins when it is a positive finite number; otherwise the global env default
59
- * `DORA_INCIDENT_WINDOW_HOURS` applies. Centralized so the DORA correlation, the
60
- * incidents list, and the wiring-test dry-run all agree on the same rule.
61
- */
62
- function resolveIncidentWindowHours(override) {
63
- return override != null && Number.isFinite(override) && override > 0 ? override : DORA_INCIDENT_WINDOW_HOURS;
64
- }
65
- /**
66
- * Reporting retention windows (Phase 7). Records in `pipeline_events`,
67
- * `deployment_outcomes`, and `incidents` grow unbounded without a sweep, so a
68
- * split, per-org retention purge (see {@link ReportingService.purgeExpiredReportingData})
69
- * hard-deletes rows older than these windows, by `created_at`:
70
- * - **Standard events** — `pipeline_events` with `environment IS NULL`
71
- * (non-deploy STAGE/ACTION/build). High volume → short default (30 days).
72
- * - **DORA source** — `pipeline_events` with `environment IS NOT NULL` (deploy
73
- * stages) plus all of `deployment_outcomes` and `incidents`. Low volume →
74
- * longer default (180 days). DORA history is therefore bounded by this window;
75
- * the report query still hard-caps at 365 days (a longer per-org override only
76
- * retains raw source rows, never widens a report).
77
- * `ingest_health` and `dora_settings` are never purged. Env-overridable globals;
78
- * a per-org override in `dora_settings` wins (see {@link resolveEventRetentionDays}).
79
- */
80
- const RETENTION_MIN_DAYS = 1;
81
- const RETENTION_MAX_DAYS = 730;
82
- /** Parse a positive-int env day-count, clamped to [MIN, MAX], else `fallback`. */
83
- function retentionEnvDays(name, fallback) {
84
- const raw = Number(process.env[name]);
85
- if (!Number.isFinite(raw) || !Number.isInteger(raw) || raw < RETENTION_MIN_DAYS)
86
- return fallback;
87
- return Math.min(raw, RETENTION_MAX_DAYS);
88
- }
89
- const REPORTING_EVENT_RETENTION_DAYS = retentionEnvDays('REPORTING_EVENT_RETENTION_DAYS', 30);
90
- const REPORTING_DORA_RETENTION_DAYS = retentionEnvDays('REPORTING_DORA_RETENTION_DAYS', 180);
91
- /** Effective standard-event retention (days): a valid per-org override wins,
92
- * else the global env default. Shared by the sweep + the settings surface so
93
- * they can't drift. The `-1` unlimited sentinel (Phase 8) passes straight
94
- * through — the sweep reads it as "keep forever, skip this org's standard
95
- * events". A positive override clamps to [1, RETENTION_MAX_DAYS]; a `null`, a
96
- * non-integer, or any other out-of-range value (e.g. 0, -2) falls back to the
97
- * env default. */
98
- export function resolveEventRetentionDays(override) {
99
- if (override === -1)
100
- return -1;
101
- return override != null && Number.isInteger(override) && override >= RETENTION_MIN_DAYS
102
- ? Math.min(override, RETENTION_MAX_DAYS) : REPORTING_EVENT_RETENTION_DAYS;
103
- }
104
- /** Effective DORA-source retention (days): a valid per-org override wins, else
105
- * the global env default. The `-1` unlimited sentinel (Phase 8) passes straight
106
- * through — the sweep reads it as "keep forever, skip this org's DORA-source
107
- * windows". A positive override clamps to [1, RETENTION_MAX_DAYS]; a `null`, a
108
- * non-integer, or any other out-of-range value (e.g. 0, -2) falls back to the
109
- * env default. */
110
- export function resolveDoraRetentionDays(override) {
111
- if (override === -1)
112
- return -1;
113
- return override != null && Number.isInteger(override) && override >= RETENTION_MIN_DAYS
114
- ? Math.min(override, RETENTION_MAX_DAYS) : REPORTING_DORA_RETENTION_DAYS;
115
- }
116
- /** The cutoff instant for a retention window: rows with `created_at` strictly
117
- * before this (`< cutoff`) are expired. Deterministic for a fixed `now`. */
118
- export function retentionCutoff(now, days) {
119
- return new Date(now.getTime() - days * 86_400_000);
120
- }
121
- // DORA performance bands (thresholds from the DORA/Accelerate reports). Each
122
- // helper returns `null` when there's no sample to classify.
123
- /** Deployment frequency by deploys/day: elite ≥1/day, high ≥1/week, medium ≥1/month. */
124
- function doraLevelForFrequency(perDay, deployments) {
125
- if (deployments <= 0)
126
- return null;
127
- if (perDay >= 1)
128
- return 'elite';
129
- if (perDay >= 1 / 7)
130
- return 'high';
131
- if (perDay >= 1 / 30)
132
- return 'medium';
133
- return 'low';
134
- }
135
- /** Change failure rate by percent: elite ≤5%, high ≤10%, medium ≤15%. */
136
- function doraLevelForChangeFailure(pct, total) {
137
- if (total <= 0)
138
- return null;
139
- if (pct <= 5)
140
- return 'elite';
141
- if (pct <= 10)
142
- return 'high';
143
- if (pct <= 15)
144
- return 'medium';
145
- return 'low';
146
- }
147
- /** Time to restore by seconds: elite <1h, high <1 day, medium <1 week. */
148
- function doraLevelForRestore(avgSeconds) {
149
- if (avgSeconds == null)
150
- return null;
151
- if (avgSeconds < 3600)
152
- return 'elite';
153
- if (avgSeconds < 86400)
154
- return 'high';
155
- if (avgSeconds < 604800)
156
- return 'medium';
157
- return 'low';
158
- }
159
- /** Lead time by seconds: elite <1 day, high <1 week, medium <1 month. */
160
- function doraLevelForLeadTime(medianSeconds) {
161
- if (medianSeconds == null)
162
- return null;
163
- if (medianSeconds < 86400)
164
- return 'elite';
165
- if (medianSeconds < 604800)
166
- return 'high';
167
- if (medianSeconds < 2592000)
168
- return 'medium';
169
- return 'low';
170
- }
171
- /**
172
- * Round `value` to `digits` decimal places, returning a real number. Small
173
- * module-private helper so the DORA shaping doesn't repeat the
174
- * `Number(Number(x).toFixed(n))` pattern (toFixed alone yields a string).
175
- */
176
- function round(value, digits) {
177
- return Number(value.toFixed(digits));
178
- }
179
- /**
180
- * Median of a numeric sample, or `null` when empty. Used for measured lead time
181
- * and MTTR — both are cross-source gaps computed in JS from clamped deltas, so
182
- * the median lives here rather than in SQL PERCENTILE_CONT (keeps the golden
183
- * fixture tests able to prove the metric math without a live Postgres).
184
- */
185
- function median(values) {
186
- if (values.length === 0)
187
- return null;
188
- const s = [...values].sort((a, b) => a - b);
189
- const mid = Math.floor(s.length / 2);
190
- return s.length % 2 === 1 ? s[mid] : (s[mid - 1] + s[mid]) / 2;
191
- }
192
- /**
193
- * Roll a group of deploy/stage events (grouped per execution) up to one terminal
194
- * status: FAILED wins, then SUCCEEDED, else OTHER (still-running / non-terminal).
195
- * Shared by the three per-(env|stage, execution) rollup CTEs — DORA metrics, DORA
196
- * trend, and build health — so the precedence can't drift between them. Assumes the
197
- * grouped event alias is `e`.
198
- */
199
- const terminalStatusRollup = sql `CASE
200
- WHEN bool_or(e.status = 'FAILED') THEN 'FAILED'
201
- WHEN bool_or(e.status = 'SUCCEEDED') THEN 'SUCCEEDED'
202
- ELSE 'OTHER'
203
- END`;
204
- /** Optional `[from,to]` window on `e.started_at` for the execution reports —
205
- * a no-op `sql` fragment when either bound is absent (all-time). Shared by the
206
- * execution-count and per-pipeline-execution reports so they narrow identically. */
207
- function optionalStartedAtRange(range) {
208
- return range?.from && range?.to
209
- ? sql `AND e.started_at >= ${range.from}::timestamptz AND e.started_at <= ${range.to}::timestamptz`
210
- : sql ``;
211
- }
212
- // ─── Service ────────────────────────────────────────────
213
- /**
214
- * Read-only reporting service for pipeline execution and plugin inventory aggregations.
215
- * Does not extend CrudService — reports are aggregate queries, not entity CRUD.
216
- *
217
- * All queries are cached in-memory to avoid repeated expensive SQL aggregations:
218
- * - Inventory queries (plugin summary/distribution/versions): 5 min TTL
219
- * - Timeseries queries (execution/build metrics with date ranges): 2 min TTL
220
- */
221
19
  export class ReportingService {
222
20
  /** Invalidate all cached reports for an org (call after event ingest). */
223
21
  async invalidateOrg(orgId) {
@@ -365,54 +163,9 @@ export class ReportingService {
365
163
  return { inserted, skipped, unregisteredPipelineIds };
366
164
  }
367
165
  // ── Category 1: Pipeline Execution & Performance ──
368
- /**
369
- * Build the org-scope predicate for a report query. With `orgIds` (the
370
- * org → team rollup — a parent's `[self, ...descendants]`) it becomes an
371
- * `IN (...)` over the subtree; otherwise the single-org `= $org`. Returns a
372
- * `multi` flag so callers can run multi-org reads under sysadmin context
373
- * (the subtree spans orgs outside the request's RLS scope) and salt the
374
- * cache key.
375
- */
376
- orgScope(orgId, orgIds) {
377
- // Defense-in-depth: the multi-org rollup runs under sysadmin context (RLS
378
- // OFF, see runReport), so `orgIds` is the ONLY tenancy gate on the read. The
379
- // route resolves it from the platform's authoritative descendants endpoint as
380
- // `[self, ...descendants]`, but validate the subtree defensively here before
381
- // the bypass: the requesting (anchor) org MUST appear in the set. A set that
382
- // omits the caller's own org is a malformed/spoofed rollup — collapse to the
383
- // safe single-org scope rather than reading an arbitrary org under sysadmin.
384
- // (Full descendant-membership validation needs the org tree, which this
385
- // service does not hold — see the report FLAG.)
386
- const anchor = orgId.toLowerCase();
387
- const provided = (orgIds ?? []).filter((id) => typeof id === 'string' && id.length > 0);
388
- const anchored = provided.some((id) => id.toLowerCase() === anchor);
389
- if (provided.length > 0 && !anchored) {
390
- logger.warn('Reporting rollup rejected: requesting org absent from resolved subtree; using single-org scope', {
391
- orgId: anchor, subtreeSize: provided.length,
392
- });
393
- }
394
- const ids = provided.length > 0 && anchored ? provided : [orgId];
395
- const multi = ids.length > 1;
396
- const pred = multi
397
- ? sql `IN (${sql.join(ids.map((id) => sql `${id}`), sql `, `)})`
398
- : sql `= ${ids[0]}`;
399
- return { pred, multi };
400
- }
401
- /**
402
- * Run a report read. Single-org reads use the per-org cache (invalidated on
403
- * that org's event ingest). Rollup (multi-org) reads **bypass the cache** and
404
- * run under sysadmin context: they're admin-only and lower-frequency, and a
405
- * child org's event ingest can't invalidate a parent's rollup entry (reporting
406
- * has no org tree), so caching them would serve stale aggregates. Always fresh.
407
- */
408
- runReport(cacheKey, multi, exec) {
409
- return multi
410
- ? runWithTenantContext({ isSuperAdmin: true }, exec)
411
- : timeseriesCache.getOrSet(cacheKey, exec);
412
- }
413
166
  /** 1.1 Execution count per pipeline with status breakdown. */
414
167
  async getExecutionCount(orgId, orgIds, range) {
415
- const { pred, multi } = this.orgScope(orgId, orgIds);
168
+ const { pred, multi } = orgScope(orgId, orgIds);
416
169
  // Optional [from,to] window on the execution's started_at, mirroring the
417
170
  // sibling timeseries reports so the dashboard date-range picker narrows the
418
171
  // count too (an empty range = all-time, preserving the prior behavior). The
@@ -437,7 +190,7 @@ export class ReportingService {
437
190
  GROUP BY p.id
438
191
  ORDER BY total DESC
439
192
  `).then(r => drizzleRows(r.rows)));
440
- return this.runReport(`${orgId}:exec-count:${range?.from ?? ''}:${range?.to ?? ''}`, multi, exec);
193
+ return runReport(`${orgId}:exec-count:${range?.from ?? ''}:${range?.to ?? ''}`, multi, exec);
441
194
  }
442
195
  /**
443
196
  * 1.1b Per-pipeline execution history — DISTINCT executions for one pipeline,
@@ -456,7 +209,7 @@ export class ReportingService {
456
209
  * subtree. A pipelineId belonging to another org yields zero rows.
457
210
  */
458
211
  async listPipelineExecutions(orgId, pipelineId, orgIds, range, limit = 50) {
459
- const { pred, multi } = this.orgScope(orgId, orgIds);
212
+ const { pred, multi } = orgScope(orgId, orgIds);
460
213
  const rangeClause = optionalStartedAtRange(range);
461
214
  const exec = () => withTenantTx((tx) => tx.execute(sql `
462
215
  SELECT
@@ -480,12 +233,12 @@ export class ReportingService {
480
233
  ORDER BY MAX(e.created_at) DESC
481
234
  LIMIT ${limit}
482
235
  `).then(r => drizzleRows(r.rows)));
483
- return this.runReport(`${orgId}:pipeline-executions:${pipelineId}:${range?.from ?? ''}:${range?.to ?? ''}:${limit}`, multi, exec);
236
+ return runReport(`${orgId}:pipeline-executions:${pipelineId}:${range?.from ?? ''}:${range?.to ?? ''}:${limit}`, multi, exec);
484
237
  }
485
238
  /** 1.2 Success rate over time for an org. */
486
239
  async getSuccessRate(orgId, interval, from, to, orgIds) {
487
240
  assertReportInterval(interval);
488
- const { pred, multi } = this.orgScope(orgId, orgIds);
241
+ const { pred, multi } = orgScope(orgId, orgIds);
489
242
  const exec = () => withTenantTx((tx) => tx.execute(sql `
490
243
  SELECT
491
244
  DATE_TRUNC(${interval}, e.started_at)::text AS period,
@@ -501,11 +254,11 @@ export class ReportingService {
501
254
  AND e.started_at >= ${from}::timestamptz AND e.started_at <= ${to}::timestamptz
502
255
  GROUP BY period ORDER BY period
503
256
  `).then(r => drizzleRows(r.rows)));
504
- return this.runReport(`${orgId}:success-rate:${interval}:${from}:${to}`, multi, exec);
257
+ return runReport(`${orgId}:success-rate:${interval}:${from}:${to}`, multi, exec);
505
258
  }
506
259
  /** 1.3 Average duration per pipeline. */
507
260
  async getAverageDuration(orgId, from, to, orgIds) {
508
- const { pred, multi } = this.orgScope(orgId, orgIds);
261
+ const { pred, multi } = orgScope(orgId, orgIds);
509
262
  const exec = () => withTenantTx((tx) => tx.execute(sql `
510
263
  SELECT
511
264
  p.id, p.project, p.pipeline_name,
@@ -520,11 +273,11 @@ export class ReportingService {
520
273
  AND e.started_at >= ${from}::timestamptz AND e.started_at <= ${to}::timestamptz
521
274
  GROUP BY p.id ORDER BY avg_ms DESC
522
275
  `).then(r => drizzleRows(r.rows)));
523
- return this.runReport(`${orgId}:avg-duration:${from}:${to}`, multi, exec);
276
+ return runReport(`${orgId}:avg-duration:${from}:${to}`, multi, exec);
524
277
  }
525
278
  /** 1.5 Stage failure heatmap — which stages fail most. */
526
279
  async getStageFailures(orgId, from, to, orgIds) {
527
- const { pred, multi } = this.orgScope(orgId, orgIds);
280
+ const { pred, multi } = orgScope(orgId, orgIds);
528
281
  const exec = () => withTenantTx((tx) => tx.execute(sql `
529
282
  SELECT
530
283
  e.stage_name,
@@ -538,7 +291,7 @@ export class ReportingService {
538
291
  AND e.started_at >= ${from}::timestamptz AND e.started_at <= ${to}::timestamptz
539
292
  GROUP BY e.stage_name ORDER BY failures DESC
540
293
  `).then(r => drizzleRows(r.rows)));
541
- return this.runReport(`${orgId}:stage-failures:${from}:${to}`, multi, exec);
294
+ return runReport(`${orgId}:stage-failures:${from}:${to}`, multi, exec);
542
295
  }
543
296
  /**
544
297
  * Distinct deploy `environment` values observed in the window — powers the
@@ -546,7 +299,7 @@ export class ReportingService {
546
299
  * reports; only non-null environments (i.e. deploy-attributed executions).
547
300
  */
548
301
  async getReportEnvironments(orgId, from, to, orgIds) {
549
- const { pred, multi } = this.orgScope(orgId, orgIds);
302
+ const { pred, multi } = orgScope(orgId, orgIds);
550
303
  const exec = () => withTenantTx((tx) => tx.execute(sql `
551
304
  SELECT DISTINCT e.environment AS environment
552
305
  FROM ${schema.pipelineEvent} e
@@ -555,11 +308,11 @@ export class ReportingService {
555
308
  AND e.started_at >= ${from}::timestamptz AND e.started_at <= ${to}::timestamptz
556
309
  ORDER BY environment
557
310
  `).then(r => drizzleRows(r.rows).map((row) => row.environment)));
558
- return this.runReport(`${orgId}:report-envs:${from}:${to}`, multi, exec);
311
+ return runReport(`${orgId}:report-envs:${from}:${to}`, multi, exec);
559
312
  }
560
313
  /** 1.6 Stage bottlenecks — slowest stages per pipeline. */
561
314
  async getStageBottlenecks(orgId, from, to, orgIds) {
562
- const { pred, multi } = this.orgScope(orgId, orgIds);
315
+ const { pred, multi } = orgScope(orgId, orgIds);
563
316
  const exec = () => withTenantTx((tx) => tx.execute(sql `
564
317
  SELECT
565
318
  p.id, p.pipeline_name, e.stage_name,
@@ -571,11 +324,11 @@ export class ReportingService {
571
324
  AND e.started_at >= ${from}::timestamptz AND e.started_at <= ${to}::timestamptz
572
325
  GROUP BY p.id, e.stage_name ORDER BY avg_ms DESC
573
326
  `).then(r => drizzleRows(r.rows)));
574
- return this.runReport(`${orgId}:stage-bottlenecks:${from}:${to}`, multi, exec);
327
+ return runReport(`${orgId}:stage-bottlenecks:${from}:${to}`, multi, exec);
575
328
  }
576
329
  /** 1.7 Action failure rate — which plugin steps fail most. */
577
330
  async getActionFailures(orgId, from, to, orgIds) {
578
- const { pred, multi } = this.orgScope(orgId, orgIds);
331
+ const { pred, multi } = orgScope(orgId, orgIds);
579
332
  const exec = () => withTenantTx((tx) => tx.execute(sql `
580
333
  SELECT
581
334
  e.action_name,
@@ -589,7 +342,7 @@ export class ReportingService {
589
342
  AND e.started_at >= ${from}::timestamptz AND e.started_at <= ${to}::timestamptz
590
343
  GROUP BY e.action_name ORDER BY failures DESC
591
344
  `).then(r => drizzleRows(r.rows)));
592
- return this.runReport(`${orgId}:action-failures:${from}:${to}`, multi, exec);
345
+ return runReport(`${orgId}:action-failures:${from}:${to}`, multi, exec);
593
346
  }
594
347
  /**
595
348
  * 1.8 Error categorization — group failure messages. Execution report, so
@@ -598,7 +351,7 @@ export class ReportingService {
598
351
  * fresh under sysadmin via `runReport`; single-org reads keep the per-org cache.
599
352
  */
600
353
  async getErrors(orgId, from, to, limit = 20, orgIds) {
601
- const { pred, multi } = this.orgScope(orgId, orgIds);
354
+ const { pred, multi } = orgScope(orgId, orgIds);
602
355
  const exec = () => withTenantTx((tx) => tx.execute(sql `
603
356
  SELECT
604
357
  SUBSTRING(e.error_message FROM 1 FOR 200) AS error_pattern,
@@ -612,490 +365,23 @@ export class ReportingService {
612
365
  GROUP BY error_pattern ORDER BY occurrences DESC
613
366
  LIMIT ${limit}
614
367
  `).then(r => drizzleRows(r.rows)));
615
- return this.runReport(`${orgId}:errors:${from}:${to}:${limit}`, multi, exec);
368
+ return runReport(`${orgId}:errors:${from}:${to}:${limit}`, multi, exec);
616
369
  }
617
370
  /**
618
- * 1.9 DORA metrics over a [from,to] deploy-completion window, org-scoped +
619
- * rollup-aware. DEPLOY-BASIS ONLY — every metric derives from real deploy-stage
620
- * executions (`event_type='STAGE'` with a non-null `environment`, set by the
621
- * forwarder for the stages a user declared in `pb.deploys`). No run-based
622
- * fallback: a pipeline with no deploy stage produces no DORA data.
623
- *
624
- * Four scoped SQL scans run inside one tx (each org-gated by `p.org_id ${pred}`
625
- * / `o.org_id ${pred}` so a rollup passes the org→team subtree and a foreign
626
- * org's rows never enter): (1) terminal deploy rows PER (execution, env) — one
627
- * "deployment" = one execution reaching an env (D1) — → DF / deploy-time CFR /
628
- * measured lead time (lead time joins the execution's earliest commit, D2);
629
- * the scan also reaches back `windowHours` before `from` so incidents opened
630
- * near the window start can correlate to a just-prior deploy; (2) `deployment_outcomes`
631
- * in-window → post-deploy CFR component; (3) production restored/failed
632
- * outcomes joined to their deploy → MTTR; (4) registry vs deploying → coverage.
633
- * The cross-source medians (lead time, MTTR) are computed in JS from clamped
634
- * (≥0) deltas.
635
- *
636
- * @param opts.pipelineId restrict to one pipeline (per-pipeline DORA)
637
- * @param opts.environment restrict to one deploy environment
371
+ * The four DORA measures plus their per-environment breakdown.
372
+ * Implementation in ./reporting/dora.ts — see that file's header for why.
638
373
  */
639
- async getDoraMetrics(orgId, from, to, orgIds, opts = {}) {
640
- const { pred, multi } = this.orgScope(orgId, orgIds);
641
- const { pipelineId, environment } = opts;
642
- const pipelineClause = pipelineId ? sql `AND e.pipeline_id = ${pipelineId}` : sql ``;
643
- const pipelineClauseR = pipelineId ? sql `AND r.pipeline_id = ${pipelineId}` : sql ``;
644
- const envClause = environment ? sql `AND e.environment = ${environment}` : sql ``;
645
- const outcomeEnvClause = environment ? sql `AND o.environment = ${environment}` : sql ``;
646
- const incidentEnvClause = environment ? sql `AND i.environment = ${environment}` : sql ``;
647
- // Effective incident-correlation window (per-org override or the global
648
- // default). Computed here (not just in shapeDora) because the deploy scan
649
- // needs it for BOTH the correlation look-back lower bound AND the cache key.
650
- const effectiveWindowHours = resolveIncidentWindowHours(opts.incidentWindowHours);
651
- // Correlation look-back: incidents opened just inside `from` can attribute to
652
- // a deploy that completed up to `windowHours` BEFORE `from` (mirrors the
653
- // LATERAL look-back in listIncidents). Widen the deploy scan's lower bound to
654
- // `from − windowHours`; DF/CFR/lead still count only the in-`from`..`to`
655
- // subset (flagged by `in_window`), while correlation sees the wider set.
656
- const fromMs = Date.parse(from);
657
- const lookbackFrom = Number.isFinite(fromMs)
658
- ? new Date(fromMs - effectiveWindowHours * 3600 * 1000).toISOString()
659
- : from;
660
- // (1) Terminal deploy rows: PER-EXECUTION (D1), one row per (environment,
661
- // execution) — every deploy STAGE targeting that env within the execution is
662
- // rolled up to a terminal status (FAILED wins, then SUCCEEDED). A single
663
- // execution with two deploy stages to the same env is ONE deployment, not two.
664
- // completed_at = the deploy's completion (MAX over its stages). `commit_ts`
665
- // (D2) is the execution's EARLIEST commit time across ALL its events (commit
666
- // enrichment rides the PIPELINE/source event where environment IS NULL, never
667
- // the deploy STAGE row), joined by execution_id. `in_window` marks whether the
668
- // deploy completed inside [from,to] (vs. a look-back-only row kept solely for
669
- // incident correlation). execution_id is projected so post-deploy failures
670
- // (manual outcomes + correlated incidents) can dedup against their deploy.
671
- const deploySql = sql `
672
- WITH deploy_stages AS (
673
- SELECT
674
- e.environment AS environment,
675
- e.execution_id AS execution_id,
676
- ${terminalStatusRollup} AS status,
677
- MAX(e.completed_at) AS completed_at
678
- FROM ${schema.pipelineEvent} e
679
- JOIN ${schema.pipeline} p ON p.id = e.pipeline_id
680
- WHERE p.org_id ${pred} AND e.event_type = 'STAGE' AND e.environment IS NOT NULL
681
- ${pipelineClause} ${envClause}
682
- AND e.completed_at >= ${lookbackFrom}::timestamptz AND e.completed_at <= ${to}::timestamptz
683
- GROUP BY e.environment, e.execution_id
684
- ),
685
- exec_commits AS (
686
- SELECT c.execution_id AS execution_id, MIN(c.commit_timestamp) AS commit_ts
687
- FROM ${schema.pipelineEvent} c
688
- JOIN ${schema.pipeline} p ON p.id = c.pipeline_id
689
- WHERE p.org_id ${pred} AND c.commit_timestamp IS NOT NULL
690
- AND c.execution_id IN (SELECT execution_id FROM deploy_stages)
691
- GROUP BY c.execution_id
692
- )
693
- SELECT
694
- ds.environment AS environment,
695
- ds.execution_id AS execution_id,
696
- ds.status AS status,
697
- ds.completed_at::text AS completed_at,
698
- (ds.completed_at >= ${from}::timestamptz) AS in_window,
699
- ec.commit_ts::text AS commit_ts
700
- FROM deploy_stages ds
701
- LEFT JOIN exec_commits ec ON ec.execution_id = ds.execution_id`;
702
- // (2) Post-deploy outcome markers in-window (per env). Post-deploy failures
703
- // (outcome='failed') add to the CFR numerator without changing attempts.
704
- // execution_id lets the CFR dedup a manual failure against an incident that
705
- // correlates to the same deploy (no double-count).
706
- const outcomeSql = sql `
707
- SELECT o.environment AS environment, o.outcome AS outcome, o.execution_id AS execution_id
708
- FROM ${schema.deploymentOutcome} o
709
- WHERE o.org_id ${pred} ${outcomeEnvClause}
710
- AND o.at >= ${from}::timestamptz AND o.at <= ${to}::timestamptz`;
711
- // (3) MTTR — PRODUCTION-ONLY, independent of the env filter. Every production
712
- // outcome in-window; for a 'restored' one, correlate to its deploy's
713
- // completion via execution_id to measure restored.at − deployed.completed_at.
714
- // execution_id is projected so an incident-sourced recovery for the same
715
- // deploy takes precedence over the manual restored gap.
716
- const mttrSql = sql `
717
- SELECT
718
- o.outcome AS outcome,
719
- o.execution_id AS execution_id,
720
- o.at::text AS restored_at,
721
- (SELECT MAX(d.completed_at) FROM ${schema.pipelineEvent} d
722
- JOIN ${schema.pipeline} p2 ON p2.id = d.pipeline_id
723
- WHERE p2.org_id ${pred} AND d.execution_id = o.execution_id
724
- AND d.event_type = 'STAGE' AND d.environment = ${HEADLINE_ENV})::text AS deployed_at
725
- FROM ${schema.deploymentOutcome} o
726
- WHERE o.org_id ${pred} AND o.environment = ${HEADLINE_ENV}
727
- AND o.at >= ${from}::timestamptz AND o.at <= ${to}::timestamptz`;
728
- // (5) Incidents opened in-window (per env). Correlated in JS to the most
729
- // recent successful deploy → automated post-deploy failure (CFR) + real
730
- // recovery time (resolved_at − opened_at) for MTTR (production).
731
- const incidentSql = sql `
732
- SELECT i.environment AS environment, i.opened_at::text AS opened_at, i.resolved_at::text AS resolved_at
733
- FROM ${schema.incident} i
734
- WHERE i.org_id ${pred} ${incidentEnvClause}
735
- AND i.opened_at >= ${from}::timestamptz AND i.opened_at <= ${to}::timestamptz`;
736
- // (4) Coverage: registered pipelines vs those that actually deployed in-window.
737
- const coverageSql = sql `
738
- SELECT
739
- (SELECT COUNT(*)::int FROM ${schema.pipelineRegistry} r
740
- WHERE r.org_id ${pred} ${pipelineClauseR}) AS registered,
741
- (SELECT COUNT(DISTINCT e.pipeline_id)::int FROM ${schema.pipelineEvent} e
742
- JOIN ${schema.pipeline} p ON p.id = e.pipeline_id
743
- WHERE p.org_id ${pred} AND e.event_type = 'STAGE' AND e.environment IS NOT NULL
744
- ${pipelineClause} ${envClause}
745
- AND e.completed_at >= ${from}::timestamptz AND e.completed_at <= ${to}::timestamptz) AS deploying`;
746
- const exec = () => withTenantTx(async (tx) => {
747
- // Scan order is load-bearing for the generated-SQL tests: 0=deploy,
748
- // 1=outcomes, 2=mttr, 3=coverage, 4=incidents (appended last so the
749
- // earlier indices stay stable).
750
- const deployRows = drizzleRows((await tx.execute(deploySql)).rows);
751
- const outcomeRows = drizzleRows((await tx.execute(outcomeSql)).rows);
752
- const mttrRows = drizzleRows((await tx.execute(mttrSql)).rows);
753
- const coverageRow = drizzleRows((await tx.execute(coverageSql)).rows)[0];
754
- const incidentRows = drizzleRows((await tx.execute(incidentSql)).rows);
755
- return this.shapeDora(deployRows, outcomeRows, mttrRows, coverageRow, incidentRows, from, to, {
756
- pipelineId, environment,
757
- }, effectiveWindowHours);
758
- });
759
- // Cache key MUST include the effective incident window: the scorecard reads
760
- // /dora with the org's default window while an explicit /dora call may pass an
761
- // override — different windows yield different CFR/MTTR, so they must not
762
- // collide on the same key.
763
- const key = `${orgId}:dora:${from}:${to}:${pipelineId ?? ''}:${environment ?? ''}:${effectiveWindowHours}`;
764
- return this.runReport(key, multi, exec);
765
- }
766
- /**
767
- * Shape the raw DORA scan rows into the public {@link DoraMetrics}. Buckets the
768
- * terminal deploy rows by environment (DF / deploy-time CFR / measured lead),
769
- * folds in the post-deploy failure counts (manual outcomes + webhook-ingested
770
- * incidents, deduped by deploy execution), computes production MTTR from both
771
- * sources (incident `resolved_at − opened_at` taking precedence over the manual
772
- * `restored − deployed`), and reconciles coverage — all cross-source medians
773
- * over deltas clamped ≥0.
774
- *
775
- * Phase 5 incident correlation: each incident is attributed to the most recent
776
- * SUCCESSFUL deploy to its environment with `completed_at ≤ opened_at` within
777
- * {@link DORA_INCIDENT_WINDOW_HOURS}. That deploy is a post-deploy failure; an
778
- * uncorrelated incident (no eligible deploy) contributes nothing.
779
- */
780
- shapeDora(deployRows, outcomeRows, mttrRows, coverageRow, incidentRows, from, to, filters, windowHours = DORA_INCIDENT_WINDOW_HOURS) {
781
- // Window length in days (floored at 1 so a sub-day window yields the count as
782
- // the rate, never /0 or an extrapolation). Guard unparseable dates → 1 day.
783
- const spanDays = (Date.parse(to) - Date.parse(from)) / 86400000;
784
- const days = Number.isFinite(spanDays) ? Math.max(spanDays, 1) : 1;
785
- // Window end instant for MTTR right-censoring (a resolution after `to` is
786
- // unobserved). +Infinity when `to` is unparseable ⇒ no censoring (fail-open).
787
- const toParsed = Date.parse(to);
788
- const toMs = Number.isFinite(toParsed) ? toParsed : Number.POSITIVE_INFINITY;
789
- const envs = new Map();
790
- const accFor = (env) => {
791
- let a = envs.get(env);
792
- if (!a) {
793
- a = { deployments: 0, deployTimeFailures: 0, attempts: 0, leadGaps: [] };
794
- envs.set(env, a);
795
- }
796
- return a;
797
- };
798
- // A deploy row counts toward DF/CFR/lead only if it completed inside [from,to].
799
- // Look-back-only rows (in_window=false, kept for incident correlation) are
800
- // skipped here. Absent in a fixture ⇒ in-window (unit tests omit the flag).
801
- const isInWindow = (row) => row.in_window == null ? true : (row.in_window === true || row.in_window === 't');
802
- for (const row of deployRows) {
803
- const env = row.environment;
804
- if (!env)
805
- continue;
806
- if (!isInWindow(row))
807
- continue; // look-back-only row → correlation, not DF/CFR
808
- const a = accFor(env);
809
- if (row.status === 'SUCCEEDED') {
810
- a.deployments++;
811
- a.attempts++;
812
- // Measured lead time: deploy completion − execution's earliest commit time.
813
- if (row.commit_ts != null && row.completed_at != null) {
814
- const gap = (Date.parse(row.completed_at) - Date.parse(row.commit_ts)) / 1000;
815
- if (Number.isFinite(gap))
816
- a.leadGaps.push(Math.max(gap, 0));
817
- }
818
- }
819
- else if (row.status === 'FAILED') {
820
- a.deployTimeFailures++;
821
- a.attempts++;
822
- }
823
- }
824
- // Incident→deploy correlation (Phase 5). Index the SUCCESSFUL deploys per env
825
- // (execution id + completion instant), newest first, so each incident can be
826
- // attributed to the most recent deploy that completed within the window
827
- // before it opened. That execution is a post-deploy failure.
828
- const windowMs = windowHours * 3600 * 1000;
829
- const successfulByEnv = new Map();
830
- for (const row of deployRows) {
831
- if (row.status !== 'SUCCEEDED' || !row.environment || row.execution_id == null || row.completed_at == null)
832
- continue;
833
- const ms = Date.parse(row.completed_at);
834
- if (!Number.isFinite(ms))
835
- continue;
836
- const list = successfulByEnv.get(row.environment) ?? [];
837
- list.push({ exec: row.execution_id, completedMs: ms });
838
- successfulByEnv.set(row.environment, list);
839
- }
840
- for (const list of successfulByEnv.values())
841
- list.sort((a, b) => b.completedMs - a.completedMs);
842
- /** Correlate an incident to the most recent in-window successful deploy execution. */
843
- const correlate = (env, openedMs) => {
844
- const list = successfulByEnv.get(env);
845
- if (!list)
846
- return null;
847
- for (const d of list) {
848
- if (d.completedMs <= openedMs && openedMs - d.completedMs <= windowMs)
849
- return d.exec;
850
- }
851
- return null;
852
- };
853
- const correlatedIncidents = [];
854
- for (const inc of incidentRows) {
855
- if (!inc.environment || inc.opened_at == null)
856
- continue;
857
- const openedMs = Date.parse(inc.opened_at);
858
- if (!Number.isFinite(openedMs))
859
- continue;
860
- const exec = correlate(inc.environment, openedMs);
861
- if (exec == null)
862
- continue; // uncorrelated → not attributable to a deploy
863
- let resolvedGap = null;
864
- if (inc.resolved_at != null) {
865
- const resolvedMs = Date.parse(inc.resolved_at);
866
- // Right-censoring: a resolution AFTER the window end (`to`) is not observed
867
- // within the window — treat the incident as still open (gap stays null) so
868
- // MTTR never reads unbounded past `to`. The incident still counts toward the
869
- // incident total (unresolved), it just contributes no recovery time.
870
- if (Number.isFinite(resolvedMs) && resolvedMs <= toMs) {
871
- const g = (resolvedMs - openedMs) / 1000;
872
- if (Number.isFinite(g))
873
- resolvedGap = Math.max(g, 0);
874
- }
875
- }
876
- correlatedIncidents.push({ environment: inc.environment, exec, resolvedGap });
877
- }
878
- // Post-deploy failures per env — the DISTINCT set of deploy executions flagged
879
- // by a manual `failed` outcome OR a correlated incident (deduped by execution,
880
- // so a deploy flagged by both counts once). A manual outcome without an
881
- // execution id (legacy/unresolvable) still counts via a per-row sentinel.
882
- const postDeployExecsByEnv = new Map();
883
- let sentinel = 0;
884
- const flagFor = (env) => {
885
- let s = postDeployExecsByEnv.get(env);
886
- if (!s) {
887
- s = new Set();
888
- postDeployExecsByEnv.set(env, s);
889
- }
890
- return s;
891
- };
892
- for (const o of outcomeRows) {
893
- if (o.outcome !== 'failed' || !o.environment)
894
- continue;
895
- flagFor(o.environment).add(o.execution_id ?? `manual-${sentinel++}`);
896
- accFor(o.environment); // ensure env appears even with no deploy events
897
- }
898
- for (const ci of correlatedIncidents) {
899
- flagFor(ci.environment).add(ci.exec);
900
- accFor(ci.environment); // ensure env appears even if the deploy is out-of-window
901
- }
902
- const postDeployByEnv = new Map();
903
- for (const [env, set] of postDeployExecsByEnv)
904
- postDeployByEnv.set(env, set.size);
905
- const environments = [...envs.entries()]
906
- .map(([environment, a]) => {
907
- const postDeployFailures = postDeployByEnv.get(environment) ?? 0;
908
- const rawPerDay = a.deployments / days;
909
- const numerator = a.deployTimeFailures + postDeployFailures;
910
- // Clamp to [0,100]: post-deploy failures can correlate to a deploy that
911
- // completed just before the window (kept for correlation), so the numerator
912
- // can transiently exceed in-window attempts — a CFR > 100% is never valid.
913
- const rawRate = a.attempts > 0 ? Math.min(100, (numerator / a.attempts) * 100) : 0;
914
- const ltMedian = median(a.leadGaps);
915
- return {
916
- environment,
917
- deploymentFrequency: {
918
- deployments: a.deployments,
919
- perDay: round(rawPerDay, 2),
920
- level: doraLevelForFrequency(rawPerDay, a.deployments),
921
- },
922
- changeFailureRate: {
923
- rate: round(rawRate, 1),
924
- deployTimeFailures: a.deployTimeFailures,
925
- postDeployFailures,
926
- attempts: a.attempts,
927
- level: doraLevelForChangeFailure(rawRate, a.attempts),
928
- },
929
- leadTime: {
930
- deployments: a.leadGaps.length,
931
- medianSeconds: ltMedian != null ? round(ltMedian, 1) : null,
932
- level: doraLevelForLeadTime(ltMedian),
933
- },
934
- };
935
- })
936
- .sort((x, y) => {
937
- if (x.environment === HEADLINE_ENV)
938
- return -1;
939
- if (y.environment === HEADLINE_ENV)
940
- return 1;
941
- return x.environment.localeCompare(y.environment);
942
- });
943
- // MTTR — PRODUCTION-ONLY, from BOTH sources. Incidents take precedence: a
944
- // production incident correlated to a deploy contributes the real recovery
945
- // (`resolved_at − opened_at`), and any manual outcome on the SAME deploy is
946
- // skipped. Manual outcomes on other deploys keep the Phase-2 behavior
947
- // (`failed` → an incident; `restored` → a recovery gap of `restored − deployed`).
948
- let incidents = 0, restored = 0;
949
- const mttrGaps = [];
950
- // Executions already attributed to a production incident (precedence guard).
951
- const incidentExecs = new Set();
952
- for (const ci of correlatedIncidents) {
953
- if (ci.environment !== HEADLINE_ENV)
954
- continue; // MTTR is production-only
955
- incidents++;
956
- incidentExecs.add(ci.exec);
957
- if (ci.resolvedGap != null) {
958
- restored++;
959
- mttrGaps.push(ci.resolvedGap);
960
- }
961
- }
962
- for (const m of mttrRows) {
963
- // Incident precedence: don't double-count a deploy already flagged by an incident.
964
- if (m.execution_id != null && incidentExecs.has(m.execution_id))
965
- continue;
966
- if (m.outcome === 'failed') {
967
- incidents++;
968
- continue;
969
- }
970
- if (m.outcome === 'restored') {
971
- restored++;
972
- if (m.restored_at != null && m.deployed_at != null) {
973
- const gap = (Date.parse(m.restored_at) - Date.parse(m.deployed_at)) / 1000;
974
- if (Number.isFinite(gap))
975
- mttrGaps.push(Math.max(gap, 0));
976
- }
977
- }
978
- }
979
- const mttrMedian = median(mttrGaps);
980
- const registered = Number(coverageRow?.registered) || 0;
981
- const deploying = Number(coverageRow?.deploying) || 0;
982
- return {
983
- window: { from, to },
984
- filters: { pipelineId: filters.pipelineId ?? null, environment: filters.environment ?? null },
985
- headline: HEADLINE_ENV,
986
- environments,
987
- meanTimeToRestore: {
988
- incidents,
989
- restored,
990
- medianSeconds: mttrMedian != null ? round(mttrMedian, 1) : null,
991
- level: doraLevelForRestore(mttrMedian),
992
- },
993
- coverage: {
994
- registered,
995
- deploying,
996
- withoutDeploys: Math.max(registered - deploying, 0),
997
- },
998
- };
374
+ getDoraMetrics(orgId, from, to, orgIds, opts = {}) {
375
+ return doraMetrics(orgId, from, to, orgIds, opts);
999
376
  }
1000
- /**
1001
- * 1.9b DORA trend — deployment frequency + deploy-time change-failure rate
1002
- * bucketed by `interval` (day/week/month) for a sparkline. Deploy-basis like
1003
- * getDoraMetrics: buckets terminal deploy-stage executions on their
1004
- * `completed_at`. Shares the org/rollup + pipelineId/environment scoping. MTTR,
1005
- * lead time, and post-deploy CFR are intentionally omitted (too heavy to bucket).
1006
- */
1007
- async getDoraTrend(orgId, interval, from, to, orgIds, opts = {}) {
1008
- assertReportInterval(interval);
1009
- const { pred, multi } = this.orgScope(orgId, orgIds);
1010
- const { pipelineId, environment } = opts;
1011
- const pipelineClause = pipelineId ? sql `AND e.pipeline_id = ${pipelineId}` : sql ``;
1012
- const envClause = environment ? sql `AND e.environment = ${environment}` : sql ``;
1013
- const exec = () => withTenantTx((tx) => tx.execute(sql `
1014
- WITH deploys AS (
1015
- -- PER-EXECUTION deploy unit (D1): one row per (environment, execution),
1016
- -- every deploy STAGE to that env within the execution rolled up to a
1017
- -- single terminal status — NOT one row per stage.
1018
- SELECT
1019
- ${terminalStatusRollup} AS status,
1020
- MAX(e.completed_at) AS completed_at
1021
- FROM ${schema.pipelineEvent} e
1022
- JOIN ${schema.pipeline} p ON p.id = e.pipeline_id
1023
- WHERE p.org_id ${pred} AND e.event_type = 'STAGE' AND e.environment IS NOT NULL
1024
- ${pipelineClause} ${envClause}
1025
- AND e.completed_at >= ${from}::timestamptz AND e.completed_at <= ${to}::timestamptz
1026
- GROUP BY e.environment, e.execution_id
1027
- )
1028
- SELECT
1029
- DATE_TRUNC(${interval}, completed_at)::text AS period,
1030
- COUNT(*) FILTER (WHERE status = 'SUCCEEDED')::int AS deployments,
1031
- COUNT(*) FILTER (WHERE status = 'FAILED')::int AS failed,
1032
- COUNT(*) FILTER (WHERE status IN ('SUCCEEDED', 'FAILED'))::int AS total,
1033
- -- quoted alias so the raw row key is exactly the DoraTrendPoint field
1034
- COALESCE(ROUND(COUNT(*) FILTER (WHERE status = 'FAILED')::numeric
1035
- / NULLIF(COUNT(*) FILTER (WHERE status IN ('SUCCEEDED', 'FAILED')), 0) * 100, 1), 0)::float AS "changeFailurePct"
1036
- FROM deploys
1037
- GROUP BY period ORDER BY period
1038
- `).then(r => drizzleRows(r.rows)));
1039
- const key = `${orgId}:dora-trend:${interval}:${from}:${to}:${pipelineId ?? ''}:${environment ?? ''}`;
1040
- return this.runReport(key, multi, exec);
377
+ /** DORA measures bucketed over time. */
378
+ getDoraTrend(orgId, interval, from, to, orgIds, opts = {}) {
379
+ return doraTrend(orgId, interval, from, to, orgIds, opts);
1041
380
  }
1042
- /**
1043
- * 1.10 Per-pipeline BUILD HEALTH (Phase 6) — a standard (NOT `advanced_reporting`)
1044
- * per-stage breakdown for one pipeline over a [from,to] window. Aggregates the
1045
- * existing `pipeline_events` STAGE rows: each stage is rolled up per execution
1046
- * to a terminal status (FAILED wins, then SUCCEEDED) + its max duration, then
1047
- * grouped per stage into run/success/failure counts, a success rate, and
1048
- * duration percentiles (p50/p90/p99). Totals sum across stages. Org-scoped via
1049
- * the pipeline join (`p.org_id ${pred}`) + rollup-aware like the sibling reports;
1050
- * a pipelineId owned by another org returns an empty breakdown.
1051
- */
1052
- async getBuildHealth(orgId, pipelineId, from, to, orgIds) {
1053
- const { pred, multi } = this.orgScope(orgId, orgIds);
1054
- const exec = () => withTenantTx(async (tx) => {
1055
- const rows = drizzleRows((await tx.execute(sql `
1056
- WITH stage_runs AS (
1057
- SELECT
1058
- e.stage_name AS stage,
1059
- ${terminalStatusRollup} AS status,
1060
- MAX(e.duration_ms) AS duration_ms
1061
- FROM ${schema.pipelineEvent} e
1062
- JOIN ${schema.pipeline} p ON p.id = e.pipeline_id
1063
- WHERE p.org_id ${pred} AND e.pipeline_id = ${pipelineId}
1064
- AND e.event_type = 'STAGE' AND e.stage_name IS NOT NULL
1065
- AND e.started_at >= ${from}::timestamptz AND e.started_at <= ${to}::timestamptz
1066
- GROUP BY e.stage_name, e.execution_id
1067
- )
1068
- SELECT
1069
- stage,
1070
- COUNT(*)::int AS runs,
1071
- COUNT(*) FILTER (WHERE status = 'SUCCEEDED')::int AS successes,
1072
- COUNT(*) FILTER (WHERE status = 'FAILED')::int AS failures,
1073
- COALESCE(ROUND(COUNT(*) FILTER (WHERE status = 'SUCCEEDED')::numeric
1074
- / NULLIF(COUNT(*), 0) * 100, 1), 0)::float AS "successRate",
1075
- PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY duration_ms)::int AS "p50Ms",
1076
- PERCENTILE_CONT(0.9) WITHIN GROUP (ORDER BY duration_ms)::int AS "p90Ms",
1077
- PERCENTILE_CONT(0.99) WITHIN GROUP (ORDER BY duration_ms)::int AS "p99Ms"
1078
- FROM stage_runs
1079
- WHERE status IN ('SUCCEEDED', 'FAILED')
1080
- GROUP BY stage
1081
- ORDER BY runs DESC, stage
1082
- `)).rows);
1083
- // Totals sum across stages (total stage-runs / stage-failures in the window).
1084
- let runs = 0, failures = 0;
1085
- for (const s of rows) {
1086
- runs += s.runs;
1087
- failures += s.failures;
1088
- }
1089
- const failureRate = runs > 0 ? round((failures / runs) * 100, 1) : 0;
1090
- return { stages: rows, totals: { runs, failures, failureRate } };
1091
- });
1092
- return this.runReport(`${orgId}:build-health:${pipelineId}:${from}:${to}`, multi, exec);
381
+ /** Per-pipeline build health (stage pass rates over a window). */
382
+ getBuildHealth(orgId, pipelineId, from, to, orgIds) {
383
+ return buildHealth(orgId, pipelineId, from, to, orgIds);
1093
384
  }
1094
- // ── Category 2: Plugin Inventory & Builds ──
1095
- /** 2.1 Plugin summary — counts and breakdowns.
1096
- * INTENTIONALLY SINGLE-ORG (no rollup): plugin inventory is an org-owned
1097
- * asset count, not an execution/build activity report, so a parent's view is
1098
- * its own plugins — teams manage their own inventory. Single `= $org` scope. */
1099
385
  async getPluginSummary(orgId) {
1100
386
  return inventoryCache.getOrSet(`${orgId}:plugin-summary`, async () => {
1101
387
  const rows = await withTenantTx((tx) => tx.execute(sql `
@@ -1176,7 +462,7 @@ export class ReportingService {
1176
462
  // Build activity report — rollup-aware like the execution reports. These
1177
463
  // rows are gated on the pipeline_event `org_id` directly (no pipeline join),
1178
464
  // so `pred` applies to `e.org_id`.
1179
- const { pred, multi } = this.orgScope(orgId, orgIds);
465
+ const { pred, multi } = orgScope(orgId, orgIds);
1180
466
  const exec = () => withTenantTx((tx) => tx.execute(sql `
1181
467
  SELECT
1182
468
  DATE_TRUNC(${interval}, e.started_at)::text AS period,
@@ -1190,11 +476,11 @@ export class ReportingService {
1190
476
  AND e.started_at >= ${from}::timestamptz AND e.started_at <= ${to}::timestamptz
1191
477
  GROUP BY period ORDER BY period
1192
478
  `).then(r => drizzleRows(r.rows)));
1193
- return this.runReport(`${orgId}:build-success:${interval}:${from}:${to}`, multi, exec);
479
+ return runReport(`${orgId}:build-success:${interval}:${from}:${to}`, multi, exec);
1194
480
  }
1195
481
  /** 2.5 Build duration per plugin. Build activity report — rollup-aware. */
1196
482
  async getBuildDuration(orgId, from, to, orgIds) {
1197
- const { pred, multi } = this.orgScope(orgId, orgIds);
483
+ const { pred, multi } = orgScope(orgId, orgIds);
1198
484
  const exec = () => withTenantTx((tx) => tx.execute(sql `
1199
485
  SELECT
1200
486
  e.detail->>'pluginName' AS plugin_name,
@@ -1206,11 +492,11 @@ export class ReportingService {
1206
492
  AND e.started_at >= ${from}::timestamptz AND e.started_at <= ${to}::timestamptz
1207
493
  GROUP BY plugin_name ORDER BY avg_ms DESC
1208
494
  `).then(r => drizzleRows(r.rows)));
1209
- return this.runReport(`${orgId}:build-duration:${from}:${to}`, multi, exec);
495
+ return runReport(`${orgId}:build-duration:${from}:${to}`, multi, exec);
1210
496
  }
1211
497
  /** 2.6 Build failures — top error messages. Build activity report — rollup-aware. */
1212
498
  async getBuildFailures(orgId, from, to, limit = 20, orgIds) {
1213
- const { pred, multi } = this.orgScope(orgId, orgIds);
499
+ const { pred, multi } = orgScope(orgId, orgIds);
1214
500
  const exec = () => withTenantTx((tx) => tx.execute(sql `
1215
501
  SELECT
1216
502
  e.detail->>'pluginName' AS plugin_name,
@@ -1224,7 +510,7 @@ export class ReportingService {
1224
510
  ORDER BY occurrences DESC
1225
511
  LIMIT ${limit}
1226
512
  `).then(r => drizzleRows(r.rows)));
1227
- return this.runReport(`${orgId}:build-failures:${from}:${to}:${limit}`, multi, exec);
513
+ return runReport(`${orgId}:build-failures:${from}:${to}:${limit}`, multi, exec);
1228
514
  }
1229
515
  // ── Category 3: DORA write paths (post-deploy outcomes + ingest health) ──
1230
516
  /**
@@ -1561,4 +847,4 @@ export class ReportingService {
1561
847
  }
1562
848
  }
1563
849
  export const reportingService = new ReportingService();
1564
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwb3J0aW5nLXNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYXBpL3JlcG9ydGluZy1zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEMsT0FBTyxFQUFFLGtCQUFrQixFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsZ0JBQWdCLEVBQUUsbUJBQW1CLEVBQUUsNkJBQTZCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUNsSyxPQUFPLEVBQUUsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUMzQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDaEQsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxZQUFZLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUU1RSxNQUFNLE1BQU0sR0FBRyxZQUFZLENBQUMsbUJBQW1CLENBQUMsQ0FBQztBQUVqRDs7Ozs7OztHQU9HO0FBQ0gsU0FBUyxvQkFBb0IsQ0FBQyxRQUFnQjtJQUM1QyxJQUFJLENBQUUsZ0JBQXNDLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7UUFDaEUsTUFBTSxJQUFJLEtBQUssQ0FBQyw0QkFBNEIsUUFBUSxzQkFBc0IsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUMzRyxDQUFDO0FBQ0gsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsU0FBUyxhQUFhLENBQUMsS0FBeUI7SUFDOUMsT0FBTyxLQUFLLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyw2QkFBNkIsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0FBQ2hGLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxjQUFjLEdBQUcsa0JBQWtCLENBQUMsYUFB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QUcsTUFBTSxFQUFFLENBQUMsQ0FBQztZQUMvRixPQUFPLE1BQU0sQ0FBQztRQUNoQixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7Q0FDRjtBQUVELE1BQU0sQ0FBQyxNQUFNLGdCQUFnQixHQUFHLElBQUksZ0JBQWdCLEVBQUUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgeyBjcmVhdGVDYWNoZVNlcnZpY2UsIGNyZWF0ZUxvZ2dlciwgZXJyb3JNZXNzYWdlLCBSRVBPUlRfSU5URVJWQUxTLCBzY3J1YkF3c0lkZW50aWZpZXJzLCBzY3J1YkF3c0lkZW50aWZpZXJzRnJvbVN0cmluZyB9IGZyb20gJ0BwaXBlbGluZS1idWlsZGVyL2FwaS1jb3JlJztcbmltcG9ydCB7IGluQXJyYXksIHNxbCB9IGZyb20gJ2RyaXp6bGUtb3JtJztcbmltcG9ydCB7IGRyaXp6bGVSb3dzIH0gZnJvbSAnLi9jcnVkLXNlcnZpY2UuanMnO1xuaW1wb3J0IHsgc2NoZW1hIH0gZnJvbSAnLi4vZGF0YWJhc2UvZHJpenpsZS1zY2hlbWEuanMnO1xuaW1wb3J0IHsgd2l0aFRlbmFudFR4LCBydW5XaXRoVGVuYW50Q29udGV4dCB9IGZyb20gJy4uL2RhdGFiYXNlL3RlbmFuY3kuanMnO1xuXG5jb25zdCBsb2dnZXIgPSBjcmVhdGVMb2dnZXIoJ3JlcG9ydGluZy1zZXJ2aWNlJyk7XG5cbi8qKlxuICogRGVmZW5zZS1pbi1kZXB0aCBndWFyZCBmb3IgdGhlIGBEQVRFX1RSVU5DKCR7aW50ZXJ2YWx9LCDigKYpYCBidWNrZXQgYXJndW1lbnQuXG4gKiBUaGUgcm91dGUgbGF5ZXIgKGBwYXJzZVJlcG9ydEludGVydmFsYCkgaXMgdGhlIHNlY3VyaXR5IGJvdW5kYXJ5IGFuZCBhbHJlYWR5XG4gKiByZWplY3RzIHVua25vd24gaW50ZXJ2YWxzOyB0aGlzIGFzc2VydCBtYWtlcyBhbiBpbnZhbGlkIHZhbHVlIGZhaWwgZmFzdCBhdCB0aGVcbiAqIHNlcnZpY2UgYm91bmRhcnkgd2l0aCBhIGNsZWFyIGVycm9yIGluc3RlYWQgb2Ygc3VyZmFjaW5nIGEgcmF3IFBvc3RncmVzIGVycm9yXG4gKiBpZiBhIGNhbGxlciBldmVyIGJ5cGFzc2VzIHRoZSByb3V0ZSB2YWxpZGF0aW9uLiBTaGFyZXMgYXBpLWNvcmUnc1xuICogUkVQT1JUX0lOVEVSVkFMUyBhbGxvdy1saXN0IHNvIHRoZSB0d28gY2FuJ3QgZHJpZnQuXG4gKi9cbmZ1bmN0aW9uIGFzc2VydFJlcG9ydEludGVydmFsKGludGVydmFsOiBzdHJpbmcpOiB2b2lkIHtcbiAgaWYgKCEoUkVQT1JUX0lOVEVSVkFMUyBhcyByZWFkb25seSBzdHJpbmdbXSkuaW5jbHVkZXMoaW50ZXJ2YWwpKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIHJlcG9ydCBpbnRlcnZhbDogJHtpbnRlcnZhbH0uIEV4cGVjdGVkIG9uZSBvZjogJHtSRVBPUlRfSU5URVJWQUxTLmpvaW4oJywgJyl9YCk7XG4gIH1cbn1cblxuLyoqXG4gKiBTY3J1YiBBV1MgaWRlbnRpZmllcnMgZnJvbSBhbiBvcHRpb25hbCBmcmVlLWZvcm0gc3RyaW5nLCBwcmVzZXJ2aW5nIGB1bmRlZmluZWRgXG4gKiAoc28gYW4gYWJzZW50IGZpZWxkIHN0YXlzIGFic2VudCByYXRoZXIgdGhhbiBiZWNvbWluZyBhbiBlbXB0eSBzY3J1YmJlZCBzdHJpbmcpLlxuICogVGhlIERVUkFCTEUgcGVyc2lzdGVuY2UgYm91bmRhcnkgZm9yIHRoZSBpbmdlc3QgcGF0aHMg4oCUIGV2ZXJ5IHVzZXIvQVdTLWRlcml2ZWRcbiAqIHN0cmluZyBmaWVsZCBpcyBmdW5uZWxlZCB0aHJvdWdoIHRoaXMgYmVmb3JlIGluc2VydC5cbiAqL1xuZnVuY3Rpb24gc2NydWJPcHRpb25hbCh2YWx1ZTogc3RyaW5nIHwgdW5kZWZpbmVkKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIHZhbHVlICE9PSB1bmRlZmluZWQgPyBzY3J1YkF3c0lkZW50aWZpZXJzRnJvbVN0cmluZyh2YWx1ZSkgOiB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogQ2FjaGUgZm9yIHJlcG9ydGluZyBhZ2dyZWdhdGlvbnMuIFR3byB0aWVyczpcbiAqIC0gSW52ZW50b3J5IHF1ZXJpZXMgKHBsdWdpbiBzdW1tYXJ5L2Rpc3RyaWJ1dGlvbi92ZXJzaW9ucyk6IDUgbWluIFRUTCDigJQgY2hhbmdlcyBvbiBwbHVnaW4gQ1JVRFxuICogLSBFeGVjdXRpb24vYnVpbGQgcXVlcmllcyB3aXRoIGRhdGUgcmFuZ2VzOiAyIG1pbiBUVEwg4oCUIG5ldyBldmVudHMgYXJyaXZlIGNvbnRpbnVvdXNseVxuICovXG5jb25zdCBpbnZlbnRvcnlDYWNoZSA9IGNyZWF0ZUNhY2hlU2VydmljZSgncmVwb3J0OmludjonLCBwYXJzZUludChwcm9jZXNzLmVudi5DQUNIRV9UVExfUkVQT1JUX0lOVkVOVE9SWSB8fCAnMzAwJywgMTApKTtcbmNvbnN0IHRpbWVzZXJpZXNDYWNoZSA9IGNyZWF0ZUNhY2hlU2VydmljZSgncmVwb3J0OnRzOicsIHBhcnNlSW50KHByb2Nlc3MuZW52LkNBQ0hFX1RUTF9SRVBPUlRfVElNRVNFUklFUyB8fCAnMTIwJywgMTApKTtcblxuLy8g4pSA4pSA4pSAIFR5cGVzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG5pbnRlcmZhY2UgRXhlY3V0aW9uQ291bnQge1xuICBpZDogc3RyaW5nO1xuICBwcm9qZWN0OiBzdHJpbmc7XG4gIG9yZ2FuaXphdGlvbjogc3RyaW5nO1xuICBwaXBlbGluZU5hbWU6IHN0cmluZyB8IG51bGw7XG4gIHRvdGFsOiBudW1iZXI7XG4gIHN1Y2NlZWRlZDogbnVtYmVyO1xuICBmYWlsZWQ6IG51bWJlcjtcbiAgY2FuY2VsZWQ6IG51bWJlcjtcbiAgZmlyc3RFeGVjdXRpb246IHN0cmluZyB8IG51bGw7XG4gIGxhc3RFeGVjdXRpb246IHN0cmluZyB8IG51bGw7XG59XG5cbmludGVyZmFjZSBUaW1lU2VyaWVzRW50cnkge1xuICBwZXJpb2Q6IHN0cmluZztcbiAgc3VjY2VlZGVkOiBudW1iZXI7XG4gIGZhaWxlZDogbnVtYmVyO1xuICBjYW5jZWxlZDogbnVtYmVyO1xuICBzdWNjZXNzUGN0OiBudW1iZXI7XG59XG5cbmludGVyZmFjZSBEdXJhdGlvblN0YXRzIHtcbiAgaWQ6IHN0cmluZztcbiAgcHJvamVjdDogc3RyaW5nO1xuICBwaXBlbGluZU5hbWU6IHN0cmluZyB8IG51bGw7XG4gIGF2Z01zOiBudW1iZXI7XG4gIG1pbk1zOiBudW1iZXI7XG4gIG1heE1zOiBudW1iZXI7XG4gIHA5NU1zOiBudW1iZXI7XG4gIGV4ZWN1dGlvbnM6IG51bWJlcjtcbn1cblxuaW50ZXJmYWNlIFBpcGVsaW5lRXhlY3V0aW9uIHtcbiAgZXhlY3V0aW9uSWQ6IHN0cmluZztcbiAgLyoqIFJvbGxlZC11cCB0ZXJtaW5hbCBzdGF0dXM6IHN1Y2NlZWRlZCB8IGZhaWxlZCB8IGNhbmNlbGVkIHwgaW4tcHJvZ3Jlc3MuICovXG4gIHN0YXR1czogc3RyaW5nO1xuICBzdGFydGVkQXQ6IHN0cmluZyB8IG51bGw7XG4gIGVuZGVkQXQ6IHN0cmluZyB8IG51bGw7XG4gIGR1cmF0aW9uTXM6IG51bWJlciB8IG51bGw7XG4gIC8qKiBGaXJzdCBmYWlsaW5nIHN0YWdlL2FjdGlvbiBmb3IgdGhlIGV4ZWN1dGlvbiAobnVsbCB3aGVuIGl0IGRpZG4ndCBmYWlsKS4gKi9cbiAgZmFpbGluZ1N0YWdlOiBzdHJpbmcgfCBudWxsO1xuICBmYWlsaW5nQWN0aW9uOiBzdHJpbmcgfCBudWxsO1xufVxuXG5pbnRlcmZhY2UgU3RhZ2VGYWlsdXJlIHtcbiAgc3RhZ2VOYW1lOiBzdHJpbmc7XG4gIGZhaWx1cmVzOiBudW1iZXI7XG4gIHRvdGFsOiBudW1iZXI7XG4gIGZhaWx1cmVQY3Q6IG51bWJlcjtcbn1cblxuaW50ZXJmYWNlIFN0YWdlQm90dGxlbmVjayB7XG4gIGlkOiBzdHJpbmc7XG4gIHBpcGVsaW5lTmFtZTogc3RyaW5nIHwgbnVsbDtcbiAgc3RhZ2VOYW1lOiBzdHJpbmc7XG4gIGF2Z01zOiBudW1iZXI7XG4gIG1heE1zOiBudW1iZXI7XG59XG5cbmludGVyZmFjZSBBY3Rpb25GYWlsdXJlIHtcbiAgYWN0aW9uTmFtZTogc3RyaW5nO1xuICBmYWlsdXJlczogbnVtYmVyO1xuICB0b3RhbDogbnVtYmVyO1xuICBmYWlsdXJlUGN0OiBudW1iZXI7XG59XG5cbmludGVyZmFjZSBFcnJvckVudHJ5IHtcbiAgZXJyb3JQYXR0ZXJuOiBzdHJpbmc7XG4gIG9jY3VycmVuY2VzOiBudW1iZXI7XG4gIGFmZmVjdGVkUGlwZWxpbmVzOiBudW1iZXI7XG4gIGxhc3RTZWVuOiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBQbHVnaW5TdW1tYXJ5IHtcbiAgdG90YWw6IG51bWJlcjtcbiAgYWN0aXZlOiBudW1iZXI7XG4gIGluYWN0aXZlOiBudW1iZXI7XG4gIC8qKiBDb3VudHMgcGVyIHNoYXJpbmcgcnVuZyDigJQgb25lIGJ1Y2tldCBwZXIgYHZpc2liaWxpdHlgIHZhbHVlLiAqL1xuICBwdWJsaWM6IG51bWJlcjtcbiAgb3JnOiBudW1iZXI7XG4gIHByaXZhdGU6IG51bWJlcjtcbiAgdW5pcXVlTmFtZXM6IG51bWJlcjtcbn1cblxuaW50ZXJmYWNlIFR5cGVDb21wdXRlRGlzdHJpYnV0aW9uIHtcbiAgcGx1Z2luVHlwZTogc3RyaW5nO1xuICBjb21wdXRlVHlwZTogc3RyaW5nO1xuICBjb3VudDogbnVtYmVyO1xufVxuXG5pbnRlcmZhY2UgVmVyc2lvbkNvdW50IHtcbiAgbmFtZTogc3RyaW5nO1xuICB2ZXJzaW9uQ291bnQ6IG51bWJlcjtcbiAgbGF0ZXN0VmVyc2lvbjogc3RyaW5nO1xuICBoYXNEZWZhdWx0OiBib29sZWFuO1xufVxuXG5pbnRlcmZhY2UgQnVpbGRUaW1lU2VyaWVzRW50cnkge1xuICBwZXJpb2Q6IHN0cmluZztcbiAgc3VjY2VlZGVkOiBudW1iZXI7XG4gIGZhaWxlZDogbnVtYmVyO1xuICBzdWNjZXNzUGN0OiBudW1iZXI7XG59XG5cbmludGVyZmFjZSBCdWlsZER1cmF0aW9uIHtcbiAgcGx1Z2luTmFtZTogc3RyaW5nO1xuICBhdmdNczogbnVtYmVyO1xuICBtYXhNczogbnVtYmVyO1xuICBidWlsZHM6IG51bWJlcjtcbn1cblxuaW50ZXJmYWNlIEJ1aWxkRmFpbHVyZSB7XG4gIHBsdWdpbk5hbWU6IHN0cmluZztcbiAgZXJyb3JNZXNzYWdlOiBzdHJpbmc7XG4gIG9jY3VycmVuY2VzOiBudW1iZXI7XG4gIGxhc3RTZWVuOiBzdHJpbmc7XG59XG5cbi8qKlxuICogVGhlIERPUkEgaGVhZGxpbmUgZW52aXJvbm1lbnQuIERlcGxveW1lbnQgdG8gdGhpcyBsaXRlcmFsIGVudiBuYW1lIGlzIHRoZVxuICogaW5kdXN0cnktc3RhbmRhcmQgRE9SQSBzaWduYWw7IE1UVFIgaXMgbWVhc3VyZWQgcHJvZHVjdGlvbi1vbmx5LCBhbmQgdGhpc1xuICogZW52aXJvbm1lbnQncyBjYXJkIGlzIHRoZSBzdW1tYXJ5IHNob3duIGF0IHRoZSB0b3Agb2YgdGhlIHBhbmVsLlxuICovXG5jb25zdCBIRUFETElORV9FTlYgPSAncHJvZHVjdGlvbic7XG5cbi8qKlxuICogSW5jaWRlbnTihpJkZXBsb3kgY29ycmVsYXRpb24gd2luZG93IChQaGFzZSA1KS4gQW4gaW5jaWRlbnQgaXMgYXR0cmlidXRlZCB0byB0aGVcbiAqIG1vc3QgcmVjZW50IFNVQ0NFU1NGVUwgZGVwbG95IHRvIGl0cyBlbnZpcm9ubWVudCB3aG9zZSBgY29tcGxldGVkX2F0YCBpcyB3aXRoaW5cbiAqIHRoaXMgbWFueSBob3VycyBiZWZvcmUgdGhlIGluY2lkZW50J3MgYG9wZW5lZF9hdGAuIERlZmF1bHQgMjRoOyBvdmVycmlkZSB2aWFcbiAqIGBET1JBX0lOQ0lERU5UX1dJTkRPV19IT1VSU2AuIEd1YXJkZWQgdG8gYSBwb3NpdGl2ZSBmaW5pdGUgbnVtYmVyLlxuICovXG5jb25zdCBET1JBX0lOQ0lERU5UX1dJTkRPV19IT1VSUyA9ICgoKSA9PiB7XG4gIGNvbnN0IHJhdyA9IE51bWJlcihwcm9jZXNzLmVudi5ET1JBX0lOQ0lERU5UX1dJTkRPV19IT1VSUyk7XG4gIHJldHVybiBOdW1iZXIuaXNGaW5pdGUocmF3KSAmJiByYXcgPiAwID8gcmF3IDogMjQ7XG59KSgpO1xuXG4vKipcbiAqIFJlc29sdmUgdGhlIGVmZmVjdGl2ZSBpbmNpZGVudOKGkmRlcGxveSBjb3JyZWxhdGlvbiB3aW5kb3cgKFBoYXNlIDViKS4gQSBwZXItb3JnXG4gKiBvdmVycmlkZSAoZnJvbSBgZG9yYV9zZXR0aW5ncy5pbmNpZGVudF93aW5kb3dfaG91cnNgLCBzdXJmYWNlZCB0aHJvdWdoIHRoZVxuICogc2V0dGluZ3MgZW5kcG9pbnQgYW5kIHRocmVhZGVkIGludG8ge0BsaW5rIERvcmFPcHRpb25zLmluY2lkZW50V2luZG93SG91cnN9KVxuICogd2lucyB3aGVuIGl0IGlzIGEgcG9zaXRpdmUgZmluaXRlIG51bWJlcjsgb3RoZXJ3aXNlIHRoZSBnbG9iYWwgZW52IGRlZmF1bHRcbiAqIGBET1JBX0lOQ0lERU5UX1dJTkRPV19IT1VSU2AgYXBwbGllcy4gQ2VudHJhbGl6ZWQgc28gdGhlIERPUkEgY29ycmVsYXRpb24sIHRoZVxuICogaW5jaWRlbnRzIGxpc3QsIGFuZCB0aGUgd2lyaW5nLXRlc3QgZHJ5LXJ1biBhbGwgYWdyZWUgb24gdGhlIHNhbWUgcnVsZS5cbiAqL1xuZnVuY3Rpb24gcmVzb2x2ZUluY2lkZW50V2luZG93SG91cnMob3ZlcnJpZGU/OiBudW1iZXIgfCBudWxsKTogbnVtYmVyIHtcbiAgcmV0dXJuIG92ZXJyaWRlICE9IG51bGwgJiYgTnVtYmVyLmlzRmluaXRlKG92ZXJyaWRlKSAmJiBvdmVycmlkZSA+IDAgPyBvdmVycmlkZSA6IERPUkFfSU5DSURFTlRfV0lORE9XX0hPVVJTO1xufVxuXG4vKipcbiAqIFJlcG9ydGluZyByZXRlbnRpb24gd2luZG93cyAoUGhhc2UgNykuIFJlY29yZHMgaW4gYHBpcGVsaW5lX2V2ZW50c2AsXG4gKiBgZGVwbG95bWVudF9vdXRjb21lc2AsIGFuZCBgaW5jaWRlbnRzYCBncm93IHVuYm91bmRlZCB3aXRob3V0IGEgc3dlZXAsIHNvIGFcbiAqIHNwbGl0LCBwZXItb3JnIHJldGVudGlvbiBwdXJnZSAoc2VlIHtAbGluayBSZXBvcnRpbmdTZXJ2aWNlLnB1cmdlRXhwaXJlZFJlcG9ydGluZ0RhdGF9KVxuICogaGFyZC1kZWxldGVzIHJvd3Mgb2xkZXIgdGhhbiB0aGVzZSB3aW5kb3dzLCBieSBgY3JlYXRlZF9hdGA6XG4gKiAgLSAqKlN0YW5kYXJkIGV2ZW50cyoqIOKAlCBgcGlwZWxpbmVfZXZlbnRzYCB3aXRoIGBlbnZpcm9ubWVudCBJUyBOVUxMYFxuICogICAgKG5vbi1kZXBsb3kgU1RBR0UvQUNUSU9OL2J1aWxkKS4gSGlnaCB2b2x1bWUg4oaSIHNob3J0IGRlZmF1bHQgKDMwIGRheXMpLlxuICogIC0gKipET1JBIHNvdXJjZSoqIOKAlCBgcGlwZWxpbmVfZXZlbnRzYCB3aXRoIGBlbnZpcm9ubWVudCBJUyBOT1QgTlVMTGAgKGRlcGxveVxuICogICAgc3RhZ2VzKSBwbHVzIGFsbCBvZiBgZGVwbG95bWVudF9vdXRjb21lc2AgYW5kIGBpbmNpZGVudHNgLiBMb3cgdm9sdW1lIOKGklxuICogICAgbG9uZ2VyIGRlZmF1bHQgKDE4MCBkYXlzKS4gRE9SQSBoaXN0b3J5IGlzIHRoZXJlZm9yZSBib3VuZGVkIGJ5IHRoaXMgd2luZG93O1xuICogICAgdGhlIHJlcG9ydCBxdWVyeSBzdGlsbCBoYXJkLWNhcHMgYXQgMzY1IGRheXMgKGEgbG9uZ2VyIHBlci1vcmcgb3ZlcnJpZGUgb25seVxuICogICAgcmV0YWlucyByYXcgc291cmNlIHJvd3MsIG5ldmVyIHdpZGVucyBhIHJlcG9ydCkuXG4gKiBgaW5nZXN0X2hlYWx0aGAgYW5kIGBkb3JhX3NldHRpbmdzYCBhcmUgbmV2ZXIgcHVyZ2VkLiBFbnYtb3ZlcnJpZGFibGUgZ2xvYmFscztcbiAqIGEgcGVyLW9yZyBvdmVycmlkZSBpbiBgZG9yYV9zZXR0aW5nc2Agd2lucyAoc2VlIHtAbGluayByZXNvbHZlRXZlbnRSZXRlbnRpb25EYXlzfSkuXG4gKi9cbmNvbnN0IFJFVEVOVElPTl9NSU5fREFZUyA9IDE7XG5jb25zdCBSRVRFTlRJT05fTUFYX0RBWVMgPSA3MzA7XG5cbi8qKiBQYXJzZSBhIHBvc2l0aXZlLWludCBlbnYgZGF5LWNvdW50LCBjbGFtcGVkIHRvIFtNSU4sIE1BWF0sIGVsc2UgYGZhbGxiYWNrYC4gKi9cbmZ1bmN0aW9uIHJldGVudGlvbkVudkRheXMobmFtZTogc3RyaW5nLCBmYWxsYmFjazogbnVtYmVyKTogbnVtYmVyIHtcbiAgY29uc3QgcmF3ID0gTnVtYmVyKHByb2Nlc3MuZW52W25hbWVdKTtcbiAgaWYgKCFOdW1iZXIuaXNGaW5pdGUocmF3KSB8fCAhTnVtYmVyLmlzSW50ZWdlcihyYXcpIHx8IHJhdyA8IFJFVEVOVElPTl9NSU5fREFZUykgcmV0dXJuIGZhbGxiYWNrO1xuICByZXR1cm4gTWF0aC5taW4ocmF3LCBSRVRFTlRJT05fTUFYX0RBWVMpO1xufVxuXG5jb25zdCBSRVBPUlRJTkdfRVZFTlRfUkVURU5USU9OX0RBWVMgPSByZXRlbnRpb25FbnZEYXlzKCdSRVBPUlRJTkdfRVZFTlRfUkVURU5USU9OX0RBWVMnLCAzMCk7XG5jb25zdCBSRVBPUlRJTkdfRE9SQV9SRVRFTlRJT05fREFZUyA9IHJldGVudGlvbkVudkRheXMoJ1JFUE9SVElOR19ET1JBX1JFVEVOVElPTl9EQVlTJywgMTgwKTtcblxuLyoqIEVmZmVjdGl2ZSBzdGFuZGFyZC1ldmVudCByZXRlbnRpb24gKGRheXMpOiBhIHZhbGlkIHBlci1vcmcgb3ZlcnJpZGUgd2lucyxcbiAqICBlbHNlIHRoZSBnbG9iYWwgZW52IGRlZmF1bHQuIFNoYXJlZCBieSB0aGUgc3dlZXAgKyB0aGUgc2V0dGluZ3Mgc3VyZmFjZSBzb1xuICogIHRoZXkgY2FuJ3QgZHJpZnQuIFRoZSBgLTFgIHVubGltaXRlZCBzZW50aW5lbCAoUGhhc2UgOCkgcGFzc2VzIHN0cmFpZ2h0XG4gKiAgdGhyb3VnaCDigJQgdGhlIHN3ZWVwIHJlYWRzIGl0IGFzIFwia2VlcCBmb3JldmVyLCBza2lwIHRoaXMgb3JnJ3Mgc3RhbmRhcmRcbiAqICBldmVudHNcIi4gQSBwb3NpdGl2ZSBvdmVycmlkZSBjbGFtcHMgdG8gWzEsIFJFVEVOVElPTl9NQVhfREFZU107IGEgYG51bGxgLCBhXG4gKiAgbm9uLWludGVnZXIsIG9yIGFueSBvdGhlciBvdXQtb2YtcmFuZ2UgdmFsdWUgKGUuZy4gMCwgLTIpIGZhbGxzIGJhY2sgdG8gdGhlXG4gKiAgZW52IGRlZmF1bHQuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZUV2ZW50UmV0ZW50aW9uRGF5cyhvdmVycmlkZT86IG51bWJlciB8IG51bGwpOiBudW1iZXIge1xuICBpZiAob3ZlcnJpZGUgPT09IC0xKSByZXR1cm4gLTE7XG4gIHJldHVybiBvdmVycmlkZSAhPSBudWxsICYmIE51bWJlci5pc0ludGVnZXIob3ZlcnJpZGUpICYmIG92ZXJyaWRlID49IFJFVEVOVElPTl9NSU5fREFZU1xuICAgID8gTWF0aC5taW4ob3ZlcnJpZGUsIFJFVEVOVElPTl9NQVhfREFZUykgOiBSRVBPUlRJTkdfRVZFTlRfUkVURU5USU9OX0RBWVM7XG59XG5cbi8qKiBFZmZlY3RpdmUgRE9SQS1zb3VyY2UgcmV0ZW50aW9uIChkYXlzKTogYSB2YWxpZCBwZXItb3JnIG92ZXJyaWRlIHdpbnMsIGVsc2VcbiAqICB0aGUgZ2xvYmFsIGVudiBkZWZhdWx0LiBUaGUgYC0xYCB1bmxpbWl0ZWQgc2VudGluZWwgKFBoYXNlIDgpIHBhc3NlcyBzdHJhaWdodFxuICogIHRocm91Z2gg4oCUIHRoZSBzd2VlcCByZWFkcyBpdCBhcyBcImtlZXAgZm9yZXZlciwgc2tpcCB0aGlzIG9yZydzIERPUkEtc291cmNlXG4gKiAgd2luZG93c1wiLiBBIHBvc2l0aXZlIG92ZXJyaWRlIGNsYW1wcyB0byBbMSwgUkVURU5USU9OX01BWF9EQVlTXTsgYSBgbnVsbGAsIGFcbiAqICBub24taW50ZWdlciwgb3IgYW55IG90aGVyIG91dC1vZi1yYW5nZSB2YWx1ZSAoZS5nLiAwLCAtMikgZmFsbHMgYmFjayB0byB0aGVcbiAqICBlbnYgZGVmYXVsdC4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlRG9yYVJldGVudGlvbkRheXMob3ZlcnJpZGU/OiBudW1iZXIgfCBudWxsKTogbnVtYmVyIHtcbiAgaWYgKG92ZXJyaWRlID09PSAtMSkgcmV0dXJuIC0xO1xuICByZXR1cm4gb3ZlcnJpZGUgIT0gbnVsbCAmJiBOdW1iZXIuaXNJbnRlZ2VyKG92ZXJyaWRlKSAmJiBvdmVycmlkZSA+PSBSRVRFTlRJT05fTUlOX0RBWVNcbiAgICA/IE1hdGgubWluKG92ZXJyaWRlLCBSRVRFTlRJT05fTUFYX0RBWVMpIDogUkVQT1JUSU5HX0RPUkFfUkVURU5USU9OX0RBWVM7XG59XG5cbi8qKiBUaGUgY3V0b2ZmIGluc3RhbnQgZm9yIGEgcmV0ZW50aW9uIHdpbmRvdzogcm93cyB3aXRoIGBjcmVhdGVkX2F0YCBzdHJpY3RseVxuICogIGJlZm9yZSB0aGlzIChgPCBjdXRvZmZgKSBhcmUgZXhwaXJlZC4gRGV0ZXJtaW5pc3RpYyBmb3IgYSBmaXhlZCBgbm93YC4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXRlbnRpb25DdXRvZmYobm93OiBEYXRlLCBkYXlzOiBudW1iZXIpOiBEYXRlIHtcbiAgcmV0dXJuIG5ldyBEYXRlKG5vdy5nZXRUaW1lKCkgLSBkYXlzICogODZfNDAwXzAwMCk7XG59XG5cbi8qKiBQZXItb3JnIHJldGVudGlvbiBvdmVycmlkZSByb3cgKFBoYXNlIDcpLiBCb3RoIG51bGxhYmxlIOKHkiBnbG9iYWwgZGVmYXVsdHMuICovXG5leHBvcnQgaW50ZXJmYWNlIFJlcG9ydGluZ1JldGVudGlvblNldHRpbmdzIHtcbiAgZXZlbnRSZXRlbnRpb25EYXlzOiBudW1iZXIgfCBudWxsO1xuICBkb3JhUmV0ZW50aW9uRGF5czogbnVtYmVyIHwgbnVsbDtcbiAgZGVmYXVsdEV2ZW50UmV0ZW50aW9uRGF5czogbnVtYmVyO1xuICBkZWZhdWx0RG9yYVJldGVudGlvbkRheXM6IG51bWJlcjtcbn1cblxuLyoqIE9wdGlvbnMgZm9yIHRoZSByZXBvcnRpbmcgcmV0ZW50aW9uIHN3ZWVwLiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZXBvcnRpbmdSZXRlbnRpb25PcHRpb25zIHtcbiAgLyoqIFJvd3MgZGVsZXRlZCBwZXIgc3RhdGVtZW50IChkZWZhdWx0IDEwMDApLiAqL1xuICBiYXRjaFNpemU/OiBudW1iZXI7XG4gIC8qKiBNYXggYmF0Y2hlcyBwZXIgdGFibGUgcGVyIG9yZyBwZXIgdGljayAoZGVmYXVsdCA1MCk7IHRoZSByZXN0IGRlZmVycyB0b1xuICAgKiAgdGhlIG5leHQgdGljayBzbyBhIGh1Z2UgYmFja2xvZyBjYW4ndCBob2xkIGxvY2tzIHRvbyBsb25nLiAqL1xuICBtYXhCYXRjaGVzUGVyVGFibGU/OiBudW1iZXI7XG4gIC8qKiBGaXhlZCBcIm5vd1wiIGZvciB0aGUgd2hvbGUgc3dlZXAgKGRlZmF1bHQgYG5ldyBEYXRlKClgKS4gKi9cbiAgbm93PzogRGF0ZTtcbn1cblxuLyoqIFBlci1ydW4gcHVyZ2UgdGFsbGllcyAoYWxzbyBsb2dnZWQpLiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZXBvcnRpbmdSZXRlbnRpb25Db3VudHMge1xuICAvKiogT3JncyBzd2VwdCB0aGlzIHJ1bi4gKi9cbiAgb3JnczogbnVtYmVyO1xuICAvKiogU3RhbmRhcmQgYHBpcGVsaW5lX2V2ZW50c2AgKGVudmlyb25tZW50IElTIE5VTEwpIHJvd3MgcHVyZ2VkLiAqL1xuICBzdGFuZGFyZEV2ZW50czogbnVtYmVyO1xuICAvKiogRE9SQS1zb3VyY2UgYHBpcGVsaW5lX2V2ZW50c2AgKGVudmlyb25tZW50IElTIE5PVCBOVUxMKSByb3dzIHB1cmdlZC4gKi9cbiAgZG9yYUV2ZW50czogbnVtYmVyO1xuICAvKiogYGRlcGxveW1lbnRfb3V0Y29tZXNgIHJvd3MgcHVyZ2VkLiAqL1xuICBkZXBsb3ltZW50T3V0Y29tZXM6IG51bWJlcjtcbiAgLyoqIGBpbmNpZGVudHNgIHJvd3MgcHVyZ2VkLiAqL1xuICBpbmNpZGVudHM6IG51bWJlcjtcbn1cblxuLyoqXG4gKiBET1JBIHBlcmZvcm1hbmNlIGJhbmQuIGBudWxsYCA9IGluc3VmZmljaWVudCBkYXRhIHRvIGNsYXNzaWZ5IChub1xuICogZGVwbG95bWVudHMvZmFpbHVyZXMvbGVhZC10aW1lIHNhbXBsZSBpbiB0aGUgd2luZG93KSwgc28gdGhlIFVJIHNob3dzIGFcbiAqIG5ldXRyYWwgc3RhdGUgcmF0aGVyIHRoYW4gbWlzbGFiZWxpbmcgYW4gZW1wdHkgd2luZG93IGFzIFwibG93XCIuXG4gKi9cbmV4cG9ydCB0eXBlIERvcmFMZXZlbCA9ICdlbGl0ZScgfCAnaGlnaCcgfCAnbWVkaXVtJyB8ICdsb3cnIHwgbnVsbDtcblxuLyoqIE9wdGlvbmFsIHNjb3BpbmcgZm9yIHtAbGluayBSZXBvcnRpbmdTZXJ2aWNlLmdldERvcmFNZXRyaWNzfS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRG9yYU9wdGlvbnMge1xuICAvKiogUmVzdHJpY3QgdG8gYSBzaW5nbGUgcGlwZWxpbmUgKHBlci1waXBlbGluZSBET1JBKS4gKi9cbiAgcGlwZWxpbmVJZD86IHN0cmluZztcbiAgLyoqIFJlc3RyaWN0IHRvIGEgc2luZ2xlIGRlcGxveSBlbnZpcm9ubWVudCAoZWxzZSBhbGwgZGVwbG95IGVudmlyb25tZW50cykuICovXG4gIGVudmlyb25tZW50Pzogc3RyaW5nO1xuICAvKipcbiAgICogUGVyLW9yZyBpbmNpZGVudOKGkmRlcGxveSBjb3JyZWxhdGlvbiB3aW5kb3cgb3ZlcnJpZGUgKGhvdXJzKS4gV2hlbiBzZXQgKGFcbiAgICogcG9zaXRpdmUgZmluaXRlIG51bWJlciksIHRoZSBpbmNpZGVudCBjb3JyZWxhdGlvbiB1c2VzIGl0IGluc3RlYWQgb2YgdGhlXG4gICAqIGdsb2JhbCBgRE9SQV9JTkNJREVOVF9XSU5ET1dfSE9VUlNgLiBUaGUgcm91dGUgcmVzb2x2ZXMgdGhpcyBmcm9tIHRoZSBvcmcnc1xuICAgKiBgZG9yYV9zZXR0aW5nc2Agcm93IChzZWUge0BsaW5rIFJlcG9ydGluZ1NlcnZpY2UuZ2V0SW5jaWRlbnRTZXR0aW5nc30pIGFuZFxuICAgKiBwYXNzZXMgaXQgaW47IHVuc2V0IGZhbGxzIGJhY2sgdG8gdGhlIGVudiBkZWZhdWx0LlxuICAgKi9cbiAgaW5jaWRlbnRXaW5kb3dIb3Vycz86IG51bWJlcjtcbn1cblxuLyoqXG4gKiBQZXItb3JnIHJlcG9ydGluZyBzZXR0aW5ncyBzdXJmYWNlZCB0byB0aGUgb3JnLWFkbWluIHBhbmVsLiBgaW5jaWRlbnRXaW5kb3dIb3Vyc2BcbiAqIChQaGFzZSA1YikgaXMgdGhlIGluY2lkZW504oaSZGVwbG95IGNvcnJlbGF0aW9uIHdpbmRvdzsgYGV2ZW50UmV0ZW50aW9uRGF5c2AgL1xuICogYGRvcmFSZXRlbnRpb25EYXlzYCAoUGhhc2UgNykgYXJlIHRoZSB0d28gcmV0ZW50aW9uLXN3ZWVwIHdpbmRvd3MuIEVhY2ggb3ZlcnJpZGVcbiAqIGlzIGBudWxsYCB3aGVuIHVuc2V0ICh0aGUgcGFpcmVkIGBkZWZhdWx0KmAgZmllbGQgc2hvd3MgdGhlIGVudiBmYWxsYmFjayBhcHBsaWVkKS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJbmNpZGVudFNldHRpbmdzIHtcbiAgLyoqIFRoZSBvcmcncyBzdG9yZWQgY29ycmVsYXRpb24td2luZG93IG92ZXJyaWRlIGluIGhvdXJzLCBvciBgbnVsbGAgd2hlbiB1bnNldC4gKi9cbiAgaW5jaWRlbnRXaW5kb3dIb3VyczogbnVtYmVyIHwgbnVsbDtcbiAgLyoqIFRoZSBnbG9iYWwgZW52IGRlZmF1bHQgYXBwbGllZCB3aGVuIG5vIG92ZXJyaWRlIGlzIHN0b3JlZC4gKi9cbiAgZGVmYXVsdFdpbmRvd0hvdXJzOiBudW1iZXI7XG4gIC8qKiBTdGFuZGFyZC1ldmVudCByZXRlbnRpb24gb3ZlcnJpZGUgaW4gZGF5cywgb3IgYG51bGxgIHdoZW4gdW5zZXQgKFBoYXNlIDcpLiAqL1xuICBldmVudFJldGVudGlvbkRheXM6IG51bWJlciB8IG51bGw7XG4gIC8qKiBET1JBLXNvdXJjZSByZXRlbnRpb24gb3ZlcnJpZGUgaW4gZGF5cywgb3IgYG51bGxgIHdoZW4gdW5zZXQgKFBoYXNlIDcpLiAqL1xuICBkb3JhUmV0ZW50aW9uRGF5czogbnVtYmVyIHwgbnVsbDtcbiAgLyoqIEdsb2JhbCBzdGFuZGFyZC1ldmVudCByZXRlbnRpb24gZGVmYXVsdCBhcHBsaWVkIHdoZW4gdW5zZXQgKGRheXMpLiAqL1xuICBkZWZhdWx0RXZlbnRSZXRlbnRpb25EYXlzOiBudW1iZXI7XG4gIC8qKiBHbG9iYWwgRE9SQS1zb3VyY2UgcmV0ZW50aW9uIGRlZmF1bHQgYXBwbGllZCB3aGVuIHVuc2V0IChkYXlzKS4gKi9cbiAgZGVmYXVsdERvcmFSZXRlbnRpb25EYXlzOiBudW1iZXI7XG59XG5cbi8qKiBBIHBhcnRpYWwgcmVwb3J0aW5nLXNldHRpbmdzIHdyaXRlIChQaGFzZSA1YiArIDcpLiBPbmx5IHByb3ZpZGVkIGZpZWxkcyBhcmVcbiAqICB1cHNlcnRlZDsgb21pdHRlZCBmaWVsZHMgYXJlIGxlZnQgdW5jaGFuZ2VkIChhbiBvbWl0dGVkIHJldGVudGlvbiBmaWVsZCBrZWVwc1xuICogIGl0cyBzdG9yZWQgb3ZlcnJpZGUgLyB0aGUgZ2xvYmFsIGRlZmF1bHQpLiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZXBvcnRpbmdTZXR0aW5nc1BhdGNoIHtcbiAgaW5jaWRlbnRXaW5kb3dIb3Vycz86IG51bWJlcjtcbiAgZXZlbnRSZXRlbnRpb25EYXlzPzogbnVtYmVyO1xuICBkb3JhUmV0ZW50aW9uRGF5cz86IG51bWJlcjtcbn1cblxuLyoqIE9uZSByb3cgb2YgdGhlIG9yZy1hZG1pbiBpbmNpZGVudHMgbGlzdCAocmVjZW50IGluY2lkZW50cyArIGRlcGxveSBjb3JyZWxhdGlvbikuICovXG5leHBvcnQgaW50ZXJmYWNlIEluY2lkZW50TGlzdEl0ZW0ge1xuICBpbmNpZGVudElkOiBzdHJpbmc7XG4gIGVudmlyb25tZW50OiBzdHJpbmc7XG4gIHNldmVyaXR5OiBzdHJpbmc7XG4gIG9wZW5lZEF0OiBzdHJpbmcgfCBudWxsO1xuICByZXNvbHZlZEF0OiBzdHJpbmcgfCBudWxsO1xuICBjcmVhdGVkQXQ6IHN0cmluZyB8IG51bGw7XG4gIC8qKiBUcnVlIG9uY2UgdGhlIGluY2lkZW50IGhhcyBhIGByZXNvbHZlZF9hdGAuICovXG4gIHJlc29sdmVkOiBib29sZWFuO1xuICAvKiogVGhlIGNvcnJlbGF0ZWQgZGVwbG95IGV4ZWN1dGlvbiBpZCAobW9zdCByZWNlbnQgc3VjY2Vzc2Z1bCBkZXBsb3kgaW4td2luZG93KSwgb3IgbnVsbC4gKi9cbiAgY29ycmVsYXRlZEV4ZWN1dGlvbklkOiBzdHJpbmcgfCBudWxsO1xuICAvKiogVGhhdCBkZXBsb3kncyBjb21wbGV0aW9uIGluc3RhbnQsIG9yIG51bGwgd2hlbiB1bmNvcnJlbGF0ZWQuICovXG4gIGRlcGxveUNvbXBsZXRlZEF0OiBzdHJpbmcgfCBudWxsO1xufVxuXG4vKiogUmVzdWx0IG9mIHRoZSB3aXJpbmctdGVzdCBkcnktcnVuIGNvcnJlbGF0aW9uICh7QGxpbmsgUmVwb3J0aW5nU2VydmljZS50ZXN0SW5jaWRlbnRDb3JyZWxhdGlvbn0pLiAqL1xuZXhwb3J0IGludGVyZmFjZSBJbmNpZGVudFRlc3RSZXN1bHQge1xuICBlbnZpcm9ubWVudDogc3RyaW5nO1xuICAvKiogVGhlIHN5bnRoZXRpYyBpbmNpZGVudCdzIG9wZW5lZEF0IChub3csIElTTykuICovXG4gIG9wZW5lZEF0OiBzdHJpbmc7XG4gIC8qKiBUaGUgZWZmZWN0aXZlIGNvcnJlbGF0aW9uIHdpbmRvdyB1c2VkLiAqL1xuICB3aW5kb3dIb3VyczogbnVtYmVyO1xuICAvKiogV2hldGhlciBhIHJlY2VudCBzdWNjZXNzZnVsIGRlcGxveSB0byBgZW52aXJvbm1lbnRgIGNvcnJlbGF0ZWQuICovXG4gIGNvcnJlbGF0ZWQ6IGJvb2xlYW47XG4gIC8qKiBUaGUgY29ycmVsYXRlZCBkZXBsb3kgZXhlY3V0aW9uIGlkLCBvciBudWxsLiAqL1xuICBleGVjdXRpb25JZDogc3RyaW5nIHwgbnVsbDtcbiAgLyoqIFRoYXQgZGVwbG95J3MgY29tcGxldGlvbiBpbnN0YW50LCBvciBudWxsLiAqL1xuICBkZXBsb3lDb21wbGV0ZWRBdDogc3RyaW5nIHwgbnVsbDtcbn1cblxuLy8gRE9SQSBwZXJmb3JtYW5jZSBiYW5kcyAodGhyZXNob2xkcyBmcm9tIHRoZSBET1JBL0FjY2VsZXJhdGUgcmVwb3J0cykuIEVhY2hcbi8vIGhlbHBlciByZXR1cm5zIGBudWxsYCB3aGVuIHRoZXJlJ3Mgbm8gc2FtcGxlIHRvIGNsYXNzaWZ5LlxuLyoqIERlcGxveW1lbnQgZnJlcXVlbmN5IGJ5IGRlcGxveXMvZGF5OiBlbGl0ZSDiiaUxL2RheSwgaGlnaCDiiaUxL3dlZWssIG1lZGl1bSDiiaUxL21vbnRoLiAqL1xuZnVuY3Rpb24gZG9yYUxldmVsRm9yRnJlcXVlbmN5KHBlckRheTogbnVtYmVyLCBkZXBsb3ltZW50czogbnVtYmVyKTogRG9yYUxldmVsIHtcbiAgaWYgKGRlcGxveW1lbnRzIDw9IDApIHJldHVybiBudWxsO1xuICBpZiAocGVyRGF5ID49IDEpIHJldHVybiAnZWxpdGUnO1xuICBpZiAocGVyRGF5ID49IDEgLyA3KSByZXR1cm4gJ2hpZ2gnO1xuICBpZiAocGVyRGF5ID49IDEgLyAzMCkgcmV0dXJuICdtZWRpdW0nO1xuICByZXR1cm4gJ2xvdyc7XG59XG4vKiogQ2hhbmdlIGZhaWx1cmUgcmF0ZSBieSBwZXJjZW50OiBlbGl0ZSDiiaQ1JSwgaGlnaCDiiaQxMCUsIG1lZGl1bSDiiaQxNSUuICovXG5mdW5jdGlvbiBkb3JhTGV2ZWxGb3JDaGFuZ2VGYWlsdXJlKHBjdDogbnVtYmVyLCB0b3RhbDogbnVtYmVyKTogRG9yYUxldmVsIHtcbiAgaWYgKHRvdGFsIDw9IDApIHJldHVybiBudWxsO1xuICBpZiAocGN0IDw9IDUpIHJldHVybiAnZWxpdGUnO1xuICBpZiAocGN0IDw9IDEwKSByZXR1cm4gJ2hpZ2gnO1xuICBpZiAocGN0IDw9IDE1KSByZXR1cm4gJ21lZGl1bSc7XG4gIHJldHVybiAnbG93Jztcbn1cbi8qKiBUaW1lIHRvIHJlc3RvcmUgYnkgc2Vjb25kczogZWxpdGUgPDFoLCBoaWdoIDwxIGRheSwgbWVkaXVtIDwxIHdlZWsuICovXG5mdW5jdGlvbiBkb3JhTGV2ZWxGb3JSZXN0b3JlKGF2Z1NlY29uZHM6IG51bWJlciB8IG51bGwpOiBEb3JhTGV2ZWwge1xuICBpZiAoYXZnU2Vjb25kcyA9PSBudWxsKSByZXR1cm4gbnVsbDtcbiAgaWYgKGF2Z1NlY29uZHMgPCAzNjAwKSByZXR1cm4gJ2VsaXRlJztcbiAgaWYgKGF2Z1NlY29uZHMgPCA4NjQwMCkgcmV0dXJuICdoaWdoJztcbiAgaWYgKGF2Z1NlY29uZHMgPCA2MDQ4MDApIHJldHVybiAnbWVkaXVtJztcbiAgcmV0dXJuICdsb3cnO1xufVxuLyoqIExlYWQgdGltZSBieSBzZWNvbmRzOiBlbGl0ZSA8MSBkYXksIGhpZ2ggPDEgd2VlaywgbWVkaXVtIDwxIG1vbnRoLiAqL1xuZnVuY3Rpb24gZG9yYUxldmVsRm9yTGVhZFRpbWUobWVkaWFuU2Vjb25kczogbnVtYmVyIHwgbnVsbCk6IERvcmFMZXZlbCB7XG4gIGlmIChtZWRpYW5TZWNvbmRzID09IG51bGwpIHJldHVybiBudWxsO1xuICBpZiAobWVkaWFuU2Vjb25kcyA8IDg2NDAwKSByZXR1cm4gJ2VsaXRlJztcbiAgaWYgKG1lZGlhblNlY29uZHMgPCA2MDQ4MDApIHJldHVybiAnaGlnaCc7XG4gIGlmIChtZWRpYW5TZWNvbmRzIDwgMjU5MjAwMCkgcmV0dXJuICdtZWRpdW0nO1xuICByZXR1cm4gJ2xvdyc7XG59XG5cbi8qKlxuICogUm91bmQgYHZhbHVlYCB0byBgZGlnaXRzYCBkZWNpbWFsIHBsYWNlcywgcmV0dXJuaW5nIGEgcmVhbCBudW1iZXIuIFNtYWxsXG4gKiBtb2R1bGUtcHJpdmF0ZSBoZWxwZXIgc28gdGhlIERPUkEgc2hhcGluZyBkb2Vzbid0IHJlcGVhdCB0aGVcbiAqIGBOdW1iZXIoTnVtYmVyKHgpLnRvRml4ZWQobikpYCBwYXR0ZXJuICh0b0ZpeGVkIGFsb25lIHlpZWxkcyBhIHN0cmluZykuXG4gKi9cbmZ1bmN0aW9uIHJvdW5kKHZhbHVlOiBudW1iZXIsIGRpZ2l0czogbnVtYmVyKTogbnVtYmVyIHtcbiAgcmV0dXJuIE51bWJlcih2YWx1ZS50b0ZpeGVkKGRpZ2l0cykpO1xufVxuXG4vKipcbiAqIE1lZGlhbiBvZiBhIG51bWVyaWMgc2FtcGxlLCBvciBgbnVsbGAgd2hlbiBlbXB0eS4gVXNlZCBmb3IgbWVhc3VyZWQgbGVhZCB0aW1lXG4gKiBhbmQgTVRUUiDigJQgYm90aCBhcmUgY3Jvc3Mtc291cmNlIGdhcHMgY29tcHV0ZWQgaW4gSlMgZnJvbSBjbGFtcGVkIGRlbHRhcywgc29cbiAqIHRoZSBtZWRpYW4gbGl2ZXMgaGVyZSByYXRoZXIgdGhhbiBpbiBTUUwgUEVSQ0VOVElMRV9DT05UIChrZWVwcyB0aGUgZ29sZGVuXG4gKiBmaXh0dXJlIHRlc3RzIGFibGUgdG8gcHJvdmUgdGhlIG1ldHJpYyBtYXRoIHdpdGhvdXQgYSBsaXZlIFBvc3RncmVzKS5cbiAqL1xuZnVuY3Rpb24gbWVkaWFuKHZhbHVlczogbnVtYmVyW10pOiBudW1iZXIgfCBudWxsIHtcbiAgaWYgKHZhbHVlcy5sZW5ndGggPT09IDApIHJldHVybiBudWxsO1xuICBjb25zdCBzID0gWy4uLnZhbHVlc10uc29ydCgoYSwgYikgPT4gYSAtIGIpO1xuICBjb25zdCBtaWQgPSBNYXRoLmZsb29yKHMubGVuZ3RoIC8gMik7XG4gIHJldHVybiBzLmxlbmd0aCAlIDIgPT09IDEgPyBzW21pZF0gOiAoc1ttaWQgLSAxXSArIHNbbWlkXSkgLyAyO1xufVxuXG4vKipcbiAqIFJvbGwgYSBncm91cCBvZiBkZXBsb3kvc3RhZ2UgZXZlbnRzIChncm91cGVkIHBlciBleGVjdXRpb24pIHVwIHRvIG9uZSB0ZXJtaW5hbFxuICogc3RhdHVzOiBGQUlMRUQgd2lucywgdGhlbiBTVUNDRUVERUQsIGVsc2UgT1RIRVIgKHN0aWxsLXJ1bm5pbmcgLyBub24tdGVybWluYWwpLlxuICogU2hhcmVkIGJ5IHRoZSB0aHJlZSBwZXItKGVudnxzdGFnZSwgZXhlY3V0aW9uKSByb2xsdXAgQ1RFcyDigJQgRE9SQSBtZXRyaWNzLCBET1JBXG4gKiB0cmVuZCwgYW5kIGJ1aWxkIGhlYWx0aCDigJQgc28gdGhlIHByZWNlZGVuY2UgY2FuJ3QgZHJpZnQgYmV0d2VlbiB0aGVtLiBBc3N1bWVzIHRoZVxuICogZ3JvdXBlZCBldmVudCBhbGlhcyBpcyBgZWAuXG4gKi9cbmNvbnN0IHRlcm1pbmFsU3RhdHVzUm9sbHVwID0gc3FsYENBU0VcbiAgICAgICAgICAgICAgV0hFTiBib29sX29yKGUuc3RhdHVzID0gJ0ZBSUxFRCcpIFRIRU4gJ0ZBSUxFRCdcbiAgICAgICAgICAgICAgV0hFTiBib29sX29yKGUuc3RhdHVzID0gJ1NVQ0NFRURFRCcpIFRIRU4gJ1NVQ0NFRURFRCdcbiAgICAgICAgICAgICAgRUxTRSAnT1RIRVInXG4gICAgICAgICAgICBFTkRgO1xuXG4vKiogT3B0aW9uYWwgYFtmcm9tLHRvXWAgd2luZG93IG9uIGBlLnN0YXJ0ZWRfYXRgIGZvciB0aGUgZXhlY3V0aW9uIHJlcG9ydHMg4oCUXG4gKiAgYSBuby1vcCBgc3FsYCBmcmFnbWVudCB3aGVuIGVpdGhlciBib3VuZCBpcyBhYnNlbnQgKGFsbC10aW1lKS4gU2hhcmVkIGJ5IHRoZVxuICogIGV4ZWN1dGlvbi1jb3VudCBhbmQgcGVyLXBpcGVsaW5lLWV4ZWN1dGlvbiByZXBvcnRzIHNvIHRoZXkgbmFycm93IGlkZW50aWNhbGx5LiAqL1xuZnVuY3Rpb24gb3B0aW9uYWxTdGFydGVkQXRSYW5nZShyYW5nZT86IHsgZnJvbT86IHN0cmluZzsgdG8/OiBzdHJpbmcgfSk6IFJldHVyblR5cGU8dHlwZW9mIHNxbD4ge1xuICByZXR1cm4gcmFuZ2U/LmZyb20gJiYgcmFuZ2U/LnRvXG4gICAgPyBzcWxgQU5EIGUuc3RhcnRlZF9hdCA+PSAke3JhbmdlLmZyb219Ojp0aW1lc3RhbXB0eiBBTkQgZS5zdGFydGVkX2F0IDw9ICR7cmFuZ2UudG99Ojp0aW1lc3RhbXB0emBcbiAgICA6IHNxbGBgO1xufVxuXG4vKipcbiAqIFBlci1leGVjdXRpb24gdGVybWluYWwgZGVwbG95IHJvdyAoRDEg4oCUIG9uZSByb3cgcGVyIChlbnZpcm9ubWVudCwgZXhlY3V0aW9uKSxcbiAqIE5PVCBwZXIgc3RhZ2UpLiBUaGUgU1FMIHJvbGxzIGV2ZXJ5IGRlcGxveSBTVEFHRSB0YXJnZXRpbmcgYW4gZW52IHdpdGhpbiBhblxuICogZXhlY3V0aW9uIHVwIHRvIGEgc2luZ2xlIHRlcm1pbmFsIHN0YXR1czsgdGhlIEpTIHNoYXBpbmcgYnVja2V0cyB0aGVzZSBieVxuICogZW52aXJvbm1lbnQuIGBjb21taXRfdHNgIChEMikgaXMgdGhlIGV4ZWN1dGlvbidzIEVBUkxJRVNUIGNvbW1pdCB0aW1lIGFjcm9zc1xuICogYWxsIGl0cyBldmVudHMg4oCUIGNvbW1pdCBlbnJpY2htZW50IHJpZGVzIHRoZSBQSVBFTElORS9zb3VyY2UgZXZlbnQsIG5vdCB0aGVcbiAqIGRlcGxveSBTVEFHRSDigJQgam9pbmVkIGJ5IGV4ZWN1dGlvbl9pZCAobnVsbCB3aGVuIHVucmVzb2x2ZWQg4oaSIGxlYWQgYHVua25vd25gKS5cbiAqIGBpbl93aW5kb3dgIGlzIGZhbHNlIGZvciBhIGxvb2stYmFjay1vbmx5IHJvdyBrZXB0IHNvbGVseSBzbyBpbmNpZGVudHMgb3BlbmVkXG4gKiBuZWFyIGBmcm9tYCBjYW4gY29ycmVsYXRlIHRvIGEgZGVwbG95IHRoYXQgY29tcGxldGVkIGp1c3QgYmVmb3JlIHRoZSB3aW5kb3cuXG4gKi9cbmludGVyZmFjZSBEZXBsb3lSb3cge1xuICBlbnZpcm9ubWVudDogc3RyaW5nO1xuICBzdGF0dXM6ICdTVUNDRUVERUQnIHwgJ0ZBSUxFRCcgfCBzdHJpbmc7XG4gIC8qKiBEZXBsb3kgZXhlY3V0aW9uIGlkIOKAlCB0aGUgYXR0cmlidXRpb24ga2V5IGZvciBkZWR1cCBhZ2FpbnN0IG91dGNvbWVzL2luY2lkZW50cy4gKi9cbiAgZXhlY3V0aW9uX2lkOiBzdHJpbmcgfCBudWxsO1xuICBjb21wbGV0ZWRfYXQ6IHN0cmluZyB8IG51bGw7XG4gIGNvbW1pdF90czogc3RyaW5nIHwgbnVsbDtcbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhlIGRlcGxveSBjb21wbGV0ZWQgaW5zaWRlIFtmcm9tLHRvXS4gQWJzZW50ICh1bmRlZmluZWQpIGluIHVuaXRcbiAgICogZml4dHVyZXMg4oeSIHRyZWF0ZWQgYXMgaW4td2luZG93LiBgdGAvYGZgIHRvbGVyYXRlZCAocGcgYm9vbGVhbiB0ZXh0IGZvcm0pLlxuICAgKi9cbiAgaW5fd2luZG93PzogYm9vbGVhbiB8IHN0cmluZyB8IG51bGw7XG59XG5cbi8qKiBSYXcgcG9zdC1kZXBsb3kgb3V0Y29tZSBtYXJrZXIgcm93IChmcm9tIGBkZXBsb3ltZW50X291dGNvbWVzYCwgaW4td2luZG93KS4gKi9cbmludGVyZmFjZSBPdXRjb21lUm93IHtcbiAgZW52aXJvbm1lbnQ6IHN0cmluZyB8IG51bGw7XG4gIG91dGNvbWU6ICdmYWlsZWQnIHwgJ3Jlc3RvcmVkJyB8IHN0cmluZztcbiAgLyoqIEV4ZWN1dGlvbiB0aGUgdXNlciBtYXJrZWQg4oCUIGRlZHVwIGtleSBhZ2FpbnN0IGluY2lkZW50LWNvcnJlbGF0ZWQgZGVwbG95cy4gKi9cbiAgZXhlY3V0aW9uX2lkOiBzdHJpbmcgfCBudWxsO1xufVxuXG4vKiogUHJvZHVjdGlvbiByZXN0b3JlZC1pbmNpZGVudCBwYWlyOiByZWNvdmVyeSB0aW1lICsgdGhlIGRlcGxveSdzIGNvbXBsZXRpb24uICovXG5pbnRlcmZhY2UgTXR0clBhaXJSb3cge1xuICByZXN0b3JlZF9hdDogc3RyaW5nIHwgbnVsbDtcbiAgZGVwbG95ZWRfYXQ6IHN0cmluZyB8IG51bGw7XG4gIC8qKiBFeGVjdXRpb24gaWQg4oCUIGxldHMgaW5jaWRlbnQgcHJlY2VkZW5jZSBvdmVycmlkZSB0aGUgbWFudWFsIG91dGNvbWUgcGVyIGRlcGxveS4gKi9cbiAgZXhlY3V0aW9uX2lkOiBzdHJpbmcgfCBudWxsO1xufVxuXG4vKipcbiAqIFJhdyBpbmNpZGVudCByb3cgKGZyb20gYGluY2lkZW50c2AsIG9wZW5lZCBpbi13aW5kb3cpLiBDb3JyZWxhdGVkIGluIEpTIHRvIHRoZVxuICogbW9zdCByZWNlbnQgc3VjY2Vzc2Z1bCBkZXBsb3kgdG8gYGVudmlyb25tZW50YCB3aXRoaW4gRE9SQV9JTkNJREVOVF9XSU5ET1dfSE9VUlNcbiAqIOKGkiBhbiBhdXRvbWF0ZWQgcG9zdC1kZXBsb3kgZmFpbHVyZSAoQ0ZSKSArIHJlYWwgcmVjb3ZlcnkgdGltZSAoTVRUUikuXG4gKi9cbmludGVyZmFjZSBJbmNpZGVudFJvdyB7XG4gIGVudmlyb25tZW50OiBzdHJpbmc7XG4gIG9wZW5lZF9hdDogc3RyaW5nIHwgbnVsbDtcbiAgcmVzb2x2ZWRfYXQ6IHN0cmluZyB8IG51bGw7XG59XG5cbi8qKiBDb3ZlcmFnZSBjb3VudHM6IHJlZ2lzdGVyZWQgcGlwZWxpbmVzIHZzIHRob3NlIHRoYXQgYWN0dWFsbHkgZGVwbG95ZWQuICovXG5pbnRlcmZhY2UgQ292ZXJhZ2VSb3cge1xuICByZWdpc3RlcmVkOiBudW1iZXIgfCBzdHJpbmcgfCBudWxsO1xuICBkZXBsb3lpbmc6IG51bWJlciB8IHN0cmluZyB8IG51bGw7XG59XG5cbi8qKlxuICogRE9SQSBtZXRyaWNzIG92ZXIgYSBbZnJvbSx0b10gd2luZG93LCBvcmctc2NvcGVkIChzaW5nbGUtb3JnIG9yIHJvbGx1cCBzdWJ0cmVlKS5cbiAqXG4gKiBERVBMT1ktQkFTSVMg4oCUIGV2ZXJ5IG1ldHJpYyBkZXJpdmVzIGZyb20gcmVhbCBERVBMT1ktU1RBR0UgZXhlY3V0aW9ucywgaS5lLlxuICogYHBpcGVsaW5lX2V2ZW50c2Agcm93cyB3aXRoIGBldmVudF90eXBlPSdTVEFHRSdgIGFuZCBhIG5vbi1udWxsIGBlbnZpcm9ubWVudGBcbiAqICh0aGUgZm9yd2FyZGVyIHNldHMgYGVudmlyb25tZW50YCBvbmx5IGZvciB0aGUgc3RhZ2VzIGEgdXNlciBkZWNsYXJlZCBpblxuICogYHBiLmRlcGxveXNgKS4gQSBDSS1vbmx5IGJ1aWxkL3Rlc3QgcGlwZWxpbmUgd2l0aCBubyBkZXBsb3kgc3RhZ2UgcHJvZHVjZXMgTk9cbiAqIERPUkEgZGF0YSDigJQgdGhlcmUgaXMgbm8gcnVuLWJhc2VkIGZhbGxiYWNrLiBUaGUgcGFuZWwgaXMgZW1wdHkgdW50aWwgZGVwbG95ZWRcbiAqIHBpcGVsaW5lcyByZS1zeW50aCB3aXRoIHRoZSBuZXcgZGVwbG95IHRhZ3MgYW5kIHN0YXJ0IGVtaXR0aW5nIGRlcGxveSBldmVudHMuXG4gKlxuICogYHByb2R1Y3Rpb25gIGlzIHRoZSBoZWFkbGluZSBlbnZpcm9ubWVudDsgTVRUUiBpcyBtZWFzdXJlZCBwcm9kdWN0aW9uLW9ubHkuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRG9yYU1ldHJpY3Mge1xuICAvKiogVGhlIFtmcm9tLHRvXSB3aW5kb3cgZWNob2VkIGJhY2sgKGRlcGxveSBgY29tcGxldGVkX2F0YCByYW5nZSkuICovXG4gIHdpbmRvdzogeyBmcm9tOiBzdHJpbmc7IHRvOiBzdHJpbmcgfTtcbiAgLyoqIFRoZSBzY29waW5nIGFwcGxpZWQgKGVjaG9lZCBmb3IgdGhlIFVJKTsgYG51bGxgIHdoZW4gdW5zY29wZWQuICovXG4gIGZpbHRlcnM6IHsgcGlwZWxpbmVJZDogc3RyaW5nIHwgbnVsbDsgZW52aXJvbm1lbnQ6IHN0cmluZyB8IG51bGwgfTtcbiAgLyoqIFRoZSBoZWFkbGluZSBlbnZpcm9ubWVudCBuYW1lIChgcHJvZHVjdGlvbmApLiAqL1xuICBoZWFkbGluZTogc3RyaW5nO1xuICAvKiogUGVyLWVudmlyb25tZW50IERGIC8gQ0ZSIC8gbGVhZCB0aW1lLiBTb3J0ZWQgaGVhZGxpbmUtZmlyc3QsIHRoZW4gQeKGklouICovXG4gIGVudmlyb25tZW50czogRG9yYUVudk1ldHJpY3NbXTtcbiAgLyoqXG4gICAqIE1lYW4gVGltZSBUbyBSZXN0b3JlIOKAlCBQUk9EVUNUSU9OLU9OTFksIGZyb20gYGRlcGxveW1lbnRfb3V0Y29tZXNgLlxuICAgKiBgbWVkaWFuKHJlc3RvcmVkLmF0IOKIkiBkZXBsb3llZC5jb21wbGV0ZWRfYXQpYCBvdmVyIHJlc3RvcmVkIHByb2R1Y3Rpb25cbiAgICogaW5jaWRlbnRzIChkZWx0YXMgY2xhbXBlZCDiiaUwKS4gYGluY2lkZW50c2AgY291bnRzIHByb2R1Y3Rpb24gZGVwbG95cyBtYXJrZWRcbiAgICogZmFpbGVkOyBgcmVzdG9yZWRgIGNvdW50cyB0aG9zZSB0aGF0IHJlY292ZXJlZDsgYG1lZGlhblNlY29uZHNgIGlzIG51bGwgd2hlblxuICAgKiBubyByZXN0b3JlZCBpbmNpZGVudCBoYXMgYSByZXNvbHZhYmxlIGRlcGxveSB0aW1lLlxuICAgKi9cbiAgbWVhblRpbWVUb1Jlc3RvcmU6IHtcbiAgICBpbmNpZGVudHM6IG51bWJlcjtcbiAgICByZXN0b3JlZDogbnVtYmVyO1xuICAgIG1lZGlhblNlY29uZHM6IG51bWJlciB8IG51bGw7XG4gICAgbGV2ZWw6IERvcmFMZXZlbDtcbiAgfTtcbiAgLyoqXG4gICAqIENvdmVyYWdlIHJlY29uY2lsaWF0aW9uIOKAlCByZWdpc3RlcmVkIHBpcGVsaW5lcyB3aXRoIG5vIG9ic2VydmVkIGRlcGxveSBpblxuICAgKiB0aGUgd2luZG93LiBBIGhpZ2ggYHdpdGhvdXREZXBsb3lzYCBjb3VudCBtZWFucyBET1JBIGlzIGJsaW5kIHRvIG1vc3Qgb2YgdGhlXG4gICAqIGZsZWV0IChwaXBlbGluZXMgdGhhdCBoYXZlbid0IHJlLXN5bnRoZWQgd2l0aCBkZXBsb3kgdGFncywgb3IgZG9uJ3QgZGVwbG95KS5cbiAgICovXG4gIGNvdmVyYWdlOiB7XG4gICAgLyoqIFBpcGVsaW5lcyBpbiB0aGUgcmVnaXN0cnkgKG9yZy1zY29wZWQpLiAqL1xuICAgIHJlZ2lzdGVyZWQ6IG51bWJlcjtcbiAgICAvKiogUmVnaXN0ZXJlZCBwaXBlbGluZXMgd2l0aCDiiaUxIGRlcGxveS1zdGFnZSBleGVjdXRpb24gaW4gdGhlIHdpbmRvdy4gKi9cbiAgICBkZXBsb3lpbmc6IG51bWJlcjtcbiAgICAvKiogcmVnaXN0ZXJlZCDiiJIgZGVwbG95aW5nIChjbGFtcGVkIOKJpTApLiAqL1xuICAgIHdpdGhvdXREZXBsb3lzOiBudW1iZXI7XG4gIH07XG59XG5cbi8qKiBQZXItZW52aXJvbm1lbnQgRE9SQSBtZXRyaWNzIChkZXBsb3ltZW50IGZyZXF1ZW5jeSwgQ0ZSLCBsZWFkIHRpbWUpLiAqL1xuZXhwb3J0IGludGVyZmFjZSBEb3JhRW52TWV0cmljcyB7XG4gIGVudmlyb25tZW50OiBzdHJpbmc7XG4gIC8qKiBEZXBsb3ltZW50IEZyZXF1ZW5jeSDigJQgc3VjY2Vzc2Z1bCBkZXBsb3ktc3RhZ2UgZXhlY3V0aW9ucyBmb3IgdGhpcyBlbnYuICovXG4gIGRlcGxveW1lbnRGcmVxdWVuY3k6IHtcbiAgICBkZXBsb3ltZW50czogbnVtYmVyO1xuICAgIHBlckRheTogbnVtYmVyO1xuICAgIGxldmVsOiBEb3JhTGV2ZWw7XG4gIH07XG4gIC8qKlxuICAgKiBDaGFuZ2UgRmFpbHVyZSBSYXRlIOKAlCB0d28tY2xhc3M6XG4gICAqIGAoZGVwbG95VGltZUZhaWx1cmVzICsgcG9zdERlcGxveUZhaWx1cmVzKSAvIGF0dGVtcHRzYC5cbiAgICogLSBgZGVwbG95VGltZUZhaWx1cmVzYCDigJQgZGVwbG95IHN0YWdlIGByZXN1bHQ9ZmFpbGVkYCAoZnJvbSBldmVudHMpLlxuICAgKiAtIGBwb3N0RGVwbG95RmFpbHVyZXNgIOKAlCBhIHN1Y2Nlc3NmdWwgZGVwbG95IGxhdGVyIG1hcmtlZCBmYWlsZWQgaW4gcHJvZFxuICAgKiAgIChmcm9tIGBkZXBsb3ltZW50X291dGNvbWVzYCkuXG4gICAqIC0gYGF0dGVtcHRzYCDigJQgYWxsIHRlcm1pbmFsIGRlcGxveS1zdGFnZSBhdHRlbXB0cyAoc3VjY2VlZGVkICsgZmFpbGVkKS5cbiAgICovXG4gIGNoYW5nZUZhaWx1cmVSYXRlOiB7XG4gICAgcmF0ZTogbnVtYmVyO1xuICAgIGRlcGxveVRpbWVGYWlsdXJlczogbnVtYmVyO1xuICAgIHBvc3REZXBsb3lGYWlsdXJlczogbnVtYmVyO1xuICAgIGF0dGVtcHRzOiBudW1iZXI7XG4gICAgbGV2ZWw6IERvcmFMZXZlbDtcbiAgfTtcbiAgLyoqXG4gICAqIExlYWQgVGltZSDigJQgTUVBU1VSRUQ6IGBtZWRpYW4oZGVwbG95X2NvbXBsZXRlZCDiiJIgb2xkZXN0X2NvbW1pdF90aW1lKWAgb3ZlclxuICAgKiBzdWNjZXNzZnVsIGRlcGxveXMgd2l0aCBhIHJlc29sdmFibGUgY29tbWl0IHRpbWVzdGFtcCAoZGVsdGFzIGNsYW1wZWQg4omlMCkuXG4gICAqIGBtZWRpYW5TZWNvbmRzYCBpcyBgbnVsbGAgKD0gdW5rbm93bikgd2hlbiBubyBzdWNjZXNzZnVsIGRlcGxveSBpbiB0aGlzIGVudlxuICAgKiBjYXJyaWVkIGEgYGNvbW1pdF90aW1lc3RhbXBgLiBUaGUgb2xkIG1lZGlhbi1ydW4tZHVyYXRpb24gcHJveHkgaXMgcmVtb3ZlZC5cbiAgICovXG4gIGxlYWRUaW1lOiB7XG4gICAgLyoqIFN1Y2Nlc3NmdWwgZGVwbG95cyB3aXRoIGEgcmVzb2x2YWJsZSBjb21taXQgdGltZSAodGhlIG1lZGlhbiBzYW1wbGUpLiAqL1xuICAgIGRlcGxveW1lbnRzOiBudW1iZXI7XG4gICAgbWVkaWFuU2Vjb25kczogbnVtYmVyIHwgbnVsbDtcbiAgICBsZXZlbDogRG9yYUxldmVsO1xuICB9O1xufVxuXG4vKiogT25lIGludGVydmFsIGJ1Y2tldCBvZiB0aGUgRE9SQSB0cmVuZCAoZGVwbG95IGZyZXF1ZW5jeSArIGNoYW5nZSBmYWlsdXJlKS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRG9yYVRyZW5kUG9pbnQge1xuICAvKiogQnVja2V0IHN0YXJ0IChEQVRFX1RSVU5DIG9mIHRoZSBkZXBsb3kgYGNvbXBsZXRlZF9hdGApLCBJU08gdGV4dC4gKi9cbiAgcGVyaW9kOiBzdHJpbmc7XG4gIC8qKiBTdWNjZXNzZnVsIGRlcGxveS1zdGFnZSBleGVjdXRpb25zIGluIHRoZSBidWNrZXQuICovXG4gIGRlcGxveW1lbnRzOiBudW1iZXI7XG4gIC8qKiBGYWlsZWQgZGVwbG95LXN0YWdlIGV4ZWN1dGlvbnMgaW4gdGhlIGJ1Y2tldC4gKi9cbiAgZmFpbGVkOiBudW1iZXI7XG4gIC8qKiBzdWNjZWVkZWQgKyBmYWlsZWQgaW4gdGhlIGJ1Y2tldCAoZGVwbG95IGF0dGVtcHRzKS4gKi9cbiAgdG90YWw6IG51bWJlcjtcbiAgLyoqIGZhaWxlZC90b3RhbCBhcyBhIHBlcmNlbnQgKDAgd2hlbiB0b3RhbCBpcyAwKS4gRGVwbG95LXRpbWUgQ0ZSIG9ubHkuICovXG4gIGNoYW5nZUZhaWx1cmVQY3Q6IG51bWJlcjtcbn1cblxuLyoqIFBlci1zdGFnZSBidWlsZC1oZWFsdGggbWV0cmljcyAoUGhhc2UgNikgZm9yIG9uZSBwaXBlbGluZSBvdmVyIGEgd2luZG93LiAqL1xuZXhwb3J0IGludGVyZmFjZSBCdWlsZEhlYWx0aFN0YWdlIHtcbiAgc3RhZ2U6IHN0cmluZztcbiAgLyoqIFRlcm1pbmFsIHN0YWdlIHJ1bnMgKHN1Y2NlZWRlZCArIGZhaWxlZCkgaW4gdGhlIHdpbmRvdy4gKi9cbiAgcnVuczogbnVtYmVyO1xuICBzdWNjZXNzZXM6IG51bWJlcjtcbiAgZmFpbHVyZXM6IG51bWJlcjtcbiAgLyoqIHN1Y2Nlc3NlcyAvIHJ1bnMgYXMgYSBwZXJjZW50ICgwIHdoZW4gcnVucyBpcyAwKS4gKi9cbiAgc3VjY2Vzc1JhdGU6IG51bWJlcjtcbiAgLyoqIER1cmF0aW9uIHBlcmNlbnRpbGVzIG92ZXIgdGhlIHN0YWdlJ3MgdGVybWluYWwgcnVuczsgbnVsbCB3aGVuIG5vIGR1cmF0aW9ucy4gKi9cbiAgcDUwTXM6IG51bWJlciB8IG51bGw7XG4gIHA5ME1zOiBudW1iZXIgfCBudWxsO1xuICBwOTlNczogbnVtYmVyIHwgbnVsbDtcbn1cblxuLyoqXG4gKiBQZXItcGlwZWxpbmUgYnVpbGQtaGVhbHRoIGJyZWFrZG93biAoUGhhc2UgNikuIFN0YW5kYXJkIHJlcG9ydGluZyAoTk9UXG4gKiBgYWR2YW5jZWRfcmVwb3J0aW5nYC1nYXRlZCkg4oCUIHBlci1zdGFnZSBzdWNjZXNzIHJhdGUgKyB0aW1pbmcgcGVyY2VudGlsZXMsIHdpdGhcbiAqIHRvdGFscyBzdW1tZWQgYWNyb3NzIHN0YWdlcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBCdWlsZEhlYWx0aCB7XG4gIHN0YWdlczogQnVpbGRIZWFsdGhTdGFnZVtdO1xuICB0b3RhbHM6IHsgcnVuczogbnVtYmVyOyBmYWlsdXJlczogbnVtYmVyOyBmYWlsdXJlUmF0ZTogbnVtYmVyIH07XG59XG5cbi8qKiBQb3N0LWRlcGxveSBpbmNpZGVudCBtYXJrZXIgKFBoYXNlIDUpIGFjY2VwdGVkIGJ5IGBSZXBvcnRpbmdTZXJ2aWNlLnJlY29yZEluY2lkZW50YC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSW5jaWRlbnRJbnB1dCB7XG4gIGluY2lkZW50SWQ6IHN0cmluZztcbiAgZW52aXJvbm1lbnQ6IHN0cmluZztcbiAgb3BlbmVkQXQ6IHN0cmluZztcbiAgcmVzb2x2ZWRBdD86IHN0cmluZztcbiAgc2V2ZXJpdHk6IHN0cmluZztcbn1cblxuLyoqIEV2ZW50IHBheWxvYWQgYWNjZXB0ZWQgYnkgYFJlcG9ydGluZ1NlcnZpY2UuaW5nZXN0RXZlbnRzYC4gTWlycm9ycyB0aGUgcm91dGUncyBab2Qgc2hhcGUuICovXG5leHBvcnQgaW50ZXJmYWNlIEluZ2VzdEV2ZW50IHtcbiAgLyoqIFN0YWJsZSBwaXBlbGluZSBpZCB0aGUgZXZlbnRzIExhbWJkYSByZWFkIGZyb20gdGhlIGBwYi5waXBlbGluZS1pZGBcbiAgICogIHRhZyAoPSB0aGUgcGxhdGZvcm0gcGlwZWxpbmVJZCkuIFRoZSByZWdpc3RyeSBqb2luIGtleS4gKi9cbiAgcGlwZWxpbmVJZDogc3RyaW5nO1xuICBldmVudFNvdXJjZTogJ2NvZGVwaXBlbGluZScgfCAnY29kZWJ1aWxkJyB8ICdwbHVnaW4tYnVpbGQnO1xuICBldmVudFR5cGU6ICdQSVBFTElORScgfCAnU1RBR0UnIHwgJ0FDVElPTicgfCAnQlVJTEQnO1xuICBzdGF0dXM6IHN0cmluZztcbiAgZXhlY3V0aW9uSWQ/OiBzdHJpbmc7XG4gIHN0YWdlTmFtZT86IHN0cmluZztcbiAgYWN0aW9uTmFtZT86IHN0cmluZztcbiAgLyoqIEh1bWFuLXJlYWRhYmxlIGZhaWx1cmUgcmVhc29uIChBY3Rpb24gZXZlbnRzKS4gKi9cbiAgZXJyb3JNZXNzYWdlPzogc3RyaW5nO1xuICBzdGFydGVkQXQ/OiBzdHJpbmc7XG4gIGNvbXBsZXRlZEF0Pzogc3RyaW5nO1xuICBkdXJhdGlvbk1zPzogbnVtYmVyO1xuICAvKiogU291cmNlIGNvbW1pdCBpZCBvZiB0aGUgY2hhbmdlIGJlaW5nIHNoaXBwZWQgKERPUkEgZGVwbG95IGF0dHJpYnV0aW9uKS4gKi9cbiAgY29tbWl0U2hhPzogc3RyaW5nO1xuICAvKiogU291cmNlIHJlZi9icmFuY2ggKERPUkEgZGVwbG95IGF0dHJpYnV0aW9uKS4gKi9cbiAgY29tbWl0UmVmPzogc3RyaW5nO1xuICAvKiogRGVwbG95IHRhcmdldCAoZS5nLiBcInByb2R1Y3Rpb25cIikuIEl0cyBwcmVzZW5jZSBvbiBhIFNUQUdFL0FDVElPTiBldmVudFxuICAgKiAgbWFya3MgYSByZWFsIGRlcGxveW1lbnQgKGRlcml2ZWQgc2VydmVyLXNpZGUg4oCUIHRoZXJlIGlzIG5vIGBpc0RlcGxveWApLiAqL1xuICBlbnZpcm9ubWVudD86IHN0cmluZztcbiAgLyoqIE9sZGVzdCB1bnNoaXBwZWQgY29tbWl0IHRpbWVzdGFtcCAoSVNPIDg2MDEpIGZvciBtZWFzdXJlZCBsZWFkIHRpbWUuICovXG4gIGNvbW1pdFRpbWVzdGFtcD86IHN0cmluZztcbiAgLyoqIE51bWJlciBvZiBjb21taXRzIHNoaXBwZWQgaW4gdGhpcyBjaGFuZ2UgKOKJpTEpLiAqL1xuICBjb21taXRDb3VudD86IG51bWJlcjtcbiAgZGV0YWlsPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG59XG5cbi8qKlxuICogUGVyLWV2ZW50IG1ldHJpYyBkZXNjcmlwdG9yIGVtaXR0ZWQgKHZpYSB0aGUge0BsaW5rIFJlcG9ydGluZ1NlcnZpY2UuaW5nZXN0RXZlbnRzfVxuICogYG9uTWV0cmljYCBob29rKSBmb3IgZWFjaCBSRUdJU1RFUkVEIHRlcm1pbmFsIGRlcGxveS9zdGFnZSBldmVudCwgc28gdGhlIHJvdXRlXG4gKiBsYXllciBjYW4gZmFuIHRoZW0gaW50byBQcm9tZXRoZXVzIGNvdW50ZXJzIHdpdGhvdXQgcGlwZWxpbmUtZGF0YSBpbXBvcnRpbmdcbiAqIGFwaS1zZXJ2ZXIncyBtZXRyaWNzIHJlZ2lzdHJ5LiBgcmVzdWx0YCBpcyB0aGUgdGVybWluYWwgb3V0Y29tZTsgYGVudmlyb25tZW50YFxuICogaXMgbm9uLW51bGwgb25seSBmb3IgYSBkZXBsb3ktc3RhZ2UgZXZlbnQuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSW5nZXN0TWV0cmljIHtcbiAgcGlwZWxpbmVJZDogc3RyaW5nO1xuICBvcmdJZDogc3RyaW5nO1xuICBzdGFnZTogc3RyaW5nO1xuICBlbnZpcm9ubWVudDogc3RyaW5nIHwgbnVsbDtcbiAgcmVzdWx0OiAnc3VjY2VlZGVkJyB8ICdmYWlsZWQnO1xufVxuXG4vKiogQ291bnRzICsgdGhlIChwb3NzaWJseSB0cnVuY2F0ZWQpIGxpc3Qgb2YgdW5yZWdpc3RlcmVkIHBpcGVsaW5lIGlkcyB0aGUgY2FsbGVyIGNhbiBsb2cuICovXG5leHBvcnQgaW50ZXJmYWNlIEluZ2VzdFJlc3VsdCB7XG4gIGluc2VydGVkOiBudW1iZXI7XG4gIHNraXBwZWQ6IG51bWJlcjtcbiAgdW5yZWdpc3RlcmVkUGlwZWxpbmVJZHM6IHN0cmluZ1tdO1xufVxuXG4vLyDilIDilIDilIAgU2VydmljZSDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuLyoqXG4gKiBSZWFkLW9ubHkgcmVwb3J0aW5nIHNlcnZpY2UgZm9yIHBpcGVsaW5lIGV4ZWN1dGlvbiBhbmQgcGx1Z2luIGludmVudG9yeSBhZ2dyZWdhdGlvbnMuXG4gKiBEb2VzIG5vdCBleHRlbmQgQ3J1ZFNlcnZpY2Ug4oCUIHJlcG9ydHMgYXJlIGFnZ3JlZ2F0ZSBxdWVyaWVzLCBub3QgZW50aXR5IENSVUQuXG4gKlxuICogQWxsIHF1ZXJpZXMgYXJlIGNhY2hlZCBpbi1tZW1vcnkgdG8gYXZvaWQgcmVwZWF0ZWQgZXhwZW5zaXZlIFNRTCBhZ2dyZWdhdGlvbnM6XG4gKiAtIEludmVudG9yeSBxdWVyaWVzIChwbHVnaW4gc3VtbWFyeS9kaXN0cmlidXRpb24vdmVyc2lvbnMpOiA1IG1pbiBUVExcbiAqIC0gVGltZXNlcmllcyBxdWVyaWVzIChleGVjdXRpb24vYnVpbGQgbWV0cmljcyB3aXRoIGRhdGUgcmFuZ2VzKTogMiBtaW4gVFRMXG4gKi9cbmV4cG9ydCBjbGFzcyBSZXBvcnRpbmdTZXJ2aWNlIHtcblxuICAvKiogSW52YWxpZGF0ZSBhbGwgY2FjaGVkIHJlcG9ydHMgZm9yIGFuIG9yZyAoY2FsbCBhZnRlciBldmVudCBpbmdlc3QpLiAqL1xuICBhc3luYyBpbnZhbGlkYXRlT3JnKG9yZ0lkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgICBpbnZlbnRvcnlDYWNoZS5pbnZhbGlkYXRlUGF0dGVybihgJHtvcmdJZH06KmApLFxuICAgICAgdGltZXNlcmllc0NhY2hlLmludmFsaWRhdGVQYXR0ZXJuKGAke29yZ0lkfToqYCksXG4gICAgXSk7XG4gIH1cblxuICAvKipcbiAgICogUmVzb2x2ZSBpbmNvbWluZyBldmVudHMgYWdhaW5zdCB0aGUgcGlwZWxpbmUgcmVnaXN0cnksIGJhdGNoLWluc2VydCB0aGVcbiAgICogbWF0Y2hlZCBvbmVzLCBhbmQgaW52YWxpZGF0ZSByZXBvcnRpbmcgY2FjaGVzIGZvciBhZmZlY3RlZCBvcmdzLlxuICAgKiBFdmVudHMgZm9yIHVucmVnaXN0ZXJlZCBwaXBlbGluZSBpZHMgYXJlIGRyb3BwZWQgKGFuZCBsb2dnZWQgYXQgV0FSTlxuICAgKiB3aXRoIHNhbXBsZSBpZHMgc28gYW4gb3BlcmF0b3IgY2FuIHNlZSB3aGVuIEV2ZW50QnJpZGdlIGlzIGRlbGl2ZXJpbmdcbiAgICogZXZlbnRzIGZvciBwaXBlbGluZXMgdGhhdCBoYXZlbid0IGNhbGxlZCBQT1NUIC9waXBlbGluZXMvcmVnaXN0cnkgeWV0KS5cbiAgICpcbiAgICogUmV0dXJucyBjb3VudHMgKyBhIHNhbXBsZSBvZiB1bnJlZ2lzdGVyZWQgcGlwZWxpbmUgaWRzIGZvciBvYnNlcnZhYmlsaXR5LlxuICAgKi9cbiAgYXN5bmMgaW5nZXN0RXZlbnRzKGV2ZW50czogSW5nZXN0RXZlbnRbXSwgb25NZXRyaWM/OiAobTogSW5nZXN0TWV0cmljKSA9PiB2b2lkKTogUHJvbWlzZTxJbmdlc3RSZXN1bHQ+IHtcbiAgICAvLyBNdWx0aS1vcmcgYmF0Y2ggaW5zZXJ0OiB0aGUgY2FsbGVyIHJlc29sdmVzIHRvIG11bHRpcGxlIG9yZ3MgdmlhIHRoZVxuICAgIC8vIHBpcGVsaW5lLXJlZ2lzdHJ5IGxvb2t1cCBiZWxvdywgc28gdGhlIHJvdXRlIGxheWVyIE1VU1QgZXN0YWJsaXNoIGFcbiAgICAvLyBgcnVuV2l0aFRlbmFudENvbnRleHQoeyBpc1N1cGVyQWRtaW46IHRydWUgfSwgLi4uKWAgc2NvcGUgYmVmb3JlIGNhbGxpbmdcbiAgICAvLyB0aGlzIG1ldGhvZC4gVW5kZXIgRk9SQ0UnZCBSTFMsIGEgc2luZ2xlIHR4IHdpdGggYGFwcC5vcmdfaWQgPSA8b25lXG4gICAgLy8gb3JnPmAgY291bGQgb25seSB3cml0ZSBldmVudHMgZm9yIHRoYXQgb3JnOyBieXBhc3MgdmlhIHN5c2FkbWluIGlzXG4gICAgLy8gdGhlIHJpZ2h0IGdhdGUgZm9yIHRoaXMgc2VydmVyLWludGVybmFsIGNyb3NzLXRlbmFudCBlbmRwb2ludC4gU2VlXG4gICAgLy8gYXBpL3JlcG9ydGluZy9zcmMvcm91dGVzL2V2ZW50LWluZ2VzdC50cyBmb3IgdGhlIHdyYXBwZXIuXG4gICAgLy8gUnVuIGluc2VydCBpbnNpZGUgdGhlIHR4LCBidXQgQ09MTEVDVCBhZmZlY3RlZCBvcmdzIGFuZCBpbnZhbGlkYXRlXG4gICAgLy8gY2FjaGVzIEFGVEVSIHRoZSB0eCByZXNvbHZlcy4gS2VlcGluZyBpbnZhbGlkYXRpb24gaW5zaWRlIHRoZSB0eCBoZWxkXG4gICAgLy8gdGhlIHBnIGxvY2tzIG9wZW4gZm9yIHRoZSBkdXJhdGlvbiBvZiB0aGUgY2FjaGUgcm91bmQtdHJpcHMgKFJlZGlzIG9yXG4gICAgLy8gaW4tbWVtb3J5IGludmFsaWRhdGlvbnMgYXJlIHVucmVsYXRlZCB0byB0aGUgdHggYnV0IHN0aWxsIHNlcmlhbGl6ZWRcbiAgICAvLyBpdHMgY29tbWl0KS4gQ2FjaGUgVFRMIGlzIDItNSBtaW4gc28gZmlyZS1hbmQtZm9yZ2V0IHBvc3QtY29tbWl0IGlzXG4gICAgLy8gYW4gYWNjZXB0YWJsZSB0cmFkZSBmb3IgdGlnaHRlciBsb2NrIHdpbmRvd3MuXG4gICAgY29uc3QgeyBpbnNlcnRlZCwgc2tpcHBlZCwgdW5yZWdpc3RlcmVkUGlwZWxpbmVJZHMsIGFmZmVjdGVkT3JncyB9ID0gYXdhaXQgd2l0aFRlbmFudFR4KGFzeW5jICh0eCkgPT4ge1xuICAgICAgLy8gQmF0Y2gtcmVzb2x2ZSBhbGwgdW5pcXVlIHBpcGVsaW5lIGlkcyBpbiBvbmUgcXVlcnlcbiAgICAgIGNvbnN0IHVuaXF1ZUlkcyA9IFsuLi5uZXcgU2V0KGV2ZW50cy5tYXAoZSA9PiBlLnBpcGVsaW5lSWQpKV07XG4gICAgICBjb25zdCByZWdpc3RyeVJvd3MgPSBhd2FpdCB0eFxuICAgICAgICAuc2VsZWN0KHtcbiAgICAgICAgICBwaXBlbGluZUlkOiBzY2hlbWEucGlwZWxpbmVSZWdpc3RyeS5waXBlbGluZUlkLFxuICAgICAgICAgIG9yZ0lkOiBzY2hlbWEucGlwZWxpbmVSZWdpc3RyeS5vcmdJZCxcbiAgICAgICAgfSlcbiAgICAgICAgLmZyb20oc2NoZW1hLnBpcGVsaW5lUmVnaXN0cnkpXG4gICAgICAgIC53aGVyZShpbkFycmF5KHNjaGVtYS5waXBlbGluZVJlZ2lzdHJ5LnBpcGVsaW5lSWQsIHVuaXF1ZUlkcykpO1xuXG4gICAgICBjb25zdCBpZE1hcCA9IG5ldyBNYXAocmVnaXN0cnlSb3dzLm1hcChyID0+IFtyLnBpcGVsaW5lSWQsIHJdKSk7XG5cbiAgICAgIC8vIEJ1aWxkIGluc2VydCBiYXRjaCAoc2tpcCBldmVudHMgd2hvc2UgcGlwZWxpbmUgaXNuJ3QgcmVnaXN0ZXJlZClcbiAgICAgIGNvbnN0IHJvd3M6IEFycmF5PHR5cGVvZiBzY2hlbWEucGlwZWxpbmVFdmVudC4kaW5mZXJJbnNlcnQ+ID0gW107XG4gICAgICBsZXQgc2tpcHBlZExvY2FsID0gMDtcbiAgICAgIGNvbnN0IHVucmVnaXN0ZXJlZExvY2FsOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgICBmb3IgKGNvbnN0IGV2ZW50IG9mIGV2ZW50cykge1xuICAgICAgICBjb25zdCByZWdpc3RyeSA9IGlkTWFwLmdldChldmVudC5waXBlbGluZUlkKTtcbiAgICAgICAgaWYgKCFyZWdpc3RyeSkge1xuICAgICAgICAgIHNraXBwZWRMb2NhbCsrO1xuICAgICAgICAgIHVucmVnaXN0ZXJlZExvY2FsLnB1c2goZXZlbnQucGlwZWxpbmVJZCk7XG4gICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICByb3dzLnB1c2goe1xuICAgICAgICAgIC8vIHJlZ2lzdHJ5LnBpcGVsaW5lSWQgPT09IGV2ZW50LnBpcGVsaW5lSWQ7IHVzZSB0aGUgcmVnaXN0cnkncyBzbyB0aGVcbiAgICAgICAgICAvLyBGSyBpcyBhbHdheXMgYSByb3cgdGhhdCBleGlzdHMsIGFuZCBwdWxsIG9yZ0lkIGZyb20gdGhlIHJlZ2lzdHJ5IGZvclxuICAgICAgICAgIC8vIHRlbmFuY3kgKG5ldmVyIHRydXN0IHRoZSBjYWxsZXIncyBjbGFpbWVkIG9yZykuXG4gICAgICAgICAgcGlwZWxpbmVJZDogcmVnaXN0cnkucGlwZWxpbmVJZCxcbiAgICAgICAgICBvcmdJZDogcmVnaXN0cnkub3JnSWQsXG4gICAgICAgICAgZXZlbnRTb3VyY2U6IGV2ZW50LmV2ZW50U291cmNlLFxuICAgICAgICAgIGV2ZW50VHlwZTogZXZlbnQuZXZlbnRUeXBlLFxuICAgICAgICAgIHN0YXR1czogZXZlbnQuc3RhdHVzLFxuICAgICAgICAgIC8vIGV4ZWN1dGlvbklkIGlzIGFuIEFXUy1BU1NJR05FRCBpZGVudGlmaWVyIChhIFVVSUQpLCBub3QgZnJlZS1mb3JtXG4gICAgICAgICAgLy8gdXNlciB0ZXh0LCBzbyBpdCBjYW4ndCBjYXJyeSBhbiBhY2NvdW50IGlkIOKAlCBhbmQgc2NydWJiaW5nIGEgVVVJRFxuICAgICAgICAgIC8vIHRoYXQgaGFwcGVucyB0byBjb250YWluIGEgMTItZGlnaXQgcnVuIHdvdWxkIGNvcnJ1cHQgdGhlIGNvcnJlbGF0aW9uXG4gICAgICAgICAgLy8ga2V5LiBMZWZ0IGludGFjdCBieSBkZXNpZ24uXG4gICAgICAgICAgZXhlY3V0aW9uSWQ6IGV2ZW50LmV4ZWN1dGlvbklkLFxuICAgICAgICAgIC8vIHN0YWdlTmFtZS9hY3Rpb25OYW1lIGFyZSBVU0VSLUFVVEhPUkVEIHBpcGVsaW5lLXN0cnVjdHVyZSBuYW1lc1xuICAgICAgICAgIC8vIHByb21vdGVkIGZyb20gdGhlIENvZGVQaXBlbGluZSBkZXRhaWwg4oCUIHNhbWUgdW50cnVzdGVkLUFXUy1kZXJpdmVkXG4gICAgICAgICAgLy8gb3JpZ2luIGFzIGVycm9yTWVzc2FnZSBiZWxvdywgc28gc2NydWIgdGhlbSBhdCB0aGlzIHBlcnNpc3RlbmNlXG4gICAgICAgICAgLy8gYm91bmRhcnkgdG9vIChhIHN0YWdlIG5hbWVkIHdpdGggYW4gQVJOLzEyLWRpZ2l0IGlkIG11c3Qgbm90IHBlcnNpc3QpLlxuICAgICAgICAgIHN0YWdlTmFtZTogc2NydWJPcHRpb25hbChldmVudC5zdGFnZU5hbWUpLFxuICAgICAgICAgIGFjdGlvbk5hbWU6IHNjcnViT3B0aW9uYWwoZXZlbnQuYWN0aW9uTmFtZSksXG4gICAgICAgICAgLy8gSEFSRCBDT05TVFJBSU5UOiBhbiBBV1MgYWNjb3VudCBpZCBtdXN0IE5FVkVSIGJlIHBlcnNpc3RlZC4gVGhpcyBpc1xuICAgICAgICAgIC8vIHRoZSBEVVJBQkxFIHBlcnNpc3RlbmNlIGJvdW5kYXJ5IGFuZCBtdXN0IG5vdCB0cnVzdCB1cHN0cmVhbTpcbiAgICAgICAgICAvLyBDb2RlUGlwZWxpbmUvQ29kZUJ1aWxkIGZhaWx1cmUgZGV0YWlsICYgbWVzc2FnZXMgcm91dGluZWx5IGNhcnJ5XG4gICAgICAgICAgLy8gQVJOcyAoYXJuOmF3czrigKY6PGFjY291bnQtaWQ+OuKApikgYW5kIGJhcmUgMTItZGlnaXQgYWNjb3VudCBpZHMuIFNjcnViXG4gICAgICAgICAgLy8gYm90aCBmcmVlLWZvcm0gZmllbGRzIGhlcmUgYmVmb3JlIGluc2VydCAocGVyLWV2ZW50LCBub24tbXV0YXRpbmcpLlxuICAgICAgICAgIGVycm9yTWVzc2FnZTogc2NydWJPcHRpb25hbChldmVudC5lcnJvck1lc3NhZ2UpLFxuICAgICAgICAgIHN0YXJ0ZWRBdDogZXZlbnQuc3RhcnRlZEF0ID8gbmV3IERhdGUoZXZlbnQuc3RhcnRlZEF0KSA6IHVuZGVmaW5lZCxcbiAgICAgICAgICBjb21wbGV0ZWRBdDogZXZlbnQuY29tcGxldGVkQXQgPyBuZXcgRGF0ZShldmVudC5jb21wbGV0ZWRBdCkgOiB1bmRlZmluZWQsXG4gICAgICAgICAgZHVyYXRpb25NczogZXZlbnQuZHVyYXRpb25NcyxcbiAgICAgICAgICAvLyBEZXBsb3ktYXR0cmlidXRpb24gZmllbGRzIOKAlCBzY3J1YmJlZCBsaWtlIHRoZSBvdGhlciBmcmVlLWZvcm0gc3RyaW5nc1xuICAgICAgICAgIC8vIHNvIGFuIEFSTi9hY2NvdW50IGlkIGNhbiBuZXZlciBlbnRlciB2aWEgYSByZWYgb3IgZW52aXJvbm1lbnQgbmFtZS5cbiAgICAgICAgICBjb21taXRTaGE6IHNjcnViT3B0aW9uYWwoZXZlbnQuY29tbWl0U2hhKSxcbiAgICAgICAgICBjb21taXRSZWY6IHNjcnViT3B0aW9uYWwoZXZlbnQuY29tbWl0UmVmKSxcbiAgICAgICAgICBlbnZpcm9ubWVudDogc2NydWJPcHRpb25hbChldmVudC5lbnZpcm9ubWVudCksXG4gICAgICAgICAgLy8gTWVhc3VyZWQgbGVhZCB0aW1lIChQaGFzZSA0KTogb2xkZXN0IHVuc2hpcHBlZCBjb21taXQgdGltZSArIGNvdW50LlxuICAgICAgICAgIC8vIGNvbW1pdFRpbWVzdGFtcCBpcyBhbiBBV1MvU0NNLWRlcml2ZWQgaW5zdGFudCAobmV2ZXIgYWNjb3VudC1pZFxuICAgICAgICAgIC8vIHNoYXBlZCk7IGNvbW1pdENvdW50IGlzIGEgcGxhaW4gaW50ZWdlci4gTmVpdGhlciBuZWVkcyBzY3J1YmJpbmcuXG4gICAgICAgICAgY29tbWl0VGltZXN0YW1wOiBldmVudC5jb21taXRUaW1lc3RhbXAgPyBuZXcgRGF0ZShldmVudC5jb21taXRUaW1lc3RhbXApIDogdW5kZWZpbmVkLFxuICAgICAgICAgIGNvbW1pdENvdW50OiBldmVudC5jb21taXRDb3VudCxcbiAgICAgICAgICBkZXRhaWw6IGV2ZW50LmRldGFpbCAhPT0gdW5kZWZpbmVkXG4gICAgICAgICAgICA/IHNjcnViQXdzSWRlbnRpZmllcnMoZXZlbnQuZGV0YWlsKVxuICAgICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIFBoYXNlIDNiOiBmYW4gdGVybWluYWwgU1RBR0Ugb3V0Y29tZXMgaW50byBQcm9tZXRoZXVzIGNvdW50ZXJzIHZpYSB0aGVcbiAgICAgICAgLy8gcm91dGUncyBob29rIChwaXBlbGluZS1kYXRhIGNhbid0IGltcG9ydCBhcGktc2VydmVyJ3MgcmVnaXN0cnkpLiBFbWl0XG4gICAgICAgIC8vIHBlciByZWdpc3RlcmVkIHN0YWdlIGV2ZW50IHdpdGggYSB0ZXJtaW5hbCBzdWNjZWVkZWQvZmFpbGVkIHJlc3VsdDtcbiAgICAgICAgLy8gYSBub24tbnVsbCBlbnZpcm9ubWVudCBhZGRpdGlvbmFsbHkgbWFya3MgaXQgYSBkZXBsb3kgcmVzdWx0LlxuICAgICAgICBpZiAob25NZXRyaWMgJiYgZXZlbnQuZXZlbnRUeXBlID09PSAnU1RBR0UnICYmIChldmVudC5zdGF0dXMgPT09ICdTVUNDRUVERUQnIHx8IGV2ZW50LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpKSB7XG4gICAgICAgICAgb25NZXRyaWMoe1xuICAgICAgICAgICAgcGlwZWxpbmVJZDogcmVnaXN0cnkucGlwZWxpbmVJZCxcbiAgICAgICAgICAgIG9yZ0lkOiByZWdpc3RyeS5vcmdJZCxcbiAgICAgICAgICAgIHN0YWdlOiBzY3J1Yk9wdGlvbmFsKGV2ZW50LnN0YWdlTmFtZSkgPz8gJycsXG4gICAgICAgICAgICBlbnZpcm9ubWVudDogc2NydWJPcHRpb25hbChldmVudC5lbnZpcm9ubWVudCkgPz8gbnVsbCxcbiAgICAgICAgICAgIHJlc3VsdDogZXZlbnQuc3RhdHVzID09PSAnU1VDQ0VFREVEJyA/ICdzdWNjZWVkZWQnIDogJ2ZhaWxlZCcsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgLy8gU1FTIGlzIGF0LWxlYXN0LW9uY2UsIHNvIEV2ZW50QnJpZGdlIGNhbiBkZWxpdmVyIHRoZSBzYW1lIHN0YXRlLWNoYW5nZVxuICAgICAgLy8gdHdpY2UuIGBvbkNvbmZsaWN0RG9Ob3RoaW5nYCArIHRoZSBwYXJ0aWFsIHVuaXF1ZSBpbmRleCBvblxuICAgICAgLy8gKHBpcGVsaW5lX2lkLCBleGVjdXRpb25faWQsIGV2ZW50X3R5cGUsIHN0YXR1cywgc3RhZ2VfbmFtZSwgYWN0aW9uX25hbWUpXG4gICAgICAvLyBtYWtlcyByZS1kZWxpdmVyeSBpZGVtcG90ZW50LiBgcmV0dXJuaW5nYCBnaXZlcyB0aGUgUkVBTCBpbnNlcnRlZCBzZXQgc29cbiAgICAgIC8vIGNvdW50cyArIGNhY2hlIGludmFsaWRhdGlvbiBpZ25vcmUgZHVwbGljYXRlcy5cbiAgICAgIGNvbnN0IGluc2VydGVkUm93cyA9IHJvd3MubGVuZ3RoID4gMFxuICAgICAgICA/IGF3YWl0IHR4Lmluc2VydChzY2hlbWEucGlwZWxpbmVFdmVudCkudmFsdWVzKHJvd3MpXG4gICAgICAgICAgLm9uQ29uZmxpY3REb05vdGhpbmcoKVxuICAgICAgICAgIC5yZXR1cm5pbmcoeyBvcmdJZDogc2NoZW1hLnBpcGVsaW5lRXZlbnQub3JnSWQgfSlcbiAgICAgICAgOiBbXTtcblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgaW5zZXJ0ZWQ6IGluc2VydGVkUm93cy5sZW5ndGgsXG4gICAgICAgIHNraXBwZWQ6IHNraXBwZWRMb2NhbCxcbiAgICAgICAgdW5yZWdpc3RlcmVkUGlwZWxpbmVJZHM6IHVucmVnaXN0ZXJlZExvY2FsLFxuICAgICAgICBhZmZlY3RlZE9yZ3M6IFsuLi5uZXcgU2V0KGluc2VydGVkUm93cy5tYXAociA9PiByLm9yZ0lkKSldLFxuICAgICAgfTtcbiAgICB9KTtcblxuICAgIC8vIFN1cmZhY2UgdGhlIHNpbGVudCBza2lwOiBhbiB1bnJlZ2lzdGVyZWQgcGlwZWxpbmUgaWQgdXN1YWxseSBtZWFucyB0aGVcbiAgICAvLyBwaXBlbGluZSBoYXNuJ3QgY2FsbGVkIFBPU1QgL3BpcGVsaW5lcy9yZWdpc3RyeSB5ZXQgKG9yIGl0c1xuICAgIC8vIHBiLnBpcGVsaW5lLWlkIHRhZyBpcyBtaXNzaW5nL3VucmVhZGFibGUgYnkgdGhlIExhbWJkYSkuIExvZ2dpbmcgaXRcbiAgICAvLyBtYWtlcyBhIGJyb2tlbiBqb2luIHZpc2libGUgaW5zdGVhZCBvZiBsb29raW5nIGxpa2UgXCJubyBhY3Rpdml0eVwiLlxuICAgIGlmICh1bnJlZ2lzdGVyZWRQaXBlbGluZUlkcy5sZW5ndGggPiAwKSB7XG4gICAgICBsb2dnZXIud2FybignUGlwZWxpbmUgZXZlbnRzIHNraXBwZWQ6IHBpcGVsaW5lIGlkIG5vdCBmb3VuZCBpbiByZWdpc3RyeScsIHtcbiAgICAgICAgY291bnQ6IHVucmVnaXN0ZXJlZFBpcGVsaW5lSWRzLmxlbmd0aCxcbiAgICAgICAgc2FtcGxlOiB1bnJlZ2lzdGVyZWRQaXBlbGluZUlkcy5zbGljZSgwLCAzKSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIFBvc3QtY29tbWl0IGNhY2hlIGludmFsaWRhdGlvbi4gRmlyZS1hbmQtZm9yZ2V0IHdpdGggbG9nZ2luZyDigJQgVFRMIGlzXG4gICAgLy8gc2hvcnQgZW5vdWdoIHRoYXQgYSBtaXNzZWQgaW52YWxpZGF0aW9uIHNlbGYtaGVhbHMuXG4gICAgaWYgKGFmZmVjdGVkT3Jncy5sZW5ndGggPiAwKSB7XG4gICAgICB2b2lkIFByb21pc2UuYWxsKGFmZmVjdGVkT3Jncy5tYXAoKG9yZykgPT5cbiAgICAgICAgdGhpcy5pbnZhbGlkYXRlT3JnKG9yZykuY2F0Y2goKGVycikgPT4ge1xuICAgICAgICAgIGxvZ2dlci53YXJuKCdSZXBvcnRpbmcgY2FjaGUgaW52YWxpZGF0aW9uIGZhaWxlZCcsIHsgb3JnSWQ6IG9yZywgZXJyb3I6IGVycm9yTWVzc2FnZShlcnIpIH0pO1xuICAgICAgICB9KSxcbiAgICAgICkpO1xuICAgIH1cblxuICAgIHJldHVybiB7IGluc2VydGVkLCBza2lwcGVkLCB1bnJlZ2lzdGVyZWRQaXBlbGluZUlkcyB9O1xuICB9XG5cbiAgLy8g4pSA4pSAIENhdGVnb3J5IDE6IFBpcGVsaW5lIEV4ZWN1dGlvbiAmIFBlcmZvcm1hbmNlIOKUgOKUgFxuXG4gIC8qKlxuICAgKiBCdWlsZCB0aGUgb3JnLXNjb3BlIHByZWRpY2F0ZSBmb3IgYSByZXBvcnQgcXVlcnkuIFdpdGggYG9yZ0lkc2AgKHRoZVxuICAgKiBvcmcg4oaSIHRlYW0gcm9sbHVwIOKAlCBhIHBhcmVudCdzIGBbc2VsZiwgLi4uZGVzY2VuZGFudHNdYCkgaXQgYmVjb21lcyBhblxuICAgKiBgSU4gKC4uLilgIG92ZXIgdGhlIHN1YnRyZWU7IG90aGVyd2lzZSB0aGUgc2luZ2xlLW9yZyBgPSAkb3JnYC4gUmV0dXJucyBhXG4gICAqIGBtdWx0aWAgZmxhZyBzbyBjYWxsZXJzIGNhbiBydW4gbXVsdGktb3JnIHJlYWRzIHVuZGVyIHN5c2FkbWluIGNvbnRleHRcbiAgICogKHRoZSBzdWJ0cmVlIHNwYW5zIG9yZ3Mgb3V0c2lkZSB0aGUgcmVxdWVzdCdzIFJMUyBzY29wZSkgYW5kIHNhbHQgdGhlXG4gICAqIGNhY2hlIGtleS5cbiAgICovXG4gIHByaXZhdGUgb3JnU2NvcGUob3JnSWQ6IHN0cmluZywgb3JnSWRzPzogc3RyaW5nW10pIHtcbiAgICAvLyBEZWZlbnNlLWluLWRlcHRoOiB0aGUgbXVsdGktb3JnIHJvbGx1cCBydW5zIHVuZGVyIHN5c2FkbWluIGNvbnRleHQgKFJMU1xuICAgIC8vIE9GRiwgc2VlIHJ1blJlcG9ydCksIHNvIGBvcmdJZHNgIGlzIHRoZSBPTkxZIHRlbmFuY3kgZ2F0ZSBvbiB0aGUgcmVhZC4gVGhlXG4gICAgLy8gcm91dGUgcmVzb2x2ZXMgaXQgZnJvbSB0aGUgcGxhdGZvcm0ncyBhdXRob3JpdGF0aXZlIGRlc2NlbmRhbnRzIGVuZHBvaW50IGFzXG4gICAgLy8gYFtzZWxmLCAuLi5kZXNjZW5kYW50c11gLCBidXQgdmFsaWRhdGUgdGhlIHN1YnRyZWUgZGVmZW5zaXZlbHkgaGVyZSBiZWZvcmVcbiAgICAvLyB0aGUgYnlwYXNzOiB0aGUgcmVxdWVzdGluZyAoYW5jaG9yKSBvcmcgTVVTVCBhcHBlYXIgaW4gdGhlIHNldC4gQSBzZXQgdGhhdFxuICAgIC8vIG9taXRzIHRoZSBjYWxsZXIncyBvd24gb3JnIGlzIGEgbWFsZm9ybWVkL3Nwb29mZWQgcm9sbHVwIOKAlCBjb2xsYXBzZSB0byB0aGVcbiAgICAvLyBzYWZlIHNpbmdsZS1vcmcgc2NvcGUgcmF0aGVyIHRoYW4gcmVhZGluZyBhbiBhcmJpdHJhcnkgb3JnIHVuZGVyIHN5c2FkbWluLlxuICAgIC8vIChGdWxsIGRlc2NlbmRhbnQtbWVtYmVyc2hpcCB2YWxpZGF0aW9uIG5lZWRzIHRoZSBvcmcgdHJlZSwgd2hpY2ggdGhpc1xuICAgIC8vIHNlcnZpY2UgZG9lcyBub3QgaG9sZCDigJQgc2VlIHRoZSByZXBvcnQgRkxBRy4pXG4gICAgY29uc3QgYW5jaG9yID0gb3JnSWQudG9Mb3dlckNhc2UoKTtcbiAgICBjb25zdCBwcm92aWRlZCA9IChvcmdJZHMgPz8gW10pLmZpbHRlcigoaWQpID0+IHR5cGVvZiBpZCA9PT0gJ3N0cmluZycgJiYgaWQubGVuZ3RoID4gMCk7XG4gICAgY29uc3QgYW5jaG9yZWQgPSBwcm92aWRlZC5zb21lKChpZCkgPT4gaWQudG9Mb3dlckNhc2UoKSA9PT0gYW5jaG9yKTtcbiAgICBpZiAocHJvdmlkZWQubGVuZ3RoID4gMCAmJiAhYW5jaG9yZWQpIHtcbiAgICAgIGxvZ2dlci53YXJuKCdSZXBvcnRpbmcgcm9sbHVwIHJlamVjdGVkOiByZXF1ZXN0aW5nIG9yZyBhYnNlbnQgZnJvbSByZXNvbHZlZCBzdWJ0cmVlOyB1c2luZyBzaW5nbGUtb3JnIHNjb3BlJywge1xuICAgICAgICBvcmdJZDogYW5jaG9yLCBzdWJ0cmVlU2l6ZTogcHJvdmlkZWQubGVuZ3RoLFxuICAgICAgfSk7XG4gICAgfVxuICAgIGNvbnN0IGlkcyA9IHByb3ZpZGVkLmxlbmd0aCA+IDAgJiYgYW5jaG9yZWQgPyBwcm92aWRlZCA6IFtvcmdJZF07XG4gICAgY29uc3QgbXVsdGkgPSBpZHMubGVuZ3RoID4gMTtcbiAgICBjb25zdCBwcmVkID0gbXVsdGlcbiAgICAgID8gc3FsYElOICgke3NxbC5qb2luKGlkcy5tYXAoKGlkKSA9PiBzcWxgJHtpZH1gKSwgc3FsYCwgYCl9KWBcbiAgICAgIDogc3FsYD0gJHtpZHNbMF19YDtcbiAgICByZXR1cm4geyBwcmVkLCBtdWx0aSB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFJ1biBhIHJlcG9ydCByZWFkLiBTaW5nbGUtb3JnIHJlYWRzIHVzZSB0aGUgcGVyLW9yZyBjYWNoZSAoaW52YWxpZGF0ZWQgb25cbiAgICogdGhhdCBvcmcncyBldmVudCBpbmdlc3QpLiBSb2xsdXAgKG11bHRpLW9yZykgcmVhZHMgKipieXBhc3MgdGhlIGNhY2hlKiogYW5kXG4gICAqIHJ1biB1bmRlciBzeXNhZG1pbiBjb250ZXh0OiB0aGV5J3JlIGFkbWluLW9ubHkgYW5kIGxvd2VyLWZyZXF1ZW5jeSwgYW5kIGFcbiAgICogY2hpbGQgb3JnJ3MgZXZlbnQgaW5nZXN0IGNhbid0IGludmFsaWRhdGUgYSBwYXJlbnQncyByb2xsdXAgZW50cnkgKHJlcG9ydGluZ1xuICAgKiBoYXMgbm8gb3JnIHRyZWUpLCBzbyBjYWNoaW5nIHRoZW0gd291bGQgc2VydmUgc3RhbGUgYWdncmVnYXRlcy4gQWx3YXlzIGZyZXNoLlxuICAgKi9cbiAgcHJpdmF0ZSBydW5SZXBvcnQ8VD4oY2FjaGVLZXk6IHN0cmluZywgbXVsdGk6IGJvb2xlYW4sIGV4ZWM6ICgpID0+IFByb21pc2U8VD4pOiBQcm9taXNlPFQ+IHtcbiAgICByZXR1cm4gbXVsdGlcbiAgICAgID8gcnVuV2l0aFRlbmFudENvbnRleHQoeyBpc1N1cGVyQWRtaW46IHRydWUgfSwgZXhlYylcbiAgICAgIDogdGltZXNlcmllc0NhY2hlLmdldE9yU2V0KGNhY2hlS2V5LCBleGVjKTtcbiAgfVxuXG4gIC8qKiAxLjEgRXhlY3V0aW9uIGNvdW50IHBlciBwaXBlbGluZSB3aXRoIHN0YXR1cyBicmVha2Rvd24uICovXG4gIGFzeW5jIGdldEV4ZWN1dGlvbkNvdW50KG9yZ0lkOiBzdHJpbmcsIG9yZ0lkcz86IHN0cmluZ1tdLCByYW5nZT86IHsgZnJvbT86IHN0cmluZzsgdG8/OiBzdHJpbmcgfSk6IFByb21pc2U8RXhlY3V0aW9uQ291bnRbXT4ge1xuICAgIGNvbnN0IHsgcHJlZCwgbXVsdGkgfSA9IHRoaXMub3JnU2NvcGUob3JnSWQsIG9yZ0lkcyk7XG4gICAgLy8gT3B0aW9uYWwgW2Zyb20sdG9dIHdpbmRvdyBvbiB0aGUgZXhlY3V0aW9uJ3Mgc3RhcnRlZF9hdCwgbWlycm9yaW5nIHRoZVxuICAgIC8vIHNpYmxpbmcgdGltZXNlcmllcyByZXBvcnRzIHNvIHRoZSBkYXNoYm9hcmQgZGF0ZS1yYW5nZSBwaWNrZXIgbmFycm93cyB0aGVcbiAgICAvLyBjb3VudCB0b28gKGFuIGVtcHR5IHJhbmdlID0gYWxsLXRpbWUsIHByZXNlcnZpbmcgdGhlIHByaW9yIGJlaGF2aW9yKS4gVGhlXG4gICAgLy8gcmFuZ2UgcmlkZXMgdGhlIEpPSU4gc28gcGlwZWxpbmVzIHdpdGggbm8gaW4td2luZG93IGV2ZW50cyBzdGlsbCBsaXN0XG4gICAgLy8gKExFRlQgc2VtYW50aWNzIHByZXNlcnZlZCB2aWEgdGhlIGlubmVyLWpvaW4gZmlsdGVyIOKAlCBhIHBpcGVsaW5lIHdpdGggemVyb1xuICAgIC8vIG1hdGNoaW5nIGV2ZW50cyBkcm9wcyBmcm9tIHRoZSBjb3VudCwgc2FtZSBhcyBiZWZvcmUgZm9yIGl0cyB3aW5kb3cpLlxuICAgIGNvbnN0IHJhbmdlQ2xhdXNlID0gb3B0aW9uYWxTdGFydGVkQXRSYW5nZShyYW5nZSk7XG4gICAgY29uc3QgZXhlYyA9ICgpID0+IHdpdGhUZW5hbnRUeCgodHgpID0+IHR4LmV4ZWN1dGUoc3FsYFxuICAgICAgICBTRUxFQ1RcbiAgICAgICAgICBwLmlkLCBwLnByb2plY3QsIHAub3JnYW5pemF0aW9uLCBwLnBpcGVsaW5lX25hbWUsXG4gICAgICAgICAgQ09VTlQoKik6OmludCBBUyB0b3RhbCxcbiAgICAgICAgICBDT1VOVCgqKSBGSUxURVIgKFdIRVJFIGUuc3RhdHVzID0gJ1NVQ0NFRURFRCcpOjppbnQgQVMgc3VjY2VlZGVkLFxuICAgICAgICAgIENPVU5UKCopIEZJTFRFUiAoV0hFUkUgZS5zdGF0dXMgPSAnRkFJTEVEJyk6OmludCBBUyBmYWlsZWQsXG4gICAgICAgICAgQ09VTlQoKikgRklMVEVSIChXSEVSRSBlLnN0YXR1cyA9ICdDQU5DRUxFRCcpOjppbnQgQVMgY2FuY2VsZWQsXG4gICAgICAgICAgTUlOKGUuc3RhcnRlZF9hdCk6OnRleHQgQVMgZmlyc3RfZXhlY3V0aW9uLFxuICAgICAgICAgIE1BWChlLnN0YXJ0ZWRfYXQpOjp0ZXh0IEFTIGxhc3RfZXhlY3V0aW9uXG4gICAgICAgIEZST00gJHtzY2hlbWEucGlwZWxpbmV9IHBcbiAgICAgICAgSk9JTiAke3NjaGVtYS5waXBlbGluZUV2ZW50fSBlIE9OIGUucGlwZWxpbmVfaWQgPSBwLmlkXG4gICAgICAgICAgQU5EIGUuZXZlbnRfdHlwZSA9ICdQSVBFTElORScgQU5EIGUuc3RhdHVzICE9ICdTVEFSVEVEJ1xuICAgICAgICAgICR7cmFuZ2VDbGF1c2V9XG4gICAgICAgIFdIRVJFIHAub3JnX2lkICR7cHJlZH0gQU5EIHAuaXNfYWN0aXZlID0gdHJ1ZVxuICAgICAgICBHUk9VUCBCWSBwLmlkXG4gICAgICAgIE9SREVSIEJZIHRvdGFsIERFU0NcbiAgICAgIGApLnRoZW4ociA9PiBkcml6emxlUm93czxFeGVjdXRpb25Db3VudD4oci5yb3dzKSkpO1xuICAgIHJldHVybiB0aGlzLnJ1blJlcG9ydChgJHtvcmdJZH06ZXhlYy1jb3VudDoke3JhbmdlPy5mcm9tID8/ICcnfToke3JhbmdlPy50byA/PyAnJ31gLCBtdWx0aSwgZXhlYyk7XG4gIH1cblxuICAvKipcbiAgICogMS4xYiBQZXItcGlwZWxpbmUgZXhlY3V0aW9uIGhpc3Rvcnkg4oCUIERJU1RJTkNUIGV4ZWN1dGlvbnMgZm9yIG9uZSBwaXBlbGluZSxcbiAgICogbmV3ZXN0IGZpcnN0LiBHcm91cHMgYWxsIGV2ZW50cyBieSBgZXhlY3V0aW9uX2lkYCBpbiBhIHNpbmdsZSBzY2FuIGFuZFxuICAgKiByb2xscyBlYWNoIGV4ZWN1dGlvbiB1cCB0byBvbmUgcm93OlxuICAgKiAgIC0gc3RhdHVzOiBkZXJpdmVkIGZyb20gdGhlIFBJUEVMSU5FLXR5cGUgZXZlbnRzLiBGQUlMRUQgd2lucywgdGhlblxuICAgKiAgICAgU1VDQ0VFREVELCB0aGVuIENBTkNFTEVEOyBhbiBleGVjdXRpb24gd2l0aCBubyB0ZXJtaW5hbCBQSVBFTElORSBldmVudFxuICAgKiAgICAgaXMgc3RpbGwgYGluLXByb2dyZXNzYC5cbiAgICogICAtIHN0YXJ0ZWRBdC9lbmRlZEF0L2R1cmF0aW9uTXM6IGZyb20gdGhlIFBJUEVMSU5FIGxpZmVjeWNsZSBldmVudHMuXG4gICAqICAgLSBmYWlsaW5nU3RhZ2UvZmFpbGluZ0FjdGlvbjogdGhlIGZpcnN0IEZBSUxFRCBTVEFHRS9BQ1RJT04gZXZlbnQgKGNoZWFwIOKAlFxuICAgKiAgICAgc2FtZSBzY2FuLCBubyBleHRyYSBxdWVyeSkuXG4gICAqXG4gICAqIE9SRy1TQ09QSU5HOiBpZGVudGljYWwgdG8gdGhlIHNpYmxpbmcgZXhlY3V0aW9uIHJlcG9ydHMg4oCUIGpvaW5zIHRoZSBwaXBlbGluZVxuICAgKiByZWdpc3RyeSB0YWJsZSAoYHBpcGVsaW5lYCkgYW5kIGdhdGVzIG9uIGBwLm9yZ19pZCAke3ByZWR9YCwgd2hlcmUgYHByZWRgIGlzXG4gICAqIHRoZSBzaW5nbGUtb3JnIGA9ICRvcmdgIG9yICh3aXRoIGEgcm9sbHVwKSBhbiBgSU4gKC4uLilgIG92ZXIgdGhlIG9yZ+KGknRlYW1cbiAgICogc3VidHJlZS4gQSBwaXBlbGluZUlkIGJlbG9uZ2luZyB0byBhbm90aGVyIG9yZyB5aWVsZHMgemVybyByb3dzLlxuICAgKi9cbiAgYXN5bmMgbGlzdFBpcGVsaW5lRXhlY3V0aW9ucyhcbiAgICBvcmdJZDogc3RyaW5nLFxuICAgIHBpcGVsaW5lSWQ6IHN0cmluZyxcbiAgICBvcmdJZHM/OiBzdHJpbmdbXSxcbiAgICByYW5nZT86IHsgZnJvbT86IHN0cmluZzsgdG8/OiBzdHJpbmcgfSxcbiAgICBsaW1pdDogbnVtYmVyID0gNTAsXG4gICk6IFByb21pc2U8UGlwZWxpbmVFeGVjdXRpb25bXT4ge1xuICAgIGNvbnN0IHsgcHJlZCwgbXVsdGkgfSA9IHRoaXMub3JnU2NvcGUob3JnSWQsIG9yZ0lkcyk7XG4gICAgY29uc3QgcmFuZ2VDbGF1c2UgPSBvcHRpb25hbFN0YXJ0ZWRBdFJhbmdlKHJhbmdlKTtcbiAgICBjb25zdCBleGVjID0gKCkgPT4gd2l0aFRlbmFudFR4KCh0eCkgPT4gdHguZXhlY3V0ZShzcWxgXG4gICAgICAgIFNFTEVDVFxuICAgICAgICAgIGUuZXhlY3V0aW9uX2lkLFxuICAgICAgICAgIENBU0VcbiAgICAgICAgICAgIFdIRU4gYm9vbF9vcihlLmV2ZW50X3R5cGUgPSAnUElQRUxJTkUnIEFORCBlLnN0YXR1cyA9ICdGQUlMRUQnKSBUSEVOICdmYWlsZWQnXG4gICAgICAgICAgICBXSEVOIGJvb2xfb3IoZS5ldmVudF90eXBlID0gJ1BJUEVMSU5FJyBBTkQgZS5zdGF0dXMgPSAnU1VDQ0VFREVEJykgVEhFTiAnc3VjY2VlZGVkJ1xuICAgICAgICAgICAgV0hFTiBib29sX29yKGUuZXZlbnRfdHlwZSA9ICdQSVBFTElORScgQU5EIGUuc3RhdHVzID0gJ0NBTkNFTEVEJykgVEhFTiAnY2FuY2VsZWQnXG4gICAgICAgICAgICBFTFNFICdpbi1wcm9ncmVzcydcbiAgICAgICAgICBFTkQgQVMgc3RhdHVzLFxuICAgICAgICAgIE1JTihlLnN0YXJ0ZWRfYXQpIEZJTFRFUiAoV0hFUkUgZS5ldmVudF90eXBlID0gJ1BJUEVMSU5FJyk6OnRleHQgQVMgc3RhcnRlZF9hdCxcbiAgICAgICAgICBNQVgoZS5jb21wbGV0ZWRfYXQpIEZJTFRFUiAoV0hFUkUgZS5ldmVudF90eXBlID0gJ1BJUEVMSU5FJyk6OnRleHQgQVMgZW5kZWRfYXQsXG4gICAgICAgICAgTUFYKGUuZHVyYXRpb25fbXMpIEZJTFRFUiAoV0hFUkUgZS5ldmVudF90eXBlID0gJ1BJUEVMSU5FJyk6OmludCBBUyBkdXJhdGlvbl9tcyxcbiAgICAgICAgICAoQVJSQVlfQUdHKGUuc3RhZ2VfbmFtZSkgRklMVEVSIChXSEVSRSBlLmV2ZW50X3R5cGUgPSAnU1RBR0UnIEFORCBlLnN0YXR1cyA9ICdGQUlMRUQnKSlbMV0gQVMgZmFpbGluZ19zdGFnZSxcbiAgICAgICAgICAoQVJSQVlfQUdHKGUuYWN0aW9uX25hbWUpIEZJTFRFUiAoV0hFUkUgZS5ldmVudF90eXBlID0gJ0FDVElPTicgQU5EIGUuc3RhdHVzID0gJ0ZBSUxFRCcpKVsxXSBBUyBmYWlsaW5nX2FjdGlvblxuICAgICAgICBGUk9NICR7c2NoZW1hLnBpcGVsaW5lRXZlbnR9IGVcbiAgICAgICAgSk9JTiAke3NjaGVtYS5waXBlbGluZX0gcCBPTiBwLmlkID0gZS5waXBlbGluZV9pZFxuICAgICAgICBXSEVSRSBwLm9yZ19pZCAke3ByZWR9IEFORCBlLnBpcGVsaW5lX2lkID0gJHtwaXBlbGluZUlkfSBBTkQgZS5leGVjdXRpb25faWQgSVMgTk9UIE5VTExcbiAgICAgICAgICAke3JhbmdlQ2xhdXNlfVxuICAgICAgICBHUk9VUCBCWSBlLmV4ZWN1dGlvbl9pZFxuICAgICAgICBPUkRFUiBCWSBNQVgoZS5jcmVhdGVkX2F0KSBERVNDXG4gICAgICAgIExJTUlUICR7bGltaXR9XG4gICAgICBgKS50aGVuKHIgPT4gZHJpenpsZVJvd3M8UGlwZWxpbmVFeGVjdXRpb24+KHIucm93cykpKTtcbiAgICByZXR1cm4gdGhpcy5ydW5SZXBvcnQoYCR7b3JnSWR9OnBpcGVsaW5lLWV4ZWN1dGlvbnM6JHtwaXBlbGluZUlkfToke3JhbmdlPy5mcm9tID8/ICcnfToke3JhbmdlPy50byA/PyAnJ306JHtsaW1pdH1gLCBtdWx0aSwgZXhlYyk7XG4gIH1cblxuICAvKiogMS4yIFN1Y2Nlc3MgcmF0ZSBvdmVyIHRpbWUgZm9yIGFuIG9yZy4gKi9cbiAgYXN5bmMgZ2V0U3VjY2Vzc1JhdGUob3JnSWQ6IHN0cmluZywgaW50ZXJ2YWw6IHN0cmluZywgZnJvbTogc3RyaW5nLCB0bzogc3RyaW5nLCBvcmdJZHM/OiBzdHJpbmdbXSk6IFByb21pc2U8VGltZVNlcmllc0VudHJ5W10+IHtcbiAgICBhc3NlcnRSZXBvcnRJbnRlcnZhbChpbnRlcnZhbCk7XG4gICAgY29uc3QgeyBwcmVkLCBtdWx0aSB9ID0gdGhpcy5vcmdTY29wZShvcmdJZCwgb3JnSWRzKTtcbiAgICBjb25zdCBleGVjID0gKCkgPT4gd2l0aFRlbmFudFR4KCh0eCkgPT4gdHguZXhlY3V0ZShzcWxgXG4gICAgICAgIFNFTEVDVFxuICAgICAgICAgIERBVEVfVFJVTkMoJHtpbnRlcnZhbH0sIGUuc3RhcnRlZF9hdCk6OnRleHQgQVMgcGVyaW9kLFxuICAgICAgICAgIENPVU5UKCopIEZJTFRFUiAoV0hFUkUgZS5zdGF0dXMgPSAnU1VDQ0VFREVEJyk6OmludCBBUyBzdWNjZWVkZWQsXG4gICAgICAgICAgQ09VTlQoKikgRklMVEVSIChXSEVSRSBlLnN0YXR1cyA9ICdGQUlMRUQnKTo6aW50IEFTIGZhaWxlZCxcbiAgICAgICAgICBDT1VOVCgqKSBGSUxURVIgKFdIRVJFIGUuc3RhdHVzID0gJ0NBTkNFTEVEJyk6OmludCBBUyBjYW5jZWxlZCxcbiAgICAgICAgICBST1VORChDT1VOVCgqKSBGSUxURVIgKFdIRVJFIGUuc3RhdHVzID0gJ1NVQ0NFRURFRCcpOjpudW1lcmljXG4gICAgICAgICAgICAvIE5VTExJRihDT1VOVCgqKSwgMCkgKiAxMDAsIDEpOjpmbG9hdCBBUyBzdWNjZXNzX3BjdFxuICAgICAgICBGUk9NICR7c2NoZW1hLnBpcGVsaW5lRXZlbnR9IGVcbiAgICAgICAgSk9JTiAke3NjaGVtYS5waXBlbGluZX0gcCBPTiBwLmlkID0gZS5waXBlbGluZV9pZFxuICAgICAgICBXSEVSRSBwLm9yZ19pZCAke3ByZWR9IEFORCBlLmV2ZW50X3R5cGUgPSAnUElQRUxJTkUnXG4gICAgICAgICAgQU5EIGUuc3RhdHVzIElOICgnU1VDQ0VFREVEJywgJ0ZBSUxFRCcsICdDQU5DRUxFRCcpXG4gICAgICAgICAgQU5EIGUuc3RhcnRlZF9hdCA+PSAke2Zyb219Ojp0aW1lc3RhbXB0eiBBTkQgZS5zdGFydGVkX2F0IDw9ICR7dG99Ojp0aW1lc3RhbXB0elxuICAgICAgICBHUk9VUCBCWSBwZXJpb2QgT1JERVIgQlkgcGVyaW9kXG4gICAgICBgKS50aGVuKHIgPT4gZHJpenpsZVJvd3M8VGltZVNlcmllc0VudHJ5PihyLnJvd3MpKSk7XG4gICAgcmV0dXJuIHRoaXMucnVuUmVwb3J0KGAke29yZ0lkfTpzdWNjZXNzLXJhdGU6JHtpbnRlcnZhbH06JHtmcm9tfToke3RvfWAsIG11bHRpLCBleGVjKTtcbiAgfVxuXG4gIC8qKiAxLjMgQXZlcmFnZSBkdXJhdGlvbiBwZXIgcGlwZWxpbmUuICovXG4gIGFzeW5jIGdldEF2ZXJhZ2VEdXJhdGlvbihvcmdJZDogc3RyaW5nLCBmcm9tOiBzdHJpbmcsIHRvOiBzdHJpbmcsIG9yZ0lkcz86IHN0cmluZ1tdKTogUHJvbWlzZTxEdXJhdGlvblN0YXRzW10+IHtcbiAgICBjb25zdCB7IHByZWQsIG11bHRpIH0gPSB0aGlzLm9yZ1Njb3BlKG9yZ0lkLCBvcmdJZHMpO1xuICAgIGNvbnN0IGV4ZWMgPSAoKSA9PiB3aXRoVGVuYW50VHgoKHR4KSA9PiB0eC5leGVjdXRlKHNxbGBcbiAgICAgICAgU0VMRUNUXG4gICAgICAgICAgcC5pZCwgcC5wcm9qZWN0LCBwLnBpcGVsaW5lX25hbWUsXG4gICAgICAgICAgQVZHKGUuZHVyYXRpb25fbXMpOjppbnQgQVMgYXZnX21zLFxuICAgICAgICAgIE1JTihlLmR1cmF0aW9uX21zKTo6aW50IEFTIG1pbl9tcyxcbiAgICAgICAgICBNQVgoZS5kdXJhdGlvbl9tcyk6OmludCBBUyBtYXhfbXMsXG4gICAgICAgICAgUEVSQ0VOVElMRV9DT05UKDAuOTUpIFdJVEhJTiBHUk9VUCAoT1JERVIgQlkgZS5kdXJhdGlvbl9tcyk6OmludCBBUyBwOTVfbXMsXG4gICAgICAgICAgQ09VTlQoKik6OmludCBBUyBleGVjdXRpb25zXG4gICAgICAgIEZST00gJHtzY2hlbWEucGlwZWxpbmVFdmVudH0gZVxuICAgICAgICBKT0lOICR7c2NoZW1hLnBpcGVsaW5lfSBwIE9OIHAuaWQgPSBlLnBpcGVsaW5lX2lkXG4gICAgICAgIFdIRVJFIHAub3JnX2lkICR7cHJlZH0gQU5EIGUuZXZlbnRfdHlwZSA9ICdQSVBFTElORScgQU5EIGUuZHVyYXRpb25fbXMgSVMgTk9UIE5VTExcbiAgICAgICAgICBBTkQgZS5zdGFydGVkX2F0ID49ICR7ZnJvbX06OnRpbWVzdGFtcHR6IEFORCBlLnN0YXJ0ZWRfYXQgPD0gJHt0b306OnRpbWVzdGFtcHR6XG4gICAgICAgIEdST1VQIEJZIHAuaWQgT1JERVIgQlkgYXZnX21zIERFU0NcbiAgICAgIGApLnRoZW4ociA9PiBkcml6emxlUm93czxEdXJhdGlvblN0YXRzPihyLnJvd3MpKSk7XG4gICAgcmV0dXJuIHRoaXMucnVuUmVwb3J0KGAke29yZ0lkfTphdmctZHVyYXRpb246JHtmcm9tfToke3RvfWAsIG11bHRpLCBleGVjKTtcbiAgfVxuXG4gIC8qKiAxLjUgU3RhZ2UgZmFpbHVyZSBoZWF0bWFwIOKAlCB3aGljaCBzdGFnZXMgZmFpbCBtb3N0LiAqL1xuICBhc3luYyBnZXRTdGFnZUZhaWx1cmVzKG9yZ0lkOiBzdHJpbmcsIGZyb206IHN0cmluZywgdG86IHN0cmluZywgb3JnSWRzPzogc3RyaW5nW10pOiBQcm9taXNlPFN0YWdlRmFpbHVyZVtdPiB7XG4gICAgY29uc3QgeyBwcmVkLCBtdWx0aSB9ID0gdGhpcy5vcmdTY29wZShvcmdJZCwgb3JnSWRzKTtcbiAgICBjb25zdCBleGVjID0gKCkgPT4gd2l0aFRlbmFudFR4KCh0eCkgPT4gdHguZXhlY3V0ZShzcWxgXG4gICAgICAgIFNFTEVDVFxuICAgICAgICAgIGUuc3RhZ2VfbmFtZSxcbiAgICAgICAgICBDT1VOVCgqKSBGSUxURVIgKFdIRVJFIGUuc3RhdHVzID0gJ0ZBSUxFRCcpOjppbnQgQVMgZmFpbHVyZXMsXG4gICAgICAgICAgQ09VTlQoKik6OmludCBBUyB0b3RhbCxcbiAgICAgICAgICBST1VORChDT1VOVCgqKSBGSUxURVIgKFdIRVJFIGUuc3RhdHVzID0gJ0ZBSUxFRCcpOjpudW1lcmljXG4gICAgICAgICAgICAvIE5VTExJRihDT1VOVCgqKSwgMCkgKiAxMDAsIDEpOjpmbG9hdCBBUyBmYWlsdXJlX3BjdFxuICAgICAgICBGUk9NICR7c2NoZW1hLnBpcGVsaW5lRXZlbnR9IGVcbiAgICAgICAgSk9JTiAke3NjaGVtYS5waXBlbGluZX0gcCBPTiBwLmlkID0gZS5waXBlbGluZV9pZFxuICAgICAgICBXSEVSRSBwLm9yZ19pZCAke3ByZWR9IEFORCBlLmV2ZW50X3R5cGUgPSAnU1RBR0UnIEFORCBlLnN0YWdlX25hbWUgSVMgTk9UIE5VTExcbiAgICAgICAgICBBTkQgZS5zdGFydGVkX2F0ID49ICR7ZnJvbX06OnRpbWVzdGFtcHR6IEFORCBlLnN0YXJ0ZWRfYXQgPD0gJHt0b306OnRpbWVzdGFtcHR6XG4gICAgICAgIEdST1VQIEJZIGUuc3RhZ2VfbmFtZSBPUkRFUiBCWSBmYWlsdXJlcyBERVNDXG4gICAgICBgKS50aGVuKHIgPT4gZHJpenpsZVJvd3M8U3RhZ2VGYWlsdXJlPihyLnJvd3MpKSk7XG4gICAgcmV0dXJuIHRoaXMucnVuUmVwb3J0KGAke29yZ0lkfTpzdGFnZS1mYWlsdXJlczoke2Zyb219OiR7dG99YCwgbXVsdGksIGV4ZWMpO1xuICB9XG5cbiAgLyoqXG4gICAqIERpc3RpbmN0IGRlcGxveSBgZW52aXJvbm1lbnRgIHZhbHVlcyBvYnNlcnZlZCBpbiB0aGUgd2luZG93IOKAlCBwb3dlcnMgdGhlXG4gICAqIERPUkEgZW52aXJvbm1lbnQtc2NvcGUgZGF0YWxpc3QuIE9yZy1zY29wZWQgKyByb2xsdXAtYXdhcmUgbGlrZSB0aGUgc2libGluZ1xuICAgKiByZXBvcnRzOyBvbmx5IG5vbi1udWxsIGVudmlyb25tZW50cyAoaS5lLiBkZXBsb3ktYXR0cmlidXRlZCBleGVjdXRpb25zKS5cbiAgICovXG4gIGFzeW5jIGdldFJlcG9ydEVudmlyb25tZW50cyhvcmdJZDogc3RyaW5nLCBmcm9tOiBzdHJpbmcsIHRvOiBzdHJpbmcsIG9yZ0lkcz86IHN0cmluZ1tdKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAgIGNvbnN0IHsgcHJlZCwgbXVsdGkgfSA9IHRoaXMub3JnU2NvcGUob3JnSWQsIG9yZ0lkcyk7XG4gICAgY29uc3QgZXhlYyA9ICgpID0+IHdpdGhUZW5hbnRUeCgodHgpID0+IHR4LmV4ZWN1dGUoc3FsYFxuICAgICAgICBTRUxFQ1QgRElTVElOQ1QgZS5lbnZpcm9ubWVudCBBUyBlbnZpcm9ubWVudFxuICAgICAgICBGUk9NICR7c2NoZW1hLnBpcGVsaW5lRXZlbnR9IGVcbiAgICAgICAgSk9JTiAke3NjaGVtYS5waXBlbGluZX0gcCBPTiBwLmlkID0gZS5waXBlbGluZV9pZFxuICAgICAgICBXSEVSRSBwLm9yZ19pZCAke3ByZWR9IEFORCBlLmVudmlyb25tZW50IElTIE5PVCBOVUxMXG4gICAgICAgICAgQU5EIGUuc3RhcnRlZF9hdCA+PSAke2Zyb219Ojp0aW1lc3RhbXB0eiBBTkQgZS5zdGFydGVkX2F0IDw9ICR7dG99Ojp0aW1lc3RhbXB0elxuICAgICAgICBPUkRFUiBCWSBlbnZpcm9ubWVudFxuICAgICAgYCkudGhlbihyID0+IGRyaXp6bGVSb3dzPHsgZW52aXJvbm1lbnQ6IHN0cmluZyB9PihyLnJvd3MpLm1hcCgocm93KSA9PiByb3cuZW52aXJvbm1lbnQpKSk7XG4gICAgcmV0dXJuIHRoaXMucnVuUmVwb3J0KGAke29yZ0lkfTpyZXBvcnQtZW52czoke2Zyb219OiR7dG99YCwgbXVsdGksIGV4ZWMpO1xuICB9XG5cbiAgLyoqIDEuNiBTdGFnZSBib3R0bGVuZWNrcyDigJQgc2xvd2VzdCBzdGFnZXMgcGVyIHBpcGVsaW5lLiAqL1xuICBhc3luYyBnZXRTdGFnZUJvdHRsZW5lY2tzKG9yZ0lkOiBzdHJpbmcsIGZyb206IHN0cmluZywgdG86IHN0cmluZywgb3JnSWRzPzogc3RyaW5nW10pOiBQcm9taXNlPFN0YWdlQm90dGxlbmVja1tdPiB7XG4gICAgY29uc3QgeyBwcmVkLCBtdWx0aSB9ID0gdGhpcy5vcmdTY29wZShvcmdJZCwgb3JnSWRzKTtcbiAgICBjb25zdCBleGVjID0gKCkgPT4gd2l0aFRlbmFudFR4KCh0eCkgPT4gdHguZXhlY3V0ZShzcWxgXG4gICAgICAgIFNFTEVDVFxuICAgICAgICAgIHAuaWQsIHAucGlwZWxpbmVfbmFtZSwgZS5zdGFnZV9uYW1lLFxuICAgICAgICAgIEFWRyhlLmR1cmF0aW9uX21zKTo6aW50IEFTIGF2Z19tcyxcbiAgICAgICAgICBNQVgoZS5kdXJhdGlvbl9tcyk6OmludCBBUyBtYXhfbXNcbiAgICAgICAgRlJPTSAke3NjaGVtYS5waXBlbGluZUV2ZW50fSBlXG4gICAgICAgIEpPSU4gJHtzY2hlbWEucGlwZWxpbmV9IHAgT04gcC5pZCA9IGUucGlwZWxpbmVfaWRcbiAgICAgICAgV0hFUkUgcC5vcmdfaWQgJHtwcmVkfSBBTkQgZS5ldmVudF90eXBlID0gJ1NUQUdFJyBBTkQgZS5kdXJhdGlvbl9tcyBJUyBOT1QgTlVMTFxuICAgICAgICAgIEFORCBlLnN0YXJ0ZWRfYXQgPj0gJHtmcm9tfTo6dGltZXN0YW1wdHogQU5EIGUuc3RhcnRlZF9hdCA8PSAke3RvfTo6dGltZXN0YW1wdHpcbiAgICAgICAgR1JPVVAgQlkgcC5pZCwgZS5zdGFnZV9uYW1lIE9SREVSIEJZIGF2Z19tcyBERVNDXG4gICAgICBgKS50aGVuKHIgPT4gZHJpenpsZVJvd3M8U3RhZ2VCb3R0bGVuZWNrPihyLnJvd3MpKSk7XG4gICAgcmV0dXJuIHRoaXMucnVuUmVwb3J0KGAke29yZ0lkfTpzdGFnZS1ib3R0bGVuZWNrczoke2Zyb219OiR7dG99YCwgbXVsdGksIGV4ZWMpO1xuICB9XG5cbiAgLyoqIDEuNyBBY3Rpb24gZmFpbHVyZSByYXRlIOKAlCB3aGljaCBwbHVnaW4gc3RlcHMgZmFpbCBtb3N0LiAqL1xuICBhc3luYyBnZXRBY3Rpb25GYWlsdXJlcyhvcmdJZDogc3RyaW5nLCBmcm9tOiBzdHJpbmcsIHRvOiBzdHJpbmcsIG9yZ0lkcz86IHN0cmluZ1tdKTogUHJvbWlzZTxBY3Rpb25GYWlsdXJlW10+IHtcbiAgICBjb25zdCB7IHByZWQsIG11bHRpIH0gPSB0aGlzLm9yZ1Njb3BlKG9yZ0lkLCBvcmdJZHMpO1xuICAgIGNvbnN0IGV4ZWMgPSAoKSA9PiB3aXRoVGVuYW50VHgoKHR4KSA9PiB0eC5leGVjdXRlKHNxbGBcbiAgICAgICAgU0VMRUNUXG4gICAgICAgICAgZS5hY3Rpb25fbmFtZSxcbiAgICAgICAgICBDT1VOVCgqKSBGSUxURVIgKFdIRVJFIGUuc3RhdHVzID0gJ0ZBSUxFRCcpOjppbnQgQVMgZmFpbHVyZXMsXG4gICAgICAgICAgQ09VTlQoKik6OmludCBBUyB0b3RhbCxcbiAgICAgICAgICBST1VORChDT1VOVCgqKSBGSUxURVIgKFdIRVJFIGUuc3RhdHVzID0gJ0ZBSUxFRCcpOjpudW1lcmljXG4gICAgICAgICAgICAvIE5VTExJRihDT1VOVCgqKSwgMCkgKiAxMDAsIDEpOjpmbG9hdCBBUyBmYWlsdXJlX3BjdFxuICAgICAgICBGUk9NICR7c2NoZW1hLnBpcGVsaW5lRXZlbnR9IGVcbiAgICAgICAgSk9JTiAke3NjaGVtYS5waXBlbGluZX0gcCBPTiBwLmlkID0gZS5waXBlbGluZV9pZFxuICAgICAgICBXSEVSRSBwLm9yZ19pZCAke3ByZWR9IEFORCBlLmV2ZW50X3R5cGUgPSAnQUNUSU9OJyBBTkQgZS5hY3Rpb25fbmFtZSBJUyBOT1QgTlVMTFxuICAgICAgICAgIEFORCBlLnN0YXJ0ZWRfYXQgPj0gJHtmcm9tfTo6dGltZXN0YW1wdHogQU5EIGUuc3RhcnRlZF9hdCA8PSAke3RvfTo6dGltZXN0YW1wdHpcbiAgICAgICAgR1JPVVAgQlkgZS5hY3Rpb25fbmFtZSBPUkRFUiBCWSBmYWlsdXJlcyBERVNDXG4gICAgICBgKS50aGVuKHIgPT4gZHJpenpsZVJvd3M8QWN0aW9uRmFpbHVyZT4oci5yb3dzKSkpO1xuICAgIHJldHVybiB0aGlzLnJ1blJlcG9ydChgJHtvcmdJZH06YWN0aW9uLWZhaWx1cmVzOiR7ZnJvbX06JHt0b31gLCBtdWx0aSwgZXhlYyk7XG4gIH1cblxuICAvKipcbiAgICogMS44IEVycm9yIGNhdGVnb3JpemF0aW9uIOKAlCBncm91cCBmYWlsdXJlIG1lc3NhZ2VzLiBFeGVjdXRpb24gcmVwb3J0LCBzb1xuICAgKiByb2xsdXAtYXdhcmUgZXhhY3RseSBsaWtlIHRoZSBzaWJsaW5nIGV4ZWN1dGlvbiByZXBvcnRzOiB3aXRoIGBvcmdJZHNgXG4gICAqICh0aGUgb3Jn4oaSdGVhbSBzdWJ0cmVlKSB0aGUgb3JnIGdhdGUgYmVjb21lcyBhbiBgSU4gKC4uLilgIGFuZCB0aGUgcmVhZCBydW5zXG4gICAqIGZyZXNoIHVuZGVyIHN5c2FkbWluIHZpYSBgcnVuUmVwb3J0YDsgc2luZ2xlLW9yZyByZWFkcyBrZWVwIHRoZSBwZXItb3JnIGNhY2hlLlxuICAgKi9cbiAgYXN5bmMgZ2V0RXJyb3JzKG9yZ0lkOiBzdHJpbmcsIGZyb206IHN0cmluZywgdG86IHN0cmluZywgbGltaXQ6IG51bWJlciA9IDIwLCBvcmdJZHM/OiBzdHJpbmdbXSk6IFByb21pc2U8RXJyb3JFbnRyeVtdPiB7XG4gICAgY29uc3QgeyBwcmVkLCBtdWx0aSB9ID0gdGhpcy5vcmdTY29wZShvcmdJZCwgb3JnSWRzKTtcbiAgICBjb25zdCBleGVjID0gKCkgPT4gd2l0aFRlbmFudFR4KCh0eCkgPT4gdHguZXhlY3V0ZShzcWxgXG4gICAgICAgIFNFTEVDVFxuICAgICAgICAgIFNVQlNUUklORyhlLmVycm9yX21lc3NhZ2UgRlJPTSAxIEZPUiAyMDApIEFTIGVycm9yX3BhdHRlcm4sXG4gICAgICAgICAgQ09VTlQoKik6OmludCBBUyBvY2N1cnJlbmNlcyxcbiAgICAgICAgICBDT1VOVChESVNUSU5DVCBlLnBpcGVsaW5lX2lkKTo6aW50IEFTIGFmZmVjdGVkX3BpcGVsaW5lcyxcbiAgICAgICAgICBNQVgoZS5zdGFydGVkX2F0KTo6dGV4dCBBUyBsYXN0X3NlZW5cbiAgICAgICAgRlJPTSAke3NjaGVtYS5waXBlbGluZUV2ZW50fSBlXG4gICAgICAgIEpPSU4gJHtzY2hlbWEucGlwZWxpbmV9IHAgT04gcC5pZCA9IGUucGlwZWxpbmVfaWRcbiAgICAgICAgV0hFUkUgcC5vcmdfaWQgJHtwcmVkfSBBTkQgZS5zdGF0dXMgPSAnRkFJTEVEJyBBTkQgZS5lcnJvcl9tZXNzYWdlIElTIE5PVCBOVUxMXG4gICAgICAgICAgQU5EIGUuc3RhcnRlZF9hdCA+PSAke2Zyb219Ojp0aW1lc3RhbXB0eiBBTkQgZS5zdGFydGVkX2F0IDw9ICR7dG99Ojp0aW1lc3RhbXB0elxuICAgICAgICBHUk9VUCBCWSBlcnJvcl9wYXR0ZXJuIE9SREVSIEJZIG9jY3VycmVuY2VzIERFU0NcbiAgICAgICAgTElNSVQgJHtsaW1pdH1cbiAgICAgIGApLnRoZW4ociA9PiBkcml6emxlUm93czxFcnJvckVudHJ5PihyLnJvd3MpKSk7XG4gICAgcmV0dXJuIHRoaXMucnVuUmVwb3J0KGAke29yZ0lkfTplcnJvcnM6JHtmcm9tfToke3RvfToke2xpbWl0fWAsIG11bHRpLCBleGVjKTtcbiAgfVxuXG4gIC8qKlxuICAgKiAxLjkgRE9SQSBtZXRyaWNzIG92ZXIgYSBbZnJvbSx0b10gZGVwbG95LWNvbXBsZXRpb24gd2luZG93LCBvcmctc2NvcGVkICtcbiAgICogcm9sbHVwLWF3YXJlLiBERVBMT1ktQkFTSVMgT05MWSDigJQgZXZlcnkgbWV0cmljIGRlcml2ZXMgZnJvbSByZWFsIGRlcGxveS1zdGFnZVxuICAgKiBleGVjdXRpb25zIChgZXZlbnRfdHlwZT0nU1RBR0UnYCB3aXRoIGEgbm9uLW51bGwgYGVudmlyb25tZW50YCwgc2V0IGJ5IHRoZVxuICAgKiBmb3J3YXJkZXIgZm9yIHRoZSBzdGFnZXMgYSB1c2VyIGRlY2xhcmVkIGluIGBwYi5kZXBsb3lzYCkuIE5vIHJ1bi1iYXNlZFxuICAgKiBmYWxsYmFjazogYSBwaXBlbGluZSB3aXRoIG5vIGRlcGxveSBzdGFnZSBwcm9kdWNlcyBubyBET1JBIGRhdGEuXG4gICAqXG4gICAqIEZvdXIgc2NvcGVkIFNRTCBzY2FucyBydW4gaW5zaWRlIG9uZSB0eCAoZWFjaCBvcmctZ2F0ZWQgYnkgYHAub3JnX2lkICR7cHJlZH1gXG4gICAqIC8gYG8ub3JnX2lkICR7cHJlZH1gIHNvIGEgcm9sbHVwIHBhc3NlcyB0aGUgb3Jn4oaSdGVhbSBzdWJ0cmVlIGFuZCBhIGZvcmVpZ25cbiAgICogb3JnJ3Mgcm93cyBuZXZlciBlbnRlcik6ICgxKSB0ZXJtaW5hbCBkZXBsb3kgcm93cyBQRVIgKGV4ZWN1dGlvbiwgZW52KSDigJQgb25lXG4gICAqIFwiZGVwbG95bWVudFwiID0gb25lIGV4ZWN1dGlvbiByZWFjaGluZyBhbiBlbnYgKEQxKSDigJQg4oaSIERGIC8gZGVwbG95LXRpbWUgQ0ZSIC9cbiAgICogbWVhc3VyZWQgbGVhZCB0aW1lIChsZWFkIHRpbWUgam9pbnMgdGhlIGV4ZWN1dGlvbidzIGVhcmxpZXN0IGNvbW1pdCwgRDIpO1xuICAgKiB0aGUgc2NhbiBhbHNvIHJlYWNoZXMgYmFjayBgd2luZG93SG91cnNgIGJlZm9yZSBgZnJvbWAgc28gaW5jaWRlbnRzIG9wZW5lZFxuICAgKiBuZWFyIHRoZSB3aW5kb3cgc3RhcnQgY2FuIGNvcnJlbGF0ZSB0byBhIGp1c3QtcHJpb3IgZGVwbG95OyAoMikgYGRlcGxveW1lbnRfb3V0Y29tZXNgXG4gICAqIGluLXdpbmRvdyDihpIgcG9zdC1kZXBsb3kgQ0ZSIGNvbXBvbmVudDsgKDMpIHByb2R1Y3Rpb24gcmVzdG9yZWQvZmFpbGVkXG4gICAqIG91dGNvbWVzIGpvaW5lZCB0byB0aGVpciBkZXBsb3kg4oaSIE1UVFI7ICg0KSByZWdpc3RyeSB2cyBkZXBsb3lpbmcg4oaSIGNvdmVyYWdlLlxuICAgKiBUaGUgY3Jvc3Mtc291cmNlIG1lZGlhbnMgKGxlYWQgdGltZSwgTVRUUikgYXJlIGNvbXB1dGVkIGluIEpTIGZyb20gY2xhbXBlZFxuICAgKiAo4omlMCkgZGVsdGFzLlxuICAgKlxuICAgKiBAcGFyYW0gb3B0cy5waXBlbGluZUlkICAgIHJlc3RyaWN0IHRvIG9uZSBwaXBlbGluZSAocGVyLXBpcGVsaW5lIERPUkEpXG4gICAqIEBwYXJhbSBvcHRzLmVudmlyb25tZW50ICAgcmVzdHJpY3QgdG8gb25lIGRlcGxveSBlbnZpcm9ubWVudFxuICAgKi9cbiAgYXN5bmMgZ2V0RG9yYU1ldHJpY3MoXG4gICAgb3JnSWQ6IHN0cmluZyxcbiAgICBmcm9tOiBzdHJpbmcsXG4gICAgdG86IHN0cmluZyxcbiAgICBvcmdJZHM/OiBzdHJpbmdbXSxcbiAgICBvcHRzOiBEb3JhT3B0aW9ucyA9IHt9LFxuICApOiBQcm9taXNlPERvcmFNZXRyaWNzPiB7XG4gICAgY29uc3QgeyBwcmVkLCBtdWx0aSB9ID0gdGhpcy5vcmdTY29wZShvcmdJZCwgb3JnSWRzKTtcbiAgICBjb25zdCB7IHBpcGVsaW5lSWQsIGVudmlyb25tZW50IH0gPSBvcHRzO1xuICAgIGNvbnN0IHBpcGVsaW5lQ2xhdXNlID0gcGlwZWxpbmVJZCA/IHNxbGBBTkQgZS5waXBlbGluZV9pZCA9ICR7cGlwZWxpbmVJZH1gIDogc3FsYGA7XG4gICAgY29uc3QgcGlwZWxpbmVDbGF1c2VSID0gcGlwZWxpbmVJZCA/IHNxbGBBTkQgci5waXBlbGluZV9pZCA9ICR7cGlwZWxpbmVJZH1gIDogc3FsYGA7XG4gICAgY29uc3QgZW52Q2xhdXNlID0gZW52aXJvbm1lbnQgPyBzcWxgQU5EIGUuZW52aXJvbm1lbnQgPSAke2Vudmlyb25tZW50fWAgOiBzcWxgYDtcbiAgICBjb25zdCBvdXRjb21lRW52Q2xhdXNlID0gZW52aXJvbm1lbnQgPyBzcWxgQU5EIG8uZW52aXJvbm1lbnQgPSAke2Vudmlyb25tZW50fWAgOiBzcWxgYDtcbiAgICBjb25zdCBpbmNpZGVudEVudkNsYXVzZSA9IGVudmlyb25tZW50ID8gc3FsYEFORCBpLmVudmlyb25tZW50ID0gJHtlbnZpcm9ubWVudH1gIDogc3FsYGA7XG5cbiAgICAvLyBFZmZlY3RpdmUgaW5jaWRlbnQtY29ycmVsYXRpb24gd2luZG93IChwZXItb3JnIG92ZXJyaWRlIG9yIHRoZSBnbG9iYWxcbiAgICAvLyBkZWZhdWx0KS4gQ29tcHV0ZWQgaGVyZSAobm90IGp1c3QgaW4gc2hhcGVEb3JhKSBiZWNhdXNlIHRoZSBkZXBsb3kgc2NhblxuICAgIC8vIG5lZWRzIGl0IGZvciBCT1RIIHRoZSBjb3JyZWxhdGlvbiBsb29rLWJhY2sgbG93ZXIgYm91bmQgQU5EIHRoZSBjYWNoZSBrZXkuXG4gICAgY29uc3QgZWZmZWN0aXZlV2luZG93SG91cnMgPSByZXNvbHZlSW5jaWRlbnRXaW5kb3dIb3VycyhvcHRzLmluY2lkZW50V2luZG93SG91cnMpO1xuICAgIC8vIENvcnJlbGF0aW9uIGxvb2stYmFjazogaW5jaWRlbnRzIG9wZW5lZCBqdXN0IGluc2lkZSBgZnJvbWAgY2FuIGF0dHJpYnV0ZSB0b1xuICAgIC8vIGEgZGVwbG95IHRoYXQgY29tcGxldGVkIHVwIHRvIGB3aW5kb3dIb3Vyc2AgQkVGT1JFIGBmcm9tYCAobWlycm9ycyB0aGVcbiAgICAvLyBMQVRFUkFMIGxvb2stYmFjayBpbiBsaXN0SW5jaWRlbnRzKS4gV2lkZW4gdGhlIGRlcGxveSBzY2FuJ3MgbG93ZXIgYm91bmQgdG9cbiAgICAvLyBgZnJvbSDiiJIgd2luZG93SG91cnNgOyBERi9DRlIvbGVhZCBzdGlsbCBjb3VudCBvbmx5IHRoZSBpbi1gZnJvbWAuLmB0b2BcbiAgICAvLyBzdWJzZXQgKGZsYWdnZWQgYnkgYGluX3dpbmRvd2ApLCB3aGlsZSBjb3JyZWxhdGlvbiBzZWVzIHRoZSB3aWRlciBzZXQuXG4gICAgY29uc3QgZnJvbU1zID0gRGF0ZS5wYXJzZShmcm9tKTtcbiAgICBjb25zdCBsb29rYmFja0Zyb20gPSBOdW1iZXIuaXNGaW5pdGUoZnJvbU1zKVxuICAgICAgPyBuZXcgRGF0ZShmcm9tTXMgLSBlZmZlY3RpdmVXaW5kb3dIb3VycyAqIDM2MDAgKiAxMDAwKS50b0lTT1N0cmluZygpXG4gICAgICA6IGZyb207XG5cbiAgICAvLyAoMSkgVGVybWluYWwgZGVwbG95IHJvd3M6IFBFUi1FWEVDVVRJT04gKEQxKSwgb25lIHJvdyBwZXIgKGVudmlyb25tZW50LFxuICAgIC8vIGV4ZWN1dGlvbikg4oCUIGV2ZXJ5IGRlcGxveSBTVEFHRSB0YXJnZXRpbmcgdGhhdCBlbnYgd2l0aGluIHRoZSBleGVjdXRpb24gaXNcbiAgICAvLyByb2xsZWQgdXAgdG8gYSB0ZXJtaW5hbCBzdGF0dXMgKEZBSUxFRCB3aW5zLCB0aGVuIFNVQ0NFRURFRCkuIEEgc2luZ2xlXG4gICAgLy8gZXhlY3V0aW9uIHdpdGggdHdvIGRlcGxveSBzdGFnZXMgdG8gdGhlIHNhbWUgZW52IGlzIE9ORSBkZXBsb3ltZW50LCBub3QgdHdvLlxuICAgIC8vIGNvbXBsZXRlZF9hdCA9IHRoZSBkZXBsb3kncyBjb21wbGV0aW9uIChNQVggb3ZlciBpdHMgc3RhZ2VzKS4gYGNvbW1pdF90c2BcbiAgICAvLyAoRDIpIGlzIHRoZSBleGVjdXRpb24ncyBFQVJMSUVTVCBjb21taXQgdGltZSBhY3Jvc3MgQUxMIGl0cyBldmVudHMgKGNvbW1pdFxuICAgIC8vIGVucmljaG1lbnQgcmlkZXMgdGhlIFBJUEVMSU5FL3NvdXJjZSBldmVudCB3aGVyZSBlbnZpcm9ubWVudCBJUyBOVUxMLCBuZXZlclxuICAgIC8vIHRoZSBkZXBsb3kgU1RBR0Ugcm93KSwgam9pbmVkIGJ5IGV4ZWN1dGlvbl9pZC4gYGluX3dpbmRvd2AgbWFya3Mgd2hldGhlciB0aGVcbiAgICAvLyBkZXBsb3kgY29tcGxldGVkIGluc2lkZSBbZnJvbSx0b10gKHZzLiBhIGxvb2stYmFjay1vbmx5IHJvdyBrZXB0IHNvbGVseSBmb3JcbiAgICAvLyBpbmNpZGVudCBjb3JyZWxhdGlvbikuIGV4ZWN1dGlvbl9pZCBpcyBwcm9qZWN0ZWQgc28gcG9zdC1kZXBsb3kgZmFpbHVyZXNcbiAgICAvLyAobWFudWFsIG91dGNvbWVzICsgY29ycmVsYXRlZCBpbmNpZGVudHMpIGNhbiBkZWR1cCBhZ2FpbnN0IHRoZWlyIGRlcGxveS5cbiAgICBjb25zdCBkZXBsb3lTcWwgPSBzcWxgXG4gICAgICAgIFdJVEggZGVwbG95X3N0YWdlcyBBUyAoXG4gICAgICAgICAgU0VMRUNUXG4gICAgICAgICAgICBlLmVudmlyb25tZW50IEFTIGVudmlyb25tZW50LFxuICAgICAgICAgICAgZS5leGVjdXRpb25faWQgQVMgZXhlY3V0aW9uX2lkLFxuICAgICAgICAgICAgJHt0ZXJtaW5hbFN0YXR1c1JvbGx1cH0gQVMgc3RhdHVzLFxuICAgICAgICAgICAgTUFYKGUuY29tcGxldGVkX2F0KSBBUyBjb21wbGV0ZWRfYXRcbiAgICAgICAgICBGUk9NICR7c2NoZW1hLnBpcGVsaW5lRXZlbnR9IGVcbiAgICAgICAgICBKT0lOICR7c2NoZW1hLnBpcGVsaW5lfSBwIE9OIHAuaWQgPSBlLnBpcGVsaW5lX2lkXG4gICAgICAgICAgV0hFUkUgcC5vcmdfaWQgJHtwcmVkfSBBTkQgZS5ldmVudF90eXBlID0gJ1NUQUdFJyBBTkQgZS5lbnZpcm9ubWVudCBJUyBOT1QgTlVMTFxuICAgICAgICAgICAgJHtwaXBlbGluZUNsYXVzZX0gJHtlbnZDbGF1c2V9XG4gICAgICAgICAgICBBTkQgZS5jb21wbGV0ZWRfYXQgPj0gJHtsb29rYmFja0Zyb219Ojp0aW1lc3RhbXB0eiBBTkQgZS5jb21wbGV0ZWRfYXQgPD0gJHt0b306OnRpbWVzdGFtcHR6XG4gICAgICAgICAgR1JPVVAgQlkgZS5lbnZpcm9ubWVudCwgZS5leGVjdXRpb25faWRcbiAgICAgICAgKSxcbiAgICAgICAgZXhlY19jb21taXRzIEFTIChcbiAgICAgICAgICBTRUxFQ1QgYy5leGVjdXRpb25faWQgQVMgZXhlY3V0aW9uX2lkLCBNSU4oYy5jb21taXRfdGltZXN0YW1wKSBBUyBjb21taXRfdHNcbiAgICAgICAgICBGUk9NICR7c2NoZW1hLnBpcGVsaW5lRXZlbnR9IGNcbiAgICAgICAgICBKT0lOICR7c2NoZW1hLnBpcGVsaW5lfSBwIE9OIHAuaWQgPSBjLnBpcGVsaW5lX2lkXG4gICAgICAgICAgV0hFUkUgcC5vcmdfaWQgJHtwcmVkfSBBTkQgYy5jb21taXRfdGltZXN0YW1wIElTIE5PVCBOVUxMXG4gICAgICAgICAgICBBTkQgYy5leGVjdXRpb25faWQgSU4gKFNFTEVDVCBleGVjdXRpb25faWQgRlJPTSBkZXBsb3lfc3RhZ2VzKVxuICAgICAgICAgIEdST1VQIEJZIGMuZXhlY3V0aW9uX2lkXG4gICAgICAgIClcbiAgICAgICAgU0VMRUNUXG4gICAgICAgICAgZHMuZW52aXJvbm1lbnQgQVMgZW52aXJvbm1lbnQsXG4gICAgICAgICAgZHMuZXhlY3V0aW9uX2lkIEFTIGV4ZWN1dGlvbl9pZCxcbiAgICAgICAgICBkcy5zdGF0dXMgQVMgc3RhdHVzLFxuICAgICAgICAgIGRzLmNvbXBsZXRlZF9hdDo6dGV4dCBBUyBjb21wbGV0ZWRfYXQsXG4gICAgICAgICAgKGRzLmNvbXBsZXRlZF9hdCA+PSAke2Zyb219Ojp0aW1lc3RhbXB0eikgQVMgaW5fd2luZG93LFxuICAgICAgICAgIGVjLmNvbW1pdF90czo6dGV4dCBBUyBjb21taXRfdHNcbiAgICAgICAgRlJPTSBkZXBsb3lfc3RhZ2VzIGRzXG4gICAgICAgIExFRlQgSk9JTiBleGVjX2NvbW1pdHMgZWMgT04gZWMuZXhlY3V0aW9uX2lkID0gZHMuZXhlY3V0aW9uX2lkYDtcblxuICAgIC8vICgyKSBQb3N0LWRlcGxveSBvdXRjb21lIG1hcmtlcnMgaW4td2luZG93IChwZXIgZW52KS4gUG9zdC1kZXBsb3kgZmFpbHVyZXNcbiAgICAvLyAob3V0Y29tZT0nZmFpbGVkJykgYWRkIHRvIHRoZSBDRlIgbnVtZXJhdG9yIHdpdGhvdXQgY2hhbmdpbmcgYXR0ZW1wdHMuXG4gICAgLy8gZXhlY3V0aW9uX2lkIGxldHMgdGhlIENGUiBkZWR1cCBhIG1hbnVhbCBmYWlsdXJlIGFnYWluc3QgYW4gaW5jaWRlbnQgdGhhdFxuICAgIC8vIGNvcnJlbGF0ZXMgdG8gdGhlIHNhbWUgZGVwbG95IChubyBkb3VibGUtY291bnQpLlxuICAgIGNvbnN0IG91dGNvbWVTcWwgPSBzcWxgXG4gICAgICAgIFNFTEVDVCBvLmVudmlyb25tZW50IEFTIGVudmlyb25tZW50LCBvLm91dGNvbWUgQVMgb3V0Y29tZSwgby5leGVjdXRpb25faWQgQVMgZXhlY3V0aW9uX2lkXG4gICAgICAgIEZST00gJHtzY2hlbWEuZGVwbG95bWVudE91dGNvbWV9IG9cbiAgICAgICAgV0hFUkUgby5vcmdfaWQgJHtwcmVkfSAke291dGNvbWVFbnZDbGF1c2V9XG4gICAgICAgICAgQU5EIG8uYXQgPj0gJHtmcm9tfTo6dGltZXN0YW1wdHogQU5EIG8uYXQgPD0gJHt0b306OnRpbWVzdGFtcHR6YDtcblxuICAgIC8vICgzKSBNVFRSIOKAlCBQUk9EVUNUSU9OLU9OTFksIGluZGVwZW5kZW50IG9mIHRoZSBlbnYgZmlsdGVyLiBFdmVyeSBwcm9kdWN0aW9uXG4gICAgLy8gb3V0Y29tZSBpbi13aW5kb3c7IGZvciBhICdyZXN0b3JlZCcgb25lLCBjb3JyZWxhdGUgdG8gaXRzIGRlcGxveSdzXG4gICAgLy8gY29tcGxldGlvbiB2aWEgZXhlY3V0aW9uX2lkIHRvIG1lYXN1cmUgcmVzdG9yZWQuYXQg4oiSIGRlcGxveWVkLmNvbXBsZXRlZF9hdC5cbiAgICAvLyBleGVjdXRpb25faWQgaXMgcHJvamVjdGVkIHNvIGFuIGluY2lkZW50LXNvdXJjZWQgcmVjb3ZlcnkgZm9yIHRoZSBzYW1lXG4gICAgLy8gZGVwbG95IHRha2VzIHByZWNlZGVuY2Ugb3ZlciB0aGUgbWFudWFsIHJlc3RvcmVkIGdhcC5cbiAgICBjb25zdCBtdHRyU3FsID0gc3FsYFxuICAgICAgICBTRUxFQ1RcbiAgICAgICAgICBvLm91dGNvbWUgQVMgb3V0Y29tZSxcbiAgICAgICAgICBvLmV4ZWN1dGlvbl9pZCBBUyBleGVjdXRpb25faWQsXG4gICAgICAgICAgby5hdDo6dGV4dCBBUyByZXN0b3JlZF9hdCxcbiAgICAgICAgICAoU0VMRUNUIE1BWChkLmNvbXBsZXRlZF9hdCkgRlJPTSAke3NjaGVtYS5waXBlbGluZUV2ZW50fSBkXG4gICAgICAgICAgICAgSk9JTiAke3NjaGVtYS5waXBlbGluZX0gcDIgT04gcDIuaWQgPSBkLnBpcGVsaW5lX2lkXG4gICAgICAgICAgICAgV0hFUkUgcDIub3JnX2lkICR7cHJlZH0gQU5EIGQuZXhlY3V0aW9uX2lkID0gby5leGVjdXRpb25faWRcbiAgICAgICAgICAgICAgIEFORCBkLmV2ZW50X3R5cGUgPSAnU1RBR0UnIEFORCBkLmVudmlyb25tZW50ID0gJHtIRUFETElORV9FTlZ9KTo6dGV4dCBBUyBkZXBsb3llZF9hdFxuICAgICAgICBGUk9NICR7c2NoZW1hLmRlcGxveW1lbnRPdXRjb21lfSBvXG4gICAgICAgIFdIRVJFIG8ub3JnX2lkICR7cHJlZH0gQU5EIG8uZW52aXJvbm1lbnQgPSAke0hFQURMSU5FX0VOVn1cbiAgICAgICAgICBBTkQgby5hdCA+PSAke2Zyb219Ojp0aW1lc3RhbXB0eiBBTkQgby5hdCA8PSAke3RvfTo6dGltZXN0YW1wdHpgO1xuXG4gICAgLy8gKDUpIEluY2lkZW50cyBvcGVuZWQgaW4td2luZG93IChwZXIgZW52KS4gQ29ycmVsYXRlZCBpbiBKUyB0byB0aGUgbW9zdFxuICAgIC8vIHJlY2VudCBzdWNjZXNzZnVsIGRlcGxveSDihpIgYXV0b21hdGVkIHBvc3QtZGVwbG95IGZhaWx1cmUgKENGUikgKyByZWFsXG4gICAgLy8gcmVjb3ZlcnkgdGltZSAocmVzb2x2ZWRfYXQg4oiSIG9wZW5lZF9hdCkgZm9yIE1UVFIgKHByb2R1Y3Rpb24pLlxuICAgIGNvbnN0IGluY2lkZW50U3FsID0gc3FsYFxuICAgICAgICBTRUxFQ1QgaS5lbnZpcm9ubWVudCBBUyBlbnZpcm9ubWVudCwgaS5vcGVuZWRfYXQ6OnRleHQgQVMgb3BlbmVkX2F0LCBpLnJlc29sdmVkX2F0Ojp0ZXh0IEFTIHJlc29sdmVkX2F0XG4gICAgICAgIEZST00gJHtzY2hlbWEuaW5jaWRlbnR9IGlcbiAgICAgICAgV0hFUkUgaS5vcmdfaWQgJHtwcmVkfSAke2luY2lkZW50RW52Q2xhdXNlfVxuICAgICAgICAgIEFORCBpLm9wZW5lZF9hdCA+PSAke2Zyb219Ojp0aW1lc3RhbXB0eiBBTkQgaS5vcGVuZWRfYXQgPD0gJHt0b306OnRpbWVzdGFtcHR6YDtcblxuICAgIC8vICg0KSBDb3ZlcmFnZTogcmVnaXN0ZXJlZCBwaXBlbGluZXMgdnMgdGhvc2UgdGhhdCBhY3R1YWxseSBkZXBsb3llZCBpbi13aW5kb3cuXG4gICAgY29uc3QgY292ZXJhZ2VTcWwgPSBzcWxgXG4gICAgICAgIFNFTEVDVFxuICAgICAgICAgIChTRUxFQ1QgQ09VTlQoKik6OmludCBGUk9NICR7c2NoZW1hLnBpcGVsaW5lUmVnaXN0cnl9IHJcbiAgICAgICAgICAgICBXSEVSRSByLm9yZ19pZCAke3ByZWR9ICR7cGlwZWxpbmVDbGF1c2VSfSkgQVMgcmVnaXN0ZXJlZCxcbiAgICAgICAgICAoU0VMRUNUIENPVU5UKERJU1RJTkNUIGUucGlwZWxpbmVfaWQpOjppbnQgRlJPTSAke3NjaGVtYS5waXBlbGluZUV2ZW50fSBlXG4gICAgICAgICAgICAgSk9JTiAke3NjaGVtYS5waXBlbGluZX0gcCBPTiBwLmlkID0gZS5waXBlbGluZV9pZFxuICAgICAgICAgICAgIFdIRVJFIHAub3JnX2lkICR7cHJlZH0gQU5EIGUuZXZlbnRfdHlwZSA9ICdTVEFHRScgQU5EIGUuZW52aXJvbm1lbnQgSVMgTk9UIE5VTExcbiAgICAgICAgICAgICAgICR7cGlwZWxpbmVDbGF1c2V9ICR7ZW52Q2xhdXNlfVxuICAgICAgICAgICAgICAgQU5EIGUuY29tcGxldGVkX2F0ID49ICR7ZnJvbX06OnRpbWVzdGFtcHR6IEFORCBlLmNvbXBsZXRlZF9hdCA8PSAke3RvfTo6dGltZXN0YW1wdHopIEFTIGRlcGxveWluZ2A7XG5cbiAgICBjb25zdCBleGVjID0gKCkgPT4gd2l0aFRlbmFudFR4KGFzeW5jICh0eCkgPT4ge1xuICAgICAgLy8gU2NhbiBvcmRlciBpcyBsb2FkLWJlYXJpbmcgZm9yIHRoZSBnZW5lcmF0ZWQtU1FMIHRlc3RzOiAwPWRlcGxveSxcbiAgICAgIC8vIDE9b3V0Y29tZXMsIDI9bXR0ciwgMz1jb3ZlcmFnZSwgND1pbmNpZGVudHMgKGFwcGVuZGVkIGxhc3Qgc28gdGhlXG4gICAgICAvLyBlYXJsaWVyIGluZGljZXMgc3RheSBzdGFibGUpLlxuICAgICAgY29uc3QgZGVwbG95Um93cyA9IGRyaXp6bGVSb3dzPERlcGxveVJvdz4oKGF3YWl0IHR4LmV4ZWN1dGUoZGVwbG95U3FsKSkucm93cyk7XG4gICAgICBjb25zdCBvdXRjb21lUm93cyA9IGRyaXp6bGVSb3dzPE91dGNvbWVSb3c+KChhd2FpdCB0eC5leGVjdXRlKG91dGNvbWVTcWwpKS5yb3dzKTtcbiAgICAgIGNvbnN0IG10dHJSb3dzID0gZHJpenpsZVJvd3M8TXR0clBhaXJSb3cgJiB7IG91dGNvbWU6IHN0cmluZyB9PigoYXdhaXQgdHguZXhlY3V0ZShtdHRyU3FsKSkucm93cyk7XG4gICAgICBjb25zdCBjb3ZlcmFnZVJvdyA9IGRyaXp6bGVSb3dzPENvdmVyYWdlUm93PigoYXdhaXQgdHguZXhlY3V0ZShjb3ZlcmFnZVNxbCkpLnJvd3MpWzBdO1xuICAgICAgY29uc3QgaW5jaWRlbnRSb3dzID0gZHJpenpsZVJvd3M8SW5jaWRlbnRSb3c+KChhd2FpdCB0eC5leGVjdXRlKGluY2lkZW50U3FsKSkucm93cyk7XG4gICAgICByZXR1cm4gdGhpcy5zaGFwZURvcmEoZGVwbG95Um93cywgb3V0Y29tZVJvd3MsIG10dHJSb3dzLCBjb3ZlcmFnZVJvdywgaW5jaWRlbnRSb3dzLCBmcm9tLCB0bywge1xuICAgICAgICBwaXBlbGluZUlkLCBlbnZpcm9ubWVudCxcbiAgICAgIH0sIGVmZmVjdGl2ZVdpbmRvd0hvdXJzKTtcbiAgICB9KTtcbiAgICAvLyBDYWNoZSBrZXkgTVVTVCBpbmNsdWRlIHRoZSBlZmZlY3RpdmUgaW5jaWRlbnQgd2luZG93OiB0aGUgc2NvcmVjYXJkIHJlYWRzXG4gICAgLy8gL2RvcmEgd2l0aCB0aGUgb3JnJ3MgZGVmYXVsdCB3aW5kb3cgd2hpbGUgYW4gZXhwbGljaXQgL2RvcmEgY2FsbCBtYXkgcGFzcyBhblxuICAgIC8vIG92ZXJyaWRlIOKAlCBkaWZmZXJlbnQgd2luZG93cyB5aWVsZCBkaWZmZXJlbnQgQ0ZSL01UVFIsIHNvIHRoZXkgbXVzdCBub3RcbiAgICAvLyBjb2xsaWRlIG9uIHRoZSBzYW1lIGtleS5cbiAgICBjb25zdCBrZXkgPSBgJHtvcmdJZH06ZG9yYToke2Zyb219OiR7dG99OiR7cGlwZWxpbmVJZCA/PyAnJ306JHtlbnZpcm9ubWVudCA/PyAnJ306JHtlZmZlY3RpdmVXaW5kb3dIb3Vyc31gO1xuICAgIHJldHVybiB0aGlzLnJ1blJlcG9ydChrZXksIG11bHRpLCBleGVjKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTaGFwZSB0aGUgcmF3IERPUkEgc2NhbiByb3dzIGludG8gdGhlIHB1YmxpYyB7QGxpbmsgRG9yYU1ldHJpY3N9LiBCdWNrZXRzIHRoZVxuICAgKiB0ZXJtaW5hbCBkZXBsb3kgcm93cyBieSBlbnZpcm9ubWVudCAoREYgLyBkZXBsb3ktdGltZSBDRlIgLyBtZWFzdXJlZCBsZWFkKSxcbiAgICogZm9sZHMgaW4gdGhlIHBvc3QtZGVwbG95IGZhaWx1cmUgY291bnRzIChtYW51YWwgb3V0Y29tZXMgKyB3ZWJob29rLWluZ2VzdGVkXG4gICAqIGluY2lkZW50cywgZGVkdXBlZCBieSBkZXBsb3kgZXhlY3V0aW9uKSwgY29tcHV0ZXMgcHJvZHVjdGlvbiBNVFRSIGZyb20gYm90aFxuICAgKiBzb3VyY2VzIChpbmNpZGVudCBgcmVzb2x2ZWRfYXQg4oiSIG9wZW5lZF9hdGAgdGFraW5nIHByZWNlZGVuY2Ugb3ZlciB0aGUgbWFudWFsXG4gICAqIGByZXN0b3JlZCDiiJIgZGVwbG95ZWRgKSwgYW5kIHJlY29uY2lsZXMgY292ZXJhZ2Ug4oCUIGFsbCBjcm9zcy1zb3VyY2UgbWVkaWFuc1xuICAgKiBvdmVyIGRlbHRhcyBjbGFtcGVkIOKJpTAuXG4gICAqXG4gICAqIFBoYXNlIDUgaW5jaWRlbnQgY29ycmVsYXRpb246IGVhY2ggaW5jaWRlbnQgaXMgYXR0cmlidXRlZCB0byB0aGUgbW9zdCByZWNlbnRcbiAgICogU1VDQ0VTU0ZVTCBkZXBsb3kgdG8gaXRzIGVudmlyb25tZW50IHdpdGggYGNvbXBsZXRlZF9hdCDiiaQgb3BlbmVkX2F0YCB3aXRoaW5cbiAgICoge0BsaW5rIERPUkFfSU5DSURFTlRfV0lORE9XX0hPVVJTfS4gVGhhdCBkZXBsb3kgaXMgYSBwb3N0LWRlcGxveSBmYWlsdXJlOyBhblxuICAgKiB1bmNvcnJlbGF0ZWQgaW5jaWRlbnQgKG5vIGVsaWdpYmxlIGRlcGxveSkgY29udHJpYnV0ZXMgbm90aGluZy5cbiAgICovXG4gIHByaXZhdGUgc2hhcGVEb3JhKFxuICAgIGRlcGxveVJvd3M6IERlcGxveVJvd1tdLFxuICAgIG91dGNvbWVSb3dzOiBPdXRjb21lUm93W10sXG4gICAgbXR0clJvd3M6IEFycmF5PE10dHJQYWlyUm93ICYgeyBvdXRjb21lOiBzdHJpbmcgfT4sXG4gICAgY292ZXJhZ2VSb3c6IENvdmVyYWdlUm93IHwgdW5kZWZpbmVkLFxuICAgIGluY2lkZW50Um93czogSW5jaWRlbnRSb3dbXSxcbiAgICBmcm9tOiBzdHJpbmcsXG4gICAgdG86IHN0cmluZyxcbiAgICBmaWx0ZXJzOiB7IHBpcGVsaW5lSWQ/OiBzdHJpbmc7IGVudmlyb25tZW50Pzogc3RyaW5nIH0sXG4gICAgd2luZG93SG91cnM6IG51bWJlciA9IERPUkFfSU5DSURFTlRfV0lORE9XX0hPVVJTLFxuICApOiBEb3JhTWV0cmljcyB7XG4gICAgLy8gV2luZG93IGxlbmd0aCBpbiBkYXlzIChmbG9vcmVkIGF0IDEgc28gYSBzdWItZGF5IHdpbmRvdyB5aWVsZHMgdGhlIGNvdW50IGFzXG4gICAgLy8gdGhlIHJhdGUsIG5ldmVyIC8wIG9yIGFuIGV4dHJhcG9sYXRpb24pLiBHdWFyZCB1bnBhcnNlYWJsZSBkYXRlcyDihpIgMSBkYXkuXG4gICAgY29uc3Qgc3BhbkRheXMgPSAoRGF0ZS5wYXJzZSh0bykgLSBEYXRlLnBhcnNlKGZyb20pKSAvIDg2NDAwMDAwO1xuICAgIGNvbnN0IGRheXMgPSBOdW1iZXIuaXNGaW5pdGUoc3BhbkRheXMpID8gTWF0aC5tYXgoc3BhbkRheXMsIDEpIDogMTtcbiAgICAvLyBXaW5kb3cgZW5kIGluc3RhbnQgZm9yIE1UVFIgcmlnaHQtY2Vuc29yaW5nIChhIHJlc29sdXRpb24gYWZ0ZXIgYHRvYCBpc1xuICAgIC8vIHVub2JzZXJ2ZWQpLiArSW5maW5pdHkgd2hlbiBgdG9gIGlzIHVucGFyc2VhYmxlIOKHkiBubyBjZW5zb3JpbmcgKGZhaWwtb3BlbikuXG4gICAgY29uc3QgdG9QYXJzZWQgPSBEYXRlLnBhcnNlKHRvKTtcbiAgICBjb25zdCB0b01zID0gTnVtYmVyLmlzRmluaXRlKHRvUGFyc2VkKSA/IHRvUGFyc2VkIDogTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZO1xuXG4gICAgLy8gUGVyLWVudiBhY2N1bXVsYXRvci5cbiAgICBpbnRlcmZhY2UgQWNjIHtcbiAgICAgIGRlcGxveW1lbnRzOiBudW1iZXI7XG4gICAgICBkZXBsb3lUaW1lRmFpbHVyZXM6IG51bWJlcjtcbiAgICAgIGF0dGVtcHRzOiBudW1iZXI7XG4gICAgICBsZWFkR2FwczogbnVtYmVyW107XG4gICAgfVxuICAgIGNvbnN0IGVudnMgPSBuZXcgTWFwPHN0cmluZywgQWNjPigpO1xuICAgIGNvbnN0IGFjY0ZvciA9IChlbnY6IHN0cmluZyk6IEFjYyA9PiB7XG4gICAgICBsZXQgYSA9IGVudnMuZ2V0KGVudik7XG4gICAgICBpZiAoIWEpIHsgYSA9IHsgZGVwbG95bWVudHM6IDAsIGRlcGxveVRpbWVGYWlsdXJlczogMCwgYXR0ZW1wdHM6IDAsIGxlYWRHYXBzOiBbXSB9OyBlbnZzLnNldChlbnYsIGEpOyB9XG4gICAgICByZXR1cm4gYTtcbiAgICB9O1xuXG4gICAgLy8gQSBkZXBsb3kgcm93IGNvdW50cyB0b3dhcmQgREYvQ0ZSL2xlYWQgb25seSBpZiBpdCBjb21wbGV0ZWQgaW5zaWRlIFtmcm9tLHRvXS5cbiAgICAvLyBMb29rLWJhY2stb25seSByb3dzIChpbl93aW5kb3c9ZmFsc2UsIGtlcHQgZm9yIGluY2lkZW50IGNvcnJlbGF0aW9uKSBhcmVcbiAgICAvLyBza2lwcGVkIGhlcmUuIEFic2VudCBpbiBhIGZpeHR1cmUg4oeSIGluLXdpbmRvdyAodW5pdCB0ZXN0cyBvbWl0IHRoZSBmbGFnKS5cbiAgICBjb25zdCBpc0luV2luZG93ID0gKHJvdzogRGVwbG95Um93KTogYm9vbGVhbiA9PlxuICAgICAgcm93LmluX3dpbmRvdyA9PSBudWxsID8gdHJ1ZSA6IChyb3cuaW5fd2luZG93ID09PSB0cnVlIHx8IHJvdy5pbl93aW5kb3cgPT09ICd0Jyk7XG5cbiAgICBmb3IgKGNvbnN0IHJvdyBvZiBkZXBsb3lSb3dzKSB7XG4gICAgICBjb25zdCBlbnYgPSByb3cuZW52aXJvbm1lbnQ7XG4gICAgICBpZiAoIWVudikgY29udGludWU7XG4gICAgICBpZiAoIWlzSW5XaW5kb3cocm93KSkgY29udGludWU7IC8vIGxvb2stYmFjay1vbmx5IHJvdyDihpIgY29ycmVsYXRpb24sIG5vdCBERi9DRlJcbiAgICAgIGNvbnN0IGEgPSBhY2NGb3IoZW52KTtcbiAgICAgIGlmIChyb3cuc3RhdHVzID09PSAnU1VDQ0VFREVEJykge1xuICAgICAgICBhLmRlcGxveW1lbnRzKys7XG4gICAgICAgIGEuYXR0ZW1wdHMrKztcbiAgICAgICAgLy8gTWVhc3VyZWQgbGVhZCB0aW1lOiBkZXBsb3kgY29tcGxldGlvbiDiiJIgZXhlY3V0aW9uJ3MgZWFybGllc3QgY29tbWl0IHRpbWUuXG4gICAgICAgIGlmIChyb3cuY29tbWl0X3RzICE9IG51bGwgJiYgcm93LmNvbXBsZXRlZF9hdCAhPSBudWxsKSB7XG4gICAgICAgICAgY29uc3QgZ2FwID0gKERhdGUucGFyc2Uocm93LmNvbXBsZXRlZF9hdCkgLSBEYXRlLnBhcnNlKHJvdy5jb21taXRfdHMpKSAvIDEwMDA7XG4gICAgICAgICAgaWYgKE51bWJlci5pc0Zpbml0ZShnYXApKSBhLmxlYWRHYXBzLnB1c2goTWF0aC5tYXgoZ2FwLCAwKSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAocm93LnN0YXR1cyA9PT0gJ0ZBSUxFRCcpIHtcbiAgICAgICAgYS5kZXBsb3lUaW1lRmFpbHVyZXMrKztcbiAgICAgICAgYS5hdHRlbXB0cysrO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIEluY2lkZW504oaSZGVwbG95IGNvcnJlbGF0aW9uIChQaGFzZSA1KS4gSW5kZXggdGhlIFNVQ0NFU1NGVUwgZGVwbG95cyBwZXIgZW52XG4gICAgLy8gKGV4ZWN1dGlvbiBpZCArIGNvbXBsZXRpb24gaW5zdGFudCksIG5ld2VzdCBmaXJzdCwgc28gZWFjaCBpbmNpZGVudCBjYW4gYmVcbiAgICAvLyBhdHRyaWJ1dGVkIHRvIHRoZSBtb3N0IHJlY2VudCBkZXBsb3kgdGhhdCBjb21wbGV0ZWQgd2l0aGluIHRoZSB3aW5kb3dcbiAgICAvLyBiZWZvcmUgaXQgb3BlbmVkLiBUaGF0IGV4ZWN1dGlvbiBpcyBhIHBvc3QtZGVwbG95IGZhaWx1cmUuXG4gICAgY29uc3Qgd2luZG93TXMgPSB3aW5kb3dIb3VycyAqIDM2MDAgKiAxMDAwO1xuICAgIGNvbnN0IHN1Y2Nlc3NmdWxCeUVudiA9IG5ldyBNYXA8c3RyaW5nLCBBcnJheTx7IGV4ZWM6IHN0cmluZzsgY29tcGxldGVkTXM6IG51bWJlciB9Pj4oKTtcbiAgICBmb3IgKGNvbnN0IHJvdyBvZiBkZXBsb3lSb3dzKSB7XG4gICAgICBpZiAocm93LnN0YXR1cyAhPT0gJ1NVQ0NFRURFRCcgfHwgIXJvdy5lbnZpcm9ubWVudCB8fCByb3cuZXhlY3V0aW9uX2lkID09IG51bGwgfHwgcm93LmNvbXBsZXRlZF9hdCA9PSBudWxsKSBjb250aW51ZTtcbiAgICAgIGNvbnN0IG1zID0gRGF0ZS5wYXJzZShyb3cuY29tcGxldGVkX2F0KTtcbiAgICAgIGlmICghTnVtYmVyLmlzRmluaXRlKG1zKSkgY29udGludWU7XG4gICAgICBjb25zdCBsaXN0ID0gc3VjY2Vzc2Z1bEJ5RW52LmdldChyb3cuZW52aXJvbm1lbnQpID8/IFtdO1xuICAgICAgbGlzdC5wdXNoKHsgZXhlYzogcm93LmV4ZWN1dGlvbl9pZCwgY29tcGxldGVkTXM6IG1zIH0pO1xuICAgICAgc3VjY2Vzc2Z1bEJ5RW52LnNldChyb3cuZW52aXJvbm1lbnQsIGxpc3QpO1xuICAgIH1cbiAgICBmb3IgKGNvbnN0IGxpc3Qgb2Ygc3VjY2Vzc2Z1bEJ5RW52LnZhbHVlcygpKSBsaXN0LnNvcnQoKGEsIGIpID0+IGIuY29tcGxldGVkTXMgLSBhLmNvbXBsZXRlZE1zKTtcblxuICAgIC8qKiBDb3JyZWxhdGUgYW4gaW5jaWRlbnQgdG8gdGhlIG1vc3QgcmVjZW50IGluLXdpbmRvdyBzdWNjZXNzZnVsIGRlcGxveSBleGVjdXRpb24uICovXG4gICAgY29uc3QgY29ycmVsYXRlID0gKGVudjogc3RyaW5nLCBvcGVuZWRNczogbnVtYmVyKTogc3RyaW5nIHwgbnVsbCA9PiB7XG4gICAgICBjb25zdCBsaXN0ID0gc3VjY2Vzc2Z1bEJ5RW52LmdldChlbnYpO1xuICAgICAgaWYgKCFsaXN0KSByZXR1cm4gbnVsbDtcbiAgICAgIGZvciAoY29uc3QgZCBvZiBsaXN0KSB7XG4gICAgICAgIGlmIChkLmNvbXBsZXRlZE1zIDw9IG9wZW5lZE1zICYmIG9wZW5lZE1zIC0gZC5jb21wbGV0ZWRNcyA8PSB3aW5kb3dNcykgcmV0dXJuIGQuZXhlYztcbiAgICAgIH1cbiAgICAgIHJldHVybiBudWxsO1xuICAgIH07XG5cbiAgICAvLyBDb3JyZWxhdGVkIGluY2lkZW50cyAoYWxsIGVudnMg4oaSIENGUjsgcHJvZHVjdGlvbiBzdWJzZXQg4oaSIE1UVFIpLiBFYWNoIGNhcnJpZXNcbiAgICAvLyB0aGUgZGVwbG95IGV4ZWN1dGlvbiBpdCBhdHRyaWJ1dGVzIHRvICsgaXRzIHJlYWwgcmVjb3ZlcnkgZ2FwICh3aGVuIHJlc29sdmVkKS5cbiAgICBpbnRlcmZhY2UgQ29ycmVsYXRlZEluY2lkZW50IHsgZW52aXJvbm1lbnQ6IHN0cmluZzsgZXhlYzogc3RyaW5nOyByZXNvbHZlZEdhcDogbnVtYmVyIHwgbnVsbCB9XG4gICAgY29uc3QgY29ycmVsYXRlZEluY2lkZW50czogQ29ycmVsYXRlZEluY2lkZW50W10gPSBbXTtcbiAgICBmb3IgKGNvbnN0IGluYyBvZiBpbmNpZGVudFJvd3MpIHtcbiAgICAgIGlmICghaW5jLmVudmlyb25tZW50IHx8IGluYy5vcGVuZWRfYXQgPT0gbnVsbCkgY29udGludWU7XG4gICAgICBjb25zdCBvcGVuZWRNcyA9IERhdGUucGFyc2UoaW5jLm9wZW5lZF9hdCk7XG4gICAgICBpZiAoIU51bWJlci5pc0Zpbml0ZShvcGVuZWRNcykpIGNvbnRpbnVlO1xuICAgICAgY29uc3QgZXhlYyA9IGNvcnJlbGF0ZShpbmMuZW52aXJvbm1lbnQsIG9wZW5lZE1zKTtcbiAgICAgIGlmIChleGVjID09IG51bGwpIGNvbnRpbnVlOyAvLyB1bmNvcnJlbGF0ZWQg4oaSIG5vdCBhdHRyaWJ1dGFibGUgdG8gYSBkZXBsb3lcbiAgICAgIGxldCByZXNvbHZlZEdhcDogbnVtYmVyIHwgbnVsbCA9IG51bGw7XG4gICAgICBpZiAoaW5jLnJlc29sdmVkX2F0ICE9IG51bGwpIHtcbiAgICAgICAgY29uc3QgcmVzb2x2ZWRNcyA9IERhdGUucGFyc2UoaW5jLnJlc29sdmVkX2F0KTtcbiAgICAgICAgLy8gUmlnaHQtY2Vuc29yaW5nOiBhIHJlc29sdXRpb24gQUZURVIgdGhlIHdpbmRvdyBlbmQgKGB0b2ApIGlzIG5vdCBvYnNlcnZlZFxuICAgICAgICAvLyB3aXRoaW4gdGhlIHdpbmRvdyDigJQgdHJlYXQgdGhlIGluY2lkZW50IGFzIHN0aWxsIG9wZW4gKGdhcCBzdGF5cyBudWxsKSBzb1xuICAgICAgICAvLyBNVFRSIG5ldmVyIHJlYWRzIHVuYm91bmRlZCBwYXN0IGB0b2AuIFRoZSBpbmNpZGVudCBzdGlsbCBjb3VudHMgdG93YXJkIHRoZVxuICAgICAgICAvLyBpbmNpZGVudCB0b3RhbCAodW5yZXNvbHZlZCksIGl0IGp1c3QgY29udHJpYnV0ZXMgbm8gcmVjb3ZlcnkgdGltZS5cbiAgICAgICAgaWYgKE51bWJlci5pc0Zpbml0ZShyZXNvbHZlZE1zKSAmJiByZXNvbHZlZE1zIDw9IHRvTXMpIHtcbiAgICAgICAgICBjb25zdCBnID0gKHJlc29sdmVkTXMgLSBvcGVuZWRNcykgLyAxMDAwO1xuICAgICAgICAgIGlmIChOdW1iZXIuaXNGaW5pdGUoZykpIHJlc29sdmVkR2FwID0gTWF0aC5tYXgoZywgMCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGNvcnJlbGF0ZWRJbmNpZGVudHMucHVzaCh7IGVudmlyb25tZW50OiBpbmMuZW52aXJvbm1lbnQsIGV4ZWMsIHJlc29sdmVkR2FwIH0pO1xuICAgIH1cblxuICAgIC8vIFBvc3QtZGVwbG95IGZhaWx1cmVzIHBlciBlbnYg4oCUIHRoZSBESVNUSU5DVCBzZXQgb2YgZGVwbG95IGV4ZWN1dGlvbnMgZmxhZ2dlZFxuICAgIC8vIGJ5IGEgbWFudWFsIGBmYWlsZWRgIG91dGNvbWUgT1IgYSBjb3JyZWxhdGVkIGluY2lkZW50IChkZWR1cGVkIGJ5IGV4ZWN1dGlvbixcbiAgICAvLyBzbyBhIGRlcGxveSBmbGFnZ2VkIGJ5IGJvdGggY291bnRzIG9uY2UpLiBBIG1hbnVhbCBvdXRjb21lIHdpdGhvdXQgYW5cbiAgICAvLyBleGVjdXRpb24gaWQgKGxlZ2FjeS91bnJlc29sdmFibGUpIHN0aWxsIGNvdW50cyB2aWEgYSBwZXItcm93IHNlbnRpbmVsLlxuICAgIGNvbnN0IHBvc3REZXBsb3lFeGVjc0J5RW52ID0gbmV3IE1hcDxzdHJpbmcsIFNldDxzdHJpbmc+PigpO1xuICAgIGxldCBzZW50aW5lbCA9IDA7XG4gICAgY29uc3QgZmxhZ0ZvciA9IChlbnY6IHN0cmluZyk6IFNldDxzdHJpbmc+ID0+IHtcbiAgICAgIGxldCBzID0gcG9zdERlcGxveUV4ZWNzQnlFbnYuZ2V0KGVudik7XG4gICAgICBpZiAoIXMpIHsgcyA9IG5ldyBTZXQ8c3RyaW5nPigpOyBwb3N0RGVwbG95RXhlY3NCeUVudi5zZXQoZW52LCBzKTsgfVxuICAgICAgcmV0dXJuIHM7XG4gICAgfTtcbiAgICBmb3IgKGNvbnN0IG8gb2Ygb3V0Y29tZVJvd3MpIHtcbiAgICAgIGlmIChvLm91dGNvbWUgIT09ICdmYWlsZWQnIHx8ICFvLmVudmlyb25tZW50KSBjb250aW51ZTtcbiAgICAgIGZsYWdGb3Ioby5lbnZpcm9ubWVudCkuYWRkKG8uZXhlY3V0aW9uX2lkID8/IGBtYW51YWwtJHtzZW50aW5lbCsrfWApO1xuICAgICAgYWNjRm9yKG8uZW52aXJvbm1lbnQpOyAvLyBlbnN1cmUgZW52IGFwcGVhcnMgZXZlbiB3aXRoIG5vIGRlcGxveSBldmVudHNcbiAgICB9XG4gICAgZm9yIChjb25zdCBjaSBvZiBjb3JyZWxhdGVkSW5jaWRlbnRzKSB7XG4gICAgICBmbGFnRm9yKGNpLmVudmlyb25tZW50KS5hZGQoY2kuZXhlYyk7XG4gICAgICBhY2NGb3IoY2kuZW52aXJvbm1lbnQpOyAvLyBlbnN1cmUgZW52IGFwcGVhcnMgZXZlbiBpZiB0aGUgZGVwbG95IGlzIG91dC1vZi13aW5kb3dcbiAgICB9XG4gICAgY29uc3QgcG9zdERlcGxveUJ5RW52ID0gbmV3IE1hcDxzdHJpbmcsIG51bWJlcj4oKTtcbiAgICBmb3IgKGNvbnN0IFtlbnYsIHNldF0gb2YgcG9zdERlcGxveUV4ZWNzQnlFbnYpIHBvc3REZXBsb3lCeUVudi5zZXQoZW52LCBzZXQuc2l6ZSk7XG5cbiAgICBjb25zdCBlbnZpcm9ubWVudHM6IERvcmFFbnZNZXRyaWNzW10gPSBbLi4uZW52cy5lbnRyaWVzKCldXG4gICAgICAubWFwKChbZW52aXJvbm1lbnQsIGFdKSA9PiB7XG4gICAgICAgIGNvbnN0IHBvc3REZXBsb3lGYWlsdXJlcyA9IHBvc3REZXBsb3lCeUVudi5nZXQoZW52aXJvbm1lbnQpID8/IDA7XG4gICAgICAgIGNvbnN0IHJhd1BlckRheSA9IGEuZGVwbG95bWVudHMgLyBkYXlzO1xuICAgICAgICBjb25zdCBudW1lcmF0b3IgPSBhLmRlcGxveVRpbWVGYWlsdXJlcyArIHBvc3REZXBsb3lGYWlsdXJlcztcbiAgICAgICAgLy8gQ2xhbXAgdG8gWzAsMTAwXTogcG9zdC1kZXBsb3kgZmFpbHVyZXMgY2FuIGNvcnJlbGF0ZSB0byBhIGRlcGxveSB0aGF0XG4gICAgICAgIC8vIGNvbXBsZXRlZCBqdXN0IGJlZm9yZSB0aGUgd2luZG93IChrZXB0IGZvciBjb3JyZWxhdGlvbiksIHNvIHRoZSBudW1lcmF0b3JcbiAgICAgICAgLy8gY2FuIHRyYW5zaWVudGx5IGV4Y2VlZCBpbi13aW5kb3cgYXR0ZW1wdHMg4oCUIGEgQ0ZSID4gMTAwJSBpcyBuZXZlciB2YWxpZC5cbiAgICAgICAgY29uc3QgcmF3UmF0ZSA9IGEuYXR0ZW1wdHMgPiAwID8gTWF0aC5taW4oMTAwLCAobnVtZXJhdG9yIC8gYS5hdHRlbXB0cykgKiAxMDApIDogMDtcbiAgICAgICAgY29uc3QgbHRNZWRpYW4gPSBtZWRpYW4oYS5sZWFkR2Fwcyk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgZW52aXJvbm1lbnQsXG4gICAgICAgICAgZGVwbG95bWVudEZyZXF1ZW5jeToge1xuICAgICAgICAgICAgZGVwbG95bWVudHM6IGEuZGVwbG95bWVudHMsXG4gICAgICAgICAgICBwZXJEYXk6IHJvdW5kKHJhd1BlckRheSwgMiksXG4gICAgICAgICAgICBsZXZlbDogZG9yYUxldmVsRm9yRnJlcXVlbmN5KHJhd1BlckRheSwgYS5kZXBsb3ltZW50cyksXG4gICAgICAgICAgfSxcbiAgICAgICAgICBjaGFuZ2VGYWlsdXJlUmF0ZToge1xuICAgICAgICAgICAgcmF0ZTogcm91bmQocmF3UmF0ZSwgMSksXG4gICAgICAgICAgICBkZXBsb3lUaW1lRmFpbHVyZXM6IGEuZGVwbG95VGltZUZhaWx1cmVzLFxuICAgICAgICAgICAgcG9zdERlcGxveUZhaWx1cmVzLFxuICAgICAgICAgICAgYXR0ZW1wdHM6IGEuYXR0ZW1wdHMsXG4gICAgICAgICAgICBsZXZlbDogZG9yYUxldmVsRm9yQ2hhbmdlRmFpbHVyZShyYXdSYXRlLCBhLmF0dGVtcHRzKSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGxlYWRUaW1lOiB7XG4gICAgICAgICAgICBkZXBsb3ltZW50czogYS5sZWFkR2Fwcy5sZW5ndGgsXG4gICAgICAgICAgICBtZWRpYW5TZWNvbmRzOiBsdE1lZGlhbiAhPSBudWxsID8gcm91bmQobHRNZWRpYW4sIDEpIDogbnVsbCxcbiAgICAgICAgICAgIGxldmVsOiBkb3JhTGV2ZWxGb3JMZWFkVGltZShsdE1lZGlhbiksXG4gICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICAgIH0pXG4gICAgICAuc29ydCgoeCwgeSkgPT4ge1xuICAgICAgICBpZiAoeC5lbnZpcm9ubWVudCA9PT0gSEVBRExJTkVfRU5WKSByZXR1cm4gLTE7XG4gICAgICAgIGlmICh5LmVudmlyb25tZW50ID09PSBIRUFETElORV9FTlYpIHJldHVybiAxO1xuICAgICAgICByZXR1cm4geC5lbnZpcm9ubWVudC5sb2NhbGVDb21wYXJlKHkuZW52aXJvbm1lbnQpO1xuICAgICAgfSk7XG5cbiAgICAvLyBNVFRSIOKAlCBQUk9EVUNUSU9OLU9OTFksIGZyb20gQk9USCBzb3VyY2VzLiBJbmNpZGVudHMgdGFrZSBwcmVjZWRlbmNlOiBhXG4gICAgLy8gcHJvZHVjdGlvbiBpbmNpZGVudCBjb3JyZWxhdGVkIHRvIGEgZGVwbG95IGNvbnRyaWJ1dGVzIHRoZSByZWFsIHJlY292ZXJ5XG4gICAgLy8gKGByZXNvbHZlZF9hdCDiiJIgb3BlbmVkX2F0YCksIGFuZCBhbnkgbWFudWFsIG91dGNvbWUgb24gdGhlIFNBTUUgZGVwbG95IGlzXG4gICAgLy8gc2tpcHBlZC4gTWFudWFsIG91dGNvbWVzIG9uIG90aGVyIGRlcGxveXMga2VlcCB0aGUgUGhhc2UtMiBiZWhhdmlvclxuICAgIC8vIChgZmFpbGVkYCDihpIgYW4gaW5jaWRlbnQ7IGByZXN0b3JlZGAg4oaSIGEgcmVjb3ZlcnkgZ2FwIG9mIGByZXN0b3JlZCDiiJIgZGVwbG95ZWRgKS5cbiAgICBsZXQgaW5jaWRlbnRzID0gMCwgcmVzdG9yZWQgPSAwO1xuICAgIGNvbnN0IG10dHJHYXBzOiBudW1iZXJbXSA9IFtdO1xuICAgIC8vIEV4ZWN1dGlvbnMgYWxyZWFkeSBhdHRyaWJ1dGVkIHRvIGEgcHJvZHVjdGlvbiBpbmNpZGVudCAocHJlY2VkZW5jZSBndWFyZCkuXG4gICAgY29uc3QgaW5jaWRlbnRFeGVjcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgIGZvciAoY29uc3QgY2kgb2YgY29ycmVsYXRlZEluY2lkZW50cykge1xuICAgICAgaWYgKGNpLmVudmlyb25tZW50ICE9PSBIRUFETElORV9FTlYpIGNvbnRpbnVlOyAvLyBNVFRSIGlzIHByb2R1Y3Rpb24tb25seVxuICAgICAgaW5jaWRlbnRzKys7XG4gICAgICBpbmNpZGVudEV4ZWNzLmFkZChjaS5leGVjKTtcbiAgICAgIGlmIChjaS5yZXNvbHZlZEdhcCAhPSBudWxsKSB7IHJlc3RvcmVkKys7IG10dHJHYXBzLnB1c2goY2kucmVzb2x2ZWRHYXApOyB9XG4gICAgfVxuICAgIGZvciAoY29uc3QgbSBvZiBtdHRyUm93cykge1xuICAgICAgLy8gSW5jaWRlbnQgcHJlY2VkZW5jZTogZG9uJ3QgZG91YmxlLWNvdW50IGEgZGVwbG95IGFscmVhZHkgZmxhZ2dlZCBieSBhbiBpbmNpZGVudC5cbiAgICAgIGlmIChtLmV4ZWN1dGlvbl9pZCAhPSBudWxsICYmIGluY2lkZW50RXhlY3MuaGFzKG0uZXhlY3V0aW9uX2lkKSkgY29udGludWU7XG4gICAgICBpZiAobS5vdXRjb21lID09PSAnZmFpbGVkJykgeyBpbmNpZGVudHMrKzsgY29udGludWU7IH1cbiAgICAgIGlmIChtLm91dGNvbWUgPT09ICdyZXN0b3JlZCcpIHtcbiAgICAgICAgcmVzdG9yZWQrKztcbiAgICAgICAgaWYgKG0ucmVzdG9yZWRfYXQgIT0gbnVsbCAmJiBtLmRlcGxveWVkX2F0ICE9IG51bGwpIHtcbiAgICAgICAgICBjb25zdCBnYXAgPSAoRGF0ZS5wYXJzZShtLnJlc3RvcmVkX2F0KSAtIERhdGUucGFyc2UobS5kZXBsb3llZF9hdCkpIC8gMTAwMDtcbiAgICAgICAgICBpZiAoTnVtYmVyLmlzRmluaXRlKGdhcCkpIG10dHJHYXBzLnB1c2goTWF0aC5tYXgoZ2FwLCAwKSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgY29uc3QgbXR0ck1lZGlhbiA9IG1lZGlhbihtdHRyR2Fwcyk7XG5cbiAgICBjb25zdCByZWdpc3RlcmVkID0gTnVtYmVyKGNvdmVyYWdlUm93Py5yZWdpc3RlcmVkKSB8fCAwO1xuICAgIGNvbnN0IGRlcGxveWluZyA9IE51bWJlcihjb3ZlcmFnZVJvdz8uZGVwbG95aW5nKSB8fCAwO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIHdpbmRvdzogeyBmcm9tLCB0byB9LFxuICAgICAgZmlsdGVyczogeyBwaXBlbGluZUlkOiBmaWx0ZXJzLnBpcGVsaW5lSWQgPz8gbnVsbCwgZW52aXJvbm1lbnQ6IGZpbHRlcnMuZW52aXJvbm1lbnQgPz8gbnVsbCB9LFxuICAgICAgaGVhZGxpbmU6IEhFQURMSU5FX0VOVixcbiAgICAgIGVudmlyb25tZW50cyxcbiAgICAgIG1lYW5UaW1lVG9SZXN0b3JlOiB7XG4gICAgICAgIGluY2lkZW50cyxcbiAgICAgICAgcmVzdG9yZWQsXG4gICAgICAgIG1lZGlhblNlY29uZHM6IG10dHJNZWRpYW4gIT0gbnVsbCA/IHJvdW5kKG10dHJNZWRpYW4sIDEpIDogbnVsbCxcbiAgICAgICAgbGV2ZWw6IGRvcmFMZXZlbEZvclJlc3RvcmUobXR0ck1lZGlhbiksXG4gICAgICB9LFxuICAgICAgY292ZXJhZ2U6IHtcbiAgICAgICAgcmVnaXN0ZXJlZCxcbiAgICAgICAgZGVwbG95aW5nLFxuICAgICAgICB3aXRob3V0RGVwbG95czogTWF0aC5tYXgocmVnaXN0ZXJlZCAtIGRlcGxveWluZywgMCksXG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogMS45YiBET1JBIHRyZW5kIOKAlCBkZXBsb3ltZW50IGZyZXF1ZW5jeSArIGRlcGxveS10aW1lIGNoYW5nZS1mYWlsdXJlIHJhdGVcbiAgICogYnVja2V0ZWQgYnkgYGludGVydmFsYCAoZGF5L3dlZWsvbW9udGgpIGZvciBhIHNwYXJrbGluZS4gRGVwbG95LWJhc2lzIGxpa2VcbiAgICogZ2V0RG9yYU1ldHJpY3M6IGJ1Y2tldHMgdGVybWluYWwgZGVwbG95LXN0YWdlIGV4ZWN1dGlvbnMgb24gdGhlaXJcbiAgICogYGNvbXBsZXRlZF9hdGAuIFNoYXJlcyB0aGUgb3JnL3JvbGx1cCArIHBpcGVsaW5lSWQvZW52aXJvbm1lbnQgc2NvcGluZy4gTVRUUixcbiAgICogbGVhZCB0aW1lLCBhbmQgcG9zdC1kZXBsb3kgQ0ZSIGFyZSBpbnRlbnRpb25hbGx5IG9taXR0ZWQgKHRvbyBoZWF2eSB0byBidWNrZXQpLlxuICAgKi9cbiAgYXN5bmMgZ2V0RG9yYVRyZW5kKFxuICAgIG9yZ0lkOiBzdHJpbmcsXG4gICAgaW50ZXJ2YWw6IHN0cmluZyxcbiAgICBmcm9tOiBzdHJpbmcsXG4gICAgdG86IHN0cmluZyxcbiAgICBvcmdJZHM/OiBzdHJpbmdbXSxcbiAgICBvcHRzOiBEb3JhT3B0aW9ucyA9IHt9LFxuICApOiBQcm9taXNlPERvcmFUcmVuZFBvaW50W10+IHtcbiAgICBhc3NlcnRSZXBvcnRJbnRlcnZhbChpbnRlcnZhbCk7XG4gICAgY29uc3QgeyBwcmVkLCBtdWx0aSB9ID0gdGhpcy5vcmdTY29wZShvcmdJZCwgb3JnSWRzKTtcbiAgICBjb25zdCB7IHBpcGVsaW5lSWQsIGVudmlyb25tZW50IH0gPSBvcHRzO1xuICAgIGNvbnN0IHBpcGVsaW5lQ2xhdXNlID0gcGlwZWxpbmVJZCA/IHNxbGBBTkQgZS5waXBlbGluZV9pZCA9ICR7cGlwZWxpbmVJZH1gIDogc3FsYGA7XG4gICAgY29uc3QgZW52Q2xhdXNlID0gZW52aXJvbm1lbnQgPyBzcWxgQU5EIGUuZW52aXJvbm1lbnQgPSAke2Vudmlyb25tZW50fWAgOiBzcWxgYDtcbiAgICBjb25zdCBleGVjID0gKCkgPT4gd2l0aFRlbmFudFR4KCh0eCkgPT4gdHguZXhlY3V0ZShzcWxgXG4gICAgICAgIFdJVEggZGVwbG95cyBBUyAoXG4gICAgICAgICAgLS0gUEVSLUVYRUNVVElPTiBkZXBsb3kgdW5pdCAoRDEpOiBvbmUgcm93IHBlciAoZW52aXJvbm1lbnQsIGV4ZWN1dGlvbiksXG4gICAgICAgICAgLS0gZXZlcnkgZGVwbG95IFNUQUdFIHRvIHRoYXQgZW52IHdpdGhpbiB0aGUgZXhlY3V0aW9uIHJvbGxlZCB1cCB0byBhXG4gICAgICAgICAgLS0gc2luZ2xlIHRlcm1pbmFsIHN0YXR1cyDigJQgTk9UIG9uZSByb3cgcGVyIHN0YWdlLlxuICAgICAgICAgIFNFTEVDVFxuICAgICAgICAgICAgJHt0ZXJtaW5hbFN0YXR1c1JvbGx1cH0gQVMgc3RhdHVzLFxuICAgICAgICAgICAgTUFYKGUuY29tcGxldGVkX2F0KSBBUyBjb21wbGV0ZWRfYXRcbiAgICAgICAgICBGUk9NICR7c2NoZW1hLnBpcGVsaW5lRXZlbnR9IGVcbiAgICAgICAgICBKT0lOICR7c2NoZW1hLnBpcGVsaW5lfSBwIE9OIHAuaWQgPSBlLnBpcGVsaW5lX2lkXG4gICAgICAgICAgV0hFUkUgcC5vcmdfaWQgJHtwcmVkfSBBTkQgZS5ldmVudF90eXBlID0gJ1NUQUdFJyBBTkQgZS5lbnZpcm9ubWVudCBJUyBOT1QgTlVMTFxuICAgICAgICAgICAgJHtwaXBlbGluZUNsYXVzZX0gJHtlbnZDbGF1c2V9XG4gICAgICAgICAgICBBTkQgZS5jb21wbGV0ZWRfYXQgPj0gJHtmcm9tfTo6dGltZXN0YW1wdHogQU5EIGUuY29tcGxldGVkX2F0IDw9ICR7dG99Ojp0aW1lc3RhbXB0elxuICAgICAgICAgIEdST1VQIEJZIGUuZW52aXJvbm1lbnQsIGUuZXhlY3V0aW9uX2lkXG4gICAgICAgIClcbiAgICAgICAgU0VMRUNUXG4gICAgICAgICAgREFURV9UUlVOQygke2ludGVydmFsfSwgY29tcGxldGVkX2F0KTo6dGV4dCBBUyBwZXJpb2QsXG4gICAgICAgICAgQ09VTlQoKikgRklMVEVSIChXSEVSRSBzdGF0dXMgPSAnU1VDQ0VFREVEJyk6OmludCBBUyBkZXBsb3ltZW50cyxcbiAgICAgICAgICBDT1VOVCgqKSBGSUxURVIgKFdIRVJFIHN0YXR1cyA9ICdGQUlMRUQnKTo6aW50IEFTIGZhaWxlZCxcbiAgICAgICAgICBDT1VOVCgqKSBGSUxURVIgKFdIRVJFIHN0YXR1cyBJTiAoJ1NVQ0NFRURFRCcsICdGQUlMRUQnKSk6OmludCBBUyB0b3RhbCxcbiAgICAgICAgICAtLSBxdW90ZWQgYWxpYXMgc28gdGhlIHJhdyByb3cga2V5IGlzIGV4YWN0bHkgdGhlIERvcmFUcmVuZFBvaW50IGZpZWxkXG4gICAgICAgICAgQ09BTEVTQ0UoUk9VTkQoQ09VTlQoKikgRklMVEVSIChXSEVSRSBzdGF0dXMgPSAnRkFJTEVEJyk6Om51bWVyaWNcbiAgICAgICAgICAgIC8gTlVMTElGKENPVU5UKCopIEZJTFRFUiAoV0hFUkUgc3RhdHVzIElOICgnU1VDQ0VFREVEJywgJ0ZBSUxFRCcpKSwgMCkgKiAxMDAsIDEpLCAwKTo6ZmxvYXQgQVMgXCJjaGFuZ2VGYWlsdXJlUGN0XCJcbiAgICAgICAgRlJPTSBkZXBsb3lzXG4gICAgICAgIEdST1VQIEJZIHBlcmlvZCBPUkRFUiBCWSBwZXJpb2RcbiAgICAgIGApLnRoZW4ociA9PiBkcml6emxlUm93czxEb3JhVHJlbmRQb2ludD4oci5yb3dzKSkpO1xuICAgIGNvbnN0IGtleSA9IGAke29yZ0lkfTpkb3JhLXRyZW5kOiR7aW50ZXJ2YWx9OiR7ZnJvbX06JHt0b306JHtwaXBlbGluZUlkID8/ICcnfToke2Vudmlyb25tZW50ID8/ICcnfWA7XG4gICAgcmV0dXJuIHRoaXMucnVuUmVwb3J0KGtleSwgbXVsdGksIGV4ZWMpO1xuICB9XG5cbiAgLyoqXG4gICAqIDEuMTAgUGVyLXBpcGVsaW5lIEJVSUxEIEhFQUxUSCAoUGhhc2UgNikg4oCUIGEgc3RhbmRhcmQgKE5PVCBgYWR2YW5jZWRfcmVwb3J0aW5nYClcbiAgICogcGVyLXN0YWdlIGJyZWFrZG93biBmb3Igb25lIHBpcGVsaW5lIG92ZXIgYSBbZnJvbSx0b10gd2luZG93LiBBZ2dyZWdhdGVzIHRoZVxuICAgKiBleGlzdGluZyBgcGlwZWxpbmVfZXZlbnRzYCBTVEFHRSByb3dzOiBlYWNoIHN0YWdlIGlzIHJvbGxlZCB1cCBwZXIgZXhlY3V0aW9uXG4gICAqIHRvIGEgdGVybWluYWwgc3RhdHVzIChGQUlMRUQgd2lucywgdGhlbiBTVUNDRUVERUQpICsgaXRzIG1heCBkdXJhdGlvbiwgdGhlblxuICAgKiBncm91cGVkIHBlciBzdGFnZSBpbnRvIHJ1bi9zdWNjZXNzL2ZhaWx1cmUgY291bnRzLCBhIHN1Y2Nlc3MgcmF0ZSwgYW5kXG4gICAqIGR1cmF0aW9uIHBlcmNlbnRpbGVzIChwNTAvcDkwL3A5OSkuIFRvdGFscyBzdW0gYWNyb3NzIHN0YWdlcy4gT3JnLXNjb3BlZCB2aWFcbiAgICogdGhlIHBpcGVsaW5lIGpvaW4gKGBwLm9yZ19pZCAke3ByZWR9YCkgKyByb2xsdXAtYXdhcmUgbGlrZSB0aGUgc2libGluZyByZXBvcnRzO1xuICAgKiBhIHBpcGVsaW5lSWQgb3duZWQgYnkgYW5vdGhlciBvcmcgcmV0dXJucyBhbiBlbXB0eSBicmVha2Rvd24uXG4gICAqL1xuICBhc3luYyBnZXRCdWlsZEhlYWx0aChcbiAgICBvcmdJZDogc3RyaW5nLFxuICAgIHBpcGVsaW5lSWQ6IHN0cmluZyxcbiAgICBmcm9tOiBzdHJpbmcsXG4gICAgdG86IHN0cmluZyxcbiAgICBvcmdJZHM/OiBzdHJpbmdbXSxcbiAgKTogUHJvbWlzZTxCdWlsZEhlYWx0aD4ge1xuICAgIGNvbnN0IHsgcHJlZCwgbXVsdGkgfSA9IHRoaXMub3JnU2NvcGUob3JnSWQsIG9yZ0lkcyk7XG4gICAgY29uc3QgZXhlYyA9ICgpID0+IHdpdGhUZW5hbnRUeChhc3luYyAodHgpID0+IHtcbiAgICAgIGNvbnN0IHJvd3MgPSBkcml6emxlUm93czxCdWlsZEhlYWx0aFN0YWdlPigoYXdhaXQgdHguZXhlY3V0ZShzcWxgXG4gICAgICAgIFdJVEggc3RhZ2VfcnVucyBBUyAoXG4gICAgICAgICAgU0VMRUNUXG4gICAgICAgICAgICBlLnN0YWdlX25hbWUgQVMgc3RhZ2UsXG4gICAgICAgICAgICAke3Rlcm1pbmFsU3RhdHVzUm9sbHVwfSBBUyBzdGF0dXMsXG4gICAgICAgICAgICBNQVgoZS5kdXJhdGlvbl9tcykgQVMgZHVyYXRpb25fbXNcbiAgICAgICAgICBGUk9NICR7c2NoZW1hLnBpcGVsaW5lRXZlbnR9IGVcbiAgICAgICAgICBKT0lOICR7c2NoZW1hLnBpcGVsaW5lfSBwIE9OIHAuaWQgPSBlLnBpcGVsaW5lX2lkXG4gICAgICAgICAgV0hFUkUgcC5vcmdfaWQgJHtwcmVkfSBBTkQgZS5waXBlbGluZV9pZCA9ICR7cGlwZWxpbmVJZH1cbiAgICAgICAgICAgIEFORCBlLmV2ZW50X3R5cGUgPSAnU1RBR0UnIEFORCBlLnN0YWdlX25hbWUgSVMgTk9UIE5VTExcbiAgICAgICAgICAgIEFORCBlLnN0YXJ0ZWRfYXQgPj0gJHtmcm9tfTo6dGltZXN0YW1wdHogQU5EIGUuc3RhcnRlZF9hdCA8PSAke3RvfTo6dGltZXN0YW1wdHpcbiAgICAgICAgICBHUk9VUCBCWSBlLnN0YWdlX25hbWUsIGUuZXhlY3V0aW9uX2lkXG4gICAgICAgIClcbiAgICAgICAgU0VMRUNUXG4gICAgICAgICAgc3RhZ2UsXG4gICAgICAgICAgQ09VTlQoKik6OmludCBBUyBydW5zLFxuICAgICAgICAgIENPVU5UKCopIEZJTFRFUiAoV0hFUkUgc3RhdHVzID0gJ1NVQ0NFRURFRCcpOjppbnQgQVMgc3VjY2Vzc2VzLFxuICAgICAgICAgIENPVU5UKCopIEZJTFRFUiAoV0hFUkUgc3RhdHVzID0gJ0ZBSUxFRCcpOjppbnQgQVMgZmFpbHVyZXMsXG4gICAgICAgICAgQ09BTEVTQ0UoUk9VTkQoQ09VTlQoKikgRklMVEVSIChXSEVSRSBzdGF0dXMgPSAnU1VDQ0VFREVEJyk6Om51bWVyaWNcbiAgICAgICAgICAgIC8gTlVMTElGKENPVU5UKCopLCAwKSAqIDEwMCwgMSksIDApOjpmbG9hdCBBUyBcInN1Y2Nlc3NSYXRlXCIsXG4gICAgICAgICAgUEVSQ0VOVElMRV9DT05UKDAuNSkgV0lUSElOIEdST1VQIChPUkRFUiBCWSBkdXJhdGlvbl9tcyk6OmludCBBUyBcInA1ME1zXCIsXG4gICAgICAgICAgUEVSQ0VOVElMRV9DT05UKDAuOSkgV0lUSElOIEdST1VQIChPUkRFUiBCWSBkdXJhdGlvbl9tcyk6OmludCBBUyBcInA5ME1zXCIsXG4gICAgICAgICAgUEVSQ0VOVElMRV9DT05UKDAuOTkpIFdJVEhJTiBHUk9VUCAoT1JERVIgQlkgZHVyYXRpb25fbXMpOjppbnQgQVMgXCJwOTlNc1wiXG4gICAgICAgIEZST00gc3RhZ2VfcnVuc1xuICAgICAgICBXSEVSRSBzdGF0dXMgSU4gKCdTVUNDRUVERUQnLCAnRkFJTEVEJylcbiAgICAgICAgR1JPVVAgQlkgc3RhZ2VcbiAgICAgICAgT1JERVIgQlkgcnVucyBERVNDLCBzdGFnZVxuICAgICAgYCkpLnJvd3MpO1xuXG4gICAgICAvLyBUb3RhbHMgc3VtIGFjcm9zcyBzdGFnZXMgKHRvdGFsIHN0YWdlLXJ1bnMgLyBzdGFnZS1mYWlsdXJlcyBpbiB0aGUgd2luZG93KS5cbiAgICAgIGxldCBydW5zID0gMCwgZmFpbHVyZXMgPSAwO1xuICAgICAgZm9yIChjb25zdCBzIG9mIHJvd3MpIHsgcnVucyArPSBzLnJ1bnM7IGZhaWx1cmVzICs9IHMuZmFpbHVyZXM7IH1cbiAgICAgIGNvbnN0IGZhaWx1cmVSYXRlID0gcnVucyA+IDAgPyByb3VuZCgoZmFpbHVyZXMgLyBydW5zKSAqIDEwMCwgMSkgOiAwO1xuICAgICAgcmV0dXJuIHsgc3RhZ2VzOiByb3dzLCB0b3RhbHM6IHsgcnVucywgZmFpbHVyZXMsIGZhaWx1cmVSYXRlIH0gfTtcbiAgICB9KTtcbiAgICByZXR1cm4gdGhpcy5ydW5SZXBvcnQoYCR7b3JnSWR9OmJ1aWxkLWhlYWx0aDoke3BpcGVsaW5lSWR9OiR7ZnJvbX06JHt0b31gLCBtdWx0aSwgZXhlYyk7XG4gIH1cblxuICAvLyDilIDilIAgQ2F0ZWdvcnkgMjogUGx1Z2luIEludmVudG9yeSAmIEJ1aWxkcyDilIDilIBcblxuICAvKiogMi4xIFBsdWdpbiBzdW1tYXJ5IOKAlCBjb3VudHMgYW5kIGJyZWFrZG93bnMuXG4gICAqICBJTlRFTlRJT05BTExZIFNJTkdMRS1PUkcgKG5vIHJvbGx1cCk6IHBsdWdpbiBpbnZlbnRvcnkgaXMgYW4gb3JnLW93bmVkXG4gICAqICBhc3NldCBjb3VudCwgbm90IGFuIGV4ZWN1dGlvbi9idWlsZCBhY3Rpdml0eSByZXBvcnQsIHNvIGEgcGFyZW50J3MgdmlldyBpc1xuICAgKiAgaXRzIG93biBwbHVnaW5zIOKAlCB0ZWFtcyBtYW5hZ2UgdGhlaXIgb3duIGludmVudG9yeS4gU2luZ2xlIGA9ICRvcmdgIHNjb3BlLiAqL1xuICBhc3luYyBnZXRQbHVnaW5TdW1tYXJ5KG9yZ0lkOiBzdHJpbmcpOiBQcm9taXNlPFBsdWdpblN1bW1hcnk+IHtcbiAgICByZXR1cm4gaW52ZW50b3J5Q2FjaGUuZ2V0T3JTZXQoYCR7b3JnSWR9OnBsdWdpbi1zdW1tYXJ5YCwgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3Qgcm93cyA9IGF3YWl0IHdpdGhUZW5hbnRUeCgodHgpID0+IHR4LmV4ZWN1dGUoc3FsYFxuICAgICAgICBTRUxFQ1RcbiAgICAgICAgICBDT1VOVCgqKTo6aW50IEFTIHRvdGFsLFxuICAgICAgICAgIENPVU5UKCopIEZJTFRFUiAoV0hFUkUgJHtzY2hlbWEucGx1Z2luLmlzQWN0aXZlfSk6OmludCBBUyBhY3RpdmUsXG4gICAgICAgICAgQ09VTlQoKikgRklMVEVSIChXSEVSRSBOT1QgJHtzY2hlbWEucGx1Z2luLmlzQWN0aXZlfSk6OmludCBBUyBpbmFjdGl2ZSxcbiAgICAgICAgICBDT1VOVCgqKSBGSUxURVIgKFdIRVJFICR7c2NoZW1hLnBsdWdpbi52aXNpYmlsaXR5fSA9ICdwdWJsaWMnKTo6aW50IEFTIHB1YmxpYyxcbiAgICAgICAgICBDT1VOVCgqKSBGSUxURVIgKFdIRVJFICR7c2NoZW1hLnBsdWdpbi52aXNpYmlsaXR5fSA9ICdvcmcnKTo6aW50IEFTIG9yZyxcbiAgICAgICAgICBDT1VOVCgqKSBGSUxURVIgKFdIRVJFICR7c2NoZW1hLnBsdWdpbi52aXNpYmlsaXR5fSA9ICdwcml2YXRlJyk6OmludCBBUyBwcml2YXRlLFxuICAgICAgICAgIENPVU5UKERJU1RJTkNUICR7c2NoZW1hLnBsdWdpbi5uYW1lfSk6OmludCBBUyB1bmlxdWVfbmFtZXNcbiAgICAgICAgRlJPTSAke3NjaGVtYS5wbHVnaW59XG4gICAgICAgIFdIRVJFICR7c2NoZW1hLnBsdWdpbi5vcmdJZH0gPSAke29yZ0lkfVxuICAgICAgYCkpO1xuICAgICAgcmV0dXJuIChkcml6emxlUm93czxQbHVnaW5TdW1tYXJ5Pihyb3dzLnJvd3MpWzBdIHx8IHsgdG90YWw6IDAsIGFjdGl2ZTogMCwgaW5hY3RpdmU6IDAsIHB1YmxpYzogMCwgb3JnOiAwLCBwcml2YXRlOiAwLCB1bmlxdWVOYW1lczogMCB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKiAyLjIgVHlwZSAmIGNvbXB1dGUgZGlzdHJpYnV0aW9uLlxuICAgKiAgSU5URU5USU9OQUxMWSBTSU5HTEUtT1JHIChubyByb2xsdXApOiBwbHVnaW4gaW52ZW50b3J5IGlzIHBlci1vcmcgKHNlZVxuICAgKiAgZ2V0UGx1Z2luU3VtbWFyeSkuIFNpbmdsZSBgPSAkb3JnYCBzY29wZS4gKi9cbiAgYXN5bmMgZ2V0UGx1Z2luRGlzdHJpYnV0aW9uKG9yZ0lkOiBzdHJpbmcpOiBQcm9taXNlPFR5cGVDb21wdXRlRGlzdHJpYnV0aW9uW10+IHtcbiAgICByZXR1cm4gaW52ZW50b3J5Q2FjaGUuZ2V0T3JTZXQoYCR7b3JnSWR9OnBsdWdpbi1kaXN0cmlidXRpb25gLCAoKSA9PlxuICAgICAgd2l0aFRlbmFudFR4KCh0eCkgPT4gdHguZXhlY3V0ZShzcWxgXG4gICAgICAgIFNFTEVDVFxuICAgICAgICAgICR7c2NoZW1hLnBsdWdpbi5wbHVnaW5UeXBlfSBBUyBwbHVnaW5fdHlwZSxcbiAgICAgICAgICAke3NjaGVtYS5wbHVnaW4uY29tcHV0ZVR5cGV9IEFTIGNvbXB1dGVfdHlwZSxcbiAgICAgICAgICBDT1VOVCgqKTo6aW50IEFTIGNvdW50XG4gICAgICAgIEZST00gJHtzY2hlbWEucGx1Z2lufVxuICAgICAgICBXSEVSRSAke3NjaGVtYS5wbHVnaW4ub3JnSWR9ID0gJHtvcmdJZH0gQU5EICR7c2NoZW1hLnBsdWdpbi5pc0FjdGl2ZX0gPSB0cnVlXG4gICAgICAgIEdST1VQIEJZICR7c2NoZW1hLnBsdWdpbi5wbHVnaW5UeXBlfSwgJHtzY2hlbWEucGx1Z2luLmNvbXB1dGVUeXBlfVxuICAgICAgICBPUkRFUiBCWSBjb3VudCBERVNDXG4gICAgICBgKS50aGVuKHIgPT4gZHJpenpsZVJvd3M8VHlwZUNvbXB1dGVEaXN0cmlidXRpb24+KHIucm93cykpKSxcbiAgICApO1xuICB9XG5cbiAgLyoqIDIuMyBWZXJzaW9uIGNvdW50cyBwZXIgcGx1Z2luIG5hbWUuXG4gICAqICBJTlRFTlRJT05BTExZIFNJTkdMRS1PUkcgKG5vIHJvbGx1cCk6IHBsdWdpbiBpbnZlbnRvcnkgaXMgcGVyLW9yZyAoc2VlXG4gICAqICBnZXRQbHVnaW5TdW1tYXJ5KS4gU2luZ2xlIGA9ICRvcmdgIHNjb3BlLiAqL1xuICBhc3luYyBnZXRQbHVnaW5WZXJzaW9ucyhvcmdJZDogc3RyaW5nKTogUHJvbWlzZTxWZXJzaW9uQ291bnRbXT4ge1xuICAgIHJldHVybiBpbnZlbnRvcnlDYWNoZS5nZXRPclNldChgJHtvcmdJZH06cGx1Z2luLXZlcnNpb25zYCwgKCkgPT5cbiAgICAgIHdpdGhUZW5hbnRUeCgodHgpID0+IHR4LmV4ZWN1dGUoc3FsYFxuICAgICAgICBTRUxFQ1RcbiAgICAgICAgICAke3NjaGVtYS5wbHVnaW4ubmFtZX0sXG4gICAgICAgICAgQ09VTlQoKik6OmludCBBUyB2ZXJzaW9uX2NvdW50LFxuICAgICAgICAgIC0tIEhpZ2hlc3QgdmVyc2lvbiBieSBOVU1FUklDIHNlbXZlciBjb3JlIChub3QgbGV4aWNhbDogJzEwLjAuMCcgPiAnOS4wLjAnKS5cbiAgICAgICAgICAtLSBTdHJpcCBhbnkgLXByZXJlbGVhc2UvK2J1aWxkIHN1ZmZpeCBiZWZvcmUgdGhlIGludFtdIGNhc3Qgc28gaXQgY2FuJ3RcbiAgICAgICAgICAtLSBlcnJvciBvbiB2YWxpZCBzZW12ZXI7IGtlZXAgdGhlIG9yaWdpbmFsIHN0cmluZyBmb3IgZGlzcGxheS5cbiAgICAgICAgICAtLSBHVUFSRDogYSBub24tbnVtZXJpYy1kb3R0ZWQgdmVyc2lvbiAoJ2xhdGVzdCcsICcnLCAndjEnKSB3b3VsZCBtYWtlIHRoZVxuICAgICAgICAgIC0tIDo6aW50W10gY2FzdCB0aHJvdyBhbmQgYmxvdyB1cCB0aGUgV0hPTEUgb3JnIHN1bW1hcnkuIE9ubHkgY2FzdCByb3dzXG4gICAgICAgICAgLS0gd2hvc2Ugc3RyaXBwZWQgY29yZSBtYXRjaGVzIGEgbnVtZXJpYy1kb3R0ZWQgc2hhcGU7IHNvcnQgZXZlcnl0aGluZ1xuICAgICAgICAgIC0tIGVsc2UgdG8gdGhlIGJvdHRvbSB2aWEgYSBzZW50aW5lbCBBUlJBWVstMV0gc28gdGhlIHJvdyBzdGlsbCBjb3VudHMuXG4gICAgICAgICAgKGFycmF5X2FnZygke3NjaGVtYS5wbHVnaW4udmVyc2lvbn1cbiAgICAgICAgICAgICBPUkRFUiBCWSBDQVNFXG4gICAgICAgICAgICAgICBXSEVOIHJlZ2V4cF9yZXBsYWNlKCR7c2NoZW1hLnBsdWdpbi52ZXJzaW9ufSwgJ1stK10uKiQnLCAnJykgfiAnXlswLTldKyhbLl1bMC05XSspKiQnXG4gICAgICAgICAgICAgICAgIFRIRU4gc3RyaW5nX3RvX2FycmF5KHJlZ2V4cF9yZXBsYWNlKCR7c2NoZW1hLnBsdWdpbi52ZXJzaW9ufSwgJ1stK10uKiQnLCAnJyksICcuJyk6OmludFtdXG4gICAgICAgICAgICAgICBFTFNFIEFSUkFZWy0xXVxuICAgICAgICAgICAgIEVORCBERVNDXG4gICAgICAgICAgKSlbMV0gQVMgbGF0ZXN0X3ZlcnNpb24sXG4gICAgICAgICAgYm9vbF9vcigke3NjaGVtYS5wbHVnaW4uaXNEZWZhdWx0fSkgQVMgaGFzX2RlZmF1bHRcbiAgICAgICAgRlJPTSAke3NjaGVtYS5wbHVnaW59XG4gICAgICAgIFdIRVJFICR7c2NoZW1hLnBsdWdpbi5vcmdJZH0gPSAke29yZ0lkfSBBTkQgJHtzY2hlbWEucGx1Z2luLmlzQWN0aXZlfSA9IHRydWVcbiAgICAgICAgR1JPVVAgQlkgJHtzY2hlbWEucGx1Z2luLm5hbWV9XG4gICAgICAgIE9SREVSIEJZIHZlcnNpb25fY291bnQgREVTQ1xuICAgICAgYCkudGhlbihyID0+IGRyaXp6bGVSb3dzPFZlcnNpb25Db3VudD4oci5yb3dzKSkpLFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogMi40IEJ1aWxkIHN1Y2Nlc3MgcmF0ZSBvdmVyIHRpbWUuXG4gICAqXG4gICAqIFNUQVRVUyBDQVNJTkcgTk9URTogVGhpcyBxdWVyeSBmaWx0ZXJzIGJ5IGBldmVudF9zb3VyY2UgPSAncGx1Z2luLWJ1aWxkJ2BcbiAgICogYW5kIHVzZXMgbG93ZXJjYXNlIHN0YXR1cyB2YWx1ZXMgKGAnY29tcGxldGVkJ2AsIGAnZmFpbGVkJ2ApLCB3aGlsZVxuICAgKiBgZ2V0U3VjY2Vzc1JhdGVgICgxLjIpIGZpbHRlcnMgYnkgYGV2ZW50X3R5cGUgPSAnUElQRUxJTkUnYCB3aXRoXG4gICAqIHVwcGVyY2FzZSBBV1Mtc3R5bGUgc3RhdHVzZXMgKGAnU1VDQ0VFREVEJ2AsIGAnRkFJTEVEJ2AsIGAnQ0FOQ0VMRUQnYCkuXG4gICAqIFRoZSBjYXNpbmcgZHJpZnQgaXMgaW50ZW50aW9uYWwgYW5kIHRyYWNrcyB0aGUgcHJvZHVjZXI6XG4gICAqICAgLSBgcGx1Z2luLWJ1aWxkYCBldmVudHMgY29tZSBmcm9tIG91ciBvd24gYnVpbGQgcGlwZWxpbmUgKGxvd2VyY2FzZSlcbiAgICogICAtIGBQSVBFTElORWAgZXZlbnRzIGNvbWUgZnJvbSBBV1MgQ29kZVBpcGVsaW5lICh1cHBlcmNhc2UpXG4gICAqIFRoZSBpbmdlc3QgWm9kIHNjaGVtYSBhdCBhcGkvcmVwb3J0aW5nL3NyYy9yb3V0ZXMvZXZlbnQtaW5nZXN0LnRzXG4gICAqIFNIT1VMRCBlbnVtIHRoZXNlIHBlci1ldmVudFNvdXJjZSBzbyB3ZSBjYXRjaCBkcmlmdCBhdCBpbmdlc3QgcmF0aGVyXG4gICAqIHRoYW4gc2lsZW50bHkgcHJvZHVjaW5nIHplcm8gcm93cyBoZXJlLiBTZWUgZmluZGluZ3MgTjcxLlxuICAgKi9cbiAgYXN5bmMgZ2V0QnVpbGRTdWNjZXNzUmF0ZShvcmdJZDogc3RyaW5nLCBpbnRlcnZhbDogc3RyaW5nLCBmcm9tOiBzdHJpbmcsIHRvOiBzdHJpbmcsIG9yZ0lkcz86IHN0cmluZ1tdKTogUHJvbWlzZTxCdWlsZFRpbWVTZXJpZXNFbnRyeVtdPiB7XG4gICAgYXNzZXJ0UmVwb3J0SW50ZXJ2YWwoaW50ZXJ2YWwpO1xuICAgIC8vIEJ1aWxkIGFjdGl2aXR5IHJlcG9ydCDigJQgcm9sbHVwLWF3YXJlIGxpa2UgdGhlIGV4ZWN1dGlvbiByZXBvcnRzLiBUaGVzZVxuICAgIC8vIHJvd3MgYXJlIGdhdGVkIG9uIHRoZSBwaXBlbGluZV9ldmVudCBgb3JnX2lkYCBkaXJlY3RseSAobm8gcGlwZWxpbmUgam9pbiksXG4gICAgLy8gc28gYHByZWRgIGFwcGxpZXMgdG8gYGUub3JnX2lkYC5cbiAgICBjb25zdCB7IHByZWQsIG11bHRpIH0gPSB0aGlzLm9yZ1Njb3BlKG9yZ0lkLCBvcmdJZHMpO1xuICAgIGNvbnN0IGV4ZWMgPSAoKSA9PiB3aXRoVGVuYW50VHgoKHR4KSA9PiB0eC5leGVjdXRlKHNxbGBcbiAgICAgICAgU0VMRUNUXG4gICAgICAgICAgREFURV9UUlVOQygke2ludGVydmFsfSwgZS5zdGFydGVkX2F0KTo6dGV4dCBBUyBwZXJpb2QsXG4gICAgICAgICAgQ09VTlQoKikgRklMVEVSIChXSEVSRSBlLnN0YXR1cyA9ICdjb21wbGV0ZWQnKTo6aW50IEFTIHN1Y2NlZWRlZCxcbiAgICAgICAgICBDT1VOVCgqKSBGSUxURVIgKFdIRVJFIGUuc3RhdHVzID0gJ2ZhaWxlZCcpOjppbnQgQVMgZmFpbGVkLFxuICAgICAgICAgIFJPVU5EKENPVU5UKCopIEZJTFRFUiAoV0hFUkUgZS5zdGF0dXMgPSAnY29tcGxldGVkJyk6Om51bWVyaWNcbiAgICAgICAgICAgIC8gTlVMTElGKENPVU5UKCopLCAwKSAqIDEwMCwgMSk6OmZsb2F0IEFTIHN1Y2Nlc3NfcGN0XG4gICAgICAgIEZST00gJHtzY2hlbWEucGlwZWxpbmVFdmVudH0gZVxuICAgICAgICBXSEVSRSBlLm9yZ19pZCAke3ByZWR9IEFORCBlLmV2ZW50X3NvdXJjZSA9ICdwbHVnaW4tYnVpbGQnXG4gICAgICAgICAgQU5EIGUuc3RhdHVzIElOICgnY29tcGxldGVkJywgJ2ZhaWxlZCcpXG4gICAgICAgICAgQU5EIGUuc3RhcnRlZF9hdCA+PSAke2Zyb219Ojp0aW1lc3RhbXB0eiBBTkQgZS5zdGFydGVkX2F0IDw9ICR7dG99Ojp0aW1lc3RhbXB0elxuICAgICAgICBHUk9VUCBCWSBwZXJpb2QgT1JERVIgQlkgcGVyaW9kXG4gICAgICBgKS50aGVuKHIgPT4gZHJpenpsZVJvd3M8QnVpbGRUaW1lU2VyaWVzRW50cnk+KHIucm93cykpKTtcbiAgICByZXR1cm4gdGhpcy5ydW5SZXBvcnQoYCR7b3JnSWR9OmJ1aWxkLXN1Y2Nlc3M6JHtpbnRlcnZhbH06JHtmcm9tfToke3RvfWAsIG11bHRpLCBleGVjKTtcbiAgfVxuXG4gIC8qKiAyLjUgQnVpbGQgZHVyYXRpb24gcGVyIHBsdWdpbi4gQnVpbGQgYWN0aXZpdHkgcmVwb3J0IOKAlCByb2xsdXAtYXdhcmUuICovXG4gIGFzeW5jIGdldEJ1aWxkRHVyYXRpb24ob3JnSWQ6IHN0cmluZywgZnJvbTogc3RyaW5nLCB0bzogc3RyaW5nLCBvcmdJZHM/OiBzdHJpbmdbXSk6IFByb21pc2U8QnVpbGREdXJhdGlvbltdPiB7XG4gICAgY29uc3QgeyBwcmVkLCBtdWx0aSB9ID0gdGhpcy5vcmdTY29wZShvcmdJZCwgb3JnSWRzKTtcbiAgICBjb25zdCBleGVjID0gKCkgPT4gd2l0aFRlbmFudFR4KCh0eCkgPT4gdHguZXhlY3V0ZShzcWxgXG4gICAgICAgIFNFTEVDVFxuICAgICAgICAgIGUuZGV0YWlsLT4+J3BsdWdpbk5hbWUnIEFTIHBsdWdpbl9uYW1lLFxuICAgICAgICAgIEFWRyhlLmR1cmF0aW9uX21zKTo6aW50IEFTIGF2Z19tcyxcbiAgICAgICAgICBNQVgoZS5kdXJhdGlvbl9tcyk6OmludCBBUyBtYXhfbXMsXG4gICAgICAgICAgQ09VTlQoKik6OmludCBBUyBidWlsZHNcbiAgICAgICAgRlJPTSAke3NjaGVtYS5waXBlbGluZUV2ZW50fSBlXG4gICAgICAgIFdIRVJFIGUub3JnX2lkICR7cHJlZH0gQU5EIGUuZXZlbnRfc291cmNlID0gJ3BsdWdpbi1idWlsZCcgQU5EIGUuZHVyYXRpb25fbXMgSVMgTk9UIE5VTExcbiAgICAgICAgICBBTkQgZS5zdGFydGVkX2F0ID49ICR7ZnJvbX06OnRpbWVzdGFtcHR6IEFORCBlLnN0YXJ0ZWRfYXQgPD0gJHt0b306OnRpbWVzdGFtcHR6XG4gICAgICAgIEdST1VQIEJZIHBsdWdpbl9uYW1lIE9SREVSIEJZIGF2Z19tcyBERVNDXG4gICAgICBgKS50aGVuKHIgPT4gZHJpenpsZVJvd3M8QnVpbGREdXJhdGlvbj4oci5yb3dzKSkpO1xuICAgIHJldHVybiB0aGlzLnJ1blJlcG9ydChgJHtvcmdJZH06YnVpbGQtZHVyYXRpb246JHtmcm9tfToke3RvfWAsIG11bHRpLCBleGVjKTtcbiAgfVxuXG4gIC8qKiAyLjYgQnVpbGQgZmFpbHVyZXMg4oCUIHRvcCBlcnJvciBtZXNzYWdlcy4gQnVpbGQgYWN0aXZpdHkgcmVwb3J0IOKAlCByb2xsdXAtYXdhcmUuICovXG4gIGFzeW5jIGdldEJ1aWxkRmFpbHVyZXMob3JnSWQ6IHN0cmluZywgZnJvbTogc3RyaW5nLCB0bzogc3RyaW5nLCBsaW1pdDogbnVtYmVyID0gMjAsIG9yZ0lkcz86IHN0cmluZ1tdKTogUHJvbWlzZTxCdWlsZEZhaWx1cmVbXT4ge1xuICAgIGNvbnN0IHsgcHJlZCwgbXVsdGkgfSA9IHRoaXMub3JnU2NvcGUob3JnSWQsIG9yZ0lkcyk7XG4gICAgY29uc3QgZXhlYyA9ICgpID0+IHdpdGhUZW5hbnRUeCgodHgpID0+IHR4LmV4ZWN1dGUoc3FsYFxuICAgICAgICBTRUxFQ1RcbiAgICAgICAgICBlLmRldGFpbC0+PidwbHVnaW5OYW1lJyBBUyBwbHVnaW5fbmFtZSxcbiAgICAgICAgICBlLmVycm9yX21lc3NhZ2UsXG4gICAgICAgICAgQ09VTlQoKik6OmludCBBUyBvY2N1cnJlbmNlcyxcbiAgICAgICAgICBNQVgoZS5zdGFydGVkX2F0KTo6dGV4dCBBUyBsYXN0X3NlZW5cbiAgICAgICAgRlJPTSAke3NjaGVtYS5waXBlbGluZUV2ZW50fSBlXG4gICAgICAgIFdIRVJFIGUub3JnX2lkICR7cHJlZH0gQU5EIGUuZXZlbnRfc291cmNlID0gJ3BsdWdpbi1idWlsZCcgQU5EIGUuc3RhdHVzID0gJ2ZhaWxlZCdcbiAgICAgICAgICBBTkQgZS5zdGFydGVkX2F0ID49ICR7ZnJvbX06OnRpbWVzdGFtcHR6IEFORCBlLnN0YXJ0ZWRfYXQgPD0gJHt0b306OnRpbWVzdGFtcHR6XG4gICAgICAgIEdST1VQIEJZIHBsdWdpbl9uYW1lLCBlLmVycm9yX21lc3NhZ2VcbiAgICAgICAgT1JERVIgQlkgb2NjdXJyZW5jZXMgREVTQ1xuICAgICAgICBMSU1JVCAke2xpbWl0fVxuICAgICAgYCkudGhlbihyID0+IGRyaXp6bGVSb3dzPEJ1aWxkRmFpbHVyZT4oci5yb3dzKSkpO1xuICAgIHJldHVybiB0aGlzLnJ1blJlcG9ydChgJHtvcmdJZH06YnVpbGQtZmFpbHVyZXM6JHtmcm9tfToke3RvfToke2xpbWl0fWAsIG11bHRpLCBleGVjKTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBDYXRlZ29yeSAzOiBET1JBIHdyaXRlIHBhdGhzIChwb3N0LWRlcGxveSBvdXRjb21lcyArIGluZ2VzdCBoZWFsdGgpIOKUgOKUgFxuXG4gIC8qKlxuICAgKiBSZWNvcmQgYSBtYW51YWwgcG9zdC1kZXBsb3kgb3V0Y29tZSBtYXJrZXIgKFBoYXNlIDIpOiBhIHVzZXIgbWFya3MgYVxuICAgKiBkZXBsb3ltZW50IGBmYWlsZWRgIChhIHByb2R1Y3Rpb24gaW5jaWRlbnQgbGlua2VkIHRvIHRoZSBkZXBsb3kpIG9yXG4gICAqIGByZXN0b3JlZGAgKHJlY292ZXJlZCkuIElkZW1wb3RlbnQg4oCUIGtleWVkIG9uIChleGVjdXRpb25faWQsIG91dGNvbWUpIHNvIGFcbiAgICogZHVwbGljYXRlIFBPU1QgcmVmcmVzaGVzIGBhdGAgcmF0aGVyIHRoYW4gZG91YmxlLWNvdW50aW5nLCB3aGlsZSBhXG4gICAqIGZhaWxlZOKGknJlc3RvcmVkIHBhaXIgc3RheXMgdHdvIHJvd3MuIEZlZWRzIHRoZSBwb3N0LWRlcGxveSBDRlIgY29tcG9uZW50IGFuZFxuICAgKiB0aGUgcmVhbCBNVFRSLiBSdW5zIHVuZGVyIHRoZSBjYWxsZXIncyBvcmcgY29udGV4dCAoUkxTIFdJVEggQ0hFQ0spLlxuICAgKi9cbiAgYXN5bmMgcmVjb3JkRGVwbG95bWVudE91dGNvbWUoXG4gICAgb3JnSWQ6IHN0cmluZyxcbiAgICBleGVjdXRpb25JZDogc3RyaW5nLFxuICAgIGlucHV0OiB7IG91dGNvbWU6ICdmYWlsZWQnIHwgJ3Jlc3RvcmVkJzsgYXQ6IHN0cmluZzsgZW52aXJvbm1lbnQ/OiBzdHJpbmcgfSxcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgcnVuV2l0aFRlbmFudENvbnRleHQoeyBvcmdJZCwgaXNTdXBlckFkbWluOiBmYWxzZSB9LCAoKSA9PlxuICAgICAgd2l0aFRlbmFudFR4KCh0eCkgPT4gdHguaW5zZXJ0KHNjaGVtYS5kZXBsb3ltZW50T3V0Y29tZSkudmFsdWVzKHtcbiAgICAgICAgZXhlY3V0aW9uSWQsXG4gICAgICAgIG9yZ0lkLFxuICAgICAgICBlbnZpcm9ubWVudDogc2NydWJPcHRpb25hbChpbnB1dC5lbnZpcm9ubWVudCksXG4gICAgICAgIG91dGNvbWU6IGlucHV0Lm91dGNvbWUsXG4gICAgICAgIGF0OiBuZXcgRGF0ZShpbnB1dC5hdCksXG4gICAgICB9KS5vbkNvbmZsaWN0RG9VcGRhdGUoe1xuICAgICAgICB0YXJnZXQ6IFtzY2hlbWEuZGVwbG95bWVudE91dGNvbWUuZXhlY3V0aW9uSWQsIHNjaGVtYS5kZXBsb3ltZW50T3V0Y29tZS5vdXRjb21lXSxcbiAgICAgICAgc2V0OiB7XG4gICAgICAgICAgYXQ6IG5ldyBEYXRlKGlucHV0LmF0KSxcbiAgICAgICAgICBlbnZpcm9ubWVudDogc2NydWJPcHRpb25hbChpbnB1dC5lbnZpcm9ubWVudCkgPz8gbnVsbCxcbiAgICAgICAgfSxcbiAgICAgIH0pKSxcbiAgICApO1xuICAgIC8vIE91dGNvbWUgY2hhbmdlcyB0aGUgRE9SQSBhZ2dyZWdhdGUg4oCUIGRyb3AgdGhlIG9yZydzIGNhY2hlZCByZXBvcnRzLlxuICAgIGF3YWl0IHRoaXMuaW52YWxpZGF0ZU9yZyhvcmdJZCkuY2F0Y2goKGVycikgPT4ge1xuICAgICAgbG9nZ2VyLndhcm4oJ1JlcG9ydGluZyBjYWNoZSBpbnZhbGlkYXRpb24gZmFpbGVkJywgeyBvcmdJZCwgZXJyb3I6IGVycm9yTWVzc2FnZShlcnIpIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEluZ2VzdCBhIHByb2R1Y3Rpb24gaW5jaWRlbnQgKFBoYXNlIDUpIGZyb20gdGhlIG9yZydzIGluY2lkZW50IHRvb2xpbmdcbiAgICogKFBhZ2VyRHV0eSAvIERhdGFkb2cgLyBBbGVydG1hbmFnZXIgd2ViaG9vaykuIElkZW1wb3RlbnQg4oCUIGtleWVkIG9uXG4gICAqIChvcmdfaWQsIGluY2lkZW50X2lkKSBzbyBhIGxhdGVyIHJlc29sdmUgcmUtcG9zdCB1cHNlcnRzIGByZXNvbHZlZF9hdGBcbiAgICogKGFuZCByZWZyZXNoZXMgdGhlIG90aGVyIG11dGFibGUgZmllbGRzKSBpbnN0ZWFkIG9mIGluc2VydGluZyBhIGR1cGxpY2F0ZS5cbiAgICogRE9SQSBjb3JyZWxhdGVzIGVhY2ggaW5jaWRlbnQgdG8gdGhlIG1vc3QgcmVjZW50IHN1Y2Nlc3NmdWwgZGVwbG95IHRvIGl0c1xuICAgKiBgZW52aXJvbm1lbnRgLCBwcm9kdWNpbmcgYW4gYXV0b21hdGVkIHBvc3QtZGVwbG95IGZhaWx1cmUgKyBhIHJlYWwgTVRUUi5cbiAgICogUnVucyB1bmRlciB0aGUgY2FsbGVyJ3Mgb3JnIGNvbnRleHQgKFJMUyBXSVRIIENIRUNLKTsgZnJlZS1mb3JtIGZpZWxkcyBhcmVcbiAgICogQVdTLWlkIHNjcnViYmVkIGF0IHRoaXMgcGVyc2lzdGVuY2UgYm91bmRhcnkgbGlrZSB0aGUgb3RoZXIgaW5nZXN0IHBhdGhzLlxuICAgKi9cbiAgYXN5bmMgcmVjb3JkSW5jaWRlbnQob3JnSWQ6IHN0cmluZywgaW5wdXQ6IEluY2lkZW50SW5wdXQpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBpbmNpZGVudElkID0gc2NydWJBd3NJZGVudGlmaWVyc0Zyb21TdHJpbmcoaW5wdXQuaW5jaWRlbnRJZCk7XG4gICAgY29uc3QgZW52aXJvbm1lbnQgPSBzY3J1YkF3c0lkZW50aWZpZXJzRnJvbVN0cmluZyhpbnB1dC5lbnZpcm9ubWVudCk7XG4gICAgY29uc3Qgc2V2ZXJpdHkgPSBzY3J1YkF3c0lkZW50aWZpZXJzRnJvbVN0cmluZyhpbnB1dC5zZXZlcml0eSk7XG4gICAgY29uc3Qgb3BlbmVkQXQgPSBuZXcgRGF0ZShpbnB1dC5vcGVuZWRBdCk7XG4gICAgY29uc3QgcmVzb2x2ZWRBdCA9IGlucHV0LnJlc29sdmVkQXQgPyBuZXcgRGF0ZShpbnB1dC5yZXNvbHZlZEF0KSA6IG51bGw7XG4gICAgYXdhaXQgcnVuV2l0aFRlbmFudENvbnRleHQoeyBvcmdJZCwgaXNTdXBlckFkbWluOiBmYWxzZSB9LCAoKSA9PlxuICAgICAgd2l0aFRlbmFudFR4KCh0eCkgPT4gdHguaW5zZXJ0KHNjaGVtYS5pbmNpZGVudCkudmFsdWVzKHtcbiAgICAgICAgaW5jaWRlbnRJZCxcbiAgICAgICAgb3JnSWQsXG4gICAgICAgIGVudmlyb25tZW50LFxuICAgICAgICBvcGVuZWRBdCxcbiAgICAgICAgcmVzb2x2ZWRBdCxcbiAgICAgICAgc2V2ZXJpdHksXG4gICAgICB9KS5vbkNvbmZsaWN0RG9VcGRhdGUoe1xuICAgICAgICB0YXJnZXQ6IFtzY2hlbWEuaW5jaWRlbnQub3JnSWQsIHNjaGVtYS5pbmNpZGVudC5pbmNpZGVudElkXSxcbiAgICAgICAgc2V0OiB7IGVudmlyb25tZW50LCBvcGVuZWRBdCwgcmVzb2x2ZWRBdCwgc2V2ZXJpdHkgfSxcbiAgICAgIH0pKSxcbiAgICApO1xuICAgIC8vIEEgbmV3L3VwZGF0ZWQgaW5jaWRlbnQgY2hhbmdlcyB0aGUgRE9SQSBhZ2dyZWdhdGUg4oCUIGRyb3AgY2FjaGVkIHJlcG9ydHMuXG4gICAgYXdhaXQgdGhpcy5pbnZhbGlkYXRlT3JnKG9yZ0lkKS5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICBsb2dnZXIud2FybignUmVwb3J0aW5nIGNhY2hlIGludmFsaWRhdGlvbiBmYWlsZWQnLCB7IG9yZ0lkLCBlcnJvcjogZXJyb3JNZXNzYWdlKGVycikgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVhZCB0aGUgcGVyLW9yZyBET1JBIHNldHRpbmdzIChQaGFzZSA1YikuIFJldHVybnMgdGhlIHN0b3JlZFxuICAgKiBgaW5jaWRlbnRXaW5kb3dIb3Vyc2Agb3ZlcnJpZGUgKG9yIGBudWxsYCB3aGVuIHVuc2V0KSBwbHVzIHRoZSBnbG9iYWwgZW52XG4gICAqIGRlZmF1bHQsIHNvIHRoZSBzZXR0aW5ncyBVSSBjYW4gc2hvdyBib3RoLiBSdW5zIHVuZGVyIHRoZSBjYWxsZXIncyB0ZW5hbnRcbiAgICogY29udGV4dCAoUkxTLXNjb3BlZCk7IGEgc2luZ2xlLW9yZyByZWFkLlxuICAgKi9cbiAgYXN5bmMgZ2V0SW5jaWRlbnRTZXR0aW5ncyhvcmdJZDogc3RyaW5nKTogUHJvbWlzZTxJbmNpZGVudFNldHRpbmdzPiB7XG4gICAgY29uc3Qgcm93cyA9IGRyaXp6bGVSb3dzPHtcbiAgICAgIGluY2lkZW50X3dpbmRvd19ob3VyczogbnVtYmVyIHwgbnVsbDtcbiAgICAgIGV2ZW50X3JldGVudGlvbl9kYXlzOiBudW1iZXIgfCBudWxsO1xuICAgICAgZG9yYV9yZXRlbnRpb25fZGF5czogbnVtYmVyIHwgbnVsbDtcbiAgICB9PigoYXdhaXQgd2l0aFRlbmFudFR4KCh0eCkgPT4gdHguZXhlY3V0ZShzcWxgXG4gICAgICAgIFNFTEVDVCAke3NjaGVtYS5kb3JhU2V0dGluZ3MuaW5jaWRlbnRXaW5kb3dIb3Vyc30gQVMgaW5jaWRlbnRfd2luZG93X2hvdXJzLFxuICAgICAgICAgICAgICAgJHtzY2hlbWEuZG9yYVNldHRpbmdzLmV2ZW50UmV0ZW50aW9uRGF5c30gQVMgZXZlbnRfcmV0ZW50aW9uX2RheXMsXG4gICAgICAgICAgICAgICAke3NjaGVtYS5kb3JhU2V0dGluZ3MuZG9yYVJldGVudGlvbkRheXN9IEFTIGRvcmFfcmV0ZW50aW9uX2RheXNcbiAgICAgICAgRlJPTSAke3NjaGVtYS5kb3JhU2V0dGluZ3N9XG4gICAgICAgIFdIRVJFICR7c2NoZW1hLmRvcmFTZXR0aW5ncy5vcmdJZH0gPSAke29yZ0lkfVxuICAgICAgICBMSU1JVCAxXG4gICAgICBgKSkpLnJvd3MpO1xuICAgIGNvbnN0IHJvdyA9IHJvd3NbMF07XG4gICAgcmV0dXJuIHtcbiAgICAgIGluY2lkZW50V2luZG93SG91cnM6IHJvdz8uaW5jaWRlbnRfd2luZG93X2hvdXJzICE9IG51bGwgPyBOdW1iZXIocm93LmluY2lkZW50X3dpbmRvd19ob3VycykgOiBudWxsLFxuICAgICAgZGVmYXVsdFdpbmRvd0hvdXJzOiBET1JBX0lOQ0lERU5UX1dJTkRPV19IT1VSUyxcbiAgICAgIGV2ZW50UmV0ZW50aW9uRGF5czogcm93Py5ldmVudF9yZXRlbnRpb25fZGF5cyAhPSBudWxsID8gTnVtYmVyKHJvdy5ldmVudF9yZXRlbnRpb25fZGF5cykgOiBudWxsLFxuICAgICAgZG9yYVJldGVudGlvbkRheXM6IHJvdz8uZG9yYV9yZXRlbnRpb25fZGF5cyAhPSBudWxsID8gTnVtYmVyKHJvdy5kb3JhX3JldGVudGlvbl9kYXlzKSA6IG51bGwsXG4gICAgICBkZWZhdWx0RXZlbnRSZXRlbnRpb25EYXlzOiBSRVBPUlRJTkdfRVZFTlRfUkVURU5USU9OX0RBWVMsXG4gICAgICBkZWZhdWx0RG9yYVJldGVudGlvbkRheXM6IFJFUE9SVElOR19ET1JBX1JFVEVOVElPTl9EQVlTLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogVXBzZXJ0IHBlci1vcmcgcmVwb3J0aW5nIHNldHRpbmdzIChQaGFzZSA1YiBpbmNpZGVudCB3aW5kb3cgKyBQaGFzZSA3XG4gICAqIHJldGVudGlvbiBvdmVycmlkZXMpLCBpZGVtcG90ZW50IG9uIGBvcmdfaWRgLiBBIHBhcnRpYWwgd3JpdGUg4oCUIG9ubHkgdGhlXG4gICAqIGZpZWxkcyBwcmVzZW50IGluIGBwYXRjaGAgYXJlIHNldCAoc28gdXBkYXRpbmcgcmV0ZW50aW9uIG5ldmVyIGNsZWFycyB0aGVcbiAgICogaW5jaWRlbnQgd2luZG93LCBhbmQgdmljZS12ZXJzYSkuIFNldCBzZWxmLXNlcnZlIGJ5IGFuIG9yZyBhZG1pbiB2aWFcbiAgICogYFBVVCAvYXBpL3JlcG9ydHMvc2V0dGluZ3MvaW5jaWRlbnRzYC4gUnVucyB1bmRlciB0aGUgY2FsbGVyJ3Mgb3JnIGNvbnRleHRcbiAgICogKFJMUyBXSVRIIENIRUNLKTsgYSBjaGFuZ2VkIHZhbHVlIGFmZmVjdHMgRE9SQSBhZ2dyZWdhdGVzIHNvIHRoZSBvcmcnc1xuICAgKiBjYWNoZWQgcmVwb3J0cyBhcmUgZHJvcHBlZC5cbiAgICovXG4gIGFzeW5jIHNldFJlcG9ydGluZ1NldHRpbmdzKG9yZ0lkOiBzdHJpbmcsIHBhdGNoOiBSZXBvcnRpbmdTZXR0aW5nc1BhdGNoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3Qgc2V0OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHsgdXBkYXRlZEF0OiBuZXcgRGF0ZSgpIH07XG4gICAgaWYgKHBhdGNoLmluY2lkZW50V2luZG93SG91cnMgIT09IHVuZGVmaW5lZCkgc2V0LmluY2lkZW50V2luZG93SG91cnMgPSBwYXRjaC5pbmNpZGVudFdpbmRvd0hvdXJzO1xuICAgIGlmIChwYXRjaC5ldmVudFJldGVudGlvbkRheXMgIT09IHVuZGVmaW5lZCkgc2V0LmV2ZW50UmV0ZW50aW9uRGF5cyA9IHBhdGNoLmV2ZW50UmV0ZW50aW9uRGF5cztcbiAgICBpZiAocGF0Y2guZG9yYVJldGVudGlvbkRheXMgIT09IHVuZGVmaW5lZCkgc2V0LmRvcmFSZXRlbnRpb25EYXlzID0gcGF0Y2guZG9yYVJldGVudGlvbkRheXM7XG4gICAgYXdhaXQgcnVuV2l0aFRlbmFudENvbnRleHQoeyBvcmdJZCwgaXNTdXBlckFkbWluOiBmYWxzZSB9LCAoKSA9PlxuICAgICAgd2l0aFRlbmFudFR4KCh0eCkgPT4gdHguaW5zZXJ0KHNjaGVtYS5kb3JhU2V0dGluZ3MpLnZhbHVlcyh7XG4gICAgICAgIG9yZ0lkLFxuICAgICAgICBpbmNpZGVudFdpbmRvd0hvdXJzOiBwYXRjaC5pbmNpZGVudFdpbmRvd0hvdXJzLFxuICAgICAgICBldmVudFJldGVudGlvbkRheXM6IHBhdGNoLmV2ZW50UmV0ZW50aW9uRGF5cyxcbiAgICAgICAgZG9yYVJldGVudGlvbkRheXM6IHBhdGNoLmRvcmFSZXRlbnRpb25EYXlzLFxuICAgICAgICB1cGRhdGVkQXQ6IG5ldyBEYXRlKCksXG4gICAgICB9KS5vbkNvbmZsaWN0RG9VcGRhdGUoe1xuICAgICAgICB0YXJnZXQ6IHNjaGVtYS5kb3JhU2V0dGluZ3Mub3JnSWQsXG4gICAgICAgIHNldCxcbiAgICAgIH0pKSxcbiAgICApO1xuICAgIGF3YWl0IHRoaXMuaW52YWxpZGF0ZU9yZyhvcmdJZCkuY2F0Y2goKGVycikgPT4ge1xuICAgICAgbG9nZ2VyLndhcm4oJ1JlcG9ydGluZyBjYWNoZSBpbnZhbGlkYXRpb24gZmFpbGVkJywgeyBvcmdJZCwgZXJyb3I6IGVycm9yTWVzc2FnZShlcnIpIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIExpc3QgcmVjZW50IGluY2lkZW50cyBmb3IgYW4gb3JnIChQaGFzZSA1YiBvcmctYWRtaW4gc3VyZmFjZSksIG5ld2VzdCBmaXJzdCxcbiAgICogcGFnaW5hdGVkLiBFYWNoIHJvdyBjYXJyaWVzIGl0cyByZXNvbHZlZCBzdGF0ZSBhbmQgaXRzIGRlcGxveSBjb3JyZWxhdGlvbiDigJRcbiAgICogdGhlIG1vc3QgcmVjZW50IFNVQ0NFU1NGVUwgZGVwbG95IHRvIHRoZSBpbmNpZGVudCdzIGBlbnZpcm9ubWVudGAgd2hvc2VcbiAgICogYGNvbXBsZXRlZF9hdGAgZmFsbHMgd2l0aGluIHRoZSBlZmZlY3RpdmUgcGVyLW9yZyBjb3JyZWxhdGlvbiB3aW5kb3cgYmVmb3JlXG4gICAqIGBvcGVuZWRfYXRgICh0aGUgc2FtZSBydWxlIERPUkEncyBDRlIvTVRUUiBjb3JyZWxhdGlvbiBhcHBsaWVzKS4gU2luZ2xlLW9yZ1xuICAgKiAobm8gcm9sbHVwKSDigJQgYW4gb3JnIGFkbWluIHZpZXdzIHRoZWlyIG93biBvcmcncyBpbmNpZGVudHMuIFJMUy1zY29wZWQgdmlhXG4gICAqIHRoZSBgcC5vcmdfaWRgL2BpLm9yZ19pZGAgcHJlZGljYXRlcyArIHRoZSB0ZW5hbnQgY29udGV4dC5cbiAgICovXG4gIGFzeW5jIGxpc3RJbmNpZGVudHMob3JnSWQ6IHN0cmluZywgb3B0czogeyBsaW1pdDogbnVtYmVyOyBvZmZzZXQ6IG51bWJlciB9KTogUHJvbWlzZTxJbmNpZGVudExpc3RJdGVtW10+IHtcbiAgICBjb25zdCB7IGluY2lkZW50V2luZG93SG91cnMgfSA9IGF3YWl0IHRoaXMuZ2V0SW5jaWRlbnRTZXR0aW5ncyhvcmdJZCk7XG4gICAgY29uc3Qgd2luZG93SG91cnMgPSByZXNvbHZlSW5jaWRlbnRXaW5kb3dIb3VycyhpbmNpZGVudFdpbmRvd0hvdXJzKTtcbiAgICBjb25zdCBsaW1pdCA9IE1hdGgubWF4KDEsIE1hdGgubWluKG9wdHMubGltaXQsIDIwMCkpO1xuICAgIGNvbnN0IG9mZnNldCA9IE1hdGgubWF4KDAsIG9wdHMub2Zmc2V0KTtcbiAgICByZXR1cm4gd2l0aFRlbmFudFR4KCh0eCkgPT4gdHguZXhlY3V0ZShzcWxgXG4gICAgICAgIFNFTEVDVFxuICAgICAgICAgIGkuaW5jaWRlbnRfaWQgQVMgXCJpbmNpZGVudElkXCIsXG4gICAgICAgICAgaS5lbnZpcm9ubWVudCBBUyBlbnZpcm9ubWVudCxcbiAgICAgICAgICBpLnNldmVyaXR5IEFTIHNldmVyaXR5LFxuICAgICAgICAgIGkub3BlbmVkX2F0Ojp0ZXh0IEFTIFwib3BlbmVkQXRcIixcbiAgICAgICAgICBpLnJlc29sdmVkX2F0Ojp0ZXh0IEFTIFwicmVzb2x2ZWRBdFwiLFxuICAgICAgICAgIGkuY3JlYXRlZF9hdDo6dGV4dCBBUyBcImNyZWF0ZWRBdFwiLFxuICAgICAgICAgIChpLnJlc29sdmVkX2F0IElTIE5PVCBOVUxMKSBBUyByZXNvbHZlZCxcbiAgICAgICAgICBjb3JyLmV4ZWN1dGlvbl9pZCBBUyBcImNvcnJlbGF0ZWRFeGVjdXRpb25JZFwiLFxuICAgICAgICAgIGNvcnIuY29tcGxldGVkX2F0Ojp0ZXh0IEFTIFwiZGVwbG95Q29tcGxldGVkQXRcIlxuICAgICAgICBGUk9NICR7c2NoZW1hLmluY2lkZW50fSBpXG4gICAgICAgIExFRlQgSk9JTiBMQVRFUkFMIChcbiAgICAgICAgICBTRUxFQ1QgZS5leGVjdXRpb25faWQsIGUuY29tcGxldGVkX2F0XG4gICAgICAgICAgRlJPTSAke3NjaGVtYS5waXBlbGluZUV2ZW50fSBlXG4gICAgICAgICAgSk9JTiAke3NjaGVtYS5waXBlbGluZX0gcCBPTiBwLmlkID0gZS5waXBlbGluZV9pZFxuICAgICAgICAgIFdIRVJFIHAub3JnX2lkID0gJHtvcmdJZH0gQU5EIGUuZXZlbnRfdHlwZSA9ICdTVEFHRSdcbiAgICAgICAgICAgIEFORCBlLmVudmlyb25tZW50ID0gaS5lbnZpcm9ubWVudCBBTkQgZS5zdGF0dXMgPSAnU1VDQ0VFREVEJ1xuICAgICAgICAgICAgQU5EIGUuY29tcGxldGVkX2F0IDw9IGkub3BlbmVkX2F0XG4gICAgICAgICAgICBBTkQgZS5jb21wbGV0ZWRfYXQgPj0gaS5vcGVuZWRfYXQgLSBtYWtlX2ludGVydmFsKGhvdXJzID0+ICR7d2luZG93SG91cnN9OjppbnQpXG4gICAgICAgICAgT1JERVIgQlkgZS5jb21wbGV0ZWRfYXQgREVTQ1xuICAgICAgICAgIExJTUlUIDFcbiAgICAgICAgKSBjb3JyIE9OIHRydWVcbiAgICAgICAgV0hFUkUgaS5vcmdfaWQgPSAke29yZ0lkfVxuICAgICAgICBPUkRFUiBCWSBpLm9wZW5lZF9hdCBERVNDXG4gICAgICAgIExJTUlUICR7bGltaXR9IE9GRlNFVCAke29mZnNldH1cbiAgICAgIGApLnRoZW4oKHIpID0+IGRyaXp6bGVSb3dzPEluY2lkZW50TGlzdEl0ZW0+KHIucm93cykubWFwKChyb3cpID0+ICh7XG4gICAgICAuLi5yb3csXG4gICAgICByZXNvbHZlZDogcm93LnJlc29sdmVkID09PSB0cnVlIHx8IChyb3cucmVzb2x2ZWQgYXMgdW5rbm93bikgPT09ICd0JyxcbiAgICAgIGNvcnJlbGF0ZWRFeGVjdXRpb25JZDogcm93LmNvcnJlbGF0ZWRFeGVjdXRpb25JZCA/PyBudWxsLFxuICAgICAgZGVwbG95Q29tcGxldGVkQXQ6IHJvdy5kZXBsb3lDb21wbGV0ZWRBdCA/PyBudWxsLFxuICAgIH0pKSkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFdpcmluZy10ZXN0IGRyeS1ydW4gKFBoYXNlIDViKTogd291bGQgYSBzeW50aGV0aWMgaW5jaWRlbnQgb3BlbmluZyBOT1cgZm9yXG4gICAqIGBlbnZpcm9ubWVudGAgY29ycmVsYXRlIHRvIGEgcmVjZW50IHN1Y2Nlc3NmdWwgZGVwbG95IHVuZGVyIHRoZSBvcmcnc1xuICAgKiBlZmZlY3RpdmUgd2luZG93PyBUaGlzIGlzIGEgTk9OLXBlcnNpc3RpbmcgY29ycmVsYXRpb24gY2hlY2sg4oCUIGl0IHZlcmlmaWVzXG4gICAqIHRoZSBhZG1pbidzIGVudmlyb25tZW50IG5hbWluZyArIHdpbmRvdyBsaW5lIHVwIHdpdGggcmVhbCBkZXBsb3kgZXZlbnRzXG4gICAqIFdJVEhPVVQgd3JpdGluZyBhbiBpbmNpZGVudCAoc28gYSBcInRlc3RcIiBuZXZlciBwb2xsdXRlcyBDRlIvTVRUUikuIFJMUy1zY29wZWQuXG4gICAqL1xuICBhc3luYyB0ZXN0SW5jaWRlbnRDb3JyZWxhdGlvbihvcmdJZDogc3RyaW5nLCBlbnZpcm9ubWVudDogc3RyaW5nKTogUHJvbWlzZTxJbmNpZGVudFRlc3RSZXN1bHQ+IHtcbiAgICBjb25zdCBlbnYgPSBzY3J1YkF3c0lkZW50aWZpZXJzRnJvbVN0cmluZyhlbnZpcm9ubWVudCk7XG4gICAgY29uc3Qgb3BlbmVkQXQgPSBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCk7XG4gICAgY29uc3QgeyBpbmNpZGVudFdpbmRvd0hvdXJzIH0gPSBhd2FpdCB0aGlzLmdldEluY2lkZW50U2V0dGluZ3Mob3JnSWQpO1xuICAgIGNvbnN0IHdpbmRvd0hvdXJzID0gcmVzb2x2ZUluY2lkZW50V2luZG93SG91cnMoaW5jaWRlbnRXaW5kb3dIb3Vycyk7XG4gICAgY29uc3Qgcm93cyA9IGRyaXp6bGVSb3dzPHsgZXhlY3V0aW9uX2lkOiBzdHJpbmcgfCBudWxsOyBjb21wbGV0ZWRfYXQ6IHN0cmluZyB8IG51bGwgfT4oKGF3YWl0IHdpdGhUZW5hbnRUeCgodHgpID0+IHR4LmV4ZWN1dGUoc3FsYFxuICAgICAgICBTRUxFQ1QgZS5leGVjdXRpb25faWQgQVMgZXhlY3V0aW9uX2lkLCBlLmNvbXBsZXRlZF9hdDo6dGV4dCBBUyBjb21wbGV0ZWRfYXRcbiAgICAgICAgRlJPTSAke3NjaGVtYS5waXBlbGluZUV2ZW50fSBlXG4gICAgICAgIEpPSU4gJHtzY2hlbWEucGlwZWxpbmV9IHAgT04gcC5pZCA9IGUucGlwZWxpbmVfaWRcbiAgICAgICAgV0hFUkUgcC5vcmdfaWQgPSAke29yZ0lkfSBBTkQgZS5ldmVudF90eXBlID0gJ1NUQUdFJ1xuICAgICAgICAgIEFORCBlLmVudmlyb25tZW50ID0gJHtlbnZ9IEFORCBlLnN0YXR1cyA9ICdTVUNDRUVERUQnXG4gICAgICAgICAgQU5EIGUuY29tcGxldGVkX2F0IDw9ICR7b3BlbmVkQXR9Ojp0aW1lc3RhbXB0elxuICAgICAgICAgIEFORCBlLmNvbXBsZXRlZF9hdCA+PSAke29wZW5lZEF0fTo6dGltZXN0YW1wdHogLSBtYWtlX2ludGVydmFsKGhvdXJzID0+ICR7d2luZG93SG91cnN9OjppbnQpXG4gICAgICAgIE9SREVSIEJZIGUuY29tcGxldGVkX2F0IERFU0NcbiAgICAgICAgTElNSVQgMVxuICAgICAgYCkpKS5yb3dzKTtcbiAgICBjb25zdCBoaXQgPSByb3dzWzBdO1xuICAgIHJldHVybiB7XG4gICAgICBlbnZpcm9ubWVudDogZW52LFxuICAgICAgb3BlbmVkQXQsXG4gICAgICB3aW5kb3dIb3VycyxcbiAgICAgIGNvcnJlbGF0ZWQ6IGhpdD8uZXhlY3V0aW9uX2lkICE9IG51bGwsXG4gICAgICBleGVjdXRpb25JZDogaGl0Py5leGVjdXRpb25faWQgPz8gbnVsbCxcbiAgICAgIGRlcGxveUNvbXBsZXRlZEF0OiBoaXQ/LmNvbXBsZXRlZF9hdCA/PyBudWxsLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogVXBzZXJ0IHBlci1vcmcgaW5nZXN0aW9uIGhlYWx0aCAoUGhhc2UgMyk6IHRoZSBBV1MgZXZlbnRzIExhbWJkYSBwZXJpb2RpY2FsbHlcbiAgICogcmVwb3J0cyBmb3J3YXJkZWQvZHJvcHBlZCBjb3VudGVycyArIHRoZSBsYXN0IGV2ZW50IHRpbWVzdGFtcCBzbyB0aGUgUmVwb3J0c1xuICAgKiBVSSBjYW4gc2hvdyBmbG93aW5nIC8gc3RhbGUgLyBkcm9wcGluZy4gT25lIHJvdyBwZXIgb3JnICh1cHNlcnQgb24gb3JnX2lkKS5cbiAgICovXG4gIGFzeW5jIHJlY29yZEluZ2VzdEhlYWx0aChcbiAgICBvcmdJZDogc3RyaW5nLFxuICAgIGlucHV0OiB7IGZvcndhcmRlZD86IG51bWJlcjsgZHJvcHBlZD86IG51bWJlcjsgbGFzdEV2ZW50QXQ/OiBzdHJpbmcgfSxcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgbGFzdEV2ZW50QXQgPSBpbnB1dC5sYXN0RXZlbnRBdCA/IG5ldyBEYXRlKGlucHV0Lmxhc3RFdmVudEF0KSA6IHVuZGVmaW5lZDtcbiAgICBhd2FpdCBydW5XaXRoVGVuYW50Q29udGV4dCh7IG9yZ0lkLCBpc1N1cGVyQWRtaW46IGZhbHNlIH0sICgpID0+XG4gICAgICB3aXRoVGVuYW50VHgoKHR4KSA9PiB0eC5pbnNlcnQoc2NoZW1hLmluZ2VzdEhlYWx0aCkudmFsdWVzKHtcbiAgICAgICAgb3JnSWQsXG4gICAgICAgIGZvcndhcmRlZDogaW5wdXQuZm9yd2FyZGVkLFxuICAgICAgICBkcm9wcGVkOiBpbnB1dC5kcm9wcGVkLFxuICAgICAgICBsYXN0RXZlbnRBdCxcbiAgICAgICAgdXBkYXRlZEF0OiBuZXcgRGF0ZSgpLFxuICAgICAgfSkub25Db25mbGljdERvVXBkYXRlKHtcbiAgICAgICAgdGFyZ2V0OiBzY2hlbWEuaW5nZXN0SGVhbHRoLm9yZ0lkLFxuICAgICAgICBzZXQ6IHtcbiAgICAgICAgICBmb3J3YXJkZWQ6IGlucHV0LmZvcndhcmRlZCxcbiAgICAgICAgICBkcm9wcGVkOiBpbnB1dC5kcm9wcGVkLFxuICAgICAgICAgIGxhc3RFdmVudEF0LFxuICAgICAgICAgIHVwZGF0ZWRBdDogbmV3IERhdGUoKSxcbiAgICAgICAgfSxcbiAgICAgIH0pKSxcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEJhdGNoZWQgaGFyZC1ERUxFVEUgb2Ygb25lIHJlcG9ydGluZyB0YWJsZSdzIHJvd3MgZXhwaXJlZCBwYXN0IGEgYGNyZWF0ZWRfYXRgXG4gICAqIGN1dG9mZiwgc2NvcGVkIHRvIGFuIG9yZyBhbmQgYW4gb3B0aW9uYWwgcm93IHByZWRpY2F0ZSAoUGhhc2UgNykuIFVzZXMgYVxuICAgKiBgY3RpZGAtaW4tc3VicXVlcnkgTElNSVQgc28gZWFjaCBzdGF0ZW1lbnQgdG91Y2hlcyBhdCBtb3N0IGBiYXRjaFNpemVgIHJvd3NcbiAgICogKHNob3J0IGxvY2sgd2luZG93cywgbm8gbG9uZyB0YWJsZSBzY2FuIHVuZGVyIGxvY2spOyBgUkVUVVJOSU5HIDFgIGxldHMgdXNcbiAgICogY291bnQgdmlhIGAucm93cy5sZW5ndGhgIHdpdGhvdXQgZGVwZW5kaW5nIG9uIHRoZSBkcml2ZXIncyBgcm93Q291bnRgLiBMb29wc1xuICAgKiB1bnRpbCBhIHNob3J0IGJhdGNoIChkcmFpbmVkKSBvciB0aGUgcGVyLXRpY2sgY2FwLCB0aGVuIGRlZmVycyB0aGUgcmVzdC5cbiAgICogTVVTVCBydW4gaW5zaWRlIGEgc3lzYWRtaW4gdGVuYW50IHNjb3BlIChzZWUgcHVyZ2VFeHBpcmVkUmVwb3J0aW5nRGF0YSkgc28gaXRcbiAgICogYnlwYXNzZXMgUkxTIGFuZCBjYW4gZGVsZXRlIGFjcm9zcyB0aGUgb3JnJ3Mgcm93cy5cbiAgICovXG4gIGFzeW5jICNwdXJnZVJlcG9ydGluZ1RhYmxlQmF0Y2hlZChcbiAgICB0YWJsZVNxbDogUmV0dXJuVHlwZTx0eXBlb2Ygc3FsPixcbiAgICBwcmVkaWNhdGU6IFJldHVyblR5cGU8dHlwZW9mIHNxbD4sXG4gICAgYmF0Y2hTaXplOiBudW1iZXIsXG4gICAgbWF4QmF0Y2hlczogbnVtYmVyLFxuICApOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIGxldCB0b3RhbCA9IDA7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBtYXhCYXRjaGVzOyBpKyspIHtcbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IHdpdGhUZW5hbnRUeCgodHgpID0+IHR4LmV4ZWN1dGUoc3FsYFxuICAgICAgICBERUxFVEUgRlJPTSAke3RhYmxlU3FsfVxuICAgICAgICBXSEVSRSBjdGlkIElOIChcbiAgICAgICAgICBTRUxFQ1QgY3RpZCBGUk9NICR7dGFibGVTcWx9XG4gICAgICAgICAgV0hFUkUgJHtwcmVkaWNhdGV9XG4gICAgICAgICAgTElNSVQgJHtiYXRjaFNpemV9XG4gICAgICAgIClcbiAgICAgICAgUkVUVVJOSU5HIDFcbiAgICAgIGApKTtcbiAgICAgIGNvbnN0IHB1cmdlZCA9IGRyaXp6bGVSb3dzPHVua25vd24+KHJlcy5yb3dzKS5sZW5ndGg7XG4gICAgICB0b3RhbCArPSBwdXJnZWQ7XG4gICAgICBpZiAocHVyZ2VkIDwgYmF0Y2hTaXplKSBicmVhazsgLy8gZHJhaW5lZFxuICAgICAgaWYgKGkgPT09IG1heEJhdGNoZXMgLSAxKSB7XG4gICAgICAgIGxvZ2dlci53YXJuKCdSZXBvcnRpbmcgcmV0ZW50aW9uIGhpdCBwZXItdGljayBjYXA7IHJlbWFpbmluZyByb3dzIGRlZmVycmVkJywge1xuICAgICAgICAgIHB1cmdlZFRoaXNUaWNrOiB0b3RhbCxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0b3RhbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXBvcnRpbmcgcmV0ZW50aW9uIHN3ZWVwIChQaGFzZSA3KS4gSGFyZC1kZWxldGVzIHJvd3Mgb2xkZXIgdGhhbiB0aGVpclxuICAgKiByZXRlbnRpb24gd2luZG93LCBieSBgY3JlYXRlZF9hdGAsIGFjcm9zcyBldmVyeSBvcmcgdGhhdCBoYXMgcmVwb3J0aW5nIGRhdGEg4oCUXG4gICAqIGEgKipzcGxpdCoqIHBvbGljeSBzbyBoaWdoLXZvbHVtZSBzdGFuZGFyZCBldmVudHMgZXhwaXJlIGZhc3RlciB0aGFuIHRoZVxuICAgKiBsb3ctdm9sdW1lIERPUkEgc291cmNlOlxuICAgKiAgLSBgcGlwZWxpbmVfZXZlbnRzIFdIRVJFIGVudmlyb25tZW50IElTIE5VTExgIOKGkiBzdGFuZGFyZC1ldmVudCB3aW5kb3cuXG4gICAqICAtIGBwaXBlbGluZV9ldmVudHMgV0hFUkUgZW52aXJvbm1lbnQgSVMgTk9UIE5VTExgIChkZXBsb3kgc3RhZ2VzKSxcbiAgICogICAgYGRlcGxveW1lbnRfb3V0Y29tZXNgLCBhbmQgYGluY2lkZW50c2Ag4oaSIERPUkEtc291cmNlIHdpbmRvdy5cbiAgICogRWFjaCBvcmcncyB3aW5kb3dzIGNvbWUgZnJvbSBpdHMgYGRvcmFfc2V0dGluZ3NgIG92ZXJyaWRlLCBlbHNlIHRoZSBnbG9iYWxcbiAgICogZW52IGRlZmF1bHRzIChzZWUge0BsaW5rIHJlc29sdmVFdmVudFJldGVudGlvbkRheXN9IC8ge0BsaW5rIHJlc29sdmVEb3JhUmV0ZW50aW9uRGF5c30pLlxuICAgKiBgaW5nZXN0X2hlYWx0aGAgYW5kIGBkb3JhX3NldHRpbmdzYCBhcmUgbmV2ZXIgcHVyZ2VkLiBPbmUgYG5vd2AgZm9yIHRoZSB3aG9sZVxuICAgKiB0aWNrIChyb3dzIGNyb3NzaW5nIHRoZSBib3VuZGFyeSBtaWQtc3dlZXAgd2FpdCBmb3IgdGhlIG5leHQpLiBFc3RhYmxpc2hlcyBhXG4gICAqIHN5c2FkbWluIHRlbmFudCBzY29wZSBzbyB0aGUgZGVsZXRlcyBzcGFuIGFsbCBvcmdzIC8gYnlwYXNzIFJMUyDigJQgdGhpcyBpcyBhXG4gICAqIGNyb3NzLXRlbmFudCBob3VzZWtlZXBpbmcgam9iLiBSZXR1cm5zIChhbmQgbG9ncykgcGVyLXdpbmRvdyBwdXJnZSB0YWxsaWVzLlxuICAgKi9cbiAgYXN5bmMgcHVyZ2VFeHBpcmVkUmVwb3J0aW5nRGF0YShvcHRzOiBSZXBvcnRpbmdSZXRlbnRpb25PcHRpb25zID0ge30pOiBQcm9taXNlPFJlcG9ydGluZ1JldGVudGlvbkNvdW50cz4ge1xuICAgIGNvbnN0IGJhdGNoU2l6ZSA9IE1hdGgubWF4KDEsIG9wdHMuYmF0Y2hTaXplID8/IDEwMDApO1xuICAgIGNvbnN0IG1heEJhdGNoZXMgPSBNYXRoLm1heCgxLCBvcHRzLm1heEJhdGNoZXNQZXJUYWJsZSA/PyA1MCk7XG4gICAgY29uc3Qgbm93ID0gb3B0cy5ub3cgPz8gbmV3IERhdGUoKTtcbiAgICBjb25zdCBjb3VudHM6IFJlcG9ydGluZ1JldGVudGlvbkNvdW50cyA9IHtcbiAgICAgIG9yZ3M6IDAsIHN0YW5kYXJkRXZlbnRzOiAwLCBkb3JhRXZlbnRzOiAwLCBkZXBsb3ltZW50T3V0Y29tZXM6IDAsIGluY2lkZW50czogMCxcbiAgICB9O1xuXG4gICAgcmV0dXJuIHJ1bldpdGhUZW5hbnRDb250ZXh0KHsgaXNTdXBlckFkbWluOiB0cnVlIH0sIGFzeW5jICgpID0+IHtcbiAgICAgIC8vIEVudW1lcmF0ZSBldmVyeSBvcmcgd2l0aCByZXBvcnRpbmcgZGF0YSAodW5pb24gYWNyb3NzIHRoZSB0aHJlZSB0YWJsZXMpLlxuICAgICAgY29uc3Qgb3JnUm93cyA9IGRyaXp6bGVSb3dzPHsgb3JnX2lkOiBzdHJpbmcgfT4oKGF3YWl0IHdpdGhUZW5hbnRUeCgodHgpID0+IHR4LmV4ZWN1dGUoc3FsYFxuICAgICAgICBTRUxFQ1QgRElTVElOQ1Qgb3JnX2lkIEZST00gKFxuICAgICAgICAgIFNFTEVDVCAke3NjaGVtYS5waXBlbGluZUV2ZW50Lm9yZ0lkfSBBUyBvcmdfaWQgRlJPTSAke3NjaGVtYS5waXBlbGluZUV2ZW50fVxuICAgICAgICAgIFVOSU9OXG4gICAgICAgICAgU0VMRUNUICR7c2NoZW1hLmRlcGxveW1lbnRPdXRjb21lLm9yZ0lkfSBBUyBvcmdfaWQgRlJPTSAke3NjaGVtYS5kZXBsb3ltZW50T3V0Y29tZX1cbiAgICAgICAgICBVTklPTlxuICAgICAgICAgIFNFTEVDVCAke3NjaGVtYS5pbmNpZGVudC5vcmdJZH0gQVMgb3JnX2lkIEZST00gJHtzY2hlbWEuaW5jaWRlbnR9XG4gICAgICAgICkgQVMgb3Jnc1xuICAgICAgYCkpKS5yb3dzKTtcbiAgICAgIGlmIChvcmdSb3dzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIGNvdW50cztcblxuICAgICAgLy8gUGVyLW9yZyByZXRlbnRpb24gb3ZlcnJpZGVzIChhIHNpbmdsZSByZWFkOyBvcmdzIHdpdGhvdXQgYSByb3cgdXNlIGRlZmF1bHRzKS5cbiAgICAgIGNvbnN0IG92ZXJyaWRlUm93cyA9IGRyaXp6bGVSb3dzPHtcbiAgICAgICAgb3JnX2lkOiBzdHJpbmc7XG4gICAgICAgIGV2ZW50X3JldGVudGlvbl9kYXlzOiBudW1iZXIgfCBudWxsO1xuICAgICAgICBkb3JhX3JldGVudGlvbl9kYXlzOiBudW1iZXIgfCBudWxsO1xuICAgICAgfT4oKGF3YWl0IHdpdGhUZW5hbnRUeCgodHgpID0+IHR4LmV4ZWN1dGUoc3FsYFxuICAgICAgICBTRUxFQ1QgJHtzY2hlbWEuZG9yYVNldHRpbmdzLm9yZ0lkfSBBUyBvcmdfaWQsXG4gICAgICAgICAgICAgICAke3NjaGVtYS5kb3JhU2V0dGluZ3MuZXZlbnRSZXRlbnRpb25EYXlzfSBBUyBldmVudF9yZXRlbnRpb25fZGF5cyxcbiAgICAgICAgICAgICAgICR7c2NoZW1hLmRvcmFTZXR0aW5ncy5kb3JhUmV0ZW50aW9uRGF5c30gQVMgZG9yYV9yZXRlbnRpb25fZGF5c1xuICAgICAgICBGUk9NICR7c2NoZW1hLmRvcmFTZXR0aW5nc31cbiAgICAgIGApKSkucm93cyk7XG4gICAgICBjb25zdCBvdmVycmlkZXMgPSBuZXcgTWFwKG92ZXJyaWRlUm93cy5tYXAoKHIpID0+IFtyLm9yZ19pZCwgcl0pKTtcblxuICAgICAgY29uc3QgZXZlbnRzVGFibGUgPSBzcWxgJHtzY2hlbWEucGlwZWxpbmVFdmVudH1gO1xuICAgICAgY29uc3Qgb3V0Y29tZXNUYWJsZSA9IHNxbGAke3NjaGVtYS5kZXBsb3ltZW50T3V0Y29tZX1gO1xuICAgICAgY29uc3QgaW5jaWRlbnRzVGFibGUgPSBzcWxgJHtzY2hlbWEuaW5jaWRlbnR9YDtcblxuICAgICAgZm9yIChjb25zdCB7IG9yZ19pZDogb3JnSWQgfSBvZiBvcmdSb3dzKSB7XG4gICAgICAgIGNvbnN0IG92ID0gb3ZlcnJpZGVzLmdldChvcmdJZCk7XG4gICAgICAgIGNvbnN0IGV2ZW50RGF5cyA9IHJlc29sdmVFdmVudFJldGVudGlvbkRheXMob3Y/LmV2ZW50X3JldGVudGlvbl9kYXlzKTtcbiAgICAgICAgY29uc3QgZG9yYURheXMgPSByZXNvbHZlRG9yYVJldGVudGlvbkRheXMob3Y/LmRvcmFfcmV0ZW50aW9uX2RheXMpO1xuICAgICAgICAvLyBgLTFgID0gdW5saW1pdGVkIChQaGFzZSA4KToga2VlcCBmb3JldmVyLCBza2lwIHRoYXQgd2luZG93J3MgZGVsZXRlcyBmb3JcbiAgICAgICAgLy8gdGhpcyBvcmcuIFN0YW5kYXJkLWV2ZW50IGFuZCBET1JBLXNvdXJjZSB3aW5kb3dzIGFyZSBpbmRlcGVuZGVudDsgYW4gb3JnXG4gICAgICAgIC8vIHdpdGggYm90aCBgLTFgIGlzIGZ1bGx5IHNraXBwZWQuIExvZyB0aGUgc2tpcCBzbyBpdCdzIG9ic2VydmFibGUuXG4gICAgICAgIGNvbnN0IHNraXBFdmVudHMgPSBldmVudERheXMgPT09IC0xO1xuICAgICAgICBjb25zdCBza2lwRG9yYSA9IGRvcmFEYXlzID09PSAtMTtcbiAgICAgICAgaWYgKHNraXBFdmVudHMgfHwgc2tpcERvcmEpIHtcbiAgICAgICAgICBsb2dnZXIuaW5mbygnUmVwb3J0aW5nIHJldGVudGlvbiBzd2VlcCBza2lwcGluZyB1bmxpbWl0ZWQgd2luZG93KHMpJywge1xuICAgICAgICAgICAgb3JnSWQsXG4gICAgICAgICAgICBzdGFuZGFyZEV2ZW50czogc2tpcEV2ZW50cyA/ICd1bmxpbWl0ZWQnIDogZXZlbnREYXlzLFxuICAgICAgICAgICAgZG9yYVNvdXJjZTogc2tpcERvcmEgPyAndW5saW1pdGVkJyA6IGRvcmFEYXlzLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFza2lwRXZlbnRzKSB7XG4gICAgICAgICAgY29uc3QgZXZlbnRDdXRvZmYgPSByZXRlbnRpb25DdXRvZmYobm93LCBldmVudERheXMpO1xuICAgICAgICAgIGNvdW50cy5zdGFuZGFyZEV2ZW50cyArPSBhd2FpdCB0aGlzLiNwdXJnZVJlcG9ydGluZ1RhYmxlQmF0Y2hlZChcbiAgICAgICAgICAgIGV2ZW50c1RhYmxlLFxuICAgICAgICAgICAgc3FsYG9yZ19pZCA9ICR7b3JnSWR9IEFORCBlbnZpcm9ubWVudCBJUyBOVUxMIEFORCBjcmVhdGVkX2F0IDwgJHtldmVudEN1dG9mZn1gLFxuICAgICAgICAgICAgYmF0Y2hTaXplLCBtYXhCYXRjaGVzLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXNraXBEb3JhKSB7XG4gICAgICAgICAgY29uc3QgZG9yYUN1dG9mZiA9IHJldGVudGlvbkN1dG9mZihub3csIGRvcmFEYXlzKTtcbiAgICAgICAgICBjb3VudHMuZG9yYUV2ZW50cyArPSBhd2FpdCB0aGlzLiNwdXJnZVJlcG9ydGluZ1RhYmxlQmF0Y2hlZChcbiAgICAgICAgICAgIGV2ZW50c1RhYmxlLFxuICAgICAgICAgICAgc3FsYG9yZ19pZCA9ICR7b3JnSWR9IEFORCBlbnZpcm9ubWVudCBJUyBOT1QgTlVMTCBBTkQgY3JlYXRlZF9hdCA8ICR7ZG9yYUN1dG9mZn1gLFxuICAgICAgICAgICAgYmF0Y2hTaXplLCBtYXhCYXRjaGVzLFxuICAgICAgICAgICk7XG4gICAgICAgICAgY291bnRzLmRlcGxveW1lbnRPdXRjb21lcyArPSBhd2FpdCB0aGlzLiNwdXJnZVJlcG9ydGluZ1RhYmxlQmF0Y2hlZChcbiAgICAgICAgICAgIG91dGNvbWVzVGFibGUsXG4gICAgICAgICAgICBzcWxgb3JnX2lkID0gJHtvcmdJZH0gQU5EIGNyZWF0ZWRfYXQgPCAke2RvcmFDdXRvZmZ9YCxcbiAgICAgICAgICAgIGJhdGNoU2l6ZSwgbWF4QmF0Y2hlcyxcbiAgICAgICAgICApO1xuICAgICAgICAgIGNvdW50cy5pbmNpZGVudHMgKz0gYXdhaXQgdGhpcy4jcHVyZ2VSZXBvcnRpbmdUYWJsZUJhdGNoZWQoXG4gICAgICAgICAgICBpbmNpZGVudHNUYWJsZSxcbiAgICAgICAgICAgIHNxbGBvcmdfaWQgPSAke29yZ0lkfSBBTkQgY3JlYXRlZF9hdCA8ICR7ZG9yYUN1dG9mZn1gLFxuICAgICAgICAgICAgYmF0Y2hTaXplLCBtYXhCYXRjaGVzLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgY291bnRzLm9yZ3MgKz0gMTtcbiAgICAgIH1cblxuICAgICAgY29uc3QgcHVyZ2VkQW55ID0gY291bnRzLnN0YW5kYXJkRXZlbnRzICsgY291bnRzLmRvcmFFdmVudHMgKyBjb3VudHMuZGVwbG95bWVudE91dGNvbWVzICsgY291bnRzLmluY2lkZW50cztcbiAgICAgIGlmIChwdXJnZWRBbnkgPiAwKSBsb2dnZXIuaW5mbygnUmVwb3J0aW5nIHJldGVudGlvbiBzd2VlcCBwdXJnZWQgZXhwaXJlZCByb3dzJywgeyAuLi5jb3VudHMgfSk7XG4gICAgICByZXR1cm4gY291bnRzO1xuICAgIH0pO1xuICB9XG59XG5cbmV4cG9ydCBjb25zdCByZXBvcnRpbmdTZXJ2aWNlID0gbmV3IFJlcG9ydGluZ1NlcnZpY2UoKTtcbiJdfQ==
850
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwb3J0aW5nLXNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYXBpL3JlcG9ydGluZy1zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEMsT0FBTyxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsbUJBQW1CLEVBQUUsNkJBQTZCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUM1SCxPQUFPLEVBQUUsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUMzQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDaEQsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxZQUFZLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUU1RSxnRkFBZ0Y7QUFDaEYsNEVBQTRFO0FBQzVFLE9BQU8sRUFBRSxjQUFjLEVBQUUsZUFBZSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDeEUsT0FBTyxFQUFFLDBCQUEwQixFQUFFLDBCQUEwQixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDckcsT0FBTyxFQUNMLGNBQWMsSUFBSSxXQUFXLEVBQzdCLFlBQVksSUFBSSxTQUFTLEVBQ3pCLGNBQWMsSUFBSSxXQUFXLEdBQzlCLE1BQU0scUJBQXFCLENBQUM7QUFDN0IsT0FBTyxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUNqRSw4RUFBOEU7QUFDOUUsT0FBTyxFQUNMLDhCQUE4QixFQUFFLDZCQUE2QixFQUM3RCx5QkFBeUIsRUFBRSx3QkFBd0IsRUFBRSxlQUFlLEdBQ3JFLE1BQU0sMEJBQTBCLENBQUM7QUFDbEMsT0FBTyxFQUFFLG9CQUFvQixFQUFFLGFBQWEsRUFBRSxzQkFBc0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBd0J6RyxPQUFPLEVBQUUs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LFNBQVMsRUFBRSxVQUFVLENBQ3RCLENBQUM7Z0JBQ0osQ0FBQztnQkFDRCxNQUFNLENBQUMsSUFBSSxJQUFJLENBQUMsQ0FBQztZQUNuQixDQUFDO1lBRUQsTUFBTSxTQUFTLEdBQUcsTUFBTSxDQUFDLGNBQWMsR0FBRyxNQUFNLENBQUMsVUFBVSxHQUFHLE1BQU0sQ0FBQyxrQkFBa0IsR0FBRyxNQUFNLENBQUMsU0FBUyxDQUFDO1lBQzNHLElBQUksU0FBUyxHQUFHLENBQUM7Z0JBQUUsTUFBTSxDQUFDLElBQUksQ0FBQywrQ0FBK0MsRUFBRSxFQUFFLEdBQUcsTUFBTSxFQUFFLENBQUMsQ0FBQztZQUMvRixPQUFPLE1BQU0sQ0FBQztRQUNoQixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7Q0FDRjtBQUVELE1BQU0sQ0FBQyxNQUFNLGdCQUFnQixHQUFHLElBQUksZ0JBQWdCLEVBQUUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgeyBjcmVhdGVMb2dnZXIsIGVycm9yTWVzc2FnZSwgc2NydWJBd3NJZGVudGlmaWVycywgc2NydWJBd3NJZGVudGlmaWVyc0Zyb21TdHJpbmcgfSBmcm9tICdAcGlwZWxpbmUtYnVpbGRlci9hcGktY29yZSc7XG5pbXBvcnQgeyBpbkFycmF5LCBzcWwgfSBmcm9tICdkcml6emxlLW9ybSc7XG5pbXBvcnQgeyBkcml6emxlUm93cyB9IGZyb20gJy4vY3J1ZC1zZXJ2aWNlLmpzJztcbmltcG9ydCB7IHNjaGVtYSB9IGZyb20gJy4uL2RhdGFiYXNlL2RyaXp6bGUtc2NoZW1hLmpzJztcbmltcG9ydCB7IHdpdGhUZW5hbnRUeCwgcnVuV2l0aFRlbmFudENvbnRleHQgfSBmcm9tICcuLi9kYXRhYmFzZS90ZW5hbmN5LmpzJztcblxuLy8gRXh0cmFjdGVkIGZvciBzaXplIOKAlCBzZWUgLi9yZXBvcnRpbmcvLiBFdmVyeXRoaW5nIHB1YmxpYyBpcyByZS1leHBvcnRlZCBiZWxvd1xuLy8gc28gYEBwaXBlbGluZS1idWlsZGVyL3BpcGVsaW5lLWRhdGFgJ3Mgc3VyZmFjZSBpcyB1bmNoYW5nZWQgYnkgdGhlIHNwbGl0LlxuaW1wb3J0IHsgaW52ZW50b3J5Q2FjaGUsIHRpbWVzZXJpZXNDYWNoZSB9IGZyb20gJy4vcmVwb3J0aW5nL2NhY2hlcy5qcyc7XG5pbXBvcnQgeyBET1JBX0lOQ0lERU5UX1dJTkRPV19IT1VSUywgcmVzb2x2ZUluY2lkZW50V2luZG93SG91cnMgfSBmcm9tICcuL3JlcG9ydGluZy9kb3JhLXNjb3JpbmcuanMnO1xuaW1wb3J0IHtcbiAgZ2V0RG9yYU1ldHJpY3MgYXMgZG9yYU1ldHJpY3MsXG4gIGdldERvcmFUcmVuZCBhcyBkb3JhVHJlbmQsXG4gIGdldEJ1aWxkSGVhbHRoIGFzIGJ1aWxkSGVhbHRoLFxufSBmcm9tICcuL3JlcG9ydGluZy9kb3JhLmpzJztcbmltcG9ydCB7IG9yZ1Njb3BlLCBydW5SZXBvcnQgfSBmcm9tICcuL3JlcG9ydGluZy9xdWVyeS1zY29wZS5qcyc7XG4vLyBBbGlhc2VkOiB0aGUgbW9kdWxlIGZ1bmN0aW9ucyBhbmQgdGhlIGRlbGVnYXRpbmcgbWV0aG9kcyBiZWxvdyBzaGFyZSBuYW1lcy5cbmltcG9ydCB7XG4gIFJFUE9SVElOR19FVkVOVF9SRVRFTlRJT05fREFZUywgUkVQT1JUSU5HX0RPUkFfUkVURU5USU9OX0RBWVMsXG4gIHJlc29sdmVFdmVudFJldGVudGlvbkRheXMsIHJlc29sdmVEb3JhUmV0ZW50aW9uRGF5cywgcmV0ZW50aW9uQ3V0b2ZmLFxufSBmcm9tICcuL3JlcG9ydGluZy9yZXRlbnRpb24uanMnO1xuaW1wb3J0IHsgYXNzZXJ0UmVwb3J0SW50ZXJ2YWwsIHNjcnViT3B0aW9uYWwsIG9wdGlvbmFsU3RhcnRlZEF0UmFuZ2UgfSBmcm9tICcuL3JlcG9ydGluZy9zcWwtaGVscGVycy5qcyc7XG5pbXBvcnQgdHlwZSB7XG4gIEV4ZWN1dGlvbkNvdW50LCBUaW1lU2VyaWVzRW50cnksIER1cmF0aW9uU3RhdHMsIFBpcGVsaW5lRXhlY3V0aW9uLCBTdGFnZUZhaWx1cmUsIFN0YWdlQm90dGxlbmVjayxcbiAgQWN0aW9uRmFpbHVyZSwgRXJyb3JFbnRyeSwgUGx1Z2luU3VtbWFyeSwgVHlwZUNvbXB1dGVEaXN0cmlidXRpb24sIFZlcnNpb25Db3VudCxcbiAgQnVpbGRUaW1lU2VyaWVzRW50cnksIEJ1aWxkRHVyYXRpb24sIEJ1aWxkRmFpbHVyZSxcbiAgUmVwb3J0aW5nUmV0ZW50aW9uT3B0aW9ucywgUmVwb3J0aW5nUmV0ZW50aW9uQ291bnRzLFxuICBEb3JhT3B0aW9ucywgSW5jaWRlbnRTZXR0aW5ncywgUmVwb3J0aW5nU2V0dGluZ3NQYXRjaCwgSW5jaWRlbnRMaXN0SXRlbSwgSW5jaWRlbnRUZXN0UmVzdWx0LFxuICBEb3JhTWV0cmljcywgRG9yYVRyZW5kUG9pbnQsIEJ1aWxkSGVhbHRoLCBJbmNpZGVudElucHV0LFxuICBJbmdlc3RFdmVudCwgSW5nZXN0TWV0cmljLCBJbmdlc3RSZXN1bHQsXG59IGZyb20gJy4vcmVwb3J0aW5nL3R5cGVzLmpzJztcblxuLy8gUmUtZXhwb3J0IEVYQUNUTFkgdGhlIHN1cmZhY2UgdGhpcyBtb2R1bGUgaGFkIGJlZm9yZSB0aGUgc3BsaXQg4oCUIG5vIG1vcmUuXG4vLyBgc3JjL2luZGV4LnRzYCBkb2VzIGBleHBvcnQgKiBmcm9tICcuL2FwaS9yZXBvcnRpbmctc2VydmljZS5qcydgLCBzbyBhbnl0aGluZ1xuLy8gcmUtZXhwb3J0ZWQgaGVyZSBiZWNvbWVzIHBhcnQgb2YgdGhlIHBhY2thZ2UncyBwdWJsaWMgQVBJLiBFbnVtZXJhdGVkIHJhdGhlclxuLy8gdGhhbiBgZXhwb3J0ICpgIGZvciB0aGF0IHJlYXNvbjogdGhlIGV4dHJhY3RlZCBtb2R1bGVzIGFsc28gZXhwb3J0IGludGVybmFsc1xuLy8gKG9yZ1Njb3BlLCBydW5SZXBvcnQsIHRoZSBjYWNoZXMsIHRoZSBET1JBIHJvdyBzaGFwZXMpIHRoYXQgd2VyZSBwcml2YXRlXG4vLyBiZWZvcmUgYW5kIG11c3Qgc3RheSB0aGF0IHdheS5cbmV4cG9ydCB0eXBlIHtcbiAgQnVpbGRIZWFsdGgsIEJ1aWxkSGVhbHRoU3RhZ2UsIERvcmFFbnZNZXRyaWNzLCBEb3JhTGV2ZWwsIERvcmFNZXRyaWNzLCBEb3JhT3B0aW9ucywgRG9yYVRyZW5kUG9pbnQsXG4gIEluY2lkZW50SW5wdXQsIEluY2lkZW50TGlzdEl0ZW0sIEluY2lkZW50U2V0dGluZ3MsIEluY2lkZW50VGVzdFJlc3VsdCxcbiAgSW5nZXN0RXZlbnQsIEluZ2VzdE1ldHJpYywgSW5nZXN0UmVzdWx0LFxuICBSZXBvcnRpbmdSZXRlbnRpb25Db3VudHMsIFJlcG9ydGluZ1JldGVudGlvbk9wdGlvbnMsIFJlcG9ydGluZ1JldGVudGlvblNldHRpbmdzLFxuICBSZXBvcnRpbmdTZXR0aW5nc1BhdGNoLFxufSBmcm9tICcuL3JlcG9ydGluZy90eXBlcy5qcyc7XG5leHBvcnQgeyByZXNvbHZlRG9yYVJldGVudGlvbkRheXMsIHJlc29sdmVFdmVudFJldGVudGlvbkRheXMsIHJldGVudGlvbkN1dG9mZiB9IGZyb20gJy4vcmVwb3J0aW5nL3JldGVudGlvbi5qcyc7XG5cblxuY29uc3QgbG9nZ2VyID0gY3JlYXRlTG9nZ2VyKCdyZXBvcnRpbmctc2VydmljZScpO1xuXG5leHBvcnQgY2xhc3MgUmVwb3J0aW5nU2VydmljZSB7XG5cbiAgLyoqIEludmFsaWRhdGUgYWxsIGNhY2hlZCByZXBvcnRzIGZvciBhbiBvcmcgKGNhbGwgYWZ0ZXIgZXZlbnQgaW5nZXN0KS4gKi9cbiAgYXN5bmMgaW52YWxpZGF0ZU9yZyhvcmdJZDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgaW52ZW50b3J5Q2FjaGUuaW52YWxpZGF0ZVBhdHRlcm4oYCR7b3JnSWR9OipgKSxcbiAgICAgIHRpbWVzZXJpZXNDYWNoZS5pbnZhbGlkYXRlUGF0dGVybihgJHtvcmdJZH06KmApLFxuICAgIF0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc29sdmUgaW5jb21pbmcgZXZlbnRzIGFnYWluc3QgdGhlIHBpcGVsaW5lIHJlZ2lzdHJ5LCBiYXRjaC1pbnNlcnQgdGhlXG4gICAqIG1hdGNoZWQgb25lcywgYW5kIGludmFsaWRhdGUgcmVwb3J0aW5nIGNhY2hlcyBmb3IgYWZmZWN0ZWQgb3Jncy5cbiAgICogRXZlbnRzIGZvciB1bnJlZ2lzdGVyZWQgcGlwZWxpbmUgaWRzIGFyZSBkcm9wcGVkIChhbmQgbG9nZ2VkIGF0IFdBUk5cbiAgICogd2l0aCBzYW1wbGUgaWRzIHNvIGFuIG9wZXJhdG9yIGNhbiBzZWUgd2hlbiBFdmVudEJyaWRnZSBpcyBkZWxpdmVyaW5nXG4gICAqIGV2ZW50cyBmb3IgcGlwZWxpbmVzIHRoYXQgaGF2ZW4ndCBjYWxsZWQgUE9TVCAvcGlwZWxpbmVzL3JlZ2lzdHJ5IHlldCkuXG4gICAqXG4gICAqIFJldHVybnMgY291bnRzICsgYSBzYW1wbGUgb2YgdW5yZWdpc3RlcmVkIHBpcGVsaW5lIGlkcyBmb3Igb2JzZXJ2YWJpbGl0eS5cbiAgICovXG4gIGFzeW5jIGluZ2VzdEV2ZW50cyhldmVudHM6IEluZ2VzdEV2ZW50W10sIG9uTWV0cmljPzogKG06IEluZ2VzdE1ldHJpYykgPT4gdm9pZCk6IFByb21pc2U8SW5nZXN0UmVzdWx0PiB7XG4gICAgLy8gTXVsdGktb3JnIGJhdGNoIGluc2VydDogdGhlIGNhbGxlciByZXNvbHZlcyB0byBtdWx0aXBsZSBvcmdzIHZpYSB0aGVcbiAgICAvLyBwaXBlbGluZS1yZWdpc3RyeSBsb29rdXAgYmVsb3csIHNvIHRoZSByb3V0ZSBsYXllciBNVVNUIGVzdGFibGlzaCBhXG4gICAgLy8gYHJ1bldpdGhUZW5hbnRDb250ZXh0KHsgaXNTdXBlckFkbWluOiB0cnVlIH0sIC4uLilgIHNjb3BlIGJlZm9yZSBjYWxsaW5nXG4gICAgLy8gdGhpcyBtZXRob2QuIFVuZGVyIEZPUkNFJ2QgUkxTLCBhIHNpbmdsZSB0eCB3aXRoIGBhcHAub3JnX2lkID0gPG9uZVxuICAgIC8vIG9yZz5gIGNvdWxkIG9ubHkgd3JpdGUgZXZlbnRzIGZvciB0aGF0IG9yZzsgYnlwYXNzIHZpYSBzeXNhZG1pbiBpc1xuICAgIC8vIHRoZSByaWdodCBnYXRlIGZvciB0aGlzIHNlcnZlci1pbnRlcm5hbCBjcm9zcy10ZW5hbnQgZW5kcG9pbnQuIFNlZVxuICAgIC8vIGFwaS9yZXBvcnRpbmcvc3JjL3JvdXRlcy9ldmVudC1pbmdlc3QudHMgZm9yIHRoZSB3cmFwcGVyLlxuICAgIC8vIFJ1biBpbnNlcnQgaW5zaWRlIHRoZSB0eCwgYnV0IENPTExFQ1QgYWZmZWN0ZWQgb3JncyBhbmQgaW52YWxpZGF0ZVxuICAgIC8vIGNhY2hlcyBBRlRFUiB0aGUgdHggcmVzb2x2ZXMuIEtlZXBpbmcgaW52YWxpZGF0aW9uIGluc2lkZSB0aGUgdHggaGVsZFxuICAgIC8vIHRoZSBwZyBsb2NrcyBvcGVuIGZvciB0aGUgZHVyYXRpb24gb2YgdGhlIGNhY2hlIHJvdW5kLXRyaXBzIChSZWRpcyBvclxuICAgIC8vIGluLW1lbW9yeSBpbnZhbGlkYXRpb25zIGFyZSB1bnJlbGF0ZWQgdG8gdGhlIHR4IGJ1dCBzdGlsbCBzZXJpYWxpemVkXG4gICAgLy8gaXRzIGNvbW1pdCkuIENhY2hlIFRUTCBpcyAyLTUgbWluIHNvIGZpcmUtYW5kLWZvcmdldCBwb3N0LWNvbW1pdCBpc1xuICAgIC8vIGFuIGFjY2VwdGFibGUgdHJhZGUgZm9yIHRpZ2h0ZXIgbG9jayB3aW5kb3dzLlxuICAgIGNvbnN0IHsgaW5zZXJ0ZWQsIHNraXBwZWQsIHVucmVnaXN0ZXJlZFBpcGVsaW5lSWRzLCBhZmZlY3RlZE9yZ3MgfSA9IGF3YWl0IHdpdGhUZW5hbnRUeChhc3luYyAodHgpID0+IHtcbiAgICAgIC8vIEJhdGNoLXJlc29sdmUgYWxsIHVuaXF1ZSBwaXBlbGluZSBpZHMgaW4gb25lIHF1ZXJ5XG4gICAgICBjb25zdCB1bmlxdWVJZHMgPSBbLi4ubmV3IFNldChldmVudHMubWFwKGUgPT4gZS5waXBlbGluZUlkKSldO1xuICAgICAgY29uc3QgcmVnaXN0cnlSb3dzID0gYXdhaXQgdHhcbiAgICAgICAgLnNlbGVjdCh7XG4gICAgICAgICAgcGlwZWxpbmVJZDogc2NoZW1hLnBpcGVsaW5lUmVnaXN0cnkucGlwZWxpbmVJZCxcbiAgICAgICAgICBvcmdJZDogc2NoZW1hLnBpcGVsaW5lUmVnaXN0cnkub3JnSWQsXG4gICAgICAgIH0pXG4gICAgICAgIC5mcm9tKHNjaGVtYS5waXBlbGluZVJlZ2lzdHJ5KVxuICAgICAgICAud2hlcmUoaW5BcnJheShzY2hlbWEucGlwZWxpbmVSZWdpc3RyeS5waXBlbGluZUlkLCB1bmlxdWVJZHMpKTtcblxuICAgICAgY29uc3QgaWRNYXAgPSBuZXcgTWFwKHJlZ2lzdHJ5Um93cy5tYXAociA9PiBbci5waXBlbGluZUlkLCByXSkpO1xuXG4gICAgICAvLyBCdWlsZCBpbnNlcnQgYmF0Y2ggKHNraXAgZXZlbnRzIHdob3NlIHBpcGVsaW5lIGlzbid0IHJlZ2lzdGVyZWQpXG4gICAgICBjb25zdCByb3dzOiBBcnJheTx0eXBlb2Ygc2NoZW1hLnBpcGVsaW5lRXZlbnQuJGluZmVySW5zZXJ0PiA9IFtdO1xuICAgICAgbGV0IHNraXBwZWRMb2NhbCA9IDA7XG4gICAgICBjb25zdCB1bnJlZ2lzdGVyZWRMb2NhbDogc3RyaW5nW10gPSBbXTtcblxuICAgICAgZm9yIChjb25zdCBldmVudCBvZiBldmVudHMpIHtcbiAgICAgICAgY29uc3QgcmVnaXN0cnkgPSBpZE1hcC5nZXQoZXZlbnQucGlwZWxpbmVJZCk7XG4gICAgICAgIGlmICghcmVnaXN0cnkpIHtcbiAgICAgICAgICBza2lwcGVkTG9jYWwrKztcbiAgICAgICAgICB1bnJlZ2lzdGVyZWRMb2NhbC5wdXNoKGV2ZW50LnBpcGVsaW5lSWQpO1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgcm93cy5wdXNoKHtcbiAgICAgICAgICAvLyByZWdpc3RyeS5waXBlbGluZUlkID09PSBldmVudC5waXBlbGluZUlkOyB1c2UgdGhlIHJlZ2lzdHJ5J3Mgc28gdGhlXG4gICAgICAgICAgLy8gRksgaXMgYWx3YXlzIGEgcm93IHRoYXQgZXhpc3RzLCBhbmQgcHVsbCBvcmdJZCBmcm9tIHRoZSByZWdpc3RyeSBmb3JcbiAgICAgICAgICAvLyB0ZW5hbmN5IChuZXZlciB0cnVzdCB0aGUgY2FsbGVyJ3MgY2xhaW1lZCBvcmcpLlxuICAgICAgICAgIHBpcGVsaW5lSWQ6IHJlZ2lzdHJ5LnBpcGVsaW5lSWQsXG4gICAgICAgICAgb3JnSWQ6IHJlZ2lzdHJ5Lm9yZ0lkLFxuICAgICAgICAgIGV2ZW50U291cmNlOiBldmVudC5ldmVudFNvdXJjZSxcbiAgICAgICAgICBldmVudFR5cGU6IGV2ZW50LmV2ZW50VHlwZSxcbiAgICAgICAgICBzdGF0dXM6IGV2ZW50LnN0YXR1cyxcbiAgICAgICAgICAvLyBleGVjdXRpb25JZCBpcyBhbiBBV1MtQVNTSUdORUQgaWRlbnRpZmllciAoYSBVVUlEKSwgbm90IGZyZWUtZm9ybVxuICAgICAgICAgIC8vIHVzZXIgdGV4dCwgc28gaXQgY2FuJ3QgY2FycnkgYW4gYWNjb3VudCBpZCDigJQgYW5kIHNjcnViYmluZyBhIFVVSURcbiAgICAgICAgICAvLyB0aGF0IGhhcHBlbnMgdG8gY29udGFpbiBhIDEyLWRpZ2l0IHJ1biB3b3VsZCBjb3JydXB0IHRoZSBjb3JyZWxhdGlvblxuICAgICAgICAgIC8vIGtleS4gTGVmdCBpbnRhY3QgYnkgZGVzaWduLlxuICAgICAgICAgIGV4ZWN1dGlvbklkOiBldmVudC5leGVjdXRpb25JZCxcbiAgICAgICAgICAvLyBzdGFnZU5hbWUvYWN0aW9uTmFtZSBhcmUgVVNFUi1BVVRIT1JFRCBwaXBlbGluZS1zdHJ1Y3R1cmUgbmFtZXNcbiAgICAgICAgICAvLyBwcm9tb3RlZCBmcm9tIHRoZSBDb2RlUGlwZWxpbmUgZGV0YWlsIOKAlCBzYW1lIHVudHJ1c3RlZC1BV1MtZGVyaXZlZFxuICAgICAgICAgIC8vIG9yaWdpbiBhcyBlcnJvck1lc3NhZ2UgYmVsb3csIHNvIHNjcnViIHRoZW0gYXQgdGhpcyBwZXJzaXN0ZW5jZVxuICAgICAgICAgIC8vIGJvdW5kYXJ5IHRvbyAoYSBzdGFnZSBuYW1lZCB3aXRoIGFuIEFSTi8xMi1kaWdpdCBpZCBtdXN0IG5vdCBwZXJzaXN0KS5cbiAgICAgICAgICBzdGFnZU5hbWU6IHNjcnViT3B0aW9uYWwoZXZlbnQuc3RhZ2VOYW1lKSxcbiAgICAgICAgICBhY3Rpb25OYW1lOiBzY3J1Yk9wdGlvbmFsKGV2ZW50LmFjdGlvbk5hbWUpLFxuICAgICAgICAgIC8vIEhBUkQgQ09OU1RSQUlOVDogYW4gQVdTIGFjY291bnQgaWQgbXVzdCBORVZFUiBiZSBwZXJzaXN0ZWQuIFRoaXMgaXNcbiAgICAgICAgICAvLyB0aGUgRFVSQUJMRSBwZXJzaXN0ZW5jZSBib3VuZGFyeSBhbmQgbXVzdCBub3QgdHJ1c3QgdXBzdHJlYW06XG4gICAgICAgICAgLy8gQ29kZVBpcGVsaW5lL0NvZGVCdWlsZCBmYWlsdXJlIGRldGFpbCAmIG1lc3NhZ2VzIHJvdXRpbmVseSBjYXJyeVxuICAgICAgICAgIC8vIEFSTnMgKGFybjphd3M64oCmOjxhY2NvdW50LWlkPjrigKYpIGFuZCBiYXJlIDEyLWRpZ2l0IGFjY291bnQgaWRzLiBTY3J1YlxuICAgICAgICAgIC8vIGJvdGggZnJlZS1mb3JtIGZpZWxkcyBoZXJlIGJlZm9yZSBpbnNlcnQgKHBlci1ldmVudCwgbm9uLW11dGF0aW5nKS5cbiAgICAgICAgICBlcnJvck1lc3NhZ2U6IHNjcnViT3B0aW9uYWwoZXZlbnQuZXJyb3JNZXNzYWdlKSxcbiAgICAgICAgICBzdGFydGVkQXQ6IGV2ZW50LnN0YXJ0ZWRBdCA/IG5ldyBEYXRlKGV2ZW50LnN0YXJ0ZWRBdCkgOiB1bmRlZmluZWQsXG4gICAgICAgICAgY29tcGxldGVkQXQ6IGV2ZW50LmNvbXBsZXRlZEF0ID8gbmV3IERhdGUoZXZlbnQuY29tcGxldGVkQXQpIDogdW5kZWZpbmVkLFxuICAgICAgICAgIGR1cmF0aW9uTXM6IGV2ZW50LmR1cmF0aW9uTXMsXG4gICAgICAgICAgLy8gRGVwbG95LWF0dHJpYnV0aW9uIGZpZWxkcyDigJQgc2NydWJiZWQgbGlrZSB0aGUgb3RoZXIgZnJlZS1mb3JtIHN0cmluZ3NcbiAgICAgICAgICAvLyBzbyBhbiBBUk4vYWNjb3VudCBpZCBjYW4gbmV2ZXIgZW50ZXIgdmlhIGEgcmVmIG9yIGVudmlyb25tZW50IG5hbWUuXG4gICAgICAgICAgY29tbWl0U2hhOiBzY3J1Yk9wdGlvbmFsKGV2ZW50LmNvbW1pdFNoYSksXG4gICAgICAgICAgY29tbWl0UmVmOiBzY3J1Yk9wdGlvbmFsKGV2ZW50LmNvbW1pdFJlZiksXG4gICAgICAgICAgZW52aXJvbm1lbnQ6IHNjcnViT3B0aW9uYWwoZXZlbnQuZW52aXJvbm1lbnQpLFxuICAgICAgICAgIC8vIE1lYXN1cmVkIGxlYWQgdGltZSAoUGhhc2UgNCk6IG9sZGVzdCB1bnNoaXBwZWQgY29tbWl0IHRpbWUgKyBjb3VudC5cbiAgICAgICAgICAvLyBjb21taXRUaW1lc3RhbXAgaXMgYW4gQVdTL1NDTS1kZXJpdmVkIGluc3RhbnQgKG5ldmVyIGFjY291bnQtaWRcbiAgICAgICAgICAvLyBzaGFwZWQpOyBjb21taXRDb3VudCBpcyBhIHBsYWluIGludGVnZXIuIE5laXRoZXIgbmVlZHMgc2NydWJiaW5nLlxuICAgICAgICAgIGNvbW1pdFRpbWVzdGFtcDogZXZlbnQuY29tbWl0VGltZXN0YW1wID8gbmV3IERhdGUoZXZlbnQuY29tbWl0VGltZXN0YW1wKSA6IHVuZGVmaW5lZCxcbiAgICAgICAgICBjb21taXRDb3VudDogZXZlbnQuY29tbWl0Q291bnQsXG4gICAgICAgICAgZGV0YWlsOiBldmVudC5kZXRhaWwgIT09IHVuZGVmaW5lZFxuICAgICAgICAgICAgPyBzY3J1YkF3c0lkZW50aWZpZXJzKGV2ZW50LmRldGFpbClcbiAgICAgICAgICAgIDogdW5kZWZpbmVkLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyBQaGFzZSAzYjogZmFuIHRlcm1pbmFsIFNUQUdFIG91dGNvbWVzIGludG8gUHJvbWV0aGV1cyBjb3VudGVycyB2aWEgdGhlXG4gICAgICAgIC8vIHJvdXRlJ3MgaG9vayAocGlwZWxpbmUtZGF0YSBjYW4ndCBpbXBvcnQgYXBpLXNlcnZlcidzIHJlZ2lzdHJ5KS4gRW1pdFxuICAgICAgICAvLyBwZXIgcmVnaXN0ZXJlZCBzdGFnZSBldmVudCB3aXRoIGEgdGVybWluYWwgc3VjY2VlZGVkL2ZhaWxlZCByZXN1bHQ7XG4gICAgICAgIC8vIGEgbm9uLW51bGwgZW52aXJvbm1lbnQgYWRkaXRpb25hbGx5IG1hcmtzIGl0IGEgZGVwbG95IHJlc3VsdC5cbiAgICAgICAgaWYgKG9uTWV0cmljICYmIGV2ZW50LmV2ZW50VHlwZSA9PT0gJ1NUQUdFJyAmJiAoZXZlbnQuc3RhdHVzID09PSAnU1VDQ0VFREVEJyB8fCBldmVudC5zdGF0dXMgPT09ICdGQUlMRUQnKSkge1xuICAgICAgICAgIG9uTWV0cmljKHtcbiAgICAgICAgICAgIHBpcGVsaW5lSWQ6IHJlZ2lzdHJ5LnBpcGVsaW5lSWQsXG4gICAgICAgICAgICBvcmdJZDogcmVnaXN0cnkub3JnSWQsXG4gICAgICAgICAgICBzdGFnZTogc2NydWJPcHRpb25hbChldmVudC5zdGFnZU5hbWUpID8/ICcnLFxuICAgICAgICAgICAgZW52aXJvbm1lbnQ6IHNjcnViT3B0aW9uYWwoZXZlbnQuZW52aXJvbm1lbnQpID8/IG51bGwsXG4gICAgICAgICAgICByZXN1bHQ6IGV2ZW50LnN0YXR1cyA9PT0gJ1NVQ0NFRURFRCcgPyAnc3VjY2VlZGVkJyA6ICdmYWlsZWQnLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIFNRUyBpcyBhdC1sZWFzdC1vbmNlLCBzbyBFdmVudEJyaWRnZSBjYW4gZGVsaXZlciB0aGUgc2FtZSBzdGF0ZS1jaGFuZ2VcbiAgICAgIC8vIHR3aWNlLiBgb25Db25mbGljdERvTm90aGluZ2AgKyB0aGUgcGFydGlhbCB1bmlxdWUgaW5kZXggb25cbiAgICAgIC8vIChwaXBlbGluZV9pZCwgZXhlY3V0aW9uX2lkLCBldmVudF90eXBlLCBzdGF0dXMsIHN0YWdlX25hbWUsIGFjdGlvbl9uYW1lKVxuICAgICAgLy8gbWFrZXMgcmUtZGVsaXZlcnkgaWRlbXBvdGVudC4gYHJldHVybmluZ2AgZ2l2ZXMgdGhlIFJFQUwgaW5zZXJ0ZWQgc2V0IHNvXG4gICAgICAvLyBjb3VudHMgKyBjYWNoZSBpbnZhbGlkYXRpb24gaWdub3JlIGR1cGxpY2F0ZXMuXG4gICAgICBjb25zdCBpbnNlcnRlZFJvd3MgPSByb3dzLmxlbmd0aCA+IDBcbiAgICAgICAgPyBhd2FpdCB0eC5pbnNlcnQoc2NoZW1hLnBpcGVsaW5lRXZlbnQpLnZhbHVlcyhyb3dzKVxuICAgICAgICAgIC5vbkNvbmZsaWN0RG9Ob3RoaW5nKClcbiAgICAgICAgICAucmV0dXJuaW5nKHsgb3JnSWQ6IHNjaGVtYS5waXBlbGluZUV2ZW50Lm9yZ0lkIH0pXG4gICAgICAgIDogW107XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIGluc2VydGVkOiBpbnNlcnRlZFJvd3MubGVuZ3RoLFxuICAgICAgICBza2lwcGVkOiBza2lwcGVkTG9jYWwsXG4gICAgICAgIHVucmVnaXN0ZXJlZFBpcGVsaW5lSWRzOiB1bnJlZ2lzdGVyZWRMb2NhbCxcbiAgICAgICAgYWZmZWN0ZWRPcmdzOiBbLi4ubmV3IFNldChpbnNlcnRlZFJvd3MubWFwKHIgPT4gci5vcmdJZCkpXSxcbiAgICAgIH07XG4gICAgfSk7XG5cbiAgICAvLyBTdXJmYWNlIHRoZSBzaWxlbnQgc2tpcDogYW4gdW5yZWdpc3RlcmVkIHBpcGVsaW5lIGlkIHVzdWFsbHkgbWVhbnMgdGhlXG4gICAgLy8gcGlwZWxpbmUgaGFzbid0IGNhbGxlZCBQT1NUIC9waXBlbGluZXMvcmVnaXN0cnkgeWV0IChvciBpdHNcbiAgICAvLyBwYi5waXBlbGluZS1pZCB0YWcgaXMgbWlzc2luZy91bnJlYWRhYmxlIGJ5IHRoZSBMYW1iZGEpLiBMb2dnaW5nIGl0XG4gICAgLy8gbWFrZXMgYSBicm9rZW4gam9pbiB2aXNpYmxlIGluc3RlYWQgb2YgbG9va2luZyBsaWtlIFwibm8gYWN0aXZpdHlcIi5cbiAgICBpZiAodW5yZWdpc3RlcmVkUGlwZWxpbmVJZHMubGVuZ3RoID4gMCkge1xuICAgICAgbG9nZ2VyLndhcm4oJ1BpcGVsaW5lIGV2ZW50cyBza2lwcGVkOiBwaXBlbGluZSBpZCBub3QgZm91bmQgaW4gcmVnaXN0cnknLCB7XG4gICAgICAgIGNvdW50OiB1bnJlZ2lzdGVyZWRQaXBlbGluZUlkcy5sZW5ndGgsXG4gICAgICAgIHNhbXBsZTogdW5yZWdpc3RlcmVkUGlwZWxpbmVJZHMuc2xpY2UoMCwgMyksXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBQb3N0LWNvbW1pdCBjYWNoZSBpbnZhbGlkYXRpb24uIEZpcmUtYW5kLWZvcmdldCB3aXRoIGxvZ2dpbmcg4oCUIFRUTCBpc1xuICAgIC8vIHNob3J0IGVub3VnaCB0aGF0IGEgbWlzc2VkIGludmFsaWRhdGlvbiBzZWxmLWhlYWxzLlxuICAgIGlmIChhZmZlY3RlZE9yZ3MubGVuZ3RoID4gMCkge1xuICAgICAgdm9pZCBQcm9taXNlLmFsbChhZmZlY3RlZE9yZ3MubWFwKChvcmcpID0+XG4gICAgICAgIHRoaXMuaW52YWxpZGF0ZU9yZyhvcmcpLmNhdGNoKChlcnIpID0+IHtcbiAgICAgICAgICBsb2dnZXIud2FybignUmVwb3J0aW5nIGNhY2hlIGludmFsaWRhdGlvbiBmYWlsZWQnLCB7IG9yZ0lkOiBvcmcsIGVycm9yOiBlcnJvck1lc3NhZ2UoZXJyKSB9KTtcbiAgICAgICAgfSksXG4gICAgICApKTtcbiAgICB9XG5cbiAgICByZXR1cm4geyBpbnNlcnRlZCwgc2tpcHBlZCwgdW5yZWdpc3RlcmVkUGlwZWxpbmVJZHMgfTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBDYXRlZ29yeSAxOiBQaXBlbGluZSBFeGVjdXRpb24gJiBQZXJmb3JtYW5jZSDilIDilIBcblxuXG4gIC8qKiAxLjEgRXhlY3V0aW9uIGNvdW50IHBlciBwaXBlbGluZSB3aXRoIHN0YXR1cyBicmVha2Rvd24uICovXG4gIGFzeW5jIGdldEV4ZWN1dGlvbkNvdW50KG9yZ0lkOiBzdHJpbmcsIG9yZ0lkcz86IHN0cmluZ1tdLCByYW5nZT86IHsgZnJvbT86IHN0cmluZzsgdG8/OiBzdHJpbmcgfSk6IFByb21pc2U8RXhlY3V0aW9uQ291bnRbXT4ge1xuICAgIGNvbnN0IHsgcHJlZCwgbXVsdGkgfSA9IG9yZ1Njb3BlKG9yZ0lkLCBvcmdJZHMpO1xuICAgIC8vIE9wdGlvbmFsIFtmcm9tLHRvXSB3aW5kb3cgb24gdGhlIGV4ZWN1dGlvbidzIHN0YXJ0ZWRfYXQsIG1pcnJvcmluZyB0aGVcbiAgICAvLyBzaWJsaW5nIHRpbWVzZXJpZXMgcmVwb3J0cyBzbyB0aGUgZGFzaGJvYXJkIGRhdGUtcmFuZ2UgcGlja2VyIG5hcnJvd3MgdGhlXG4gICAgLy8gY291bnQgdG9vIChhbiBlbXB0eSByYW5nZSA9IGFsbC10aW1lLCBwcmVzZXJ2aW5nIHRoZSBwcmlvciBiZWhhdmlvcikuIFRoZVxuICAgIC8vIHJhbmdlIHJpZGVzIHRoZSBKT0lOIHNvIHBpcGVsaW5lcyB3aXRoIG5vIGluLXdpbmRvdyBldmVudHMgc3RpbGwgbGlzdFxuICAgIC8vIChMRUZUIHNlbWFudGljcyBwcmVzZXJ2ZWQgdmlhIHRoZSBpbm5lci1qb2luIGZpbHRlciDigJQgYSBwaXBlbGluZSB3aXRoIHplcm9cbiAgICAvLyBtYXRjaGluZyBldmVudHMgZHJvcHMgZnJvbSB0aGUgY291bnQsIHNhbWUgYXMgYmVmb3JlIGZvciBpdHMgd2luZG93KS5cbiAgICBjb25zdCByYW5nZUNsYXVzZSA9IG9wdGlvbmFsU3RhcnRlZEF0UmFuZ2UocmFuZ2UpO1xuICAgIGNvbnN0IGV4ZWMgPSAoKSA9PiB3aXRoVGVuYW50VHgoKHR4KSA9PiB0eC5leGVjdXRlKHNxbGBcbiAgICAgICAgU0VMRUNUXG4gICAgICAgICAgcC5pZCwgcC5wcm9qZWN0LCBwLm9yZ2FuaXphdGlvbiwgcC5waXBlbGluZV9uYW1lLFxuICAgICAgICAgIENPVU5UKCopOjppbnQgQVMgdG90YWwsXG4gICAgICAgICAgQ09VTlQoKikgRklMVEVSIChXSEVSRSBlLnN0YXR1cyA9ICdTVUNDRUVERUQnKTo6aW50IEFTIHN1Y2NlZWRlZCxcbiAgICAgICAgICBDT1VOVCgqKSBGSUxURVIgKFdIRVJFIGUuc3RhdHVzID0gJ0ZBSUxFRCcpOjppbnQgQVMgZmFpbGVkLFxuICAgICAgICAgIENPVU5UKCopIEZJTFRFUiAoV0hFUkUgZS5zdGF0dXMgPSAnQ0FOQ0VMRUQnKTo6aW50IEFTIGNhbmNlbGVkLFxuICAgICAgICAgIE1JTihlLnN0YXJ0ZWRfYXQpOjp0ZXh0IEFTIGZpcnN0X2V4ZWN1dGlvbixcbiAgICAgICAgICBNQVgoZS5zdGFydGVkX2F0KTo6dGV4dCBBUyBsYXN0X2V4ZWN1dGlvblxuICAgICAgICBGUk9NICR7c2NoZW1hLnBpcGVsaW5lfSBwXG4gICAgICAgIEpPSU4gJHtzY2hlbWEucGlwZWxpbmVFdmVudH0gZSBPTiBlLnBpcGVsaW5lX2lkID0gcC5pZFxuICAgICAgICAgIEFORCBlLmV2ZW50X3R5cGUgPSAnUElQRUxJTkUnIEFORCBlLnN0YXR1cyAhPSAnU1RBUlRFRCdcbiAgICAgICAgICAke3JhbmdlQ2xhdXNlfVxuICAgICAgICBXSEVSRSBwLm9yZ19pZCAke3ByZWR9IEFORCBwLmlzX2FjdGl2ZSA9IHRydWVcbiAgICAgICAgR1JPVVAgQlkgcC5pZFxuICAgICAgICBPUkRFUiBCWSB0b3RhbCBERVNDXG4gICAgICBgKS50aGVuKHIgPT4gZHJpenpsZVJvd3M8RXhlY3V0aW9uQ291bnQ+KHIucm93cykpKTtcbiAgICByZXR1cm4gcnVuUmVwb3J0KGAke29yZ0lkfTpleGVjLWNvdW50OiR7cmFuZ2U/LmZyb20gPz8gJyd9OiR7cmFuZ2U/LnRvID8/ICcnfWAsIG11bHRpLCBleGVjKTtcbiAgfVxuXG4gIC8qKlxuICAgKiAxLjFiIFBlci1waXBlbGluZSBleGVjdXRpb24gaGlzdG9yeSDigJQgRElTVElOQ1QgZXhlY3V0aW9ucyBmb3Igb25lIHBpcGVsaW5lLFxuICAgKiBuZXdlc3QgZmlyc3QuIEdyb3VwcyBhbGwgZXZlbnRzIGJ5IGBleGVjdXRpb25faWRgIGluIGEgc2luZ2xlIHNjYW4gYW5kXG4gICAqIHJvbGxzIGVhY2ggZXhlY3V0aW9uIHVwIHRvIG9uZSByb3c6XG4gICAqICAgLSBzdGF0dXM6IGRlcml2ZWQgZnJvbSB0aGUgUElQRUxJTkUtdHlwZSBldmVudHMuIEZBSUxFRCB3aW5zLCB0aGVuXG4gICAqICAgICBTVUNDRUVERUQsIHRoZW4gQ0FOQ0VMRUQ7IGFuIGV4ZWN1dGlvbiB3aXRoIG5vIHRlcm1pbmFsIFBJUEVMSU5FIGV2ZW50XG4gICAqICAgICBpcyBzdGlsbCBgaW4tcHJvZ3Jlc3NgLlxuICAgKiAgIC0gc3RhcnRlZEF0L2VuZGVkQXQvZHVyYXRpb25NczogZnJvbSB0aGUgUElQRUxJTkUgbGlmZWN5Y2xlIGV2ZW50cy5cbiAgICogICAtIGZhaWxpbmdTdGFnZS9mYWlsaW5nQWN0aW9uOiB0aGUgZmlyc3QgRkFJTEVEIFNUQUdFL0FDVElPTiBldmVudCAoY2hlYXAg4oCUXG4gICAqICAgICBzYW1lIHNjYW4sIG5vIGV4dHJhIHF1ZXJ5KS5cbiAgICpcbiAgICogT1JHLVNDT1BJTkc6IGlkZW50aWNhbCB0byB0aGUgc2libGluZyBleGVjdXRpb24gcmVwb3J0cyDigJQgam9pbnMgdGhlIHBpcGVsaW5lXG4gICAqIHJlZ2lzdHJ5IHRhYmxlIChgcGlwZWxpbmVgKSBhbmQgZ2F0ZXMgb24gYHAub3JnX2lkICR7cHJlZH1gLCB3aGVyZSBgcHJlZGAgaXNcbiAgICogdGhlIHNpbmdsZS1vcmcgYD0gJG9yZ2Agb3IgKHdpdGggYSByb2xsdXApIGFuIGBJTiAoLi4uKWAgb3ZlciB0aGUgb3Jn4oaSdGVhbVxuICAgKiBzdWJ0cmVlLiBBIHBpcGVsaW5lSWQgYmVsb25naW5nIHRvIGFub3RoZXIgb3JnIHlpZWxkcyB6ZXJvIHJvd3MuXG4gICAqL1xuICBhc3luYyBsaXN0UGlwZWxpbmVFeGVjdXRpb25zKFxuICAgIG9yZ0lkOiBzdHJpbmcsXG4gICAgcGlwZWxpbmVJZDogc3RyaW5nLFxuICAgIG9yZ0lkcz86IHN0cmluZ1tdLFxuICAgIHJhbmdlPzogeyBmcm9tPzogc3RyaW5nOyB0bz86IHN0cmluZyB9LFxuICAgIGxpbWl0OiBudW1iZXIgPSA1MCxcbiAgKTogUHJvbWlzZTxQaXBlbGluZUV4ZWN1dGlvbltdPiB7XG4gICAgY29uc3QgeyBwcmVkLCBtdWx0aSB9ID0gb3JnU2NvcGUob3JnSWQsIG9yZ0lkcyk7XG4gICAgY29uc3QgcmFuZ2VDbGF1c2UgPSBvcHRpb25hbFN0YXJ0ZWRBdFJhbmdlKHJhbmdlKTtcbiAgICBjb25zdCBleGVjID0gKCkgPT4gd2l0aFRlbmFudFR4KCh0eCkgPT4gdHguZXhlY3V0ZShzcWxgXG4gICAgICAgIFNFTEVDVFxuICAgICAgICAgIGUuZXhlY3V0aW9uX2lkLFxuICAgICAgICAgIENBU0VcbiAgICAgICAgICAgIFdIRU4gYm9vbF9vcihlLmV2ZW50X3R5cGUgPSAnUElQRUxJTkUnIEFORCBlLnN0YXR1cyA9ICdGQUlMRUQnKSBUSEVOICdmYWlsZWQnXG4gICAgICAgICAgICBXSEVOIGJvb2xfb3IoZS5ldmVudF90eXBlID0gJ1BJUEVMSU5FJyBBTkQgZS5zdGF0dXMgPSAnU1VDQ0VFREVEJykgVEhFTiAnc3VjY2VlZGVkJ1xuICAgICAgICAgICAgV0hFTiBib29sX29yKGUuZXZlbnRfdHlwZSA9ICdQSVBFTElORScgQU5EIGUuc3RhdHVzID0gJ0NBTkNFTEVEJykgVEhFTiAnY2FuY2VsZWQnXG4gICAgICAgICAgICBFTFNFICdpbi1wcm9ncmVzcydcbiAgICAgICAgICBFTkQgQVMgc3RhdHVzLFxuICAgICAgICAgIE1JTihlLnN0YXJ0ZWRfYXQpIEZJTFRFUiAoV0hFUkUgZS5ldmVudF90eXBlID0gJ1BJUEVMSU5FJyk6OnRleHQgQVMgc3RhcnRlZF9hdCxcbiAgICAgICAgICBNQVgoZS5jb21wbGV0ZWRfYXQpIEZJTFRFUiAoV0hFUkUgZS5ldmVudF90eXBlID0gJ1BJUEVMSU5FJyk6OnRleHQgQVMgZW5kZWRfYXQsXG4gICAgICAgICAgTUFYKGUuZHVyYXRpb25fbXMpIEZJTFRFUiAoV0hFUkUgZS5ldmVudF90eXBlID0gJ1BJUEVMSU5FJyk6OmludCBBUyBkdXJhdGlvbl9tcyxcbiAgICAgICAgICAoQVJSQVlfQUdHKGUuc3RhZ2VfbmFtZSkgRklMVEVSIChXSEVSRSBlLmV2ZW50X3R5cGUgPSAnU1RBR0UnIEFORCBlLnN0YXR1cyA9ICdGQUlMRUQnKSlbMV0gQVMgZmFpbGluZ19zdGFnZSxcbiAgICAgICAgICAoQVJSQVlfQUdHKGUuYWN0aW9uX25hbWUpIEZJTFRFUiAoV0hFUkUgZS5ldmVudF90eXBlID0gJ0FDVElPTicgQU5EIGUuc3RhdHVzID0gJ0ZBSUxFRCcpKVsxXSBBUyBmYWlsaW5nX2FjdGlvblxuICAgICAgICBGUk9NICR7c2NoZW1hLnBpcGVsaW5lRXZlbnR9IGVcbiAgICAgICAgSk9JTiAke3NjaGVtYS5waXBlbGluZX0gcCBPTiBwLmlkID0gZS5waXBlbGluZV9pZFxuICAgICAgICBXSEVSRSBwLm9yZ19pZCAke3ByZWR9IEFORCBlLnBpcGVsaW5lX2lkID0gJHtwaXBlbGluZUlkfSBBTkQgZS5leGVjdXRpb25faWQgSVMgTk9UIE5VTExcbiAgICAgICAgICAke3JhbmdlQ2xhdXNlfVxuICAgICAgICBHUk9VUCBCWSBlLmV4ZWN1dGlvbl9pZFxuICAgICAgICBPUkRFUiBCWSBNQVgoZS5jcmVhdGVkX2F0KSBERVNDXG4gICAgICAgIExJTUlUICR7bGltaXR9XG4gICAgICBgKS50aGVuKHIgPT4gZHJpenpsZVJvd3M8UGlwZWxpbmVFeGVjdXRpb24+KHIucm93cykpKTtcbiAgICByZXR1cm4gcnVuUmVwb3J0KGAke29yZ0lkfTpwaXBlbGluZS1leGVjdXRpb25zOiR7cGlwZWxpbmVJZH06JHtyYW5nZT8uZnJvbSA/PyAnJ306JHtyYW5nZT8udG8gPz8gJyd9OiR7bGltaXR9YCwgbXVsdGksIGV4ZWMpO1xuICB9XG5cbiAgLyoqIDEuMiBTdWNjZXNzIHJhdGUgb3ZlciB0aW1lIGZvciBhbiBvcmcuICovXG4gIGFzeW5jIGdldFN1Y2Nlc3NSYXRlKG9yZ0lkOiBzdHJpbmcsIGludGVydmFsOiBzdHJpbmcsIGZyb206IHN0cmluZywgdG86IHN0cmluZywgb3JnSWRzPzogc3RyaW5nW10pOiBQcm9taXNlPFRpbWVTZXJpZXNFbnRyeVtdPiB7XG4gICAgYXNzZXJ0UmVwb3J0SW50ZXJ2YWwoaW50ZXJ2YWwpO1xuICAgIGNvbnN0IHsgcHJlZCwgbXVsdGkgfSA9IG9yZ1Njb3BlKG9yZ0lkLCBvcmdJZHMpO1xuICAgIGNvbnN0IGV4ZWMgPSAoKSA9PiB3aXRoVGVuYW50VHgoKHR4KSA9PiB0eC5leGVjdXRlKHNxbGBcbiAgICAgICAgU0VMRUNUXG4gICAgICAgICAgREFURV9UUlVOQygke2ludGVydmFsfSwgZS5zdGFydGVkX2F0KTo6dGV4dCBBUyBwZXJpb2QsXG4gICAgICAgICAgQ09VTlQoKikgRklMVEVSIChXSEVSRSBlLnN0YXR1cyA9ICdTVUNDRUVERUQnKTo6aW50IEFTIHN1Y2NlZWRlZCxcbiAgICAgICAgICBDT1VOVCgqKSBGSUxURVIgKFdIRVJFIGUuc3RhdHVzID0gJ0ZBSUxFRCcpOjppbnQgQVMgZmFpbGVkLFxuICAgICAgICAgIENPVU5UKCopIEZJTFRFUiAoV0hFUkUgZS5zdGF0dXMgPSAnQ0FOQ0VMRUQnKTo6aW50IEFTIGNhbmNlbGVkLFxuICAgICAgICAgIFJPVU5EKENPVU5UKCopIEZJTFRFUiAoV0hFUkUgZS5zdGF0dXMgPSAnU1VDQ0VFREVEJyk6Om51bWVyaWNcbiAgICAgICAgICAgIC8gTlVMTElGKENPVU5UKCopLCAwKSAqIDEwMCwgMSk6OmZsb2F0IEFTIHN1Y2Nlc3NfcGN0XG4gICAgICAgIEZST00gJHtzY2hlbWEucGlwZWxpbmVFdmVudH0gZVxuICAgICAgICBKT0lOICR7c2NoZW1hLnBpcGVsaW5lfSBwIE9OIHAuaWQgPSBlLnBpcGVsaW5lX2lkXG4gICAgICAgIFdIRVJFIHAub3JnX2lkICR7cHJlZH0gQU5EIGUuZXZlbnRfdHlwZSA9ICdQSVBFTElORSdcbiAgICAgICAgICBBTkQgZS5zdGF0dXMgSU4gKCdTVUNDRUVERUQnLCAnRkFJTEVEJywgJ0NBTkNFTEVEJylcbiAgICAgICAgICBBTkQgZS5zdGFydGVkX2F0ID49ICR7ZnJvbX06OnRpbWVzdGFtcHR6IEFORCBlLnN0YXJ0ZWRfYXQgPD0gJHt0b306OnRpbWVzdGFtcHR6XG4gICAgICAgIEdST1VQIEJZIHBlcmlvZCBPUkRFUiBCWSBwZXJpb2RcbiAgICAgIGApLnRoZW4ociA9PiBkcml6emxlUm93czxUaW1lU2VyaWVzRW50cnk+KHIucm93cykpKTtcbiAgICByZXR1cm4gcnVuUmVwb3J0KGAke29yZ0lkfTpzdWNjZXNzLXJhdGU6JHtpbnRlcnZhbH06JHtmcm9tfToke3RvfWAsIG11bHRpLCBleGVjKTtcbiAgfVxuXG4gIC8qKiAxLjMgQXZlcmFnZSBkdXJhdGlvbiBwZXIgcGlwZWxpbmUuICovXG4gIGFzeW5jIGdldEF2ZXJhZ2VEdXJhdGlvbihvcmdJZDogc3RyaW5nLCBmcm9tOiBzdHJpbmcsIHRvOiBzdHJpbmcsIG9yZ0lkcz86IHN0cmluZ1tdKTogUHJvbWlzZTxEdXJhdGlvblN0YXRzW10+IHtcbiAgICBjb25zdCB7IHByZWQsIG11bHRpIH0gPSBvcmdTY29wZShvcmdJZCwgb3JnSWRzKTtcbiAgICBjb25zdCBleGVjID0gKCkgPT4gd2l0aFRlbmFudFR4KCh0eCkgPT4gdHguZXhlY3V0ZShzcWxgXG4gICAgICAgIFNFTEVDVFxuICAgICAgICAgIHAuaWQsIHAucHJvamVjdCwgcC5waXBlbGluZV9uYW1lLFxuICAgICAgICAgIEFWRyhlLmR1cmF0aW9uX21zKTo6aW50IEFTIGF2Z19tcyxcbiAgICAgICAgICBNSU4oZS5kdXJhdGlvbl9tcyk6OmludCBBUyBtaW5fbXMsXG4gICAgICAgICAgTUFYKGUuZHVyYXRpb25fbXMpOjppbnQgQVMgbWF4X21zLFxuICAgICAgICAgIFBFUkNFTlRJTEVfQ09OVCgwLjk1KSBXSVRISU4gR1JPVVAgKE9SREVSIEJZIGUuZHVyYXRpb25fbXMpOjppbnQgQVMgcDk1X21zLFxuICAgICAgICAgIENPVU5UKCopOjppbnQgQVMgZXhlY3V0aW9uc1xuICAgICAgICBGUk9NICR7c2NoZW1hLnBpcGVsaW5lRXZlbnR9IGVcbiAgICAgICAgSk9JTiAke3NjaGVtYS5waXBlbGluZX0gcCBPTiBwLmlkID0gZS5waXBlbGluZV9pZFxuICAgICAgICBXSEVSRSBwLm9yZ19pZCAke3ByZWR9IEFORCBlLmV2ZW50X3R5cGUgPSAnUElQRUxJTkUnIEFORCBlLmR1cmF0aW9uX21zIElTIE5PVCBOVUxMXG4gICAgICAgICAgQU5EIGUuc3RhcnRlZF9hdCA+PSAke2Zyb219Ojp0aW1lc3RhbXB0eiBBTkQgZS5zdGFydGVkX2F0IDw9ICR7dG99Ojp0aW1lc3RhbXB0elxuICAgICAgICBHUk9VUCBCWSBwLmlkIE9SREVSIEJZIGF2Z19tcyBERVNDXG4gICAgICBgKS50aGVuKHIgPT4gZHJpenpsZVJvd3M8RHVyYXRpb25TdGF0cz4oci5yb3dzKSkpO1xuICAgIHJldHVybiBydW5SZXBvcnQoYCR7b3JnSWR9OmF2Zy1kdXJhdGlvbjoke2Zyb219OiR7dG99YCwgbXVsdGksIGV4ZWMpO1xuICB9XG5cbiAgLyoqIDEuNSBTdGFnZSBmYWlsdXJlIGhlYXRtYXAg4oCUIHdoaWNoIHN0YWdlcyBmYWlsIG1vc3QuICovXG4gIGFzeW5jIGdldFN0YWdlRmFpbHVyZXMob3JnSWQ6IHN0cmluZywgZnJvbTogc3RyaW5nLCB0bzogc3RyaW5nLCBvcmdJZHM/OiBzdHJpbmdbXSk6IFByb21pc2U8U3RhZ2VGYWlsdXJlW10+IHtcbiAgICBjb25zdCB7IHByZWQsIG11bHRpIH0gPSBvcmdTY29wZShvcmdJZCwgb3JnSWRzKTtcbiAgICBjb25zdCBleGVjID0gKCkgPT4gd2l0aFRlbmFudFR4KCh0eCkgPT4gdHguZXhlY3V0ZShzcWxgXG4gICAgICAgIFNFTEVDVFxuICAgICAgICAgIGUuc3RhZ2VfbmFtZSxcbiAgICAgICAgICBDT1VOVCgqKSBGSUxURVIgKFdIRVJFIGUuc3RhdHVzID0gJ0ZBSUxFRCcpOjppbnQgQVMgZmFpbHVyZXMsXG4gICAgICAgICAgQ09VTlQoKik6OmludCBBUyB0b3RhbCxcbiAgICAgICAgICBST1VORChDT1VOVCgqKSBGSUxURVIgKFdIRVJFIGUuc3RhdHVzID0gJ0ZBSUxFRCcpOjpudW1lcmljXG4gICAgICAgICAgICAvIE5VTExJRihDT1VOVCgqKSwgMCkgKiAxMDAsIDEpOjpmbG9hdCBBUyBmYWlsdXJlX3BjdFxuICAgICAgICBGUk9NICR7c2NoZW1hLnBpcGVsaW5lRXZlbnR9IGVcbiAgICAgICAgSk9JTiAke3NjaGVtYS5waXBlbGluZX0gcCBPTiBwLmlkID0gZS5waXBlbGluZV9pZFxuICAgICAgICBXSEVSRSBwLm9yZ19pZCAke3ByZWR9IEFORCBlLmV2ZW50X3R5cGUgPSAnU1RBR0UnIEFORCBlLnN0YWdlX25hbWUgSVMgTk9UIE5VTExcbiAgICAgICAgICBBTkQgZS5zdGFydGVkX2F0ID49ICR7ZnJvbX06OnRpbWVzdGFtcHR6IEFORCBlLnN0YXJ0ZWRfYXQgPD0gJHt0b306OnRpbWVzdGFtcHR6XG4gICAgICAgIEdST1VQIEJZIGUuc3RhZ2VfbmFtZSBPUkRFUiBCWSBmYWlsdXJlcyBERVNDXG4gICAgICBgKS50aGVuKHIgPT4gZHJpenpsZVJvd3M8U3RhZ2VGYWlsdXJlPihyLnJvd3MpKSk7XG4gICAgcmV0dXJuIHJ1blJlcG9ydChgJHtvcmdJZH06c3RhZ2UtZmFpbHVyZXM6JHtmcm9tfToke3RvfWAsIG11bHRpLCBleGVjKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEaXN0aW5jdCBkZXBsb3kgYGVudmlyb25tZW50YCB2YWx1ZXMgb2JzZXJ2ZWQgaW4gdGhlIHdpbmRvdyDigJQgcG93ZXJzIHRoZVxuICAgKiBET1JBIGVudmlyb25tZW50LXNjb3BlIGRhdGFsaXN0LiBPcmctc2NvcGVkICsgcm9sbHVwLWF3YXJlIGxpa2UgdGhlIHNpYmxpbmdcbiAgICogcmVwb3J0czsgb25seSBub24tbnVsbCBlbnZpcm9ubWVudHMgKGkuZS4gZGVwbG95LWF0dHJpYnV0ZWQgZXhlY3V0aW9ucykuXG4gICAqL1xuICBhc3luYyBnZXRSZXBvcnRFbnZpcm9ubWVudHMob3JnSWQ6IHN0cmluZywgZnJvbTogc3RyaW5nLCB0bzogc3RyaW5nLCBvcmdJZHM/OiBzdHJpbmdbXSk6IFByb21pc2U8c3RyaW5nW10+IHtcbiAgICBjb25zdCB7IHByZWQsIG11bHRpIH0gPSBvcmdTY29wZShvcmdJZCwgb3JnSWRzKTtcbiAgICBjb25zdCBleGVjID0gKCkgPT4gd2l0aFRlbmFudFR4KCh0eCkgPT4gdHguZXhlY3V0ZShzcWxgXG4gICAgICAgIFNFTEVDVCBESVNUSU5DVCBlLmVudmlyb25tZW50IEFTIGVudmlyb25tZW50XG4gICAgICAgIEZST00gJHtzY2hlbWEucGlwZWxpbmVFdmVudH0gZVxuICAgICAgICBKT0lOICR7c2NoZW1hLnBpcGVsaW5lfSBwIE9OIHAuaWQgPSBlLnBpcGVsaW5lX2lkXG4gICAgICAgIFdIRVJFIHAub3JnX2lkICR7cHJlZH0gQU5EIGUuZW52aXJvbm1lbnQgSVMgTk9UIE5VTExcbiAgICAgICAgICBBTkQgZS5zdGFydGVkX2F0ID49ICR7ZnJvbX06OnRpbWVzdGFtcHR6IEFORCBlLnN0YXJ0ZWRfYXQgPD0gJHt0b306OnRpbWVzdGFtcHR6XG4gICAgICAgIE9SREVSIEJZIGVudmlyb25tZW50XG4gICAgICBgKS50aGVuKHIgPT4gZHJpenpsZVJvd3M8eyBlbnZpcm9ubWVudDogc3RyaW5nIH0+KHIucm93cykubWFwKChyb3cpID0+IHJvdy5lbnZpcm9ubWVudCkpKTtcbiAgICByZXR1cm4gcnVuUmVwb3J0KGAke29yZ0lkfTpyZXBvcnQtZW52czoke2Zyb219OiR7dG99YCwgbXVsdGksIGV4ZWMpO1xuICB9XG5cbiAgLyoqIDEuNiBTdGFnZSBib3R0bGVuZWNrcyDigJQgc2xvd2VzdCBzdGFnZXMgcGVyIHBpcGVsaW5lLiAqL1xuICBhc3luYyBnZXRTdGFnZUJvdHRsZW5lY2tzKG9yZ0lkOiBzdHJpbmcsIGZyb206IHN0cmluZywgdG86IHN0cmluZywgb3JnSWRzPzogc3RyaW5nW10pOiBQcm9taXNlPFN0YWdlQm90dGxlbmVja1tdPiB7XG4gICAgY29uc3QgeyBwcmVkLCBtdWx0aSB9ID0gb3JnU2NvcGUob3JnSWQsIG9yZ0lkcyk7XG4gICAgY29uc3QgZXhlYyA9ICgpID0+IHdpdGhUZW5hbnRUeCgodHgpID0+IHR4LmV4ZWN1dGUoc3FsYFxuICAgICAgICBTRUxFQ1RcbiAgICAgICAgICBwLmlkLCBwLnBpcGVsaW5lX25hbWUsIGUuc3RhZ2VfbmFtZSxcbiAgICAgICAgICBBVkcoZS5kdXJhdGlvbl9tcyk6OmludCBBUyBhdmdfbXMsXG4gICAgICAgICAgTUFYKGUuZHVyYXRpb25fbXMpOjppbnQgQVMgbWF4X21zXG4gICAgICAgIEZST00gJHtzY2hlbWEucGlwZWxpbmVFdmVudH0gZVxuICAgICAgICBKT0lOICR7c2NoZW1hLnBpcGVsaW5lfSBwIE9OIHAuaWQgPSBlLnBpcGVsaW5lX2lkXG4gICAgICAgIFdIRVJFIHAub3JnX2lkICR7cHJlZH0gQU5EIGUuZXZlbnRfdHlwZSA9ICdTVEFHRScgQU5EIGUuZHVyYXRpb25fbXMgSVMgTk9UIE5VTExcbiAgICAgICAgICBBTkQgZS5zdGFydGVkX2F0ID49ICR7ZnJvbX06OnRpbWVzdGFtcHR6IEFORCBlLnN0YXJ0ZWRfYXQgPD0gJHt0b306OnRpbWVzdGFtcHR6XG4gICAgICAgIEdST1VQIEJZIHAuaWQsIGUuc3RhZ2VfbmFtZSBPUkRFUiBCWSBhdmdfbXMgREVTQ1xuICAgICAgYCkudGhlbihyID0+IGRyaXp6bGVSb3dzPFN0YWdlQm90dGxlbmVjaz4oci5yb3dzKSkpO1xuICAgIHJldHVybiBydW5SZXBvcnQoYCR7b3JnSWR9OnN0YWdlLWJvdHRsZW5lY2tzOiR7ZnJvbX06JHt0b31gLCBtdWx0aSwgZXhlYyk7XG4gIH1cblxuICAvKiogMS43IEFjdGlvbiBmYWlsdXJlIHJhdGUg4oCUIHdoaWNoIHBsdWdpbiBzdGVwcyBmYWlsIG1vc3QuICovXG4gIGFzeW5jIGdldEFjdGlvbkZhaWx1cmVzKG9yZ0lkOiBzdHJpbmcsIGZyb206IHN0cmluZywgdG86IHN0cmluZywgb3JnSWRzPzogc3RyaW5nW10pOiBQcm9taXNlPEFjdGlvbkZhaWx1cmVbXT4ge1xuICAgIGNvbnN0IHsgcHJlZCwgbXVsdGkgfSA9IG9yZ1Njb3BlKG9yZ0lkLCBvcmdJZHMpO1xuICAgIGNvbnN0IGV4ZWMgPSAoKSA9PiB3aXRoVGVuYW50VHgoKHR4KSA9PiB0eC5leGVjdXRlKHNxbGBcbiAgICAgICAgU0VMRUNUXG4gICAgICAgICAgZS5hY3Rpb25fbmFtZSxcbiAgICAgICAgICBDT1VOVCgqKSBGSUxURVIgKFdIRVJFIGUuc3RhdHVzID0gJ0ZBSUxFRCcpOjppbnQgQVMgZmFpbHVyZXMsXG4gICAgICAgICAgQ09VTlQoKik6OmludCBBUyB0b3RhbCxcbiAgICAgICAgICBST1VORChDT1VOVCgqKSBGSUxURVIgKFdIRVJFIGUuc3RhdHVzID0gJ0ZBSUxFRCcpOjpudW1lcmljXG4gICAgICAgICAgICAvIE5VTExJRihDT1VOVCgqKSwgMCkgKiAxMDAsIDEpOjpmbG9hdCBBUyBmYWlsdXJlX3BjdFxuICAgICAgICBGUk9NICR7c2NoZW1hLnBpcGVsaW5lRXZlbnR9IGVcbiAgICAgICAgSk9JTiAke3NjaGVtYS5waXBlbGluZX0gcCBPTiBwLmlkID0gZS5waXBlbGluZV9pZFxuICAgICAgICBXSEVSRSBwLm9yZ19pZCAke3ByZWR9IEFORCBlLmV2ZW50X3R5cGUgPSAnQUNUSU9OJyBBTkQgZS5hY3Rpb25fbmFtZSBJUyBOT1QgTlVMTFxuICAgICAgICAgIEFORCBlLnN0YXJ0ZWRfYXQgPj0gJHtmcm9tfTo6dGltZXN0YW1wdHogQU5EIGUuc3RhcnRlZF9hdCA8PSAke3RvfTo6dGltZXN0YW1wdHpcbiAgICAgICAgR1JPVVAgQlkgZS5hY3Rpb25fbmFtZSBPUkRFUiBCWSBmYWlsdXJlcyBERVNDXG4gICAgICBgKS50aGVuKHIgPT4gZHJpenpsZVJvd3M8QWN0aW9uRmFpbHVyZT4oci5yb3dzKSkpO1xuICAgIHJldHVybiBydW5SZXBvcnQoYCR7b3JnSWR9OmFjdGlvbi1mYWlsdXJlczoke2Zyb219OiR7dG99YCwgbXVsdGksIGV4ZWMpO1xuICB9XG5cbiAgLyoqXG4gICAqIDEuOCBFcnJvciBjYXRlZ29yaXphdGlvbiDigJQgZ3JvdXAgZmFpbHVyZSBtZXNzYWdlcy4gRXhlY3V0aW9uIHJlcG9ydCwgc29cbiAgICogcm9sbHVwLWF3YXJlIGV4YWN0bHkgbGlrZSB0aGUgc2libGluZyBleGVjdXRpb24gcmVwb3J0czogd2l0aCBgb3JnSWRzYFxuICAgKiAodGhlIG9yZ+KGknRlYW0gc3VidHJlZSkgdGhlIG9yZyBnYXRlIGJlY29tZXMgYW4gYElOICguLi4pYCBhbmQgdGhlIHJlYWQgcnVuc1xuICAgKiBmcmVzaCB1bmRlciBzeXNhZG1pbiB2aWEgYHJ1blJlcG9ydGA7IHNpbmdsZS1vcmcgcmVhZHMga2VlcCB0aGUgcGVyLW9yZyBjYWNoZS5cbiAgICovXG4gIGFzeW5jIGdldEVycm9ycyhvcmdJZDogc3RyaW5nLCBmcm9tOiBzdHJpbmcsIHRvOiBzdHJpbmcsIGxpbWl0OiBudW1iZXIgPSAyMCwgb3JnSWRzPzogc3RyaW5nW10pOiBQcm9taXNlPEVycm9yRW50cnlbXT4ge1xuICAgIGNvbnN0IHsgcHJlZCwgbXVsdGkgfSA9IG9yZ1Njb3BlKG9yZ0lkLCBvcmdJZHMpO1xuICAgIGNvbnN0IGV4ZWMgPSAoKSA9PiB3aXRoVGVuYW50VHgoKHR4KSA9PiB0eC5leGVjdXRlKHNxbGBcbiAgICAgICAgU0VMRUNUXG4gICAgICAgICAgU1VCU1RSSU5HKGUuZXJyb3JfbWVzc2FnZSBGUk9NIDEgRk9SIDIwMCkgQVMgZXJyb3JfcGF0dGVybixcbiAgICAgICAgICBDT1VOVCgqKTo6aW50IEFTIG9jY3VycmVuY2VzLFxuICAgICAgICAgIENPVU5UKERJU1RJTkNUIGUucGlwZWxpbmVfaWQpOjppbnQgQVMgYWZmZWN0ZWRfcGlwZWxpbmVzLFxuICAgICAgICAgIE1BWChlLnN0YXJ0ZWRfYXQpOjp0ZXh0IEFTIGxhc3Rfc2VlblxuICAgICAgICBGUk9NICR7c2NoZW1hLnBpcGVsaW5lRXZlbnR9IGVcbiAgICAgICAgSk9JTiAke3NjaGVtYS5waXBlbGluZX0gcCBPTiBwLmlkID0gZS5waXBlbGluZV9pZFxuICAgICAgICBXSEVSRSBwLm9yZ19pZCAke3ByZWR9IEFORCBlLnN0YXR1cyA9ICdGQUlMRUQnIEFORCBlLmVycm9yX21lc3NhZ2UgSVMgTk9UIE5VTExcbiAgICAgICAgICBBTkQgZS5zdGFydGVkX2F0ID49ICR7ZnJvbX06OnRpbWVzdGFtcHR6IEFORCBlLnN0YXJ0ZWRfYXQgPD0gJHt0b306OnRpbWVzdGFtcHR6XG4gICAgICAgIEdST1VQIEJZIGVycm9yX3BhdHRlcm4gT1JERVIgQlkgb2NjdXJyZW5jZXMgREVTQ1xuICAgICAgICBMSU1JVCAke2xpbWl0fVxuICAgICAgYCkudGhlbihyID0+IGRyaXp6bGVSb3dzPEVycm9yRW50cnk+KHIucm93cykpKTtcbiAgICByZXR1cm4gcnVuUmVwb3J0KGAke29yZ0lkfTplcnJvcnM6JHtmcm9tfToke3RvfToke2xpbWl0fWAsIG11bHRpLCBleGVjKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgZm91ciBET1JBIG1lYXN1cmVzIHBsdXMgdGhlaXIgcGVyLWVudmlyb25tZW50IGJyZWFrZG93bi5cbiAgICogSW1wbGVtZW50YXRpb24gaW4gLi9yZXBvcnRpbmcvZG9yYS50cyDigJQgc2VlIHRoYXQgZmlsZSdzIGhlYWRlciBmb3Igd2h5LlxuICAgKi9cbiAgZ2V0RG9yYU1ldHJpY3MoXG4gICAgb3JnSWQ6IHN0cmluZywgZnJvbTogc3RyaW5nLCB0bzogc3RyaW5nLCBvcmdJZHM/OiBzdHJpbmdbXSwgb3B0czogRG9yYU9wdGlvbnMgPSB7fSxcbiAgKTogUHJvbWlzZTxEb3JhTWV0cmljcz4ge1xuICAgIHJldHVybiBkb3JhTWV0cmljcyhvcmdJZCwgZnJvbSwgdG8sIG9yZ0lkcywgb3B0cyk7XG4gIH1cblxuICAvKiogRE9SQSBtZWFzdXJlcyBidWNrZXRlZCBvdmVyIHRpbWUuICovXG4gIGdldERvcmFUcmVuZChcbiAgICBvcmdJZDogc3RyaW5nLCBpbnRlcnZhbDogc3RyaW5nLCBmcm9tOiBzdHJpbmcsIHRvOiBzdHJpbmcsIG9yZ0lkcz86IHN0cmluZ1tdLCBvcHRzOiBEb3JhT3B0aW9ucyA9IHt9LFxuICApOiBQcm9taXNlPERvcmFUcmVuZFBvaW50W10+IHtcbiAgICByZXR1cm4gZG9yYVRyZW5kKG9yZ0lkLCBpbnRlcnZhbCwgZnJvbSwgdG8sIG9yZ0lkcywgb3B0cyk7XG4gIH1cblxuICAvKiogUGVyLXBpcGVsaW5lIGJ1aWxkIGhlYWx0aCAoc3RhZ2UgcGFzcyByYXRlcyBvdmVyIGEgd2luZG93KS4gKi9cbiAgZ2V0QnVpbGRIZWFsdGgoXG4gICAgb3JnSWQ6IHN0cmluZywgcGlwZWxpbmVJZDogc3RyaW5nLCBmcm9tOiBzdHJpbmcsIHRvOiBzdHJpbmcsIG9yZ0lkcz86IHN0cmluZ1tdLFxuICApOiBQcm9taXNlPEJ1aWxkSGVhbHRoPiB7XG4gICAgcmV0dXJuIGJ1aWxkSGVhbHRoKG9yZ0lkLCBwaXBlbGluZUlkLCBmcm9tLCB0bywgb3JnSWRzKTtcbiAgfVxuXG4gIGFzeW5jIGdldFBsdWdpblN1bW1hcnkob3JnSWQ6IHN0cmluZyk6IFByb21pc2U8UGx1Z2luU3VtbWFyeT4ge1xuICAgIHJldHVybiBpbnZlbnRvcnlDYWNoZS5nZXRPclNldChgJHtvcmdJZH06cGx1Z2luLXN1bW1hcnlgLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCByb3dzID0gYXdhaXQgd2l0aFRlbmFudFR4KCh0eCkgPT4gdHguZXhlY3V0ZShzcWxgXG4gICAgICAgIFNFTEVDVFxuICAgICAgICAgIENPVU5UKCopOjppbnQgQVMgdG90YWwsXG4gICAgICAgICAgQ09VTlQoKikgRklMVEVSIChXSEVSRSAke3NjaGVtYS5wbHVnaW4uaXNBY3RpdmV9KTo6aW50IEFTIGFjdGl2ZSxcbiAgICAgICAgICBDT1VOVCgqKSBGSUxURVIgKFdIRVJFIE5PVCAke3NjaGVtYS5wbHVnaW4uaXNBY3RpdmV9KTo6aW50IEFTIGluYWN0aXZlLFxuICAgICAgICAgIENPVU5UKCopIEZJTFRFUiAoV0hFUkUgJHtzY2hlbWEucGx1Z2luLnZpc2liaWxpdHl9ID0gJ3B1YmxpYycpOjppbnQgQVMgcHVibGljLFxuICAgICAgICAgIENPVU5UKCopIEZJTFRFUiAoV0hFUkUgJHtzY2hlbWEucGx1Z2luLnZpc2liaWxpdHl9ID0gJ29yZycpOjppbnQgQVMgb3JnLFxuICAgICAgICAgIENPVU5UKCopIEZJTFRFUiAoV0hFUkUgJHtzY2hlbWEucGx1Z2luLnZpc2liaWxpdHl9ID0gJ3ByaXZhdGUnKTo6aW50IEFTIHByaXZhdGUsXG4gICAgICAgICAgQ09VTlQoRElTVElOQ1QgJHtzY2hlbWEucGx1Z2luLm5hbWV9KTo6aW50IEFTIHVuaXF1ZV9uYW1lc1xuICAgICAgICBGUk9NICR7c2NoZW1hLnBsdWdpbn1cbiAgICAgICAgV0hFUkUgJHtzY2hlbWEucGx1Z2luLm9yZ0lkfSA9ICR7b3JnSWR9XG4gICAgICBgKSk7XG4gICAgICByZXR1cm4gKGRyaXp6bGVSb3dzPFBsdWdpblN1bW1hcnk+KHJvd3Mucm93cylbMF0gfHwgeyB0b3RhbDogMCwgYWN0aXZlOiAwLCBpbmFjdGl2ZTogMCwgcHVibGljOiAwLCBvcmc6IDAsIHByaXZhdGU6IDAsIHVuaXF1ZU5hbWVzOiAwIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqIDIuMiBUeXBlICYgY29tcHV0ZSBkaXN0cmlidXRpb24uXG4gICAqICBJTlRFTlRJT05BTExZIFNJTkdMRS1PUkcgKG5vIHJvbGx1cCk6IHBsdWdpbiBpbnZlbnRvcnkgaXMgcGVyLW9yZyAoc2VlXG4gICAqICBnZXRQbHVnaW5TdW1tYXJ5KS4gU2luZ2xlIGA9ICRvcmdgIHNjb3BlLiAqL1xuICBhc3luYyBnZXRQbHVnaW5EaXN0cmlidXRpb24ob3JnSWQ6IHN0cmluZyk6IFByb21pc2U8VHlwZUNvbXB1dGVEaXN0cmlidXRpb25bXT4ge1xuICAgIHJldHVybiBpbnZlbnRvcnlDYWNoZS5nZXRPclNldChgJHtvcmdJZH06cGx1Z2luLWRpc3RyaWJ1dGlvbmAsICgpID0+XG4gICAgICB3aXRoVGVuYW50VHgoKHR4KSA9PiB0eC5leGVjdXRlKHNxbGBcbiAgICAgICAgU0VMRUNUXG4gICAgICAgICAgJHtzY2hlbWEucGx1Z2luLnBsdWdpblR5cGV9IEFTIHBsdWdpbl90eXBlLFxuICAgICAgICAgICR7c2NoZW1hLnBsdWdpbi5jb21wdXRlVHlwZX0gQVMgY29tcHV0ZV90eXBlLFxuICAgICAgICAgIENPVU5UKCopOjppbnQgQVMgY291bnRcbiAgICAgICAgRlJPTSAke3NjaGVtYS5wbHVnaW59XG4gICAgICAgIFdIRVJFICR7c2NoZW1hLnBsdWdpbi5vcmdJZH0gPSAke29yZ0lkfSBBTkQgJHtzY2hlbWEucGx1Z2luLmlzQWN0aXZlfSA9IHRydWVcbiAgICAgICAgR1JPVVAgQlkgJHtzY2hlbWEucGx1Z2luLnBsdWdpblR5cGV9LCAke3NjaGVtYS5wbHVnaW4uY29tcHV0ZVR5cGV9XG4gICAgICAgIE9SREVSIEJZIGNvdW50IERFU0NcbiAgICAgIGApLnRoZW4ociA9PiBkcml6emxlUm93czxUeXBlQ29tcHV0ZURpc3RyaWJ1dGlvbj4oci5yb3dzKSkpLFxuICAgICk7XG4gIH1cblxuICAvKiogMi4zIFZlcnNpb24gY291bnRzIHBlciBwbHVnaW4gbmFtZS5cbiAgICogIElOVEVOVElPTkFMTFkgU0lOR0xFLU9SRyAobm8gcm9sbHVwKTogcGx1Z2luIGludmVudG9yeSBpcyBwZXItb3JnIChzZWVcbiAgICogIGdldFBsdWdpblN1bW1hcnkpLiBTaW5nbGUgYD0gJG9yZ2Agc2NvcGUuICovXG4gIGFzeW5jIGdldFBsdWdpblZlcnNpb25zKG9yZ0lkOiBzdHJpbmcpOiBQcm9taXNlPFZlcnNpb25Db3VudFtdPiB7XG4gICAgcmV0dXJuIGludmVudG9yeUNhY2hlLmdldE9yU2V0KGAke29yZ0lkfTpwbHVnaW4tdmVyc2lvbnNgLCAoKSA9PlxuICAgICAgd2l0aFRlbmFudFR4KCh0eCkgPT4gdHguZXhlY3V0ZShzcWxgXG4gICAgICAgIFNFTEVDVFxuICAgICAgICAgICR7c2NoZW1hLnBsdWdpbi5uYW1lfSxcbiAgICAgICAgICBDT1VOVCgqKTo6aW50IEFTIHZlcnNpb25fY291bnQsXG4gICAgICAgICAgLS0gSGlnaGVzdCB2ZXJzaW9uIGJ5IE5VTUVSSUMgc2VtdmVyIGNvcmUgKG5vdCBsZXhpY2FsOiAnMTAuMC4wJyA+ICc5LjAuMCcpLlxuICAgICAgICAgIC0tIFN0cmlwIGFueSAtcHJlcmVsZWFzZS8rYnVpbGQgc3VmZml4IGJlZm9yZSB0aGUgaW50W10gY2FzdCBzbyBpdCBjYW4ndFxuICAgICAgICAgIC0tIGVycm9yIG9uIHZhbGlkIHNlbXZlcjsga2VlcCB0aGUgb3JpZ2luYWwgc3RyaW5nIGZvciBkaXNwbGF5LlxuICAgICAgICAgIC0tIEdVQVJEOiBhIG5vbi1udW1lcmljLWRvdHRlZCB2ZXJzaW9uICgnbGF0ZXN0JywgJycsICd2MScpIHdvdWxkIG1ha2UgdGhlXG4gICAgICAgICAgLS0gOjppbnRbXSBjYXN0IHRocm93IGFuZCBibG93IHVwIHRoZSBXSE9MRSBvcmcgc3VtbWFyeS4gT25seSBjYXN0IHJvd3NcbiAgICAgICAgICAtLSB3aG9zZSBzdHJpcHBlZCBjb3JlIG1hdGNoZXMgYSBudW1lcmljLWRvdHRlZCBzaGFwZTsgc29ydCBldmVyeXRoaW5nXG4gICAgICAgICAgLS0gZWxzZSB0byB0aGUgYm90dG9tIHZpYSBhIHNlbnRpbmVsIEFSUkFZWy0xXSBzbyB0aGUgcm93IHN0aWxsIGNvdW50cy5cbiAgICAgICAgICAoYXJyYXlfYWdnKCR7c2NoZW1hLnBsdWdpbi52ZXJzaW9ufVxuICAgICAgICAgICAgIE9SREVSIEJZIENBU0VcbiAgICAgICAgICAgICAgIFdIRU4gcmVnZXhwX3JlcGxhY2UoJHtzY2hlbWEucGx1Z2luLnZlcnNpb259LCAnWy0rXS4qJCcsICcnKSB+ICdeWzAtOV0rKFsuXVswLTldKykqJCdcbiAgICAgICAgICAgICAgICAgVEhFTiBzdHJpbmdfdG9fYXJyYXkocmVnZXhwX3JlcGxhY2UoJHtzY2hlbWEucGx1Z2luLnZlcnNpb259LCAnWy0rXS4qJCcsICcnKSwgJy4nKTo6aW50W11cbiAgICAgICAgICAgICAgIEVMU0UgQVJSQVlbLTFdXG4gICAgICAgICAgICAgRU5EIERFU0NcbiAgICAgICAgICApKVsxXSBBUyBsYXRlc3RfdmVyc2lvbixcbiAgICAgICAgICBib29sX29yKCR7c2NoZW1hLnBsdWdpbi5pc0RlZmF1bHR9KSBBUyBoYXNfZGVmYXVsdFxuICAgICAgICBGUk9NICR7c2NoZW1hLnBsdWdpbn1cbiAgICAgICAgV0hFUkUgJHtzY2hlbWEucGx1Z2luLm9yZ0lkfSA9ICR7b3JnSWR9IEFORCAke3NjaGVtYS5wbHVnaW4uaXNBY3RpdmV9ID0gdHJ1ZVxuICAgICAgICBHUk9VUCBCWSAke3NjaGVtYS5wbHVnaW4ubmFtZX1cbiAgICAgICAgT1JERVIgQlkgdmVyc2lvbl9jb3VudCBERVNDXG4gICAgICBgKS50aGVuKHIgPT4gZHJpenpsZVJvd3M8VmVyc2lvbkNvdW50PihyLnJvd3MpKSksXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiAyLjQgQnVpbGQgc3VjY2VzcyByYXRlIG92ZXIgdGltZS5cbiAgICpcbiAgICogU1RBVFVTIENBU0lORyBOT1RFOiBUaGlzIHF1ZXJ5IGZpbHRlcnMgYnkgYGV2ZW50X3NvdXJjZSA9ICdwbHVnaW4tYnVpbGQnYFxuICAgKiBhbmQgdXNlcyBsb3dlcmNhc2Ugc3RhdHVzIHZhbHVlcyAoYCdjb21wbGV0ZWQnYCwgYCdmYWlsZWQnYCksIHdoaWxlXG4gICAqIGBnZXRTdWNjZXNzUmF0ZWAgKDEuMikgZmlsdGVycyBieSBgZXZlbnRfdHlwZSA9ICdQSVBFTElORSdgIHdpdGhcbiAgICogdXBwZXJjYXNlIEFXUy1zdHlsZSBzdGF0dXNlcyAoYCdTVUNDRUVERUQnYCwgYCdGQUlMRUQnYCwgYCdDQU5DRUxFRCdgKS5cbiAgICogVGhlIGNhc2luZyBkcmlmdCBpcyBpbnRlbnRpb25hbCBhbmQgdHJhY2tzIHRoZSBwcm9kdWNlcjpcbiAgICogICAtIGBwbHVnaW4tYnVpbGRgIGV2ZW50cyBjb21lIGZyb20gb3VyIG93biBidWlsZCBwaXBlbGluZSAobG93ZXJjYXNlKVxuICAgKiAgIC0gYFBJUEVMSU5FYCBldmVudHMgY29tZSBmcm9tIEFXUyBDb2RlUGlwZWxpbmUgKHVwcGVyY2FzZSlcbiAgICogVGhlIGluZ2VzdCBab2Qgc2NoZW1hIGF0IGFwaS9yZXBvcnRpbmcvc3JjL3JvdXRlcy9ldmVudC1pbmdlc3QudHNcbiAgICogU0hPVUxEIGVudW0gdGhlc2UgcGVyLWV2ZW50U291cmNlIHNvIHdlIGNhdGNoIGRyaWZ0IGF0IGluZ2VzdCByYXRoZXJcbiAgICogdGhhbiBzaWxlbnRseSBwcm9kdWNpbmcgemVybyByb3dzIGhlcmUuIFNlZSBmaW5kaW5ncyBONzEuXG4gICAqL1xuICBhc3luYyBnZXRCdWlsZFN1Y2Nlc3NSYXRlKG9yZ0lkOiBzdHJpbmcsIGludGVydmFsOiBzdHJpbmcsIGZyb206IHN0cmluZywgdG86IHN0cmluZywgb3JnSWRzPzogc3RyaW5nW10pOiBQcm9taXNlPEJ1aWxkVGltZVNlcmllc0VudHJ5W10+IHtcbiAgICBhc3NlcnRSZXBvcnRJbnRlcnZhbChpbnRlcnZhbCk7XG4gICAgLy8gQnVpbGQgYWN0aXZpdHkgcmVwb3J0IOKAlCByb2xsdXAtYXdhcmUgbGlrZSB0aGUgZXhlY3V0aW9uIHJlcG9ydHMuIFRoZXNlXG4gICAgLy8gcm93cyBhcmUgZ2F0ZWQgb24gdGhlIHBpcGVsaW5lX2V2ZW50IGBvcmdfaWRgIGRpcmVjdGx5IChubyBwaXBlbGluZSBqb2luKSxcbiAgICAvLyBzbyBgcHJlZGAgYXBwbGllcyB0byBgZS5vcmdfaWRgLlxuICAgIGNvbnN0IHsgcHJlZCwgbXVsdGkgfSA9IG9yZ1Njb3BlKG9yZ0lkLCBvcmdJZHMpO1xuICAgIGNvbnN0IGV4ZWMgPSAoKSA9PiB3aXRoVGVuYW50VHgoKHR4KSA9PiB0eC5leGVjdXRlKHNxbGBcbiAgICAgICAgU0VMRUNUXG4gICAgICAgICAgREFURV9UUlVOQygke2ludGVydmFsfSwgZS5zdGFydGVkX2F0KTo6dGV4dCBBUyBwZXJpb2QsXG4gICAgICAgICAgQ09VTlQoKikgRklMVEVSIChXSEVSRSBlLnN0YXR1cyA9ICdjb21wbGV0ZWQnKTo6aW50IEFTIHN1Y2NlZWRlZCxcbiAgICAgICAgICBDT1VOVCgqKSBGSUxURVIgKFdIRVJFIGUuc3RhdHVzID0gJ2ZhaWxlZCcpOjppbnQgQVMgZmFpbGVkLFxuICAgICAgICAgIFJPVU5EKENPVU5UKCopIEZJTFRFUiAoV0hFUkUgZS5zdGF0dXMgPSAnY29tcGxldGVkJyk6Om51bWVyaWNcbiAgICAgICAgICAgIC8gTlVMTElGKENPVU5UKCopLCAwKSAqIDEwMCwgMSk6OmZsb2F0IEFTIHN1Y2Nlc3NfcGN0XG4gICAgICAgIEZST00gJHtzY2hlbWEucGlwZWxpbmVFdmVudH0gZVxuICAgICAgICBXSEVSRSBlLm9yZ19pZCAke3ByZWR9IEFORCBlLmV2ZW50X3NvdXJjZSA9ICdwbHVnaW4tYnVpbGQnXG4gICAgICAgICAgQU5EIGUuc3RhdHVzIElOICgnY29tcGxldGVkJywgJ2ZhaWxlZCcpXG4gICAgICAgICAgQU5EIGUuc3RhcnRlZF9hdCA+PSAke2Zyb219Ojp0aW1lc3RhbXB0eiBBTkQgZS5zdGFydGVkX2F0IDw9ICR7dG99Ojp0aW1lc3RhbXB0elxuICAgICAgICBHUk9VUCBCWSBwZXJpb2QgT1JERVIgQlkgcGVyaW9kXG4gICAgICBgKS50aGVuKHIgPT4gZHJpenpsZVJvd3M8QnVpbGRUaW1lU2VyaWVzRW50cnk+KHIucm93cykpKTtcbiAgICByZXR1cm4gcnVuUmVwb3J0KGAke29yZ0lkfTpidWlsZC1zdWNjZXNzOiR7aW50ZXJ2YWx9OiR7ZnJvbX06JHt0b31gLCBtdWx0aSwgZXhlYyk7XG4gIH1cblxuICAvKiogMi41IEJ1aWxkIGR1cmF0aW9uIHBlciBwbHVnaW4uIEJ1aWxkIGFjdGl2aXR5IHJlcG9ydCDigJQgcm9sbHVwLWF3YXJlLiAqL1xuICBhc3luYyBnZXRCdWlsZER1cmF0aW9uKG9yZ0lkOiBzdHJpbmcsIGZyb206IHN0cmluZywgdG86IHN0cmluZywgb3JnSWRzPzogc3RyaW5nW10pOiBQcm9taXNlPEJ1aWxkRHVyYXRpb25bXT4ge1xuICAgIGNvbnN0IHsgcHJlZCwgbXVsdGkgfSA9IG9yZ1Njb3BlKG9yZ0lkLCBvcmdJZHMpO1xuICAgIGNvbnN0IGV4ZWMgPSAoKSA9PiB3aXRoVGVuYW50VHgoKHR4KSA9PiB0eC5leGVjdXRlKHNxbGBcbiAgICAgICAgU0VMRUNUXG4gICAgICAgICAgZS5kZXRhaWwtPj4ncGx1Z2luTmFtZScgQVMgcGx1Z2luX25hbWUsXG4gICAgICAgICAgQVZHKGUuZHVyYXRpb25fbXMpOjppbnQgQVMgYXZnX21zLFxuICAgICAgICAgIE1BWChlLmR1cmF0aW9uX21zKTo6aW50IEFTIG1heF9tcyxcbiAgICAgICAgICBDT1VOVCgqKTo6aW50IEFTIGJ1aWxkc1xuICAgICAgICBGUk9NICR7c2NoZW1hLnBpcGVsaW5lRXZlbnR9IGVcbiAgICAgICAgV0hFUkUgZS5vcmdfaWQgJHtwcmVkfSBBTkQgZS5ldmVudF9zb3VyY2UgPSAncGx1Z2luLWJ1aWxkJyBBTkQgZS5kdXJhdGlvbl9tcyBJUyBOT1QgTlVMTFxuICAgICAgICAgIEFORCBlLnN0YXJ0ZWRfYXQgPj0gJHtmcm9tfTo6dGltZXN0YW1wdHogQU5EIGUuc3RhcnRlZF9hdCA8PSAke3RvfTo6dGltZXN0YW1wdHpcbiAgICAgICAgR1JPVVAgQlkgcGx1Z2luX25hbWUgT1JERVIgQlkgYXZnX21zIERFU0NcbiAgICAgIGApLnRoZW4ociA9PiBkcml6emxlUm93czxCdWlsZER1cmF0aW9uPihyLnJvd3MpKSk7XG4gICAgcmV0dXJuIHJ1blJlcG9ydChgJHtvcmdJZH06YnVpbGQtZHVyYXRpb246JHtmcm9tfToke3RvfWAsIG11bHRpLCBleGVjKTtcbiAgfVxuXG4gIC8qKiAyLjYgQnVpbGQgZmFpbHVyZXMg4oCUIHRvcCBlcnJvciBtZXNzYWdlcy4gQnVpbGQgYWN0aXZpdHkgcmVwb3J0IOKAlCByb2xsdXAtYXdhcmUuICovXG4gIGFzeW5jIGdldEJ1aWxkRmFpbHVyZXMob3JnSWQ6IHN0cmluZywgZnJvbTogc3RyaW5nLCB0bzogc3RyaW5nLCBsaW1pdDogbnVtYmVyID0gMjAsIG9yZ0lkcz86IHN0cmluZ1tdKTogUHJvbWlzZTxCdWlsZEZhaWx1cmVbXT4ge1xuICAgIGNvbnN0IHsgcHJlZCwgbXVsdGkgfSA9IG9yZ1Njb3BlKG9yZ0lkLCBvcmdJZHMpO1xuICAgIGNvbnN0IGV4ZWMgPSAoKSA9PiB3aXRoVGVuYW50VHgoKHR4KSA9PiB0eC5leGVjdXRlKHNxbGBcbiAgICAgICAgU0VMRUNUXG4gICAgICAgICAgZS5kZXRhaWwtPj4ncGx1Z2luTmFtZScgQVMgcGx1Z2luX25hbWUsXG4gICAgICAgICAgZS5lcnJvcl9tZXNzYWdlLFxuICAgICAgICAgIENPVU5UKCopOjppbnQgQVMgb2NjdXJyZW5jZXMsXG4gICAgICAgICAgTUFYKGUuc3RhcnRlZF9hdCk6OnRleHQgQVMgbGFzdF9zZWVuXG4gICAgICAgIEZST00gJHtzY2hlbWEucGlwZWxpbmVFdmVudH0gZVxuICAgICAgICBXSEVSRSBlLm9yZ19pZCAke3ByZWR9IEFORCBlLmV2ZW50X3NvdXJjZSA9ICdwbHVnaW4tYnVpbGQnIEFORCBlLnN0YXR1cyA9ICdmYWlsZWQnXG4gICAgICAgICAgQU5EIGUuc3RhcnRlZF9hdCA+PSAke2Zyb219Ojp0aW1lc3RhbXB0eiBBTkQgZS5zdGFydGVkX2F0IDw9ICR7dG99Ojp0aW1lc3RhbXB0elxuICAgICAgICBHUk9VUCBCWSBwbHVnaW5fbmFtZSwgZS5lcnJvcl9tZXNzYWdlXG4gICAgICAgIE9SREVSIEJZIG9jY3VycmVuY2VzIERFU0NcbiAgICAgICAgTElNSVQgJHtsaW1pdH1cbiAgICAgIGApLnRoZW4ociA9PiBkcml6emxlUm93czxCdWlsZEZhaWx1cmU+KHIucm93cykpKTtcbiAgICByZXR1cm4gcnVuUmVwb3J0KGAke29yZ0lkfTpidWlsZC1mYWlsdXJlczoke2Zyb219OiR7dG99OiR7bGltaXR9YCwgbXVsdGksIGV4ZWMpO1xuICB9XG5cbiAgLy8g4pSA4pSAIENhdGVnb3J5IDM6IERPUkEgd3JpdGUgcGF0aHMgKHBvc3QtZGVwbG95IG91dGNvbWVzICsgaW5nZXN0IGhlYWx0aCkg4pSA4pSAXG5cbiAgLyoqXG4gICAqIFJlY29yZCBhIG1hbnVhbCBwb3N0LWRlcGxveSBvdXRjb21lIG1hcmtlciAoUGhhc2UgMik6IGEgdXNlciBtYXJrcyBhXG4gICAqIGRlcGxveW1lbnQgYGZhaWxlZGAgKGEgcHJvZHVjdGlvbiBpbmNpZGVudCBsaW5rZWQgdG8gdGhlIGRlcGxveSkgb3JcbiAgICogYHJlc3RvcmVkYCAocmVjb3ZlcmVkKS4gSWRlbXBvdGVudCDigJQga2V5ZWQgb24gKGV4ZWN1dGlvbl9pZCwgb3V0Y29tZSkgc28gYVxuICAgKiBkdXBsaWNhdGUgUE9TVCByZWZyZXNoZXMgYGF0YCByYXRoZXIgdGhhbiBkb3VibGUtY291bnRpbmcsIHdoaWxlIGFcbiAgICogZmFpbGVk4oaScmVzdG9yZWQgcGFpciBzdGF5cyB0d28gcm93cy4gRmVlZHMgdGhlIHBvc3QtZGVwbG95IENGUiBjb21wb25lbnQgYW5kXG4gICAqIHRoZSByZWFsIE1UVFIuIFJ1bnMgdW5kZXIgdGhlIGNhbGxlcidzIG9yZyBjb250ZXh0IChSTFMgV0lUSCBDSEVDSykuXG4gICAqL1xuICBhc3luYyByZWNvcmREZXBsb3ltZW50T3V0Y29tZShcbiAgICBvcmdJZDogc3RyaW5nLFxuICAgIGV4ZWN1dGlvbklkOiBzdHJpbmcsXG4gICAgaW5wdXQ6IHsgb3V0Y29tZTogJ2ZhaWxlZCcgfCAncmVzdG9yZWQnOyBhdDogc3RyaW5nOyBlbnZpcm9ubWVudD86IHN0cmluZyB9LFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCBydW5XaXRoVGVuYW50Q29udGV4dCh7IG9yZ0lkLCBpc1N1cGVyQWRtaW46IGZhbHNlIH0sICgpID0+XG4gICAgICB3aXRoVGVuYW50VHgoKHR4KSA9PiB0eC5pbnNlcnQoc2NoZW1hLmRlcGxveW1lbnRPdXRjb21lKS52YWx1ZXMoe1xuICAgICAgICBleGVjdXRpb25JZCxcbiAgICAgICAgb3JnSWQsXG4gICAgICAgIGVudmlyb25tZW50OiBzY3J1Yk9wdGlvbmFsKGlucHV0LmVudmlyb25tZW50KSxcbiAgICAgICAgb3V0Y29tZTogaW5wdXQub3V0Y29tZSxcbiAgICAgICAgYXQ6IG5ldyBEYXRlKGlucHV0LmF0KSxcbiAgICAgIH0pLm9uQ29uZmxpY3REb1VwZGF0ZSh7XG4gICAgICAgIHRhcmdldDogW3NjaGVtYS5kZXBsb3ltZW50T3V0Y29tZS5leGVjdXRpb25JZCwgc2NoZW1hLmRlcGxveW1lbnRPdXRjb21lLm91dGNvbWVdLFxuICAgICAgICBzZXQ6IHtcbiAgICAgICAgICBhdDogbmV3IERhdGUoaW5wdXQuYXQpLFxuICAgICAgICAgIGVudmlyb25tZW50OiBzY3J1Yk9wdGlvbmFsKGlucHV0LmVudmlyb25tZW50KSA/PyBudWxsLFxuICAgICAgICB9LFxuICAgICAgfSkpLFxuICAgICk7XG4gICAgLy8gT3V0Y29tZSBjaGFuZ2VzIHRoZSBET1JBIGFnZ3JlZ2F0ZSDigJQgZHJvcCB0aGUgb3JnJ3MgY2FjaGVkIHJlcG9ydHMuXG4gICAgYXdhaXQgdGhpcy5pbnZhbGlkYXRlT3JnKG9yZ0lkKS5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICBsb2dnZXIud2FybignUmVwb3J0aW5nIGNhY2hlIGludmFsaWRhdGlvbiBmYWlsZWQnLCB7IG9yZ0lkLCBlcnJvcjogZXJyb3JNZXNzYWdlKGVycikgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogSW5nZXN0IGEgcHJvZHVjdGlvbiBpbmNpZGVudCAoUGhhc2UgNSkgZnJvbSB0aGUgb3JnJ3MgaW5jaWRlbnQgdG9vbGluZ1xuICAgKiAoUGFnZXJEdXR5IC8gRGF0YWRvZyAvIEFsZXJ0bWFuYWdlciB3ZWJob29rKS4gSWRlbXBvdGVudCDigJQga2V5ZWQgb25cbiAgICogKG9yZ19pZCwgaW5jaWRlbnRfaWQpIHNvIGEgbGF0ZXIgcmVzb2x2ZSByZS1wb3N0IHVwc2VydHMgYHJlc29sdmVkX2F0YFxuICAgKiAoYW5kIHJlZnJlc2hlcyB0aGUgb3RoZXIgbXV0YWJsZSBmaWVsZHMpIGluc3RlYWQgb2YgaW5zZXJ0aW5nIGEgZHVwbGljYXRlLlxuICAgKiBET1JBIGNvcnJlbGF0ZXMgZWFjaCBpbmNpZGVudCB0byB0aGUgbW9zdCByZWNlbnQgc3VjY2Vzc2Z1bCBkZXBsb3kgdG8gaXRzXG4gICAqIGBlbnZpcm9ubWVudGAsIHByb2R1Y2luZyBhbiBhdXRvbWF0ZWQgcG9zdC1kZXBsb3kgZmFpbHVyZSArIGEgcmVhbCBNVFRSLlxuICAgKiBSdW5zIHVuZGVyIHRoZSBjYWxsZXIncyBvcmcgY29udGV4dCAoUkxTIFdJVEggQ0hFQ0spOyBmcmVlLWZvcm0gZmllbGRzIGFyZVxuICAgKiBBV1MtaWQgc2NydWJiZWQgYXQgdGhpcyBwZXJzaXN0ZW5jZSBib3VuZGFyeSBsaWtlIHRoZSBvdGhlciBpbmdlc3QgcGF0aHMuXG4gICAqL1xuICBhc3luYyByZWNvcmRJbmNpZGVudChvcmdJZDogc3RyaW5nLCBpbnB1dDogSW5jaWRlbnRJbnB1dCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGluY2lkZW50SWQgPSBzY3J1YkF3c0lkZW50aWZpZXJzRnJvbVN0cmluZyhpbnB1dC5pbmNpZGVudElkKTtcbiAgICBjb25zdCBlbnZpcm9ubWVudCA9IHNjcnViQXdzSWRlbnRpZmllcnNGcm9tU3RyaW5nKGlucHV0LmVudmlyb25tZW50KTtcbiAgICBjb25zdCBzZXZlcml0eSA9IHNjcnViQXdzSWRlbnRpZmllcnNGcm9tU3RyaW5nKGlucHV0LnNldmVyaXR5KTtcbiAgICBjb25zdCBvcGVuZWRBdCA9IG5ldyBEYXRlKGlucHV0Lm9wZW5lZEF0KTtcbiAgICBjb25zdCByZXNvbHZlZEF0ID0gaW5wdXQucmVzb2x2ZWRBdCA/IG5ldyBEYXRlKGlucHV0LnJlc29sdmVkQXQpIDogbnVsbDtcbiAgICBhd2FpdCBydW5XaXRoVGVuYW50Q29udGV4dCh7IG9yZ0lkLCBpc1N1cGVyQWRtaW46IGZhbHNlIH0sICgpID0+XG4gICAgICB3aXRoVGVuYW50VHgoKHR4KSA9PiB0eC5pbnNlcnQoc2NoZW1hLmluY2lkZW50KS52YWx1ZXMoe1xuICAgICAgICBpbmNpZGVudElkLFxuICAgICAgICBvcmdJZCxcbiAgICAgICAgZW52aXJvbm1lbnQsXG4gICAgICAgIG9wZW5lZEF0LFxuICAgICAgICByZXNvbHZlZEF0LFxuICAgICAgICBzZXZlcml0eSxcbiAgICAgIH0pLm9uQ29uZmxpY3REb1VwZGF0ZSh7XG4gICAgICAgIHRhcmdldDogW3NjaGVtYS5pbmNpZGVudC5vcmdJZCwgc2NoZW1hLmluY2lkZW50LmluY2lkZW50SWRdLFxuICAgICAgICBzZXQ6IHsgZW52aXJvbm1lbnQsIG9wZW5lZEF0LCByZXNvbHZlZEF0LCBzZXZlcml0eSB9LFxuICAgICAgfSkpLFxuICAgICk7XG4gICAgLy8gQSBuZXcvdXBkYXRlZCBpbmNpZGVudCBjaGFuZ2VzIHRoZSBET1JBIGFnZ3JlZ2F0ZSDigJQgZHJvcCBjYWNoZWQgcmVwb3J0cy5cbiAgICBhd2FpdCB0aGlzLmludmFsaWRhdGVPcmcob3JnSWQpLmNhdGNoKChlcnIpID0+IHtcbiAgICAgIGxvZ2dlci53YXJuKCdSZXBvcnRpbmcgY2FjaGUgaW52YWxpZGF0aW9uIGZhaWxlZCcsIHsgb3JnSWQsIGVycm9yOiBlcnJvck1lc3NhZ2UoZXJyKSB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWFkIHRoZSBwZXItb3JnIERPUkEgc2V0dGluZ3MgKFBoYXNlIDViKS4gUmV0dXJucyB0aGUgc3RvcmVkXG4gICAqIGBpbmNpZGVudFdpbmRvd0hvdXJzYCBvdmVycmlkZSAob3IgYG51bGxgIHdoZW4gdW5zZXQpIHBsdXMgdGhlIGdsb2JhbCBlbnZcbiAgICogZGVmYXVsdCwgc28gdGhlIHNldHRpbmdzIFVJIGNhbiBzaG93IGJvdGguIFJ1bnMgdW5kZXIgdGhlIGNhbGxlcidzIHRlbmFudFxuICAgKiBjb250ZXh0IChSTFMtc2NvcGVkKTsgYSBzaW5nbGUtb3JnIHJlYWQuXG4gICAqL1xuICBhc3luYyBnZXRJbmNpZGVudFNldHRpbmdzKG9yZ0lkOiBzdHJpbmcpOiBQcm9taXNlPEluY2lkZW50U2V0dGluZ3M+IHtcbiAgICBjb25zdCByb3dzID0gZHJpenpsZVJvd3M8e1xuICAgICAgaW5jaWRlbnRfd2luZG93X2hvdXJzOiBudW1iZXIgfCBudWxsO1xuICAgICAgZXZlbnRfcmV0ZW50aW9uX2RheXM6IG51bWJlciB8IG51bGw7XG4gICAgICBkb3JhX3JldGVudGlvbl9kYXlzOiBudW1iZXIgfCBudWxsO1xuICAgIH0+KChhd2FpdCB3aXRoVGVuYW50VHgoKHR4KSA9PiB0eC5leGVjdXRlKHNxbGBcbiAgICAgICAgU0VMRUNUICR7c2NoZW1hLmRvcmFTZXR0aW5ncy5pbmNpZGVudFdpbmRvd0hvdXJzfSBBUyBpbmNpZGVudF93aW5kb3dfaG91cnMsXG4gICAgICAgICAgICAgICAke3NjaGVtYS5kb3JhU2V0dGluZ3MuZXZlbnRSZXRlbnRpb25EYXlzfSBBUyBldmVudF9yZXRlbnRpb25fZGF5cyxcbiAgICAgICAgICAgICAgICR7c2NoZW1hLmRvcmFTZXR0aW5ncy5kb3JhUmV0ZW50aW9uRGF5c30gQVMgZG9yYV9yZXRlbnRpb25fZGF5c1xuICAgICAgICBGUk9NICR7c2NoZW1hLmRvcmFTZXR0aW5nc31cbiAgICAgICAgV0hFUkUgJHtzY2hlbWEuZG9yYVNldHRpbmdzLm9yZ0lkfSA9ICR7b3JnSWR9XG4gICAgICAgIExJTUlUIDFcbiAgICAgIGApKSkucm93cyk7XG4gICAgY29uc3Qgcm93ID0gcm93c1swXTtcbiAgICByZXR1cm4ge1xuICAgICAgaW5jaWRlbnRXaW5kb3dIb3Vyczogcm93Py5pbmNpZGVudF93aW5kb3dfaG91cnMgIT0gbnVsbCA/IE51bWJlcihyb3cuaW5jaWRlbnRfd2luZG93X2hvdXJzKSA6IG51bGwsXG4gICAgICBkZWZhdWx0V2luZG93SG91cnM6IERPUkFfSU5DSURFTlRfV0lORE9XX0hPVVJTLFxuICAgICAgZXZlbnRSZXRlbnRpb25EYXlzOiByb3c/LmV2ZW50X3JldGVudGlvbl9kYXlzICE9IG51bGwgPyBOdW1iZXIocm93LmV2ZW50X3JldGVudGlvbl9kYXlzKSA6IG51bGwsXG4gICAgICBkb3JhUmV0ZW50aW9uRGF5czogcm93Py5kb3JhX3JldGVudGlvbl9kYXlzICE9IG51bGwgPyBOdW1iZXIocm93LmRvcmFfcmV0ZW50aW9uX2RheXMpIDogbnVsbCxcbiAgICAgIGRlZmF1bHRFdmVudFJldGVudGlvbkRheXM6IFJFUE9SVElOR19FVkVOVF9SRVRFTlRJT05fREFZUyxcbiAgICAgIGRlZmF1bHREb3JhUmV0ZW50aW9uRGF5czogUkVQT1JUSU5HX0RPUkFfUkVURU5USU9OX0RBWVMsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVcHNlcnQgcGVyLW9yZyByZXBvcnRpbmcgc2V0dGluZ3MgKFBoYXNlIDViIGluY2lkZW50IHdpbmRvdyArIFBoYXNlIDdcbiAgICogcmV0ZW50aW9uIG92ZXJyaWRlcyksIGlkZW1wb3RlbnQgb24gYG9yZ19pZGAuIEEgcGFydGlhbCB3cml0ZSDigJQgb25seSB0aGVcbiAgICogZmllbGRzIHByZXNlbnQgaW4gYHBhdGNoYCBhcmUgc2V0IChzbyB1cGRhdGluZyByZXRlbnRpb24gbmV2ZXIgY2xlYXJzIHRoZVxuICAgKiBpbmNpZGVudCB3aW5kb3csIGFuZCB2aWNlLXZlcnNhKS4gU2V0IHNlbGYtc2VydmUgYnkgYW4gb3JnIGFkbWluIHZpYVxuICAgKiBgUFVUIC9hcGkvcmVwb3J0cy9zZXR0aW5ncy9pbmNpZGVudHNgLiBSdW5zIHVuZGVyIHRoZSBjYWxsZXIncyBvcmcgY29udGV4dFxuICAgKiAoUkxTIFdJVEggQ0hFQ0spOyBhIGNoYW5nZWQgdmFsdWUgYWZmZWN0cyBET1JBIGFnZ3JlZ2F0ZXMgc28gdGhlIG9yZydzXG4gICAqIGNhY2hlZCByZXBvcnRzIGFyZSBkcm9wcGVkLlxuICAgKi9cbiAgYXN5bmMgc2V0UmVwb3J0aW5nU2V0dGluZ3Mob3JnSWQ6IHN0cmluZywgcGF0Y2g6IFJlcG9ydGluZ1NldHRpbmdzUGF0Y2gpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBzZXQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+ID0geyB1cGRhdGVkQXQ6IG5ldyBEYXRlKCkgfTtcbiAgICBpZiAocGF0Y2guaW5jaWRlbnRXaW5kb3dIb3VycyAhPT0gdW5kZWZpbmVkKSBzZXQuaW5jaWRlbnRXaW5kb3dIb3VycyA9IHBhdGNoLmluY2lkZW50V2luZG93SG91cnM7XG4gICAgaWYgKHBhdGNoLmV2ZW50UmV0ZW50aW9uRGF5cyAhPT0gdW5kZWZpbmVkKSBzZXQuZXZlbnRSZXRlbnRpb25EYXlzID0gcGF0Y2guZXZlbnRSZXRlbnRpb25EYXlzO1xuICAgIGlmIChwYXRjaC5kb3JhUmV0ZW50aW9uRGF5cyAhPT0gdW5kZWZpbmVkKSBzZXQuZG9yYVJldGVudGlvbkRheXMgPSBwYXRjaC5kb3JhUmV0ZW50aW9uRGF5cztcbiAgICBhd2FpdCBydW5XaXRoVGVuYW50Q29udGV4dCh7IG9yZ0lkLCBpc1N1cGVyQWRtaW46IGZhbHNlIH0sICgpID0+XG4gICAgICB3aXRoVGVuYW50VHgoKHR4KSA9PiB0eC5pbnNlcnQoc2NoZW1hLmRvcmFTZXR0aW5ncykudmFsdWVzKHtcbiAgICAgICAgb3JnSWQsXG4gICAgICAgIGluY2lkZW50V2luZG93SG91cnM6IHBhdGNoLmluY2lkZW50V2luZG93SG91cnMsXG4gICAgICAgIGV2ZW50UmV0ZW50aW9uRGF5czogcGF0Y2guZXZlbnRSZXRlbnRpb25EYXlzLFxuICAgICAgICBkb3JhUmV0ZW50aW9uRGF5czogcGF0Y2guZG9yYVJldGVudGlvbkRheXMsXG4gICAgICAgIHVwZGF0ZWRBdDogbmV3IERhdGUoKSxcbiAgICAgIH0pLm9uQ29uZmxpY3REb1VwZGF0ZSh7XG4gICAgICAgIHRhcmdldDogc2NoZW1hLmRvcmFTZXR0aW5ncy5vcmdJZCxcbiAgICAgICAgc2V0LFxuICAgICAgfSkpLFxuICAgICk7XG4gICAgYXdhaXQgdGhpcy5pbnZhbGlkYXRlT3JnKG9yZ0lkKS5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICBsb2dnZXIud2FybignUmVwb3J0aW5nIGNhY2hlIGludmFsaWRhdGlvbiBmYWlsZWQnLCB7IG9yZ0lkLCBlcnJvcjogZXJyb3JNZXNzYWdlKGVycikgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogTGlzdCByZWNlbnQgaW5jaWRlbnRzIGZvciBhbiBvcmcgKFBoYXNlIDViIG9yZy1hZG1pbiBzdXJmYWNlKSwgbmV3ZXN0IGZpcnN0LFxuICAgKiBwYWdpbmF0ZWQuIEVhY2ggcm93IGNhcnJpZXMgaXRzIHJlc29sdmVkIHN0YXRlIGFuZCBpdHMgZGVwbG95IGNvcnJlbGF0aW9uIOKAlFxuICAgKiB0aGUgbW9zdCByZWNlbnQgU1VDQ0VTU0ZVTCBkZXBsb3kgdG8gdGhlIGluY2lkZW50J3MgYGVudmlyb25tZW50YCB3aG9zZVxuICAgKiBgY29tcGxldGVkX2F0YCBmYWxscyB3aXRoaW4gdGhlIGVmZmVjdGl2ZSBwZXItb3JnIGNvcnJlbGF0aW9uIHdpbmRvdyBiZWZvcmVcbiAgICogYG9wZW5lZF9hdGAgKHRoZSBzYW1lIHJ1bGUgRE9SQSdzIENGUi9NVFRSIGNvcnJlbGF0aW9uIGFwcGxpZXMpLiBTaW5nbGUtb3JnXG4gICAqIChubyByb2xsdXApIOKAlCBhbiBvcmcgYWRtaW4gdmlld3MgdGhlaXIgb3duIG9yZydzIGluY2lkZW50cy4gUkxTLXNjb3BlZCB2aWFcbiAgICogdGhlIGBwLm9yZ19pZGAvYGkub3JnX2lkYCBwcmVkaWNhdGVzICsgdGhlIHRlbmFudCBjb250ZXh0LlxuICAgKi9cbiAgYXN5bmMgbGlzdEluY2lkZW50cyhvcmdJZDogc3RyaW5nLCBvcHRzOiB7IGxpbWl0OiBudW1iZXI7IG9mZnNldDogbnVtYmVyIH0pOiBQcm9taXNlPEluY2lkZW50TGlzdEl0ZW1bXT4ge1xuICAgIGNvbnN0IHsgaW5jaWRlbnRXaW5kb3dIb3VycyB9ID0gYXdhaXQgdGhpcy5nZXRJbmNpZGVudFNldHRpbmdzKG9yZ0lkKTtcbiAgICBjb25zdCB3aW5kb3dIb3VycyA9IHJlc29sdmVJbmNpZGVudFdpbmRvd0hvdXJzKGluY2lkZW50V2luZG93SG91cnMpO1xuICAgIGNvbnN0IGxpbWl0ID0gTWF0aC5tYXgoMSwgTWF0aC5taW4ob3B0cy5saW1pdCwgMjAwKSk7XG4gICAgY29uc3Qgb2Zmc2V0ID0gTWF0aC5tYXgoMCwgb3B0cy5vZmZzZXQpO1xuICAgIHJldHVybiB3aXRoVGVuYW50VHgoKHR4KSA9PiB0eC5leGVjdXRlKHNxbGBcbiAgICAgICAgU0VMRUNUXG4gICAgICAgICAgaS5pbmNpZGVudF9pZCBBUyBcImluY2lkZW50SWRcIixcbiAgICAgICAgICBpLmVudmlyb25tZW50IEFTIGVudmlyb25tZW50LFxuICAgICAgICAgIGkuc2V2ZXJpdHkgQVMgc2V2ZXJpdHksXG4gICAgICAgICAgaS5vcGVuZWRfYXQ6OnRleHQgQVMgXCJvcGVuZWRBdFwiLFxuICAgICAgICAgIGkucmVzb2x2ZWRfYXQ6OnRleHQgQVMgXCJyZXNvbHZlZEF0XCIsXG4gICAgICAgICAgaS5jcmVhdGVkX2F0Ojp0ZXh0IEFTIFwiY3JlYXRlZEF0XCIsXG4gICAgICAgICAgKGkucmVzb2x2ZWRfYXQgSVMgTk9UIE5VTEwpIEFTIHJlc29sdmVkLFxuICAgICAgICAgIGNvcnIuZXhlY3V0aW9uX2lkIEFTIFwiY29ycmVsYXRlZEV4ZWN1dGlvbklkXCIsXG4gICAgICAgICAgY29yci5jb21wbGV0ZWRfYXQ6OnRleHQgQVMgXCJkZXBsb3lDb21wbGV0ZWRBdFwiXG4gICAgICAgIEZST00gJHtzY2hlbWEuaW5jaWRlbnR9IGlcbiAgICAgICAgTEVGVCBKT0lOIExBVEVSQUwgKFxuICAgICAgICAgIFNFTEVDVCBlLmV4ZWN1dGlvbl9pZCwgZS5jb21wbGV0ZWRfYXRcbiAgICAgICAgICBGUk9NICR7c2NoZW1hLnBpcGVsaW5lRXZlbnR9IGVcbiAgICAgICAgICBKT0lOICR7c2NoZW1hLnBpcGVsaW5lfSBwIE9OIHAuaWQgPSBlLnBpcGVsaW5lX2lkXG4gICAgICAgICAgV0hFUkUgcC5vcmdfaWQgPSAke29yZ0lkfSBBTkQgZS5ldmVudF90eXBlID0gJ1NUQUdFJ1xuICAgICAgICAgICAgQU5EIGUuZW52aXJvbm1lbnQgPSBpLmVudmlyb25tZW50IEFORCBlLnN0YXR1cyA9ICdTVUNDRUVERUQnXG4gICAgICAgICAgICBBTkQgZS5jb21wbGV0ZWRfYXQgPD0gaS5vcGVuZWRfYXRcbiAgICAgICAgICAgIEFORCBlLmNvbXBsZXRlZF9hdCA+PSBpLm9wZW5lZF9hdCAtIG1ha2VfaW50ZXJ2YWwoaG91cnMgPT4gJHt3aW5kb3dIb3Vyc306OmludClcbiAgICAgICAgICBPUkRFUiBCWSBlLmNvbXBsZXRlZF9hdCBERVNDXG4gICAgICAgICAgTElNSVQgMVxuICAgICAgICApIGNvcnIgT04gdHJ1ZVxuICAgICAgICBXSEVSRSBpLm9yZ19pZCA9ICR7b3JnSWR9XG4gICAgICAgIE9SREVSIEJZIGkub3BlbmVkX2F0IERFU0NcbiAgICAgICAgTElNSVQgJHtsaW1pdH0gT0ZGU0VUICR7b2Zmc2V0fVxuICAgICAgYCkudGhlbigocikgPT4gZHJpenpsZVJvd3M8SW5jaWRlbnRMaXN0SXRlbT4oci5yb3dzKS5tYXAoKHJvdykgPT4gKHtcbiAgICAgIC4uLnJvdyxcbiAgICAgIHJlc29sdmVkOiByb3cucmVzb2x2ZWQgPT09IHRydWUgfHwgKHJvdy5yZXNvbHZlZCBhcyB1bmtub3duKSA9PT0gJ3QnLFxuICAgICAgY29ycmVsYXRlZEV4ZWN1dGlvbklkOiByb3cuY29ycmVsYXRlZEV4ZWN1dGlvbklkID8/IG51bGwsXG4gICAgICBkZXBsb3lDb21wbGV0ZWRBdDogcm93LmRlcGxveUNvbXBsZXRlZEF0ID8/IG51bGwsXG4gICAgfSkpKSk7XG4gIH1cblxuICAvKipcbiAgICogV2lyaW5nLXRlc3QgZHJ5LXJ1biAoUGhhc2UgNWIpOiB3b3VsZCBhIHN5bnRoZXRpYyBpbmNpZGVudCBvcGVuaW5nIE5PVyBmb3JcbiAgICogYGVudmlyb25tZW50YCBjb3JyZWxhdGUgdG8gYSByZWNlbnQgc3VjY2Vzc2Z1bCBkZXBsb3kgdW5kZXIgdGhlIG9yZydzXG4gICAqIGVmZmVjdGl2ZSB3aW5kb3c/IFRoaXMgaXMgYSBOT04tcGVyc2lzdGluZyBjb3JyZWxhdGlvbiBjaGVjayDigJQgaXQgdmVyaWZpZXNcbiAgICogdGhlIGFkbWluJ3MgZW52aXJvbm1lbnQgbmFtaW5nICsgd2luZG93IGxpbmUgdXAgd2l0aCByZWFsIGRlcGxveSBldmVudHNcbiAgICogV0lUSE9VVCB3cml0aW5nIGFuIGluY2lkZW50IChzbyBhIFwidGVzdFwiIG5ldmVyIHBvbGx1dGVzIENGUi9NVFRSKS4gUkxTLXNjb3BlZC5cbiAgICovXG4gIGFzeW5jIHRlc3RJbmNpZGVudENvcnJlbGF0aW9uKG9yZ0lkOiBzdHJpbmcsIGVudmlyb25tZW50OiBzdHJpbmcpOiBQcm9taXNlPEluY2lkZW50VGVzdFJlc3VsdD4ge1xuICAgIGNvbnN0IGVudiA9IHNjcnViQXdzSWRlbnRpZmllcnNGcm9tU3RyaW5nKGVudmlyb25tZW50KTtcbiAgICBjb25zdCBvcGVuZWRBdCA9IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKTtcbiAgICBjb25zdCB7IGluY2lkZW50V2luZG93SG91cnMgfSA9IGF3YWl0IHRoaXMuZ2V0SW5jaWRlbnRTZXR0aW5ncyhvcmdJZCk7XG4gICAgY29uc3Qgd2luZG93SG91cnMgPSByZXNvbHZlSW5jaWRlbnRXaW5kb3dIb3VycyhpbmNpZGVudFdpbmRvd0hvdXJzKTtcbiAgICBjb25zdCByb3dzID0gZHJpenpsZVJvd3M8eyBleGVjdXRpb25faWQ6IHN0cmluZyB8IG51bGw7IGNvbXBsZXRlZF9hdDogc3RyaW5nIHwgbnVsbCB9PigoYXdhaXQgd2l0aFRlbmFudFR4KCh0eCkgPT4gdHguZXhlY3V0ZShzcWxgXG4gICAgICAgIFNFTEVDVCBlLmV4ZWN1dGlvbl9pZCBBUyBleGVjdXRpb25faWQsIGUuY29tcGxldGVkX2F0Ojp0ZXh0IEFTIGNvbXBsZXRlZF9hdFxuICAgICAgICBGUk9NICR7c2NoZW1hLnBpcGVsaW5lRXZlbnR9IGVcbiAgICAgICAgSk9JTiAke3NjaGVtYS5waXBlbGluZX0gcCBPTiBwLmlkID0gZS5waXBlbGluZV9pZFxuICAgICAgICBXSEVSRSBwLm9yZ19pZCA9ICR7b3JnSWR9IEFORCBlLmV2ZW50X3R5cGUgPSAnU1RBR0UnXG4gICAgICAgICAgQU5EIGUuZW52aXJvbm1lbnQgPSAke2Vudn0gQU5EIGUuc3RhdHVzID0gJ1NVQ0NFRURFRCdcbiAgICAgICAgICBBTkQgZS5jb21wbGV0ZWRfYXQgPD0gJHtvcGVuZWRBdH06OnRpbWVzdGFtcHR6XG4gICAgICAgICAgQU5EIGUuY29tcGxldGVkX2F0ID49ICR7b3BlbmVkQXR9Ojp0aW1lc3RhbXB0eiAtIG1ha2VfaW50ZXJ2YWwoaG91cnMgPT4gJHt3aW5kb3dIb3Vyc306OmludClcbiAgICAgICAgT1JERVIgQlkgZS5jb21wbGV0ZWRfYXQgREVTQ1xuICAgICAgICBMSU1JVCAxXG4gICAgICBgKSkpLnJvd3MpO1xuICAgIGNvbnN0IGhpdCA9IHJvd3NbMF07XG4gICAgcmV0dXJuIHtcbiAgICAgIGVudmlyb25tZW50OiBlbnYsXG4gICAgICBvcGVuZWRBdCxcbiAgICAgIHdpbmRvd0hvdXJzLFxuICAgICAgY29ycmVsYXRlZDogaGl0Py5leGVjdXRpb25faWQgIT0gbnVsbCxcbiAgICAgIGV4ZWN1dGlvbklkOiBoaXQ/LmV4ZWN1dGlvbl9pZCA/PyBudWxsLFxuICAgICAgZGVwbG95Q29tcGxldGVkQXQ6IGhpdD8uY29tcGxldGVkX2F0ID8/IG51bGwsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVcHNlcnQgcGVyLW9yZyBpbmdlc3Rpb24gaGVhbHRoIChQaGFzZSAzKTogdGhlIEFXUyBldmVudHMgTGFtYmRhIHBlcmlvZGljYWxseVxuICAgKiByZXBvcnRzIGZvcndhcmRlZC9kcm9wcGVkIGNvdW50ZXJzICsgdGhlIGxhc3QgZXZlbnQgdGltZXN0YW1wIHNvIHRoZSBSZXBvcnRzXG4gICAqIFVJIGNhbiBzaG93IGZsb3dpbmcgLyBzdGFsZSAvIGRyb3BwaW5nLiBPbmUgcm93IHBlciBvcmcgKHVwc2VydCBvbiBvcmdfaWQpLlxuICAgKi9cbiAgYXN5bmMgcmVjb3JkSW5nZXN0SGVhbHRoKFxuICAgIG9yZ0lkOiBzdHJpbmcsXG4gICAgaW5wdXQ6IHsgZm9yd2FyZGVkPzogbnVtYmVyOyBkcm9wcGVkPzogbnVtYmVyOyBsYXN0RXZlbnRBdD86IHN0cmluZyB9LFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBsYXN0RXZlbnRBdCA9IGlucHV0Lmxhc3RFdmVudEF0ID8gbmV3IERhdGUoaW5wdXQubGFzdEV2ZW50QXQpIDogdW5kZWZpbmVkO1xuICAgIGF3YWl0IHJ1bldpdGhUZW5hbnRDb250ZXh0KHsgb3JnSWQsIGlzU3VwZXJBZG1pbjogZmFsc2UgfSwgKCkgPT5cbiAgICAgIHdpdGhUZW5hbnRUeCgodHgpID0+IHR4Lmluc2VydChzY2hlbWEuaW5nZXN0SGVhbHRoKS52YWx1ZXMoe1xuICAgICAgICBvcmdJZCxcbiAgICAgICAgZm9yd2FyZGVkOiBpbnB1dC5mb3J3YXJkZWQsXG4gICAgICAgIGRyb3BwZWQ6IGlucHV0LmRyb3BwZWQsXG4gICAgICAgIGxhc3RFdmVudEF0LFxuICAgICAgICB1cGRhdGVkQXQ6IG5ldyBEYXRlKCksXG4gICAgICB9KS5vbkNvbmZsaWN0RG9VcGRhdGUoe1xuICAgICAgICB0YXJnZXQ6IHNjaGVtYS5pbmdlc3RIZWFsdGgub3JnSWQsXG4gICAgICAgIHNldDoge1xuICAgICAgICAgIGZvcndhcmRlZDogaW5wdXQuZm9yd2FyZGVkLFxuICAgICAgICAgIGRyb3BwZWQ6IGlucHV0LmRyb3BwZWQsXG4gICAgICAgICAgbGFzdEV2ZW50QXQsXG4gICAgICAgICAgdXBkYXRlZEF0OiBuZXcgRGF0ZSgpLFxuICAgICAgICB9LFxuICAgICAgfSkpLFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQmF0Y2hlZCBoYXJkLURFTEVURSBvZiBvbmUgcmVwb3J0aW5nIHRhYmxlJ3Mgcm93cyBleHBpcmVkIHBhc3QgYSBgY3JlYXRlZF9hdGBcbiAgICogY3V0b2ZmLCBzY29wZWQgdG8gYW4gb3JnIGFuZCBhbiBvcHRpb25hbCByb3cgcHJlZGljYXRlIChQaGFzZSA3KS4gVXNlcyBhXG4gICAqIGBjdGlkYC1pbi1zdWJxdWVyeSBMSU1JVCBzbyBlYWNoIHN0YXRlbWVudCB0b3VjaGVzIGF0IG1vc3QgYGJhdGNoU2l6ZWAgcm93c1xuICAgKiAoc2hvcnQgbG9jayB3aW5kb3dzLCBubyBsb25nIHRhYmxlIHNjYW4gdW5kZXIgbG9jayk7IGBSRVRVUk5JTkcgMWAgbGV0cyB1c1xuICAgKiBjb3VudCB2aWEgYC5yb3dzLmxlbmd0aGAgd2l0aG91dCBkZXBlbmRpbmcgb24gdGhlIGRyaXZlcidzIGByb3dDb3VudGAuIExvb3BzXG4gICAqIHVudGlsIGEgc2hvcnQgYmF0Y2ggKGRyYWluZWQpIG9yIHRoZSBwZXItdGljayBjYXAsIHRoZW4gZGVmZXJzIHRoZSByZXN0LlxuICAgKiBNVVNUIHJ1biBpbnNpZGUgYSBzeXNhZG1pbiB0ZW5hbnQgc2NvcGUgKHNlZSBwdXJnZUV4cGlyZWRSZXBvcnRpbmdEYXRhKSBzbyBpdFxuICAgKiBieXBhc3NlcyBSTFMgYW5kIGNhbiBkZWxldGUgYWNyb3NzIHRoZSBvcmcncyByb3dzLlxuICAgKi9cbiAgYXN5bmMgI3B1cmdlUmVwb3J0aW5nVGFibGVCYXRjaGVkKFxuICAgIHRhYmxlU3FsOiBSZXR1cm5UeXBlPHR5cGVvZiBzcWw+LFxuICAgIHByZWRpY2F0ZTogUmV0dXJuVHlwZTx0eXBlb2Ygc3FsPixcbiAgICBiYXRjaFNpemU6IG51bWJlcixcbiAgICBtYXhCYXRjaGVzOiBudW1iZXIsXG4gICk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgbGV0IHRvdGFsID0gMDtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG1heEJhdGNoZXM7IGkrKykge1xuICAgICAgY29uc3QgcmVzID0gYXdhaXQgd2l0aFRlbmFudFR4KCh0eCkgPT4gdHguZXhlY3V0ZShzcWxgXG4gICAgICAgIERFTEVURSBGUk9NICR7dGFibGVTcWx9XG4gICAgICAgIFdIRVJFIGN0aWQgSU4gKFxuICAgICAgICAgIFNFTEVDVCBjdGlkIEZST00gJHt0YWJsZVNxbH1cbiAgICAgICAgICBXSEVSRSAke3ByZWRpY2F0ZX1cbiAgICAgICAgICBMSU1JVCAke2JhdGNoU2l6ZX1cbiAgICAgICAgKVxuICAgICAgICBSRVRVUk5JTkcgMVxuICAgICAgYCkpO1xuICAgICAgY29uc3QgcHVyZ2VkID0gZHJpenpsZVJvd3M8dW5rbm93bj4ocmVzLnJvd3MpLmxlbmd0aDtcbiAgICAgIHRvdGFsICs9IHB1cmdlZDtcbiAgICAgIGlmIChwdXJnZWQgPCBiYXRjaFNpemUpIGJyZWFrOyAvLyBkcmFpbmVkXG4gICAgICBpZiAoaSA9PT0gbWF4QmF0Y2hlcyAtIDEpIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oJ1JlcG9ydGluZyByZXRlbnRpb24gaGl0IHBlci10aWNrIGNhcDsgcmVtYWluaW5nIHJvd3MgZGVmZXJyZWQnLCB7XG4gICAgICAgICAgcHVyZ2VkVGhpc1RpY2s6IHRvdGFsLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRvdGFsO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlcG9ydGluZyByZXRlbnRpb24gc3dlZXAgKFBoYXNlIDcpLiBIYXJkLWRlbGV0ZXMgcm93cyBvbGRlciB0aGFuIHRoZWlyXG4gICAqIHJldGVudGlvbiB3aW5kb3csIGJ5IGBjcmVhdGVkX2F0YCwgYWNyb3NzIGV2ZXJ5IG9yZyB0aGF0IGhhcyByZXBvcnRpbmcgZGF0YSDigJRcbiAgICogYSAqKnNwbGl0KiogcG9saWN5IHNvIGhpZ2gtdm9sdW1lIHN0YW5kYXJkIGV2ZW50cyBleHBpcmUgZmFzdGVyIHRoYW4gdGhlXG4gICAqIGxvdy12b2x1bWUgRE9SQSBzb3VyY2U6XG4gICAqICAtIGBwaXBlbGluZV9ldmVudHMgV0hFUkUgZW52aXJvbm1lbnQgSVMgTlVMTGAg4oaSIHN0YW5kYXJkLWV2ZW50IHdpbmRvdy5cbiAgICogIC0gYHBpcGVsaW5lX2V2ZW50cyBXSEVSRSBlbnZpcm9ubWVudCBJUyBOT1QgTlVMTGAgKGRlcGxveSBzdGFnZXMpLFxuICAgKiAgICBgZGVwbG95bWVudF9vdXRjb21lc2AsIGFuZCBgaW5jaWRlbnRzYCDihpIgRE9SQS1zb3VyY2Ugd2luZG93LlxuICAgKiBFYWNoIG9yZydzIHdpbmRvd3MgY29tZSBmcm9tIGl0cyBgZG9yYV9zZXR0aW5nc2Agb3ZlcnJpZGUsIGVsc2UgdGhlIGdsb2JhbFxuICAgKiBlbnYgZGVmYXVsdHMgKHNlZSB7QGxpbmsgcmVzb2x2ZUV2ZW50UmV0ZW50aW9uRGF5c30gLyB7QGxpbmsgcmVzb2x2ZURvcmFSZXRlbnRpb25EYXlzfSkuXG4gICAqIGBpbmdlc3RfaGVhbHRoYCBhbmQgYGRvcmFfc2V0dGluZ3NgIGFyZSBuZXZlciBwdXJnZWQuIE9uZSBgbm93YCBmb3IgdGhlIHdob2xlXG4gICAqIHRpY2sgKHJvd3MgY3Jvc3NpbmcgdGhlIGJvdW5kYXJ5IG1pZC1zd2VlcCB3YWl0IGZvciB0aGUgbmV4dCkuIEVzdGFibGlzaGVzIGFcbiAgICogc3lzYWRtaW4gdGVuYW50IHNjb3BlIHNvIHRoZSBkZWxldGVzIHNwYW4gYWxsIG9yZ3MgLyBieXBhc3MgUkxTIOKAlCB0aGlzIGlzIGFcbiAgICogY3Jvc3MtdGVuYW50IGhvdXNla2VlcGluZyBqb2IuIFJldHVybnMgKGFuZCBsb2dzKSBwZXItd2luZG93IHB1cmdlIHRhbGxpZXMuXG4gICAqL1xuICBhc3luYyBwdXJnZUV4cGlyZWRSZXBvcnRpbmdEYXRhKG9wdHM6IFJlcG9ydGluZ1JldGVudGlvbk9wdGlvbnMgPSB7fSk6IFByb21pc2U8UmVwb3J0aW5nUmV0ZW50aW9uQ291bnRzPiB7XG4gICAgY29uc3QgYmF0Y2hTaXplID0gTWF0aC5tYXgoMSwgb3B0cy5iYXRjaFNpemUgPz8gMTAwMCk7XG4gICAgY29uc3QgbWF4QmF0Y2hlcyA9IE1hdGgubWF4KDEsIG9wdHMubWF4QmF0Y2hlc1BlclRhYmxlID8/IDUwKTtcbiAgICBjb25zdCBub3cgPSBvcHRzLm5vdyA/PyBuZXcgRGF0ZSgpO1xuICAgIGNvbnN0IGNvdW50czogUmVwb3J0aW5nUmV0ZW50aW9uQ291bnRzID0ge1xuICAgICAgb3JnczogMCwgc3RhbmRhcmRFdmVudHM6IDAsIGRvcmFFdmVudHM6IDAsIGRlcGxveW1lbnRPdXRjb21lczogMCwgaW5jaWRlbnRzOiAwLFxuICAgIH07XG5cbiAgICByZXR1cm4gcnVuV2l0aFRlbmFudENvbnRleHQoeyBpc1N1cGVyQWRtaW46IHRydWUgfSwgYXN5bmMgKCkgPT4ge1xuICAgICAgLy8gRW51bWVyYXRlIGV2ZXJ5IG9yZyB3aXRoIHJlcG9ydGluZyBkYXRhICh1bmlvbiBhY3Jvc3MgdGhlIHRocmVlIHRhYmxlcykuXG4gICAgICBjb25zdCBvcmdSb3dzID0gZHJpenpsZVJvd3M8eyBvcmdfaWQ6IHN0cmluZyB9PigoYXdhaXQgd2l0aFRlbmFudFR4KCh0eCkgPT4gdHguZXhlY3V0ZShzcWxgXG4gICAgICAgIFNFTEVDVCBESVNUSU5DVCBvcmdfaWQgRlJPTSAoXG4gICAgICAgICAgU0VMRUNUICR7c2NoZW1hLnBpcGVsaW5lRXZlbnQub3JnSWR9IEFTIG9yZ19pZCBGUk9NICR7c2NoZW1hLnBpcGVsaW5lRXZlbnR9XG4gICAgICAgICAgVU5JT05cbiAgICAgICAgICBTRUxFQ1QgJHtzY2hlbWEuZGVwbG95bWVudE91dGNvbWUub3JnSWR9IEFTIG9yZ19pZCBGUk9NICR7c2NoZW1hLmRlcGxveW1lbnRPdXRjb21lfVxuICAgICAgICAgIFVOSU9OXG4gICAgICAgICAgU0VMRUNUICR7c2NoZW1hLmluY2lkZW50Lm9yZ0lkfSBBUyBvcmdfaWQgRlJPTSAke3NjaGVtYS5pbmNpZGVudH1cbiAgICAgICAgKSBBUyBvcmdzXG4gICAgICBgKSkpLnJvd3MpO1xuICAgICAgaWYgKG9yZ1Jvd3MubGVuZ3RoID09PSAwKSByZXR1cm4gY291bnRzO1xuXG4gICAgICAvLyBQZXItb3JnIHJldGVudGlvbiBvdmVycmlkZXMgKGEgc2luZ2xlIHJlYWQ7IG9yZ3Mgd2l0aG91dCBhIHJvdyB1c2UgZGVmYXVsdHMpLlxuICAgICAgY29uc3Qgb3ZlcnJpZGVSb3dzID0gZHJpenpsZVJvd3M8e1xuICAgICAgICBvcmdfaWQ6IHN0cmluZztcbiAgICAgICAgZXZlbnRfcmV0ZW50aW9uX2RheXM6IG51bWJlciB8IG51bGw7XG4gICAgICAgIGRvcmFfcmV0ZW50aW9uX2RheXM6IG51bWJlciB8IG51bGw7XG4gICAgICB9PigoYXdhaXQgd2l0aFRlbmFudFR4KCh0eCkgPT4gdHguZXhlY3V0ZShzcWxgXG4gICAgICAgIFNFTEVDVCAke3NjaGVtYS5kb3JhU2V0dGluZ3Mub3JnSWR9IEFTIG9yZ19pZCxcbiAgICAgICAgICAgICAgICR7c2NoZW1hLmRvcmFTZXR0aW5ncy5ldmVudFJldGVudGlvbkRheXN9IEFTIGV2ZW50X3JldGVudGlvbl9kYXlzLFxuICAgICAgICAgICAgICAgJHtzY2hlbWEuZG9yYVNldHRpbmdzLmRvcmFSZXRlbnRpb25EYXlzfSBBUyBkb3JhX3JldGVudGlvbl9kYXlzXG4gICAgICAgIEZST00gJHtzY2hlbWEuZG9yYVNldHRpbmdzfVxuICAgICAgYCkpKS5yb3dzKTtcbiAgICAgIGNvbnN0IG92ZXJyaWRlcyA9IG5ldyBNYXAob3ZlcnJpZGVSb3dzLm1hcCgocikgPT4gW3Iub3JnX2lkLCByXSkpO1xuXG4gICAgICBjb25zdCBldmVudHNUYWJsZSA9IHNxbGAke3NjaGVtYS5waXBlbGluZUV2ZW50fWA7XG4gICAgICBjb25zdCBvdXRjb21lc1RhYmxlID0gc3FsYCR7c2NoZW1hLmRlcGxveW1lbnRPdXRjb21lfWA7XG4gICAgICBjb25zdCBpbmNpZGVudHNUYWJsZSA9IHNxbGAke3NjaGVtYS5pbmNpZGVudH1gO1xuXG4gICAgICBmb3IgKGNvbnN0IHsgb3JnX2lkOiBvcmdJZCB9IG9mIG9yZ1Jvd3MpIHtcbiAgICAgICAgY29uc3Qgb3YgPSBvdmVycmlkZXMuZ2V0KG9yZ0lkKTtcbiAgICAgICAgY29uc3QgZXZlbnREYXlzID0gcmVzb2x2ZUV2ZW50UmV0ZW50aW9uRGF5cyhvdj8uZXZlbnRfcmV0ZW50aW9uX2RheXMpO1xuICAgICAgICBjb25zdCBkb3JhRGF5cyA9IHJlc29sdmVEb3JhUmV0ZW50aW9uRGF5cyhvdj8uZG9yYV9yZXRlbnRpb25fZGF5cyk7XG4gICAgICAgIC8vIGAtMWAgPSB1bmxpbWl0ZWQgKFBoYXNlIDgpOiBrZWVwIGZvcmV2ZXIsIHNraXAgdGhhdCB3aW5kb3cncyBkZWxldGVzIGZvclxuICAgICAgICAvLyB0aGlzIG9yZy4gU3RhbmRhcmQtZXZlbnQgYW5kIERPUkEtc291cmNlIHdpbmRvd3MgYXJlIGluZGVwZW5kZW50OyBhbiBvcmdcbiAgICAgICAgLy8gd2l0aCBib3RoIGAtMWAgaXMgZnVsbHkgc2tpcHBlZC4gTG9nIHRoZSBza2lwIHNvIGl0J3Mgb2JzZXJ2YWJsZS5cbiAgICAgICAgY29uc3Qgc2tpcEV2ZW50cyA9IGV2ZW50RGF5cyA9PT0gLTE7XG4gICAgICAgIGNvbnN0IHNraXBEb3JhID0gZG9yYURheXMgPT09IC0xO1xuICAgICAgICBpZiAoc2tpcEV2ZW50cyB8fCBza2lwRG9yYSkge1xuICAgICAgICAgIGxvZ2dlci5pbmZvKCdSZXBvcnRpbmcgcmV0ZW50aW9uIHN3ZWVwIHNraXBwaW5nIHVubGltaXRlZCB3aW5kb3cocyknLCB7XG4gICAgICAgICAgICBvcmdJZCxcbiAgICAgICAgICAgIHN0YW5kYXJkRXZlbnRzOiBza2lwRXZlbnRzID8gJ3VubGltaXRlZCcgOiBldmVudERheXMsXG4gICAgICAgICAgICBkb3JhU291cmNlOiBza2lwRG9yYSA/ICd1bmxpbWl0ZWQnIDogZG9yYURheXMsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXNraXBFdmVudHMpIHtcbiAgICAgICAgICBjb25zdCBldmVudEN1dG9mZiA9IHJldGVudGlvbkN1dG9mZihub3csIGV2ZW50RGF5cyk7XG4gICAgICAgICAgY291bnRzLnN0YW5kYXJkRXZlbnRzICs9IGF3YWl0IHRoaXMuI3B1cmdlUmVwb3J0aW5nVGFibGVCYXRjaGVkKFxuICAgICAgICAgICAgZXZlbnRzVGFibGUsXG4gICAgICAgICAgICBzcWxgb3JnX2lkID0gJHtvcmdJZH0gQU5EIGVudmlyb25tZW50IElTIE5VTEwgQU5EIGNyZWF0ZWRfYXQgPCAke2V2ZW50Q3V0b2ZmfWAsXG4gICAgICAgICAgICBiYXRjaFNpemUsIG1heEJhdGNoZXMsXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghc2tpcERvcmEpIHtcbiAgICAgICAgICBjb25zdCBkb3JhQ3V0b2ZmID0gcmV0ZW50aW9uQ3V0b2ZmKG5vdywgZG9yYURheXMpO1xuICAgICAgICAgIGNvdW50cy5kb3JhRXZlbnRzICs9IGF3YWl0IHRoaXMuI3B1cmdlUmVwb3J0aW5nVGFibGVCYXRjaGVkKFxuICAgICAgICAgICAgZXZlbnRzVGFibGUsXG4gICAgICAgICAgICBzcWxgb3JnX2lkID0gJHtvcmdJZH0gQU5EIGVudmlyb25tZW50IElTIE5PVCBOVUxMIEFORCBjcmVhdGVkX2F0IDwgJHtkb3JhQ3V0b2ZmfWAsXG4gICAgICAgICAgICBiYXRjaFNpemUsIG1heEJhdGNoZXMsXG4gICAgICAgICAgKTtcbiAgICAgICAgICBjb3VudHMuZGVwbG95bWVudE91dGNvbWVzICs9IGF3YWl0IHRoaXMuI3B1cmdlUmVwb3J0aW5nVGFibGVCYXRjaGVkKFxuICAgICAgICAgICAgb3V0Y29tZXNUYWJsZSxcbiAgICAgICAgICAgIHNxbGBvcmdfaWQgPSAke29yZ0lkfSBBTkQgY3JlYXRlZF9hdCA8ICR7ZG9yYUN1dG9mZn1gLFxuICAgICAgICAgICAgYmF0Y2hTaXplLCBtYXhCYXRjaGVzLFxuICAgICAgICAgICk7XG4gICAgICAgICAgY291bnRzLmluY2lkZW50cyArPSBhd2FpdCB0aGlzLiNwdXJnZVJlcG9ydGluZ1RhYmxlQmF0Y2hlZChcbiAgICAgICAgICAgIGluY2lkZW50c1RhYmxlLFxuICAgICAgICAgICAgc3FsYG9yZ19pZCA9ICR7b3JnSWR9IEFORCBjcmVhdGVkX2F0IDwgJHtkb3JhQ3V0b2ZmfWAsXG4gICAgICAgICAgICBiYXRjaFNpemUsIG1heEJhdGNoZXMsXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICBjb3VudHMub3JncyArPSAxO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBwdXJnZWRBbnkgPSBjb3VudHMuc3RhbmRhcmRFdmVudHMgKyBjb3VudHMuZG9yYUV2ZW50cyArIGNvdW50cy5kZXBsb3ltZW50T3V0Y29tZXMgKyBjb3VudHMuaW5jaWRlbnRzO1xuICAgICAgaWYgKHB1cmdlZEFueSA+IDApIGxvZ2dlci5pbmZvKCdSZXBvcnRpbmcgcmV0ZW50aW9uIHN3ZWVwIHB1cmdlZCBleHBpcmVkIHJvd3MnLCB7IC4uLmNvdW50cyB9KTtcbiAgICAgIHJldHVybiBjb3VudHM7XG4gICAgfSk7XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IHJlcG9ydGluZ1NlcnZpY2UgPSBuZXcgUmVwb3J0aW5nU2VydmljZSgpO1xuIl19