@pipeline-builder/api-core 5.2.3 → 5.2.4
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.
- package/lib/constants/ai-providers.d.ts +3 -22
- package/lib/constants/ai-providers.js +6 -56
- package/lib/errors/app-errors.d.ts +14 -0
- package/lib/errors/app-errors.js +21 -1
- package/lib/helpers/sse-helpers.d.ts +33 -3
- package/lib/helpers/sse-helpers.js +91 -19
- package/lib/middleware/auth.js +6 -3
- package/lib/middleware/deferred-quota-check.d.ts +5 -0
- package/lib/middleware/deferred-quota-check.js +33 -0
- package/lib/middleware/ecosystem-guard.d.ts +3 -3
- package/lib/middleware/ecosystem-guard.js +5 -5
- package/lib/middleware/index.d.ts +5 -2
- package/lib/middleware/index.js +6 -3
- package/lib/middleware/on-behalf.d.ts +37 -0
- package/lib/middleware/on-behalf.js +143 -0
- package/lib/middleware/permission-gates.d.ts +11 -0
- package/lib/middleware/permission-gates.js +7 -1
- package/lib/middleware/quota-exempt-routes.d.ts +36 -0
- package/lib/middleware/quota-exempt-routes.js +47 -0
- package/lib/middleware/route-table.d.ts +104 -0
- package/lib/middleware/route-table.js +72 -2
- package/lib/middleware/service-tokens.d.ts +8 -0
- package/lib/middleware/service-tokens.js +2 -1
- package/lib/middleware/step-up.js +11 -1
- package/lib/services/ai-call-weight.d.ts +24 -0
- package/lib/services/ai-call-weight.js +77 -0
- package/lib/services/audit-context.d.ts +105 -0
- package/lib/services/audit-context.js +134 -0
- package/lib/services/index.d.ts +7 -2
- package/lib/services/index.js +7 -2
- package/lib/services/org-ai-client.d.ts +61 -0
- package/lib/services/org-ai-client.js +112 -0
- package/lib/services/quota-increment-batcher.d.ts +81 -0
- package/lib/services/quota-increment-batcher.js +166 -0
- package/lib/services/quota.d.ts +158 -14
- package/lib/services/quota.js +252 -22
- package/lib/services/remote-audit-client.d.ts +44 -1
- package/lib/services/remote-audit-client.js +106 -20
- package/lib/services/version-vuln-policy.d.ts +174 -0
- package/lib/services/version-vuln-policy.js +242 -0
- package/lib/types/ai-catalog.d.ts +63 -0
- package/lib/types/ai-catalog.js +82 -0
- package/lib/types/ask-proposals.js +6 -6
- package/lib/types/build-catalog.d.ts +154 -0
- package/lib/types/build-catalog.js +158 -0
- package/lib/types/common.d.ts +37 -3
- package/lib/types/common.js +20 -2
- package/lib/types/ecosystem-notifications.d.ts +5 -5
- package/lib/types/ecosystem-notifications.js +9 -3
- package/lib/types/error-codes.d.ts +13 -6
- package/lib/types/error-codes.js +18 -8
- package/lib/types/feature-flags.d.ts +6 -4
- package/lib/types/feature-flags.js +11 -6
- package/lib/types/index.d.ts +6 -4
- package/lib/types/index.js +12 -5
- package/lib/types/metadata-keys.d.ts +6 -0
- package/lib/types/metadata-keys.js +4 -1
- package/lib/types/permissions.d.ts +344 -3
- package/lib/types/permissions.js +596 -21
- package/lib/types/pipeline.d.ts +39 -0
- package/lib/types/pipeline.js +57 -1
- package/lib/types/plugin-health.d.ts +0 -2
- package/lib/types/plugin-health.js +1 -11
- package/lib/types/plugin-scan.d.ts +192 -42
- package/lib/types/plugin-scan.js +159 -43
- package/lib/types/quota-catalog.d.ts +247 -0
- package/lib/types/quota-catalog.js +122 -0
- package/lib/types/quota-tiers.d.ts +118 -0
- package/lib/types/quota-tiers.js +153 -2
- package/lib/types/remote-audit-actions.d.ts +1 -1
- package/lib/types/remote-audit-actions.js +131 -1
- package/lib/types/wire-vocabulary.js +8 -1
- package/lib/utils/index.d.ts +1 -1
- package/lib/utils/index.js +2 -2
- package/lib/utils/response.d.ts +35 -2
- package/lib/utils/response.js +42 -3
- package/lib/validation/ai-schemas.d.ts +27 -0
- package/lib/validation/ai-schemas.js +31 -5
- package/lib/validation/plugin-schemas.d.ts +15 -0
- package/lib/validation/plugin-schemas.js +28 -1
- package/package.json +31 -2
package/lib/services/quota.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
// Copyright 2026 Pipeline Builder Contributors
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { currentAuditContext, sanitizeCorrelationId } from './audit-context.js';
|
|
3
4
|
import { createSafeClient } from './http-client.js';
|
|
4
|
-
import {
|
|
5
|
+
import { batcherFor } from './quota-increment-batcher.js';
|
|
6
|
+
import { onBehalfCaller } from '../middleware/on-behalf.js';
|
|
7
|
+
import { getServiceAuthHeader, isServicePrincipal } from '../middleware/service-tokens.js';
|
|
5
8
|
import { SYSTEM_ORG_ID } from '../middleware/system-org.js';
|
|
6
9
|
import { ErrorCode } from '../types/error-codes.js';
|
|
7
10
|
import { DEFAULT_TIER, isValidTier } from '../types/quota-tiers.js';
|
|
8
|
-
import { envBool } from '../utils/env.js';
|
|
11
|
+
import { envBool, envInt } from '../utils/env.js';
|
|
9
12
|
import { createLogger } from '../utils/logger.js';
|
|
10
13
|
import { emitCounter } from '../utils/metric-emitter.js';
|
|
11
14
|
import { errorMessage, sendError, sendQuotaExceeded } from '../utils/response.js';
|
|
@@ -23,6 +26,28 @@ const QUOTA_REQUEST_OPTIONS = {
|
|
|
23
26
|
maxRateLimitRetries: 0,
|
|
24
27
|
maxRetries: 1,
|
|
25
28
|
};
|
|
29
|
+
/**
|
|
30
|
+
* Budget for one `check` of a COUNTER quota (`QUOTA_CHECK_TIMEOUT_MS`, default
|
|
31
|
+
* 300), with no retry.
|
|
32
|
+
*
|
|
33
|
+
* The check is a read gate that FAILS OPEN, run ahead of the request it gates:
|
|
34
|
+
* the old 5 s timeout × 2 attempts meant a slow quota service added up to 10 s
|
|
35
|
+
* to every metered request and then let it through anyway. A short budget turns
|
|
36
|
+
* the same incident into a ≤ 300 ms fail-open (counted on
|
|
37
|
+
* `quota_fail_open_total`, which alerts) — and with the per-pod check cache in
|
|
38
|
+
* front (api-server `checkQuota`) a healthy service is asked at most once per
|
|
39
|
+
* org/type per cache TTL.
|
|
40
|
+
*
|
|
41
|
+
* `storageBytes` keeps the client timeout and one retry: it is a MEASURED read
|
|
42
|
+
* (the quota service walks the org's registry namespace on a cold cache) behind
|
|
43
|
+
* the registry's fail-CLOSED push gate, where a premature timeout refuses a push.
|
|
44
|
+
*/
|
|
45
|
+
export const QUOTA_CHECK_TIMEOUT_MS = envInt('QUOTA_CHECK_TIMEOUT_MS', 300, { min: 1 });
|
|
46
|
+
function checkRequestOptions(quotaType) {
|
|
47
|
+
if (quotaType === 'storageBytes')
|
|
48
|
+
return QUOTA_REQUEST_OPTIONS;
|
|
49
|
+
return { maxRateLimitRetries: 0, maxRetries: 0, timeout: QUOTA_CHECK_TIMEOUT_MS };
|
|
50
|
+
}
|
|
26
51
|
const logger = createLogger('quota');
|
|
27
52
|
// RESERVE FAIL MODE — explicit, single policy.
|
|
28
53
|
//
|
|
@@ -41,6 +66,121 @@ const logger = createLogger('quota');
|
|
|
41
66
|
// (`quota_fail_closed_total` / `quota_fail_open_total`) tagged with the reason.
|
|
42
67
|
// `check` (a cheap read gate) stays fail-open; `increment` is fire-and-forget.
|
|
43
68
|
const QUOTA_RESERVE_FAIL_OPEN = envBool('QUOTA_RESERVE_FAIL_OPEN', false);
|
|
69
|
+
/** Longest attribution string the client sends (the quota service enforces the same bound). */
|
|
70
|
+
const MAX_ATTRIBUTION_LEN = 200;
|
|
71
|
+
function bounded(value) {
|
|
72
|
+
return typeof value === 'string' && value.length > 0 ? value.slice(0, MAX_ATTRIBUTION_LEN) : undefined;
|
|
73
|
+
}
|
|
74
|
+
/** The principal half of an attribution block, from a VERIFIED token. */
|
|
75
|
+
function principalAttribution(user) {
|
|
76
|
+
if (!user)
|
|
77
|
+
return {};
|
|
78
|
+
return {
|
|
79
|
+
principalType: user.principalType,
|
|
80
|
+
principalId: bounded(user.sub),
|
|
81
|
+
keyId: bounded(user.parentKeyId ?? user.jti),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Attribution for the request being served: the verified principal, the matched
|
|
86
|
+
* route pattern, the pipeline (`:pipelineId` param or a sanitized
|
|
87
|
+
* `X-Pipeline-Id` header) and the request id. Read off `req` directly rather than
|
|
88
|
+
* the ambient audit context because the metering middleware runs in a `finish`
|
|
89
|
+
* listener, where the request's async scope is no longer guaranteed.
|
|
90
|
+
*/
|
|
91
|
+
export function quotaAttributionFromRequest(req) {
|
|
92
|
+
const routePath = req.route?.path;
|
|
93
|
+
const route = typeof routePath === 'string' ? `${req.method} ${(req.baseUrl ?? '') + routePath}` : undefined;
|
|
94
|
+
const header = req.headers['x-pipeline-id'];
|
|
95
|
+
const pipelineId = sanitizeCorrelationId(req.params?.pipelineId) ?? sanitizeCorrelationId(Array.isArray(header) ? header[0] : header);
|
|
96
|
+
const requestIdHeader = req.headers['x-request-id'];
|
|
97
|
+
const requestId = req.requestId
|
|
98
|
+
?? sanitizeCorrelationId(Array.isArray(requestIdHeader) ? requestIdHeader[0] : requestIdHeader);
|
|
99
|
+
return {
|
|
100
|
+
...principalAttribution(req.user),
|
|
101
|
+
...(route ? { route: route.slice(0, MAX_ATTRIBUTION_LEN) } : {}),
|
|
102
|
+
...(pipelineId ? { pipelineId } : {}),
|
|
103
|
+
...(requestId ? { requestId: bounded(requestId) } : {}),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Attribution from the ambient audit context, for calls made inside a request
|
|
108
|
+
* scope that did not pass one explicitly (the reserve / refund helpers every
|
|
109
|
+
* service uses). Empty outside any scope.
|
|
110
|
+
*/
|
|
111
|
+
function attributionFromContext() {
|
|
112
|
+
const ctx = currentAuditContext();
|
|
113
|
+
if (!ctx)
|
|
114
|
+
return {};
|
|
115
|
+
return {
|
|
116
|
+
...principalAttribution(ctx.principal?.()),
|
|
117
|
+
...(ctx.requestId ? { requestId: bounded(ctx.requestId) } : {}),
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/** The attribution a quota write sends: the explicit block, else the ambient one. */
|
|
121
|
+
function resolveAttribution(explicit) {
|
|
122
|
+
const resolved = explicit ?? attributionFromContext();
|
|
123
|
+
return Object.keys(resolved).length > 0 ? resolved : undefined;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* The quota type a metered request actually spends.
|
|
127
|
+
*
|
|
128
|
+
* `apiCalls` is the PEOPLE's budget — an interactive session. A request made by
|
|
129
|
+
* a NON-INTERACTIVE credential spends `automationCalls` instead, never both, so
|
|
130
|
+
* a fleet of self-mutating pipelines can't exhaust the console for the humans
|
|
131
|
+
* in the same org:
|
|
132
|
+
* - an org SERVICE ACCOUNT (`principalType: 'service_account'` —
|
|
133
|
+
* platform-automation, pipeline-register, reporting-ingest, registry-push);
|
|
134
|
+
* - a PERSONAL ACCESS KEY: the exchanged key token (`token_use: 'api_key'`)
|
|
135
|
+
* and anything minted while holding one (`parentKeyId`). A PAT in a CI job
|
|
136
|
+
* is automation whoever owns it — billing it as a person let one script
|
|
137
|
+
* lock its owner's teammates out of the console. CI should still use a
|
|
138
|
+
* service-account key (it survives the person leaving); either way the
|
|
139
|
+
* traffic now lands on `automationCalls`.
|
|
140
|
+
* Every other type is returned unchanged: an AI call or a pipeline creation
|
|
141
|
+
* costs the same whoever makes it.
|
|
142
|
+
*
|
|
143
|
+
* `meterQuotaOnSuccess` and `checkQuota` call this themselves, so a service
|
|
144
|
+
* mounts both with `'apiCalls'` and the split happens per request.
|
|
145
|
+
*/
|
|
146
|
+
export function meteredQuotaTypeFor(req, quotaType) {
|
|
147
|
+
if (quotaType !== 'apiCalls' || !req.user)
|
|
148
|
+
return quotaType;
|
|
149
|
+
const u = req.user;
|
|
150
|
+
if (u.principalType === 'service_account' || u.token_use === 'api_key' || u.parentKeyId)
|
|
151
|
+
return 'automationCalls';
|
|
152
|
+
return quotaType;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Whether the apiCalls/automationCalls meter AND check skip this (verified)
|
|
156
|
+
* request, and why. One function for both halves, so the gate never refuses a
|
|
157
|
+
* call the meter would not bill:
|
|
158
|
+
* - `service` — an internal service principal: peer traffic is caused by a
|
|
159
|
+
* user action the originating service already metered;
|
|
160
|
+
* - `impersonation` — a sysadmin impersonation session (`impersonatorId`).
|
|
161
|
+
* Vendor staff looking at a tenant's console must neither spend the tenant's
|
|
162
|
+
* budget nor be locked out by it while diagnosing an exhausted org; the
|
|
163
|
+
* session is audited on its own trail;
|
|
164
|
+
* - `on_behalf` — a user token FORWARDED by an internal service as part of a
|
|
165
|
+
* request already metered where it arrived (the ask agent's tools,
|
|
166
|
+
* pipeline's placeholder-plugin confirm), proven by a signed marker the
|
|
167
|
+
* user cannot forge (middleware/on-behalf.ts).
|
|
168
|
+
* Applies to the CALL budgets only: reservation-gated quotas (pipelines,
|
|
169
|
+
* plugins …) are charged whoever asks. `aiCalls` mirrors the impersonation half
|
|
170
|
+
* on its own (api-server `withAiCallReservation` skips the slot when the
|
|
171
|
+
* session is an impersonation; the call is still audited).
|
|
172
|
+
*/
|
|
173
|
+
export function callQuotaExemption(req) {
|
|
174
|
+
if (!req.user)
|
|
175
|
+
return undefined;
|
|
176
|
+
if (isServicePrincipal(req))
|
|
177
|
+
return 'service';
|
|
178
|
+
if (req.user.impersonatorId)
|
|
179
|
+
return 'impersonation';
|
|
180
|
+
if (onBehalfCaller(req))
|
|
181
|
+
return 'on_behalf';
|
|
182
|
+
return undefined;
|
|
183
|
+
}
|
|
44
184
|
/**
|
|
45
185
|
* Service-principal `Authorization` header for a quota call made on behalf of
|
|
46
186
|
* `orgId` by the CURRENT service (`SERVICE_NAME`, the same identity the health
|
|
@@ -56,6 +196,7 @@ const QUOTA_RESERVE_FAIL_OPEN = envBool('QUOTA_RESERVE_FAIL_OPEN', false);
|
|
|
56
196
|
export function getQuotaServiceAuthHeader(orgId) {
|
|
57
197
|
return getServiceAuthHeader({ serviceName: process.env.SERVICE_NAME || 'api', orgId, role: 'member' });
|
|
58
198
|
}
|
|
199
|
+
const AI_LIMIT_CODES = new Set([ErrorCode.AI_MEMBER_SHARE_EXCEEDED, ErrorCode.AI_TOKEN_BUDGET_EXCEEDED]);
|
|
59
200
|
/**
|
|
60
201
|
* Apply the explicit reserve fail-mode policy to a reservation the quota service
|
|
61
202
|
* did NOT confirm (see QUOTA_RESERVE_FAIL_OPEN above). Default: deny.
|
|
@@ -139,7 +280,7 @@ export function createQuotaService(config = {}) {
|
|
|
139
280
|
return {
|
|
140
281
|
async check(orgId, quotaType, authHeader, requestId) {
|
|
141
282
|
const path = `/quotas/${encodeURIComponent(orgId)}/${encodeURIComponent(quotaType)}`;
|
|
142
|
-
const response = await client.get(path, { headers: buildHeaders(orgId, authHeader, requestId), ...
|
|
283
|
+
const response = await client.get(path, { headers: buildHeaders(orgId, authHeader, requestId), ...checkRequestOptions(quotaType) });
|
|
143
284
|
if (!response) {
|
|
144
285
|
logger.warn('QUOTA_FAIL_OPEN: Quota service unreachable, allowing request', { orgId, quotaType });
|
|
145
286
|
emitCounter('quota_fail_open_total', { operation: 'check', reason: 'unreachable', quotaType });
|
|
@@ -154,28 +295,67 @@ export function createQuotaService(config = {}) {
|
|
|
154
295
|
}
|
|
155
296
|
return response.body.data.status;
|
|
156
297
|
},
|
|
157
|
-
async increment(orgId, quotaType, authHeader, amount = 1,
|
|
298
|
+
async increment(orgId, quotaType, authHeader, amount = 1, attribution) {
|
|
158
299
|
const path = `/quotas/${encodeURIComponent(orgId)}/increment`;
|
|
300
|
+
const attr = resolveAttribution(attribution);
|
|
159
301
|
const response = await client
|
|
160
|
-
.post(path, { quotaType, amount }, { headers: buildHeaders(orgId, authHeader, requestId), ...QUOTA_REQUEST_OPTIONS });
|
|
161
|
-
if (
|
|
302
|
+
.post(path, { quotaType, amount, ...(attr && { attribution: attr }) }, { headers: buildHeaders(orgId, authHeader, attr?.requestId), ...QUOTA_REQUEST_OPTIONS });
|
|
303
|
+
if (response?.statusCode === 429) {
|
|
304
|
+
// Over the limit: the quota service refused AND recorded the denial in
|
|
305
|
+
// its ledger. Not a failure of metering — the counter is exactly where
|
|
306
|
+
// it should be.
|
|
307
|
+
logger.debug('Quota increment refused (over limit)', { orgId, quotaType, amount });
|
|
308
|
+
}
|
|
309
|
+
else if (!response || response.statusCode !== 200) {
|
|
162
310
|
logger.warn('Failed to increment quota', {
|
|
163
311
|
orgId, quotaType, amount, statusCode: response?.statusCode,
|
|
164
312
|
});
|
|
313
|
+
// A lost metering increment is a unit the org consumed and never paid
|
|
314
|
+
// for. Counted (labelled by the emitting `service`) so a sustained rate
|
|
315
|
+
// pages instead of silently under-billing — see QuotaIncrementFailures.
|
|
316
|
+
emitCounter('quota_increment_failures_total', { reason: response ? 'non-ok' : 'unreachable', quotaType });
|
|
165
317
|
}
|
|
166
318
|
else {
|
|
167
319
|
logger.debug('Quota incremented', { orgId, quotaType, amount });
|
|
168
320
|
}
|
|
169
321
|
},
|
|
170
|
-
async
|
|
322
|
+
async incrementMetered(orgId, quotaType, authHeader, groups) {
|
|
171
323
|
const path = `/quotas/${encodeURIComponent(orgId)}/increment`;
|
|
324
|
+
const amount = groups.reduce((sum, g) => sum + g.amount, 0);
|
|
325
|
+
if (amount <= 0)
|
|
326
|
+
return { counted: 0, overshoot: 0 };
|
|
327
|
+
const response = await client.post(path, { quotaType, amount, meter: true, groups }, { headers: buildHeaders(orgId, authHeader), ...QUOTA_REQUEST_OPTIONS });
|
|
328
|
+
if (!response || response.statusCode !== 200 || !response.body?.success) {
|
|
329
|
+
logger.warn('Failed to apply metered quota increment', { orgId, quotaType, amount, statusCode: response?.statusCode });
|
|
330
|
+
// Every unit in the batch went uncounted — see QuotaIncrementFailures.
|
|
331
|
+
emitCounter('quota_increment_failures_total', { reason: response ? 'non-ok' : 'unreachable', quotaType });
|
|
332
|
+
return null;
|
|
333
|
+
}
|
|
334
|
+
const counted = response.body.data?.counted ?? amount;
|
|
335
|
+
const overshoot = response.body.data?.overshoot ?? 0;
|
|
336
|
+
logger.debug('Metered quota increment applied', { orgId, quotaType, amount, counted, overshoot });
|
|
337
|
+
return { counted, overshoot };
|
|
338
|
+
},
|
|
339
|
+
async reserve(orgId, quotaType, authHeader, amount = 1, attribution) {
|
|
340
|
+
const path = `/quotas/${encodeURIComponent(orgId)}/increment`;
|
|
341
|
+
const attr = resolveAttribution(attribution);
|
|
172
342
|
// 200 carries `data.quota`; 429 (QUOTA_EXCEEDED) carries `details.quota`.
|
|
173
343
|
// Both shapes are normalized into QuotaReserveResult.
|
|
174
|
-
const response = await client.post(path, { quotaType, amount }, { headers: buildHeaders(orgId, authHeader, requestId), ...QUOTA_REQUEST_OPTIONS });
|
|
344
|
+
const response = await client.post(path, { quotaType, amount, ...(attr && { attribution: attr }) }, { headers: buildHeaders(orgId, authHeader, attr?.requestId), ...QUOTA_REQUEST_OPTIONS });
|
|
175
345
|
if (!response)
|
|
176
346
|
return unconfirmedReserve(orgId, quotaType, 'unreachable');
|
|
177
347
|
if (response.statusCode === 429) {
|
|
178
348
|
const q = response.body.details?.quota;
|
|
349
|
+
// An optional org AI control (per-member share, token budget) refused the
|
|
350
|
+
// slot: a genuine, final denial — relayed with its own code and message.
|
|
351
|
+
if (response.body.code && AI_LIMIT_CODES.has(response.body.code)) {
|
|
352
|
+
return {
|
|
353
|
+
exceeded: true,
|
|
354
|
+
code: response.body.code,
|
|
355
|
+
...(response.body.message ? { message: response.body.message } : {}),
|
|
356
|
+
quota: q ?? { type: quotaType, limit: 0, used: 0, remaining: 0 },
|
|
357
|
+
};
|
|
358
|
+
}
|
|
179
359
|
// Only a GENUINE quota-exceeded 429 means "over quota". A generic 429 —
|
|
180
360
|
// an intervening gateway or rate limiter — did not confirm anything, so
|
|
181
361
|
// it goes through the same unconfirmed-reservation policy as an outage.
|
|
@@ -196,10 +376,11 @@ export function createQuotaService(config = {}) {
|
|
|
196
376
|
quota: q ?? { type: quotaType, limit: -1, used: 0, remaining: -1 },
|
|
197
377
|
};
|
|
198
378
|
},
|
|
199
|
-
async decrement(orgId, quotaType, authHeader, amount = 1, resetAtSnapshot,
|
|
379
|
+
async decrement(orgId, quotaType, authHeader, amount = 1, resetAtSnapshot, attribution) {
|
|
200
380
|
const path = `/quotas/${encodeURIComponent(orgId)}/decrement`;
|
|
381
|
+
const attr = resolveAttribution(attribution);
|
|
201
382
|
const response = await client
|
|
202
|
-
.post(path, { quotaType, amount, ...(resetAtSnapshot && { resetAtSnapshot }) }, { headers: buildHeaders(orgId, authHeader, requestId), ...QUOTA_REQUEST_OPTIONS });
|
|
383
|
+
.post(path, { quotaType, amount, ...(resetAtSnapshot && { resetAtSnapshot }), ...(attr && { attribution: attr }) }, { headers: buildHeaders(orgId, authHeader, attr?.requestId), ...QUOTA_REQUEST_OPTIONS });
|
|
203
384
|
if (!response || response.statusCode !== 200) {
|
|
204
385
|
// Rollback failure is logged but never propagated the action's own
|
|
205
386
|
// failure has already been surfaced to the caller; a stuck counter
|
|
@@ -212,6 +393,26 @@ export function createQuotaService(config = {}) {
|
|
|
212
393
|
logger.debug('Quota decremented', { orgId, quotaType, amount });
|
|
213
394
|
}
|
|
214
395
|
},
|
|
396
|
+
async reportUsage(orgId, quotaType, authHeader, tokens, attribution) {
|
|
397
|
+
const tokensIn = Math.max(0, Math.floor(tokens.tokensIn || 0));
|
|
398
|
+
const tokensOut = Math.max(0, Math.floor(tokens.tokensOut || 0));
|
|
399
|
+
const attr = resolveAttribution(attribution);
|
|
400
|
+
// Nothing to say: no tokens and no attribution to make a zero row useful.
|
|
401
|
+
if (tokensIn === 0 && tokensOut === 0 && !attr)
|
|
402
|
+
return;
|
|
403
|
+
const path = `/quotas/${encodeURIComponent(orgId)}/increment`;
|
|
404
|
+
try {
|
|
405
|
+
const response = await client.post(path, { quotaType, report: true, tokensIn, tokensOut, ...(attr && { attribution: attr }) }, { headers: buildHeaders(orgId, authHeader, attr?.requestId), ...QUOTA_REQUEST_OPTIONS });
|
|
406
|
+
if (!response || response.statusCode !== 200) {
|
|
407
|
+
logger.warn('Failed to report AI usage', { orgId, quotaType, statusCode: response?.statusCode });
|
|
408
|
+
emitCounter('quota_usage_report_failures_total', { reason: response ? 'non-ok' : 'unreachable', quotaType });
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
catch (err) {
|
|
412
|
+
logger.warn('Failed to report AI usage', { orgId, quotaType, error: errorMessage(err) });
|
|
413
|
+
emitCounter('quota_usage_report_failures_total', { reason: 'exception', quotaType });
|
|
414
|
+
}
|
|
415
|
+
},
|
|
215
416
|
async getTier(orgId, authHeader, requestId) {
|
|
216
417
|
const known = constantTierFor(orgId);
|
|
217
418
|
if (known)
|
|
@@ -259,21 +460,36 @@ function constantTierFor(orgId) {
|
|
|
259
460
|
return orgId.toLowerCase() === SYSTEM_ORG_ID ? 'unlimited' : null;
|
|
260
461
|
}
|
|
261
462
|
/**
|
|
262
|
-
* Fire-and-forget quota METERING increment
|
|
463
|
+
* Fire-and-forget quota METERING increment.
|
|
464
|
+
*
|
|
465
|
+
* Buffered: the unit joins the pod's per-(org, type) aggregate and is sent with
|
|
466
|
+
* the next flush (`QUOTA_INCREMENT_FLUSH_MS`, see quota-increment-batcher.ts)
|
|
467
|
+
* as one metered increment — partial admission against the cap, the excess
|
|
468
|
+
* recorded as `overshoot`. The counter therefore lags by at most one flush
|
|
469
|
+
* interval. Only the request meter uses this; reservations stay synchronous.
|
|
263
470
|
*
|
|
264
471
|
* Authenticates as the calling SERVICE ({@link getQuotaServiceAuthHeader}), never
|
|
265
|
-
* with the end user's token: `/quotas/:orgId/increment` is service-principal
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
* moved.
|
|
472
|
+
* with the end user's token: `/quotas/:orgId/increment` is service-principal
|
|
473
|
+
* only, so a forwarded user JWT was always rejected (403) and the metered quota
|
|
474
|
+
* (e.g. `apiCalls`, and the `api_pack` bundle raising it) never moved.
|
|
269
475
|
*
|
|
270
476
|
* @param quotaService - Quota service client
|
|
271
477
|
* @param orgId - Organization ID whose counter is incremented
|
|
272
478
|
* @param quotaType - Quota type to increment
|
|
273
479
|
* @param logWarn - Logging function for warnings
|
|
480
|
+
* @param attribution - Who spent the unit (defaults to the ambient request context)
|
|
274
481
|
*/
|
|
275
|
-
export function incrementQuota(quotaService, orgId, quotaType, logWarn) {
|
|
276
|
-
|
|
482
|
+
export function incrementQuota(quotaService, orgId, quotaType, logWarn, attribution) {
|
|
483
|
+
try {
|
|
484
|
+
const batcher = batcherFor(quotaService, async (org, type, groups) => {
|
|
485
|
+
await quotaService.incrementMetered(org, type, getQuotaServiceAuthHeader(org), groups);
|
|
486
|
+
});
|
|
487
|
+
batcher.add(orgId, quotaType, resolveAttribution(attribution));
|
|
488
|
+
}
|
|
489
|
+
catch (err) {
|
|
490
|
+
logWarn('Quota increment failed', { error: errorMessage(err) });
|
|
491
|
+
emitCounter('quota_increment_failures_total', { reason: 'exception', quotaType });
|
|
492
|
+
}
|
|
277
493
|
}
|
|
278
494
|
/**
|
|
279
495
|
* Atomic reserve helper for the "reserve + commit / rollback" pattern.
|
|
@@ -296,8 +512,8 @@ export function incrementQuota(quotaService, orgId, quotaType, logWarn) {
|
|
|
296
512
|
* }
|
|
297
513
|
* ```
|
|
298
514
|
*/
|
|
299
|
-
export function reserveQuota(quotaService, orgId, quotaType, authHeader, amount = 1,
|
|
300
|
-
return quotaService.reserve(orgId, quotaType, authHeader, amount,
|
|
515
|
+
export function reserveQuota(quotaService, orgId, quotaType, authHeader, amount = 1, attribution) {
|
|
516
|
+
return quotaService.reserve(orgId, quotaType, authHeader, amount, attribution);
|
|
301
517
|
}
|
|
302
518
|
/** Seconds a client should wait before retrying when quota couldn't be confirmed. */
|
|
303
519
|
const QUOTA_UNAVAILABLE_RETRY_AFTER_SECONDS = 5;
|
|
@@ -310,6 +526,17 @@ const QUOTA_UNAVAILABLE_RETRY_AFTER_SECONDS = 5;
|
|
|
310
526
|
* - otherwise → the standard 429 `QUOTA_EXCEEDED` with the X-Quota-* headers.
|
|
311
527
|
*/
|
|
312
528
|
export function sendQuotaReserveDenied(res, quotaType, reservation) {
|
|
529
|
+
if (reservation.code) {
|
|
530
|
+
// An optional org AI control (per-member share / token budget): its own
|
|
531
|
+
// code, so the client can say "your share" rather than "the org is out".
|
|
532
|
+
const resetAt = reservation.quota.resetAt;
|
|
533
|
+
if (!res.headersSent && resetAt) {
|
|
534
|
+
res.setHeader('Retry-After', Math.max(0, Math.ceil((new Date(resetAt).getTime() - Date.now()) / 1000)));
|
|
535
|
+
}
|
|
536
|
+
emitCounter('quota_denied_total', { type: quotaType });
|
|
537
|
+
sendError(res, 429, reservation.message ?? `Your organization's ${quotaType} limit for this period has been reached.`, reservation.code, { quota: reservation.quota, quotaType, ...(resetAt ? { resetAt } : {}) });
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
313
540
|
if (reservation.unavailable) {
|
|
314
541
|
if (!res.headersSent)
|
|
315
542
|
res.setHeader('Retry-After', QUOTA_UNAVAILABLE_RETRY_AFTER_SECONDS);
|
|
@@ -323,7 +550,10 @@ export function sendQuotaReserveDenied(res, quotaType, reservation) {
|
|
|
323
550
|
* Logs on failure but never throws the action that needed the rollback
|
|
324
551
|
* has already failed, no point compounding the error.
|
|
325
552
|
*/
|
|
326
|
-
export function decrementQuota(quotaService, orgId, quotaType, authHeader, logWarn, amount = 1, resetAtSnapshot) {
|
|
327
|
-
|
|
553
|
+
export function decrementQuota(quotaService, orgId, quotaType, authHeader, logWarn, amount = 1, resetAtSnapshot, attribution) {
|
|
554
|
+
const sent = attribution
|
|
555
|
+
? quotaService.decrement(orgId, quotaType, authHeader, amount, resetAtSnapshot, attribution)
|
|
556
|
+
: quotaService.decrement(orgId, quotaType, authHeader, amount, resetAtSnapshot);
|
|
557
|
+
sent.catch((err) => logWarn('Quota rollback failed', { error: errorMessage(err) }));
|
|
328
558
|
}
|
|
329
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVvdGEuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2VydmljZXMvcXVvdGEudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUl0QyxPQUFPLEVBQUUsZ0JBQWdCLEVBQXVCLE1BQU0sa0JBQWtCLENBQUM7QUFDekUsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDdkUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBRTVELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUNwRCxPQUFPLEVBQUUsWUFBWSxFQUFFLFdBQVcsRUFBa0IsTUFBTSx5QkFBeUIsQ0FBQztBQUNwRixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDMUMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsWUFBWSxFQUFFLFNBQVMsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ2xGLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUUvRDs7Ozs7Ozs7R0FRRztBQUNILE1BQU0scUJBQXFCLEdBQStEO0lBQ3hGLG1CQUFtQixFQUFFLENBQUM7SUFDdEIsVUFBVSxFQUFFLENBQUM7Q0FDZCxDQUFDO0FBRUYsTUFBTSxNQUFNLEdBQUcsWUFBWSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0FBRXJDLCtDQUErQztBQUMvQyxFQUFFO0FBQ0YsOEVBQThFO0FBQzlFLGdGQUFnRjtBQUNoRiwrRUFBK0U7QUFDL0UsNEVBQTRFO0FBQzVFLHlFQUF5RTtBQUN6RSxnRkFBZ0Y7QUFDaEYsaUZBQWlGO0FBQ2pGLG9FQUFvRTtBQUNwRSxtRUFBbUU7QUFDbkUsMkVBQTJFO0FB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RSxDQUFDO0FBRUQscUZBQXFGO0FBQ3JGLE1BQU0scUNBQXFDLEdBQUcsQ0FBQyxDQUFDO0FBRWhEOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLFVBQVUsc0JBQXNCLENBQUMsR0FBYSxFQUFFLFNBQW9CLEVBQUUsV0FBK0I7SUFDekcsSUFBSSxXQUFXLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDNUIsSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXO1lBQUUsR0FBRyxDQUFDLFNBQVMsQ0FBQyxhQUFhLEVBQUUscUNBQXFDLENBQUMsQ0FBQztRQUMxRixTQUFTLENBQ1AsR0FBRyxFQUNILEdBQUcsRUFDSCxxQkFBcUIsU0FBUyw2Q0FBNkMsRUFDM0UsU0FBUyxDQUFDLG1CQUFtQixDQUM5QixDQUFDO1FBQ0YsT0FBTztJQUNULENBQUM7SUFDRCxpQkFBaUIsQ0FBQyxHQUFHLEVBQUUsU0FBUyxFQUFFLFdBQVcsQ0FBQyxLQUFLLEVBQUUsV0FBVyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztBQUNsRixDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILE1BQU0sVUFBVSxjQUFjLENBQUUsWUFBMEIsRUFDeEQsS0FBYSxFQUNiLFNBQW9CLEVBQ3BCLFVBQWtCLEVBQ2xCLE9BQWtELEVBQ2xELE1BQU0sR0FBVyxDQUFDLEVBQ2xCLGVBQXdCO0lBRXhCLFlBQVksQ0FBQyxTQUFTLENBQUMsS0FBSyxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLGVBQWUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQVksRUFBRSxFQUFFLENBQ25HLE9BQU8sQ0FBQyx1QkFBdUIsRUFBRSxFQUFFLEtBQUssRUFBRSxZQUFZLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUMvRCxDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgdHlwZSB7IFJlc3BvbnNlIH0gZnJvbSAnZXhwcmVzcyc7XG5cbmltcG9ydCB7IGNyZWF0ZVNhZmVDbGllbnQsIHR5cGUgUmVxdWVzdE9wdGlvbnMgfSBmcm9tICcuL2h0dHAtY2xpZW50LmpzJztcbmltcG9ydCB7IGdldFNlcnZpY2VBdXRoSGVhZGVyIH0gZnJvbSAnLi4vbWlkZGxld2FyZS9zZXJ2aWNlLXRva2Vucy5qcyc7XG5pbXBvcnQgeyBTWVNURU1fT1JHX0lEIH0gZnJvbSAnLi4vbWlkZGxld2FyZS9zeXN0ZW0tb3JnLmpzJztcbmltcG9ydCB0eXBlIHsgUXVvdGFUeXBlLCBRdW90YUNoZWNrUmVzdWx0LCBTZXJ2aWNlQ29uZmlnIH0gZnJvbSAnLi4vdHlwZXMvY29tbW9uLmpzJztcbmltcG9ydCB7IEVycm9yQ29kZSB9IGZyb20gJy4uL3R5cGVzL2Vycm9yLWNvZGVzLmpzJztcbmltcG9ydCB7IERFRkFVTFRfVElFUiwgaXNWYWxpZFRpZXIsIHR5cGUgUXVvdGFUaWVyIH0gZnJvbSAnLi4vdHlwZXMvcXVvdGEtdGllcnMuanMnO1xuaW1wb3J0IHsgZW52Qm9vbCB9IGZyb20gJy4uL3V0aWxzL2Vudi5qcyc7XG5pbXBvcnQgeyBjcmVhdGVMb2dnZXIgfSBmcm9tICcuLi91dGlscy9sb2dnZXIuanMnO1xuaW1wb3J0IHsgZW1pdENvdW50ZXIgfSBmcm9tICcuLi91dGlscy9tZXRyaWMtZW1pdHRlci5qcyc7XG5pbXBvcnQgeyBlcnJvck1lc3NhZ2UsIHNlbmRFcnJvciwgc2VuZFF1b3RhRXhjZWVkZWQgfSBmcm9tICcuLi91dGlscy9yZXNwb25zZS5qcyc7XG5pbXBvcnQgeyBzZXJ2aWNlRW5kcG9pbnQgfSBmcm9tICcuLi91dGlscy9zZXJ2aWNlLXJlZ2lzdHJ5LmpzJztcblxuLyoqXG4gKiBSZXRyeSBvcHRpb25zIGZvciBxdW90YSBjYWxscyDigJQgZmFpbCBmYXN0IChhIHNsb3cgcXVvdGEgc2VydmljZSBtdXN0IG5vdCBzdGFsbCB0aGUgcmVxdWVzdCkuXG4gKlxuICogTkVWRVIgcmV0cnkgYSA0MjkuIFRoZSBxdW90YSBzZXJ2aWNlIGFuc3dlcnMgYW4gb3Zlci1saW1pdCBvcmcgd2l0aCA0MjlcbiAqIFFVT1RBX0VYQ0VFREVEIGFuZCBgUmV0cnktQWZ0ZXJgID0gc2Vjb25kcyB1bnRpbCB0aGUgcGVyaW9kIHJlc2V0czsgdGhlIEhUVFBcbiAqIGNsaWVudCBob25vcnMgdGhhdCAoY2FwcGVkIGF0IDYwcyksIHNvIGEgc2luZ2xlIHJhdGUtbGltaXQgcmV0cnkgc3RhbGxlZCB0aGVcbiAqIHJlcXVlc3Qgd2VsbCBwYXN0IHRoZSBoYW5kbGVyIHRpbWVvdXQsIHdoaWNoIHRoZW4gYW5zd2VyZWQgNTAzIGFuZCB0aGUgcmVhbFxuICogNDI5IHdhcyBsb3N0LiBBIDQyOSBpcyBhIGZpbmFsIGFuc3dlciBoZXJlLlxuICovXG5jb25zdCBRVU9UQV9SRVFVRVNUX09QVElPTlM6IFBpY2s8UmVxdWVzdE9wdGlvbnMsICdtYXhSYXRlTGltaXRSZXRyaWVzJyB8ICdtYXhSZXRyaWVzJz4gPSB7XG4gIG1heFJhdGVMaW1pdFJldHJpZXM6IDAsXG4gIG1heFJldHJpZXM6IDEsXG59O1xuXG5jb25zdCBsb2dnZXIgPSBjcmVhdGVMb2dnZXIoJ3F1b3RhJyk7XG5cbi8vIFJFU0VSVkUgRkFJTCBNT0RFIOKAlCBleHBsaWNpdCwgc2luZ2xlIHBvbGljeS5cbi8vXG4vLyBgcmVzZXJ2ZWAgZ2F0ZXMgRVhQRU5TSVZFLCBiaWxsYWJsZSByZXNvdXJjZXMgKHBpcGVsaW5lcywgcGx1Z2luIGJ1aWxkcywgQUlcbi8vIGNhbGxzLCBwbGF0Zm9ybSBmZWF0dXJlIHNsb3RzKS4gRXZlcnkgcXVvdGEgdHlwZSBpcyBhIHBlci1wZXJpb2QgRkxPVyBjb3VudGVyXG4vLyB3aXRoIG5vIGFmdGVyLXRoZS1mYWN0IHJlY29uY2lsaWF0aW9uOiBhIHVuaXQgY29uc3VtZWQgd2hpbGUgdGhlIHJlc2VydmF0aW9uXG4vLyBjb3VsZCBub3QgYmUgY29uZmlybWVkIGlzIG5ldmVyIGNvdW50ZWQsIHNvIGZhaWwtb3BlbiBsZXRzIGFuIG9yZyBjb25zdW1lXG4vLyB1bmJvdW5kZWQgdW5tZXRlcmVkIHVuaXRzIGZvciB0aGUgd2hvbGUgbGVuZ3RoIG9mIGFuIGluY2lkZW50IOKAlCBhbmQgYW5cbi8vIHVuY29uZmlybWVkIHJlc2VydmUgKHRpbWVvdXQsIG9wZW4gY2lyY3VpdCkgbWF5IGV2ZW4gaGF2ZSBsYW5kZWQgc2VydmVyLXNpZGUuXG4vLyBTbyBgcmVzZXJ2ZWAgZmFpbHMgQ0xPU0VEIHdoZW5ldmVyIHRoZSBxdW90YSBzZXJ2aWNlIGRpZCBub3QgQ09ORklSTSB0aGUgc2xvdDpcbi8vICAgLSB1bnJlYWNoYWJsZSAvIHRpbWVkIG91dCAvIGNpcmN1aXQgYnJlYWtlciBvcGVuIChubyByZXNwb25zZSksXG4vLyAgIC0gYSByZWFjaGFibGUtYnV0LWVycm9yZWQgcmVzcG9uc2UgKDV4eCwgNHh4LCBtYWxmb3JtZWQgYm9keSksXG4vLyAgIC0gYSA0MjkgdGhhdCBpcyBOT1QgYSBnZW51aW5lIFFVT1RBX0VYQ0VFREVEIChnYXRld2F5IC8gcmF0ZSBsaW1pdGVyKS5cbi8vIE9wZXJhdG9ycyB3aG8gcHJlZmVyIGF2YWlsYWJpbGl0eSBvdmVyIGVuZm9yY2VtZW50IG9wdCB0aGUgV0hPTEUgc2V0IGludG9cbi8vIGZhaWwtb3BlbiB3aXRoIFFVT1RBX1JFU0VSVkVfRkFJTF9PUEVOPXRydWUuIEJvdGggb3V0Y29tZXMgZW1pdCBhIGNvdW50ZXJcbi8vIChgcXVvdGFfZmFpbF9jbG9zZWRfdG90YWxgIC8gYHF1b3RhX2ZhaWxfb3Blbl90b3RhbGApIHRhZ2dlZCB3aXRoIHRoZSByZWFzb24uXG4vLyBgY2hlY2tgIChhIGNoZWFwIHJlYWQgZ2F0ZSkgc3RheXMgZmFpbC1vcGVuOyBgaW5jcmVtZW50YCBpcyBmaXJlLWFuZC1mb3JnZXQuXG5jb25zdCBRVU9UQV9SRVNFUlZFX0ZBSUxfT1BFTiA9IGVudkJvb2woJ1FVT1RBX1JFU0VSVkVfRkFJTF9PUEVOJywgZmFsc2UpO1xuXG4vKipcbiAqIFNlcnZpY2UtcHJpbmNpcGFsIGBBdXRob3JpemF0aW9uYCBoZWFkZXIgZm9yIGEgcXVvdGEgY2FsbCBtYWRlIG9uIGJlaGFsZiBvZlxuICogYG9yZ0lkYCBieSB0aGUgQ1VSUkVOVCBzZXJ2aWNlIChgU0VSVklDRV9OQU1FYCwgdGhlIHNhbWUgaWRlbnRpdHkgdGhlIGhlYWx0aFxuICogcm91dGVyIHJlcG9ydHMpLlxuICpcbiAqIFRoZSBxdW90YSBzZXJ2aWNlJ3MgbXV0YXRpb24gZW5kcG9pbnRzIChgLzpvcmdJZC9pbmNyZW1lbnRgLCBgL2RlY3JlbWVudGApXG4gKiByZWplY3QgYW55dGhpbmcgYnV0IGEgc2lnbmVkIHNlcnZpY2UgcHJpbmNpcGFsIG9yIGEgc3lzdGVtIGFkbWluLCBzb1xuICogZm9yd2FyZGluZyB0aGUgZW5kIHVzZXIncyBiZWFyZXIgdG9rZW4gdGhlcmUgaXMgYWx3YXlzIGEgNDAzLiBTZXJ2aWNlIHRva2Vuc1xuICogYXJlIGFsc28gZXhlbXB0IGZyb20gdGhlIHF1b3RhIHNlcnZpY2UncyBwZXItSVAgcmF0ZSBsaW1pdGVyLCBzbyBob3QtcGF0aFxuICogcXVvdGEgdHJhZmZpYyBmcm9tIGEgYnVzeSBwb2QgY2FuJ3QgZXhoYXVzdCB0aGF0IHBvZCBJUCdzIGJ1Y2tldCBhbmQgc2lsZW50bHlcbiAqIHR1cm4gZW5mb3JjZW1lbnQgb2ZmLiBTY29wZWQgdG8gdGhlIHRhcmdldCBvcmcgd2l0aCB0aGUgbG93ZXN0IHJvbGUgKG1lbWJlcikuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRRdW90YVNlcnZpY2VBdXRoSGVhZGVyKG9yZ0lkOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gZ2V0U2VydmljZUF1dGhIZWFkZXIoeyBzZXJ2aWNlTmFtZTogcHJvY2Vzcy5lbnYuU0VSVklDRV9OQU1FIHx8ICdhcGknLCBvcmdJZCwgcm9sZTogJ21lbWJlcicgfSk7XG59XG5cbi8qKlxuICogUmVzdWx0IG9mIGEgc3luY2hyb25vdXMgcXVvdGEgcmVzZXJ2YXRpb24gIHRoZSBhdG9taWMgY2hlY2sraW5jcmVtZW50XG4gKiB2YXJpYW50LiBgZXhjZWVkZWQ6IHRydWVgIG1lYW5zIHRoZSBvcGVyYXRpb24gd2FzIHJlamVjdGVkIGF0IHRoZSBEQlxuICogbGV2ZWw7IHRoZSBjYWxsZXIgc2hvdWxkIHJldHVybiA0Mjkgd2l0aG91dCBydW5uaW5nIHRoZSBnYXRlZCBhY3Rpb24uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUXVvdGFSZXNlcnZlUmVzdWx0IHtcbiAgLyoqIFRydWUgd2hlbiB0aGUgc2xvdCB3YXMgTk9UIHJlc2VydmVkIOKAlCB0aGUgZ2F0ZWQgYWN0aW9uIG11c3Qgbm90IHJ1bi4gKi9cbiAgZXhjZWVkZWQ6IGJvb2xlYW47XG4gIC8qKlxuICAgKiBTZXQgKHRydWUpIGJ5IHRoZSBxdW90YSBDTElFTlQgd2hlbiB0aGUgcmVzZXJ2YXRpb24gd2FzIGRlbmllZCBiZWNhdXNlIHRoZVxuICAgKiBxdW90YSBzZXJ2aWNlIGNvdWxkIG5vdCBDT05GSVJNIGl0ICh1bnJlYWNoYWJsZSAvIHRpbWVvdXQgLyBjaXJjdWl0IG9wZW4gL1xuICAgKiBlcnJvcmVkKSDigJQgbm90IGJlY2F1c2UgdGhlIG9yZyBpcyBvdmVyIGl0cyBsaW1pdC4gQWx3YXlzIHBhaXJlZCB3aXRoXG4gICAqIGBleGNlZWRlZDogdHJ1ZWAuIEFuc3dlciB3aXRoIHtAbGluayBzZW5kUXVvdGFSZXNlcnZlRGVuaWVkfSwgd2hpY2ggbWFwcyBpdCB0b1xuICAgKiA1MDMgaW5zdGVhZCBvZiBhIG1pc2xlYWRpbmcgNDI5IFwicXVvdGEgZXhjZWVkZWRcIi5cbiAgICovXG4gIHVuYXZhaWxhYmxlPzogYm9vbGVhbjtcbiAgcXVvdGE6IHtcbiAgICB0eXBlOiBRdW90YVR5cGU7XG4gICAgbGltaXQ6IG51bWJlcjtcbiAgICB1c2VkOiBudW1iZXI7XG4gICAgcmVtYWluaW5nOiBudW1iZXI7XG4gICAgcmVzZXRBdD86IHN0cmluZztcbiAgfTtcbn1cblxuLyoqXG4gKiBRdW90YSBzZXJ2aWNlIGNsaWVudCBpbnRlcmZhY2UuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUXVvdGFTZXJ2aWNlIHtcbiAgLyoqIENoZWNrIGlmIHF1b3RhIGlzIGF2YWlsYWJsZSAoZmFpbC1vcGVuIG9uIGVycm9yKS4gKi9cbiAgY2hlY2sob3JnSWQ6IHN0cmluZywgcXVvdGFUeXBlOiBRdW90YVR5cGUsIGF1dGhIZWFkZXI6IHN0cmluZywgcmVxdWVzdElkPzogc3RyaW5nKTogUHJvbWlzZTxRdW90YUNoZWNrUmVzdWx0PjtcbiAgLyoqIEluY3JlbWVudCBxdW90YSB1c2FnZS4gUmV0dXJucyBhIHByb21pc2Ugc28gY2FsbGVycyBjYW4gb3B0aW9uYWxseSBoYW5kbGUgZXJyb3JzLiAqL1xuICBpbmNyZW1lbnQob3JnSWQ6IHN0cmluZywgcXVvdGFUeXBlOiBRdW90YVR5cGUsIGF1dGhIZWFkZXI6IHN0cmluZywgYW1vdW50PzogbnVtYmVyLCByZXF1ZXN0SWQ/OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+O1xuICAvKipcbiAgICogQXRvbWljIHJlc2VydmUgIHRoZSBzYW1lIGF0b21pYyBjaGVjaytpbmNyZW1lbnQgYXMgYGluY3JlbWVudGAsIGJ1dFxuICAgKiBwYXJzZXMgdGhlIHJlc3BvbnNlIHNvIGNhbGxlcnMgY2FuIHNlZSB3aGV0aGVyIHRoZSBzbG90IHdhcyBhY3R1YWxseVxuICAgKiByZXNlcnZlZC4gVXNlIHRoaXMgZm9yIGV4cGVuc2l2ZSByZXNvdXJjZXMgd2hlcmUgdGhlIHBvc3QtaG9jIGZpcmUtXG4gICAqIGFuZC1mb3JnZXQgcGF0dGVybiBhbGxvd3MgY29uY3VycmVudCBvdmVyLXNwZW5kLlxuICAgKlxuICAgKiBGYWlscyBDTE9TRUQgKGBleGNlZWRlZDogdHJ1ZWApIHdoZW5ldmVyIHRoZSBzbG90IGlzIG5vdCBjb25maXJtZWQg4oCUXG4gICAqIHVucmVhY2hhYmxlLCB0aW1lb3V0LCBvcGVuIGNpcmN1aXQsIG5vbi1vaywgb3IgYSBub24tcXVvdGEgNDI5IOKAlCB1bmxlc3NcbiAgICogYFFVT1RBX1JFU0VSVkVfRkFJTF9PUEVOPXRydWVgIChzZWUgdGhlIHBvbGljeSBub3RlIGF0IHRoZSB0b3Agb2YgdGhpcyBmaWxlKS5cbiAgICovXG4gIHJlc2VydmUob3JnSWQ6IHN0cmluZywgcXVvdGFUeXBlOiBRdW90YVR5cGUsIGF1dGhIZWFkZXI6IHN0cmluZywgYW1vdW50PzogbnVtYmVyLCByZXF1ZXN0SWQ/OiBzdHJpbmcpOiBQcm9taXNlPFF1b3RhUmVzZXJ2ZVJlc3VsdD47XG4gIC8qKlxuICAgKiBSb2xsIGJhY2sgYSBwcmV2aW91c2x5IHJlc2VydmVkIHNsb3QuIEZpcmUtYW5kLWZvcmdldCDigJQgbmV2ZXIgdGhyb3dzLlxuICAgKiBQYXNzIGByZXNldEF0U25hcHNob3RgICh0aGUgYHF1b3RhLnJlc2V0QXRgIG9ic2VydmVkIHdoZW4gdGhlIHNsb3Qgd2FzXG4gICAqIHJlc2VydmVkKSB0byBtYWtlIHRoZSByb2xsYmFjayBjb25kaXRpb25hbDogaWYgdGhlIHBlcmlvZCByb2xsZWQgb3ZlclxuICAgKiBiZXR3ZWVuIHJlc2VydmUgYW5kIHJvbGxiYWNrLCB0aGUgc2VydmVyIHNraXBzIHRoZSBkZWNyZW1lbnQgc28gaXQgZG9lc24ndFxuICAgKiBzdGVhbCBjYXBhY2l0eSBmcm9tIHRoZSBuZXcgcGVyaW9kLlxuICAgKi9cbiAgZGVjcmVtZW50KG9yZ0lkOiBzdHJpbmcsIHF1b3RhVHlwZTogUXVvdGFUeXBlLCBhdXRoSGVhZGVyOiBzdHJpbmcsIGFtb3VudD86IG51bWJlciwgcmVzZXRBdFNuYXBzaG90Pzogc3RyaW5nLCByZXF1ZXN0SWQ/OiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+O1xuICAvKipcbiAgICogR2V0IHRoZSBvcmcncyBxdW90YSBgUXVvdGFUaWVyYC4gVXNlZCBieSB0aGUgcGx1Z2luLWJ1aWxkIHF1ZXVlIHBhcnRpdGlvbmluZ1xuICAgKiB0byByb3V0ZSBhIGJ1aWxkIHRvIHRoZSByaWdodCBwZXItdGllciBxdWV1ZS4gRmFpbC1vcGVuIHJldHVybnMgYERFRkFVTFRfVElFUmBcbiAgICogKGBkZXZlbG9wZXJgIHdoZW4gYmlsbGluZyBpcyBlbmFibGVkLCBgdW5saW1pdGVkYCB3aGVuIGl0J3MgZGlzYWJsZWQpOyBhXG4gICAqIG1pc2NsYXNzaWZpZWQgb3JnIHN0aWxsIGJ1aWxkcyBvbiB0aGUgZGVmYXVsdCBxdWV1ZSwganVzdCB3aXRob3V0IHRoZVxuICAgKiB0aWVyLXNjb3BlZCBzY2hlZHVsaW5nIGJvb3N0LlxuICAgKi9cbiAgZ2V0VGllcihvcmdJZDogc3RyaW5nLCBhdXRoSGVhZGVyOiBzdHJpbmcsIHJlcXVlc3RJZD86IHN0cmluZyk6IFByb21pc2U8UXVvdGFUaWVyPjtcbiAgLyoqXG4gICAqIEZBSUwtQ0xPU0VEIHR3aW4gb2Yge0BsaW5rIGdldFRpZXJ9OiB0aGUgb3JnJ3MgdGllciBhcyB0aGUgcXVvdGEgc2VydmljZVxuICAgKiBDT05GSVJNRUQgaXQsIG9yIGBudWxsYCB3aGVuIGl0IGNvdWxkIG5vdCBiZSBjb25maXJtZWQgKHVucmVhY2hhYmxlLCBub24tb2ssXG4gICAqIG1pc3Npbmcgb3IgdW5yZWNvZ25pemVkIHRpZXIpLiBGb3IgZGVjaXNpb25zIHRoYXQgbXVzdCBuZXZlciBiZSB0YWtlbiBvbiBhXG4gICAqIGd1ZXNzIOKAlCBhbnl0aGluZyB0aGF0IHJldm9rZXMsIGRvd25ncmFkZXMgb3IgZGVsZXRlcyBvbiB0aGUgc3RyZW5ndGggb2YgYVxuICAgKiB0aWVyIChlLmcuIGEgdmVyaWZpZWQtcHVibGlzaGVyIGdyYWNlIHN3ZWVwKSBtdXN0IHNraXAgdGhlIG9yZyBvbiBgbnVsbGAsXG4gICAqIG5ldmVyIGFjdCBvbiBgREVGQVVMVF9USUVSYC5cbiAgICovXG4gIGdldFRpZXJTdHJpY3Qob3JnSWQ6IHN0cmluZywgYXV0aEhlYWRlcjogc3RyaW5nLCByZXF1ZXN0SWQ/OiBzdHJpbmcpOiBQcm9taXNlPFF1b3RhVGllciB8IG51bGw+O1xufVxuXG4vKipcbiAqIENvbmZpZ3VyYXRpb24gZm9yIHF1b3RhIHNlcnZpY2UgY2xpZW50LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFF1b3RhU2VydmljZUNvbmZpZyB7XG4gIC8qKiBRdW90YSBzZXJ2aWNlIGhvc3QgKGRlZmF1bHQ6IGVudiBRVU9UQV9TRVJWSUNFX0hPU1Qgb3IgJ3F1b3RhJykgKi9cbiAgaG9zdD86IHN0cmluZztcbiAgLyoqIFF1b3RhIHNlcnZpY2UgcG9ydCAoZGVmYXVsdDogZW52IFFVT1RBX1NFUlZJQ0VfUE9SVCBvciAzMDAwKSAqL1xuICBwb3J0PzogbnVtYmVyO1xuICAvKiogUmVxdWVzdCB0aW1lb3V0IGluIG1pbGxpc2Vjb25kcyAoZGVmYXVsdDogNTAwMCkgKi9cbiAgdGltZW91dD86IG51bWJlcjtcbn1cblxuLyoqXG4gKiBBcHBseSB0aGUgZXhwbGljaXQgcmVzZXJ2ZSBmYWlsLW1vZGUgcG9saWN5IHRvIGEgcmVzZXJ2YXRpb24gdGhlIHF1b3RhIHNlcnZpY2VcbiAqIGRpZCBOT1QgY29uZmlybSAoc2VlIFFVT1RBX1JFU0VSVkVfRkFJTF9PUEVOIGFib3ZlKS4gRGVmYXVsdDogZGVueS5cbiAqL1xuZnVuY3Rpb24gdW5jb25maXJtZWRSZXNlcnZlKFxuICBvcmdJZDogc3RyaW5nLFxuICBxdW90YVR5cGU6IFF1b3RhVHlwZSxcbiAgcmVhc29uOiAndW5yZWFjaGFibGUnIHwgJ3RyYW5zaWVudC00MjknIHwgJ25vbi1vaycsXG4gIHN0YXR1c0NvZGU/OiBudW1iZXIsXG4pOiBRdW90YVJlc2VydmVSZXN1bHQge1xuICBpZiAoUVVPVEFfUkVTRVJWRV9GQUlMX09QRU4pIHtcbiAgICBsb2dnZXIud2FybignUVVPVEFfRkFJTF9PUEVOOiBxdW90YSByZXNlcnZlIG5vdCBjb25maXJtZWQsIGFsbG93aW5nIHJlcXVlc3QnLCB7IG9yZ0lkLCBxdW90YVR5cGUsIHJlYXNvbiwgc3RhdHVzQ29kZSB9KTtcbiAgICBlbWl0Q291bnRlcigncXVvdGFfZmFpbF9vcGVuX3RvdGFsJywgeyBvcGVyYXRpb246ICdyZXNlcnZlJywgcmVhc29uLCBxdW90YVR5cGUgfSk7XG4gICAgcmV0dXJuIHsgZXhjZWVkZWQ6IGZhbHNlLCBxdW90YTogeyB0eXBlOiBxdW90YVR5cGUsIGxpbWl0OiAtMSwgdXNlZDogMCwgcmVtYWluaW5nOiAtMSB9IH07XG4gIH1cbiAgbG9nZ2VyLndhcm4oJ1FVT1RBX0ZBSUxfQ0xPU0VEOiBxdW90YSByZXNlcnZlIG5vdCBjb25maXJtZWQsIGRlbnlpbmcgcmVxdWVzdCcsIHsgb3JnSWQsIHF1b3RhVHlwZSwgcmVhc29uLCBzdGF0dXNDb2RlIH0pO1xuICBlbWl0Q291bnRlcigncXVvdGFfZmFpbF9jbG9zZWRfdG90YWwnLCB7IG9wZXJhdGlvbjogJ3Jlc2VydmUnLCByZWFzb24sIHF1b3RhVHlwZSB9KTtcbiAgcmV0dXJuIHsgZXhjZWVkZWQ6IHRydWUsIHVuYXZhaWxhYmxlOiB0cnVlLCBxdW90YTogeyB0eXBlOiBxdW90YVR5cGUsIGxpbWl0OiAwLCB1c2VkOiAwLCByZW1haW5pbmc6IDAgfSB9O1xufVxuXG4vKipcbiAqIENyZWF0ZSBhIGZhaWwtb3BlbiBxdW90YSByZXN1bHQgKGFsbG93cyB0aGUgcmVxdWVzdCkuXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZUZhaWxPcGVuUmVzdWx0KCk6IFF1b3RhQ2hlY2tSZXN1bHQge1xuICByZXR1cm4ge1xuICAgIGFsbG93ZWQ6IHRydWUsXG4gICAgbGltaXQ6IC0xLFxuICAgIHVzZWQ6IDAsXG4gICAgcmVtYWluaW5nOiAtMSxcbiAgICByZXNldEF0OiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCksXG4gICAgdW5saW1pdGVkOiB0cnVlLFxuICAgIC8vIFRhZyB0aGUgc2VudGluZWwgc28gZmFpbC1jbG9zZWQgY2FsbGVycyBjYW4gdGVsbCBhbiBvdXRhZ2UgYXBhcnQgZnJvbSBhXG4gICAgLy8gcmVhbCB1bmxpbWl0ZWQgKC0xKSByZWFkaW5nLiBSZWFsIHF1b3RhIHJlc3VsdHMgbmV2ZXIgc2V0IHRoaXMuXG4gICAgZmFpbE9wZW46IHRydWUsXG4gIH07XG59XG5cbi8qKlxuICogQnVpbGQgY29tbW9uIHJlcXVlc3QgaGVhZGVycyB3aXRoIG9wdGlvbmFsIHJlcXVlc3QgSUQgZm9yIGRpc3RyaWJ1dGVkIHRyYWNpbmcuXG4gKi9cbmZ1bmN0aW9uIGJ1aWxkSGVhZGVycyhvcmdJZDogc3RyaW5nLCBhdXRoSGVhZGVyPzogc3RyaW5nLCByZXF1ZXN0SWQ/OiBzdHJpbmcpOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+IHtcbiAgY29uc3QgaGVhZGVyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHsgJ3gtb3JnLWlkJzogb3JnSWQgfTtcbiAgaWYgKGF1dGhIZWFkZXIpIGhlYWRlcnMuQXV0aG9yaXphdGlvbiA9IGF1dGhIZWFkZXI7XG4gIGlmIChyZXF1ZXN0SWQpIGhlYWRlcnNbJ1gtUmVxdWVzdC1JZCddID0gcmVxdWVzdElkO1xuICByZXR1cm4gaGVhZGVycztcbn1cblxuLyoqXG4gKiBDcmVhdGUgYSBxdW90YSBzZXJ2aWNlIGNsaWVudC5cbiAqXG4gKiBAcGFyYW0gY29uZmlnIC0gT3B0aW9uYWwgc2VydmljZSBjb25maWd1cmF0aW9uXG4gKiBAcmV0dXJucyBRdW90YSBzZXJ2aWNlIGNsaWVudFxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCBxdW90YVNlcnZpY2UgPSBjcmVhdGVRdW90YVNlcnZpY2UoKTtcbiAqXG4gKiAvLyBDaGVjayBxdW90YSBiZWZvcmUgcHJvY2Vzc2luZ1xuICogY29uc3QgcXVvdGEgPSBhd2FpdCBxdW90YVNlcnZpY2UuY2hlY2sob3JnSWQsICdhcGlDYWxscycsIGF1dGhIZWFkZXIpO1xuICogaWYgKCFxdW90YS5hbGxvd2VkKSB7XG4gKiByZXR1cm4gcmVzLnN0YXR1cyg0MjkpLmpzb24oeyBlcnJvcjogJ1F1b3RhIGV4Y2VlZGVkJyB9KTtcbiAqIH1cbiAqXG4gKiAvLyBJbmNyZW1lbnQgcXVvdGEgYWZ0ZXIgc3VjY2Vzc1xuICogcXVvdGFTZXJ2aWNlLmluY3JlbWVudChvcmdJZCwgJ2FwaUNhbGxzJywgYXV0aEhlYWRlcikuY2F0Y2goZXJyID0+IGxvZ2dlci53YXJuKCdRdW90YSBpbmNyZW1lbnQgZmFpbGVkJywgeyBlcnJvcjogZXJyIH0pKTtcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlUXVvdGFTZXJ2aWNlKGNvbmZpZzogUXVvdGFTZXJ2aWNlQ29uZmlnID0ge30pOiBRdW90YVNlcnZpY2Uge1xuICBjb25zdCBzZXJ2aWNlQ29uZmlnOiBTZXJ2aWNlQ29uZmlnID0ge1xuICAgIGhvc3Q6IGNvbmZpZy5ob3N0ID8/IHNlcnZpY2VFbmRwb2ludCgncXVvdGEnKS5ob3N0LFxuICAgIHBvcnQ6IGNvbmZpZy5wb3J0ID8/IHNlcnZpY2VFbmRwb2ludCgncXVvdGEnKS5wb3J0LFxuICAgIHRpbWVvdXQ6IGNvbmZpZy50aW1lb3V0ID8/IDUwMDAsXG4gIH07XG5cbiAgY29uc3QgY2xpZW50ID0gY3JlYXRlU2FmZUNsaWVudChzZXJ2aWNlQ29uZmlnKTtcblxuICAvKiogT25lIHRpZXIgcmVhZDogdGhlIGNvbmZpcm1lZCB0aWVyLCBvciB3aHkgdGhlcmUgaXNuJ3Qgb25lLiAqL1xuICBhc3luYyBmdW5jdGlvbiByZWFkVGllcihcbiAgICBvcmdJZDogc3RyaW5nLCBhdXRoSGVhZGVyOiBzdHJpbmcsIHJlcXVlc3RJZD86IHN0cmluZyxcbiAgKTogUHJvbWlzZTx7IHRpZXI6IFF1b3RhVGllcjsgcmVhc29uPzogdW5kZWZpbmVkOyBzdGF0dXNDb2RlPzogbnVtYmVyIH0gfCB7IHRpZXI6IG51bGw7IHJlYXNvbjogJ3VucmVhY2hhYmxlJyB8ICdub24tb2snIHwgJ2ludmFsaWQtdGllcic7IHN0YXR1c0NvZGU/OiBudW1iZXIgfT4ge1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgY2xpZW50LmdldDx7XG4gICAgICBzdWNjZXNzOiBib29sZWFuO1xuICAgICAgZGF0YT86IHsgcXVvdGE/OiB7IHRpZXI/OiBzdHJpbmcgfSB9O1xuICAgICAgbWVzc2FnZT86IHN0cmluZztcbiAgICB9PihgL3F1b3Rhcy8ke2VuY29kZVVSSUNvbXBvbmVudChvcmdJZCl9YCwgeyBoZWFkZXJzOiBidWlsZEhlYWRlcnMob3JnSWQsIGF1dGhIZWFkZXIsIHJlcXVlc3RJZCksIC4uLlFVT1RBX1JFUVVFU1RfT1BUSU9OUyB9KTtcbiAgICBpZiAoIXJlc3BvbnNlKSByZXR1cm4geyB0aWVyOiBudWxsLCByZWFzb246ICd1bnJlYWNoYWJsZScgfTtcbiAgICBpZiAocmVzcG9uc2Uuc3RhdHVzQ29kZSAhPT0gMjAwIHx8ICFyZXNwb25zZS5ib2R5Py5zdWNjZXNzKSByZXR1cm4geyB0aWVyOiBudWxsLCByZWFzb246ICdub24tb2snLCBzdGF0dXNDb2RlOiByZXNwb25zZS5zdGF0dXNDb2RlIH07XG4gICAgY29uc3QgdGllciA9IHJlc3BvbnNlLmJvZHkuZGF0YT8ucXVvdGE/LnRpZXI7XG4gICAgaWYgKCF0aWVyIHx8ICFpc1ZhbGlkVGllcih0aWVyKSkgcmV0dXJuIHsgdGllcjogbnVsbCwgcmVhc29uOiAnaW52YWxpZC10aWVyJywgc3RhdHVzQ29kZTogcmVzcG9uc2Uuc3RhdHVzQ29kZSB9O1xuICAgIHJldHVybiB7IHRpZXIsIHN0YXR1c0NvZGU6IHJlc3BvbnNlLnN0YXR1c0NvZGUgfTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgYXN5bmMgY2hlY2sob3JnSWQ6IHN0cmluZywgcXVvdGFUeXBlOiBRdW90YVR5cGUsIGF1dGhIZWFkZXI6IHN0cmluZywgcmVxdWVzdElkPzogc3RyaW5nKTogUHJvbWlzZTxRdW90YUNoZWNrUmVzdWx0PiB7XG4gICAgICBjb25zdCBwYXRoID0gYC9xdW90YXMvJHtlbmNvZGVVUklDb21wb25lbnQob3JnSWQpfS8ke2VuY29kZVVSSUNvbXBvbmVudChxdW90YVR5cGUpfWA7XG5cbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgY2xpZW50LmdldDx7XG4gICAgICAgIHN1Y2Nlc3M6IGJvb2xlYW47XG4gICAgICAgIGRhdGE/OiB7IHF1b3RhVHlwZTogc3RyaW5nOyBzdGF0dXM6IFF1b3RhQ2hlY2tSZXN1bHQgfTtcbiAgICAgICAgbWVzc2FnZT86IHN0cmluZztcbiAgICAgIH0+KHBhdGgsIHsgaGVhZGVyczogYnVpbGRIZWFkZXJzKG9yZ0lkLCBhdXRoSGVhZGVyLCByZXF1ZXN0SWQpLCAuLi5RVU9UQV9SRVFVRVNUX09QVElPTlMgfSk7XG5cbiAgICAgIGlmICghcmVzcG9uc2UpIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oJ1FVT1RBX0ZBSUxfT1BFTjogUXVvdGEgc2VydmljZSB1bnJlYWNoYWJsZSwgYWxsb3dpbmcgcmVxdWVzdCcsIHsgb3JnSWQsIHF1b3RhVHlwZSB9KTtcbiAgICAgICAgZW1pdENvdW50ZXIoJ3F1b3RhX2ZhaWxfb3Blbl90b3RhbCcsIHsgb3BlcmF0aW9uOiAnY2hlY2snLCByZWFzb246ICd1bnJlYWNoYWJsZScsIHF1b3RhVHlwZSB9KTtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZUZhaWxPcGVuUmVzdWx0KCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChyZXNwb25zZS5zdGF0dXNDb2RlICE9PSAyMDAgfHwgIXJlc3BvbnNlLmJvZHkuc3VjY2VzcyB8fCAhcmVzcG9uc2UuYm9keS5kYXRhPy5zdGF0dXMpIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oJ1FVT1RBX0ZBSUxfT1BFTjogUXVvdGEgY2hlY2sgcmV0dXJuZWQgbm9uLW9rLCBhbGxvd2luZyByZXF1ZXN0Jywge1xuICAgICAgICAgIG9yZ0lkLCBxdW90YVR5cGUsIHN0YXR1c0NvZGU6IHJlc3BvbnNlLnN0YXR1c0NvZGUsIG1lc3NhZ2U6IHJlc3BvbnNlLmJvZHkubWVzc2FnZSxcbiAgICAgICAgfSk7XG4gICAgICAgIGVtaXRDb3VudGVyKCdxdW90YV9mYWlsX29wZW5fdG90YWwnLCB7IG9wZXJhdGlvbjogJ2NoZWNrJywgcmVhc29uOiAnbm9uLW9rJywgcXVvdGFUeXBlIH0pO1xuICAgICAgICByZXR1cm4gY3JlYXRlRmFpbE9wZW5SZXN1bHQoKTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHJlc3BvbnNlLmJvZHkuZGF0YS5zdGF0dXM7XG4gICAgfSxcblxuICAgIGFzeW5jIGluY3JlbWVudChvcmdJZDogc3RyaW5nLCBxdW90YVR5cGU6IFF1b3RhVHlwZSwgYXV0aEhlYWRlcjogc3RyaW5nLCBhbW91bnQ6IG51bWJlciA9IDEsIHJlcXVlc3RJZD86IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgY29uc3QgcGF0aCA9IGAvcXVvdGFzLyR7ZW5jb2RlVVJJQ29tcG9uZW50KG9yZ0lkKX0vaW5jcmVtZW50YDtcblxuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBjbGllbnRcbiAgICAgICAgLnBvc3QocGF0aCwgeyBxdW90YVR5cGUsIGFtb3VudCB9LCB7IGhlYWRlcnM6IGJ1aWxkSGVhZGVycyhvcmdJZCwgYXV0aEhlYWRlciwgcmVxdWVzdElkKSwgLi4uUVVPVEFfUkVRVUVTVF9PUFRJT05TIH0pO1xuXG4gICAgICBpZiAoIXJlc3BvbnNlIHx8IHJlc3BvbnNlLnN0YXR1c0NvZGUgIT09IDIwMCkge1xuICAgICAgICBsb2dnZXIud2FybignRmFpbGVkIHRvIGluY3JlbWVudCBxdW90YScsIHtcbiAgICAgICAgICBvcmdJZCwgcXVvdGFUeXBlLCBhbW91bnQsIHN0YXR1c0NvZGU6IHJlc3BvbnNlPy5zdGF0dXNDb2RlLFxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZygnUXVvdGEgaW5jcmVtZW50ZWQnLCB7IG9yZ0lkLCBxdW90YVR5cGUsIGFtb3VudCB9KTtcbiAgICAgIH1cbiAgICB9LFxuXG4gICAgYXN5bmMgcmVzZXJ2ZShvcmdJZDogc3RyaW5nLCBxdW90YVR5cGU6IFF1b3RhVHlwZSwgYXV0aEhlYWRlcjogc3RyaW5nLCBhbW91bnQ6IG51bWJlciA9IDEsIHJlcXVlc3RJZD86IHN0cmluZyk6IFByb21pc2U8UXVvdGFSZXNlcnZlUmVzdWx0PiB7XG4gICAgICBjb25zdCBwYXRoID0gYC9xdW90YXMvJHtlbmNvZGVVUklDb21wb25lbnQob3JnSWQpfS9pbmNyZW1lbnRgO1xuXG4gICAgICAvLyAyMDAgY2FycmllcyBgZGF0YS5xdW90YWA7IDQyOSAoUVVPVEFfRVhDRUVERUQpIGNhcnJpZXMgYGRldGFpbHMucXVvdGFgLlxuICAgICAgLy8gQm90aCBzaGFwZXMgYXJlIG5vcm1hbGl6ZWQgaW50byBRdW90YVJlc2VydmVSZXN1bHQuXG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGNsaWVudC5wb3N0PHtcbiAgICAgICAgc3VjY2VzczogYm9vbGVhbjtcbiAgICAgICAgZGF0YT86IHsgcXVvdGE/OiBRdW90YVJlc2VydmVSZXN1bHRbJ3F1b3RhJ10gfTtcbiAgICAgICAgZGV0YWlscz86IHsgcXVvdGE/OiBRdW90YVJlc2VydmVSZXN1bHRbJ3F1b3RhJ10gfTtcbiAgICAgICAgLyoqIGBzZW5kRXJyb3JgJ3MgZXJyb3ItY29kZSBmaWVsZC4gKi9cbiAgICAgICAgY29kZT86IHN0cmluZztcbiAgICAgIH0+KHBhdGgsIHsgcXVvdGFUeXBlLCBhbW91bnQgfSwgeyBoZWFkZXJzOiBidWlsZEhlYWRlcnMob3JnSWQsIGF1dGhIZWFkZXIsIHJlcXVlc3RJZCksIC4uLlFVT1RBX1JFUVVFU1RfT1BUSU9OUyB9KTtcblxuICAgICAgaWYgKCFyZXNwb25zZSkgcmV0dXJuIHVuY29uZmlybWVkUmVzZXJ2ZShvcmdJZCwgcXVvdGFUeXBlLCAndW5yZWFjaGFibGUnKTtcblxuICAgICAgaWYgKHJlc3BvbnNlLnN0YXR1c0NvZGUgPT09IDQyOSkge1xuICAgICAgICBjb25zdCBxID0gcmVzcG9uc2UuYm9keS5kZXRhaWxzPy5xdW90YTtcbiAgICAgICAgLy8gT25seSBhIEdFTlVJTkUgcXVvdGEtZXhjZWVkZWQgNDI5IG1lYW5zIFwib3ZlciBxdW90YVwiLiBBIGdlbmVyaWMgNDI5IOKAlFxuICAgICAgICAvLyBhbiBpbnRlcnZlbmluZyBnYXRld2F5IG9yIHJhdGUgbGltaXRlciDigJQgZGlkIG5vdCBjb25maXJtIGFueXRoaW5nLCBzb1xuICAgICAgICAvLyBpdCBnb2VzIHRocm91Z2ggdGhlIHNhbWUgdW5jb25maXJtZWQtcmVzZXJ2YXRpb24gcG9saWN5IGFzIGFuIG91dGFnZS5cbiAgICAgICAgaWYgKHJlc3BvbnNlLmJvZHkuY29kZSA9PT0gRXJyb3JDb2RlLlFVT1RBX0VYQ0VFREVEIHx8IHEpIHtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZXhjZWVkZWQ6IHRydWUsXG4gICAgICAgICAgICBxdW90YTogcSA/PyB7IHR5cGU6IHF1b3RhVHlwZSwgbGltaXQ6IDAsIHVzZWQ6IDAsIHJlbWFpbmluZzogMCB9LFxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVuY29uZmlybWVkUmVzZXJ2ZShvcmdJZCwgcXVvdGFUeXBlLCAndHJhbnNpZW50LTQyOScsIHJlc3BvbnNlLnN0YXR1c0NvZGUpO1xuICAgICAgfVxuXG4gICAgICBpZiAocmVzcG9uc2Uuc3RhdHVzQ29kZSAhPT0gMjAwIHx8ICFyZXNwb25zZS5ib2R5LnN1Y2Nlc3MpIHtcbiAgICAgICAgcmV0dXJuIHVuY29uZmlybWVkUmVzZXJ2ZShvcmdJZCwgcXVvdGFUeXBlLCAnbm9uLW9rJywgcmVzcG9uc2Uuc3RhdHVzQ29kZSk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHEgPSByZXNwb25zZS5ib2R5LmRhdGE/LnF1b3RhO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgZXhjZWVkZWQ6IGZhbHNlLFxuICAgICAgICBxdW90YTogcSA/PyB7IHR5cGU6IHF1b3RhVHlwZSwgbGltaXQ6IC0xLCB1c2VkOiAwLCByZW1haW5pbmc6IC0xIH0sXG4gICAgICB9O1xuICAgIH0sXG5cbiAgICBhc3luYyBkZWNyZW1lbnQob3JnSWQ6IHN0cmluZywgcXVvdGFUeXBlOiBRdW90YVR5cGUsIGF1dGhIZWFkZXI6IHN0cmluZywgYW1vdW50OiBudW1iZXIgPSAxLCByZXNldEF0U25hcHNob3Q/OiBzdHJpbmcsIHJlcXVlc3RJZD86IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgY29uc3QgcGF0aCA9IGAvcXVvdGFzLyR7ZW5jb2RlVVJJQ29tcG9uZW50KG9yZ0lkKX0vZGVjcmVtZW50YDtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgY2xpZW50XG4gICAgICAgIC5wb3N0KHBhdGgsIHsgcXVvdGFUeXBlLCBhbW91bnQsIC4uLihyZXNldEF0U25hcHNob3QgJiYgeyByZXNldEF0U25hcHNob3QgfSkgfSwgeyBoZWFkZXJzOiBidWlsZEhlYWRlcnMob3JnSWQsIGF1dGhIZWFkZXIsIHJlcXVlc3RJZCksIC4uLlFVT1RBX1JFUVVFU1RfT1BUSU9OUyB9KTtcblxuICAgICAgaWYgKCFyZXNwb25zZSB8fCByZXNwb25zZS5zdGF0dXNDb2RlICE9PSAyMDApIHtcbiAgICAgICAgLy8gUm9sbGJhY2sgZmFpbHVyZSBpcyBsb2dnZWQgYnV0IG5ldmVyIHByb3BhZ2F0ZWQgIHRoZSBhY3Rpb24ncyBvd25cbiAgICAgICAgLy8gZmFpbHVyZSBoYXMgYWxyZWFkeSBiZWVuIHN1cmZhY2VkIHRvIHRoZSBjYWxsZXI7IGEgc3R1Y2sgY291bnRlclxuICAgICAgICAvLyByZXNvbHZlcyBvbiB0aGUgbmV4dCBwZXJpb2QgcmVzZXQuXG4gICAgICAgIGxvZ2dlci53YXJuKCdGYWlsZWQgdG8gZGVjcmVtZW50IHF1b3RhIChzbG90IHdpbGwgcmVzZXQgb24gbmV4dCBwZXJpb2QpJywge1xuICAgICAgICAgIG9yZ0lkLCBxdW90YVR5cGUsIGFtb3VudCwgc3RhdHVzQ29kZTogcmVzcG9uc2U/LnN0YXR1c0NvZGUsXG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nZ2VyLmRlYnVnKCdRdW90YSBkZWNyZW1lbnRlZCcsIHsgb3JnSWQsIHF1b3RhVHlwZSwgYW1vdW50IH0pO1xuICAgICAgfVxuICAgIH0sXG5cbiAgICBhc3luYyBnZXRUaWVyKG9yZ0lkOiBzdHJpbmcsIGF1dGhIZWFkZXI6IHN0cmluZywgcmVxdWVzdElkPzogc3RyaW5nKTogUHJvbWlzZTxRdW90YVRpZXI+IHtcbiAgICAgIGNvbnN0IGtub3duID0gY29uc3RhbnRUaWVyRm9yKG9yZ0lkKTtcbiAgICAgIGlmIChrbm93bikgcmV0dXJuIGtub3duO1xuICAgICAgY29uc3QgcmVhZCA9IGF3YWl0IHJlYWRUaWVyKG9yZ0lkLCBhdXRoSGVhZGVyLCByZXF1ZXN0SWQpO1xuICAgICAgaWYgKHJlYWQudGllcikgcmV0dXJuIHJlYWQudGllcjtcbiAgICAgIGxvZ2dlci53YXJuKGBRVU9UQV9GQUlMX09QRU46IHRpZXIgbG9va3VwIGZhaWxlZCwgZGVmYXVsdGluZyB0byAke0RFRkFVTFRfVElFUn0gdGllcmAsIHtcbiAgICAgICAgb3JnSWQsIHN0YXR1c0NvZGU6IHJlYWQuc3RhdHVzQ29kZSwgcmVhc29uOiByZWFkLnJlYXNvbiwgZGVmYXVsdFRpZXI6IERFRkFVTFRfVElFUixcbiAgICAgIH0pO1xuICAgICAgZW1pdENvdW50ZXIoJ3F1b3RhX2ZhaWxfb3Blbl90b3RhbCcsIHsgb3BlcmF0aW9uOiAndGllcicsIHJlYXNvbjogcmVhZC5yZWFzb24sIHF1b3RhVHlwZTogJ3RpZXInIH0pO1xuICAgICAgcmV0dXJuIERFRkFVTFRfVElFUjtcbiAgICB9LFxuXG4gICAgYXN5bmMgZ2V0VGllclN0cmljdChvcmdJZDogc3RyaW5nLCBhdXRoSGVhZGVyOiBzdHJpbmcsIHJlcXVlc3RJZD86IHN0cmluZyk6IFByb21pc2U8UXVvdGFUaWVyIHwgbnVsbD4ge1xuICAgICAgY29uc3Qga25vd24gPSBjb25zdGFudFRpZXJGb3Iob3JnSWQpO1xuICAgICAgaWYgKGtub3duKSByZXR1cm4ga25vd247XG4gICAgICBjb25zdCByZWFkID0gYXdhaXQgcmVhZFRpZXIob3JnSWQsIGF1dGhIZWFkZXIsIHJlcXVlc3RJZCk7XG4gICAgICBpZiAocmVhZC50aWVyKSByZXR1cm4gcmVhZC50aWVyO1xuICAgICAgbG9nZ2VyLndhcm4oJ1FVT1RBX0ZBSUxfQ0xPU0VEOiB0aWVyIGNvdWxkIG5vdCBiZSBjb25maXJtZWQnLCB7IG9yZ0lkLCBzdGF0dXNDb2RlOiByZWFkLnN0YXR1c0NvZGUsIHJlYXNvbjogcmVhZC5yZWFzb24gfSk7XG4gICAgICBlbWl0Q291bnRlcigncXVvdGFfZmFpbF9jbG9zZWRfdG90YWwnLCB7IG9wZXJhdGlvbjogJ3RpZXInLCByZWFzb246IHJlYWQucmVhc29uLCBxdW90YVR5cGU6ICd0aWVyJyB9KTtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH0sXG4gIH07XG59XG5cbi8qKlxuICogVGhlIHN5c3RlbSBvcmcncyB0aWVyIGlzIGEgQ09OU1RBTlQsIG5vdCBhIGJpbGxpbmcgZmFjdCwgc28gaXQgaXMgYW5zd2VyZWRcbiAqIHdpdGhvdXQgYSBsb29rdXAuXG4gKlxuICogVGhlIHBsYXRmb3JtJ3Mgb3duIG9yZyBpcyBhbHdheXMgYHVubGltaXRlZGAgKHBsYXRmb3JtL3NyYy9zZXJ2aWNlcy9cbiAqIGF1dGgtc2VydmljZS50cyBzZWVkcyBpdCB0aGF0IHdheSk6IG5vdGhpbmcgbWV0ZXJzIGl0IGFuZCBpdCBpcyBuZXZlciBzb2xkLlxuICogQXNraW5nIHRoZSBxdW90YSBzZXJ2aWNlIHdhcyB0aGVyZWZvcmUgYSBuZXR3b3JrIGhvcCB3aG9zZSBvbmx5IHBvc3NpYmxlXG4gKiBvdXRjb21lcyB3ZXJlIHRoZSBhbnN3ZXIgd2UgYWxyZWFkeSBrbmV3LCBvciBhIGZhaWx1cmUuXG4gKlxuICogVGhlIGZhaWx1cmUgaXMgd2hhdCBtYWRlIHRoaXMgd29ydGggZml4aW5nLiBgZ2V0VGllcmAgZmFpbHMgT1BFTiB0b1xuICogREVGQVVMVF9USUVSLCB3aGljaCB3aXRoIGJpbGxpbmcgZW5hYmxlZCBpcyBgZGV2ZWxvcGVyYCDigJQgdGhlIG1vc3RcbiAqIGNvbnN0cmFpbmVkIHRpZXIg4oCUIGFuZCBpdHMgZG9jdW1lbnRlZCBqb2IgaXMgYnVpbGQtcXVldWUgcGFydGl0aW9uaW5nLiBBXG4gKiBibGlwIGluIHRoZSBxdW90YSBzZXJ2aWNlIHRoZXJlZm9yZSByb3V0ZWQgdGhlIFNZU1RFTSBvcmcncyBidWlsZHMgb250byB0aGVcbiAqIGRldmVsb3BlciBxdWV1ZTsgdGhlIE9mZmljaWFsIGNhdGFsb2cgbG9hZCBpcyAxMTkgb2YgdGhlbS4gYGdldFRpZXJTdHJpY3RgXG4gKiBmYWlscyBDTE9TRUQgdG8gbnVsbCwgc28gYSBzd2VlcCB0aGF0IG11c3Qgbm90IGd1ZXNzIHdvdWxkIHNraXAgdGhlXG4gKiBwbGF0Zm9ybSdzIG93biBvcmcgaW5zdGVhZC5cbiAqL1xuZnVuY3Rpb24gY29uc3RhbnRUaWVyRm9yKG9yZ0lkOiBzdHJpbmcpOiBRdW90YVRpZXIgfCBudWxsIHtcbiAgcmV0dXJuIG9yZ0lkLnRvTG93ZXJDYXNlKCkgPT09IFNZU1RFTV9PUkdfSUQgPyAndW5saW1pdGVkJyA6IG51bGw7XG59XG5cbi8qKlxuICogRmlyZS1hbmQtZm9yZ2V0IHF1b3RhIE1FVEVSSU5HIGluY3JlbWVudCB3aXRoIHN0YW5kYXJkaXplZCBlcnJvciBsb2dnaW5nLlxuICpcbiAqIEF1dGhlbnRpY2F0ZXMgYXMgdGhlIGNhbGxpbmcgU0VSVklDRSAoe0BsaW5rIGdldFF1b3RhU2VydmljZUF1dGhIZWFkZXJ9KSwgbmV2ZXJcbiAqIHdpdGggdGhlIGVuZCB1c2VyJ3MgdG9rZW46IGAvcXVvdGFzLzpvcmdJZC9pbmNyZW1lbnRgIGlzIHNlcnZpY2UtcHJpbmNpcGFsIC9cbiAqIHN5c3RlbS1hZG1pbiBvbmx5LCBzbyBhIGZvcndhcmRlZCB1c2VyIEpXVCB3YXMgYWx3YXlzIHJlamVjdGVkICg0MDMpIGFuZCB0aGVcbiAqIG1ldGVyZWQgcXVvdGEgKGUuZy4gYGFwaUNhbGxzYCwgYW5kIHRoZSBgYXBpX3BhY2tgIGJ1bmRsZSByYWlzaW5nIGl0KSBuZXZlclxuICogbW92ZWQuXG4gKlxuICogQHBhcmFtIHF1b3RhU2VydmljZSAtIFF1b3RhIHNlcnZpY2UgY2xpZW50XG4gKiBAcGFyYW0gb3JnSWQgLSBPcmdhbml6YXRpb24gSUQgd2hvc2UgY291bnRlciBpcyBpbmNyZW1lbnRlZFxuICogQHBhcmFtIHF1b3RhVHlwZSAtIFF1b3RhIHR5cGUgdG8gaW5jcmVtZW50XG4gKiBAcGFyYW0gbG9nV2FybiAtIExvZ2dpbmcgZnVuY3Rpb24gZm9yIHdhcm5pbmdzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbmNyZW1lbnRRdW90YSggcXVvdGFTZXJ2aWNlOiBRdW90YVNlcnZpY2UsXG4gIG9yZ0lkOiBzdHJpbmcsXG4gIHF1b3RhVHlwZTogUXVvdGFUeXBlLFxuICBsb2dXYXJuOiAobWVzc2FnZTogc3RyaW5nLCBkYXRhPzogdW5rbm93bikgPT4gdm9pZCxcbik6IHZvaWQge1xuICBxdW90YVNlcnZpY2UuaW5jcmVtZW50KG9yZ0lkLCBxdW90YVR5cGUsIGdldFF1b3RhU2VydmljZUF1dGhIZWFkZXIob3JnSWQpKS5jYXRjaCgoZXJyOiB1bmtub3duKSA9PlxuICAgIGxvZ1dhcm4oJ1F1b3RhIGluY3JlbWVudCBmYWlsZWQnLCB7IGVycm9yOiBlcnJvck1lc3NhZ2UoZXJyKSB9KSxcbiAgKTtcbn1cblxuLyoqXG4gKiBBdG9taWMgcmVzZXJ2ZSBoZWxwZXIgZm9yIHRoZSBcInJlc2VydmUgKyBjb21taXQgLyByb2xsYmFja1wiIHBhdHRlcm4uXG4gKiBVc2UgZm9yIGV4cGVuc2l2ZSByZXNvdXJjZXMgKHBpcGVsaW5lcywgcGx1Z2lucywgQUkgY2FsbHMpIHdoZXJlIHRoZVxuICogZmlyZS1hbmQtZm9yZ2V0IHBvc3QtaG9jIGBpbmNyZW1lbnRRdW90YWAgYWxsb3dzIGNvbmN1cnJlbnQgb3Zlci1zcGVuZC5cbiAqXG4gKiBSZXR1cm5zIHRoZSBzdHJ1Y3R1cmVkIHJlc3VsdCBzbyB0aGUgY2FsbGVyIGNhbiBkZWNpZGUgd2hldGhlciB0byBydW5cbiAqIHRoZSBnYXRlZCBhY3Rpb24gb3IgNDI5IHRoZSBjbGllbnQuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IHJlc2VydmF0aW9uID0gYXdhaXQgcmVzZXJ2ZVF1b3RhKHF1b3RhU2VydmljZSwgb3JnSWQsICdwaXBlbGluZXMnLCBhdXRoSGVhZGVyKTtcbiAqIGlmIChyZXNlcnZhdGlvbi5leGNlZWRlZCkgcmV0dXJuIHNlbmRRdW90YVJlc2VydmVEZW5pZWQocmVzLCAncGlwZWxpbmVzJywgcmVzZXJ2YXRpb24pO1xuICogdHJ5IHtcbiAqIGF3YWl0IGRvRXhwZW5zaXZlVGhpbmcoKTtcbiAqIH0gY2F0Y2ggKGVycikge1xuICogLy8gUGFzcyB0aGUgcmVzZXJ2ZWQgcmVzZXRBdCBzbyBhIHBlcmlvZCByb2xsb3ZlciBkb2Vzbid0IGdldCBkb3VibGUtY2hhcmdlZC5cbiAqIGRlY3JlbWVudFF1b3RhKHF1b3RhU2VydmljZSwgb3JnSWQsICdwaXBlbGluZXMnLCBhdXRoSGVhZGVyLCBsb2dXYXJuLCAxLCByZXNlcnZhdGlvbi5xdW90YS5yZXNldEF0KTtcbiAqIHRocm93IGVycjtcbiAqIH1cbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzZXJ2ZVF1b3RhKCBxdW90YVNlcnZpY2U6IFF1b3RhU2VydmljZSxcbiAgb3JnSWQ6IHN0cmluZyxcbiAgcXVvdGFUeXBlOiBRdW90YVR5cGUsXG4gIGF1dGhIZWFkZXI6IHN0cmluZyxcbiAgYW1vdW50OiBudW1iZXIgPSAxLFxuICByZXF1ZXN0SWQ/OiBzdHJpbmcsXG4pOiBQcm9taXNlPFF1b3RhUmVzZXJ2ZVJlc3VsdD4ge1xuICByZXR1cm4gcXVvdGFTZXJ2aWNlLnJlc2VydmUob3JnSWQsIHF1b3RhVHlwZSwgYXV0aEhlYWRlciwgYW1vdW50LCByZXF1ZXN0SWQpO1xufVxuXG4vKiogU2Vjb25kcyBhIGNsaWVudCBzaG91bGQgd2FpdCBiZWZvcmUgcmV0cnlpbmcgd2hlbiBxdW90YSBjb3VsZG4ndCBiZSBjb25maXJtZWQuICovXG5jb25zdCBRVU9UQV9VTkFWQUlMQUJMRV9SRVRSWV9BRlRFUl9TRUNPTkRTID0gNTtcblxuLyoqXG4gKiBBbnN3ZXIgYSBERU5JRUQgcmVzZXJ2YXRpb24gKGByZXNlcnZhdGlvbi5leGNlZWRlZCA9PT0gdHJ1ZWApLlxuICpcbiAqIC0gYHVuYXZhaWxhYmxlYCAodGhlIHF1b3RhIHNlcnZpY2UgY291bGRuJ3QgY29uZmlybSB0aGUgc2xvdCkg4oaSICoqNTAzKipcbiAqICAgYFNFUlZJQ0VfVU5BVkFJTEFCTEVgIHdpdGggYSBzaG9ydCBgUmV0cnktQWZ0ZXJgOiB0aGUgb3JnIGlzIG5vdCBvdmVyIGl0c1xuICogICBsaW1pdCwgc28gYSA0MjkgXCJxdW90YSBleGNlZWRlZFwiIHdvdWxkIHNlbmQgdXNlcnMgdG8gdXBncmFkZSBmb3IgYW4gb3V0YWdlLlxuICogLSBvdGhlcndpc2Ug4oaSIHRoZSBzdGFuZGFyZCA0MjkgYFFVT1RBX0VYQ0VFREVEYCB3aXRoIHRoZSBYLVF1b3RhLSogaGVhZGVycy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNlbmRRdW90YVJlc2VydmVEZW5pZWQocmVzOiBSZXNwb25zZSwgcXVvdGFUeXBlOiBRdW90YVR5cGUsIHJlc2VydmF0aW9uOiBRdW90YVJlc2VydmVSZXN1bHQpOiB2b2lkIHtcbiAgaWYgKHJlc2VydmF0aW9uLnVuYXZhaWxhYmxlKSB7XG4gICAgaWYgKCFyZXMuaGVhZGVyc1NlbnQpIHJlcy5zZXRIZWFkZXIoJ1JldHJ5LUFmdGVyJywgUVVPVEFfVU5BVkFJTEFCTEVfUkVUUllfQUZURVJfU0VDT05EUyk7XG4gICAgc2VuZEVycm9yKFxuICAgICAgcmVzLFxuICAgICAgNTAzLFxuICAgICAgYFVuYWJsZSB0byBjb25maXJtICR7cXVvdGFUeXBlfSBxdW90YSByaWdodCBub3cuIFBsZWFzZSB0cnkgYWdhaW4gc2hvcnRseS5gLFxuICAgICAgRXJyb3JDb2RlLlNFUlZJQ0VfVU5BVkFJTEFCTEUsXG4gICAgKTtcbiAgICByZXR1cm47XG4gIH1cbiAgc2VuZFF1b3RhRXhjZWVkZWQocmVzLCBxdW90YVR5cGUsIHJlc2VydmF0aW9uLnF1b3RhLCByZXNlcnZhdGlvbi5xdW90YS5yZXNldEF0KTtcbn1cblxuLyoqXG4gKiBGaXJlLWFuZC1mb3JnZXQgcm9sbGJhY2sgZm9yIGEgcHJldmlvdXNseSByZXNlcnZlZCBxdW90YSBzbG90LlxuICogTG9ncyBvbiBmYWlsdXJlIGJ1dCBuZXZlciB0aHJvd3MgIHRoZSBhY3Rpb24gdGhhdCBuZWVkZWQgdGhlIHJvbGxiYWNrXG4gKiBoYXMgYWxyZWFkeSBmYWlsZWQsIG5vIHBvaW50IGNvbXBvdW5kaW5nIHRoZSBlcnJvci5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlY3JlbWVudFF1b3RhKCBxdW90YVNlcnZpY2U6IFF1b3RhU2VydmljZSxcbiAgb3JnSWQ6IHN0cmluZyxcbiAgcXVvdGFUeXBlOiBRdW90YVR5cGUsXG4gIGF1dGhIZWFkZXI6IHN0cmluZyxcbiAgbG9nV2FybjogKG1lc3NhZ2U6IHN0cmluZywgZGF0YT86IHVua25vd24pID0+IHZvaWQsXG4gIGFtb3VudDogbnVtYmVyID0gMSxcbiAgcmVzZXRBdFNuYXBzaG90Pzogc3RyaW5nLFxuKTogdm9pZCB7XG4gIHF1b3RhU2VydmljZS5kZWNyZW1lbnQob3JnSWQsIHF1b3RhVHlwZSwgYXV0aEhlYWRlciwgYW1vdW50LCByZXNldEF0U25hcHNob3QpLmNhdGNoKChlcnI6IHVua25vd24pID0+XG4gICAgbG9nV2FybignUXVvdGEgcm9sbGJhY2sgZmFpbGVkJywgeyBlcnJvcjogZXJyb3JNZXNzYWdlKGVycikgfSksXG4gICk7XG59XG4iXX0=
|
|
559
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVvdGEuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2VydmljZXMvcXVvdGEudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUl0QyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNoRixPQUFPLEVBQUUsZ0JBQWdCLEVBQXVCLE1BQU0sa0JBQWtCLENBQUM7QUFDekUsT0FBTyxFQUFFLFVBQVUsRUFBOEIsTUFBTSw4QkFBOEIsQ0FBQztBQUN0RixPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDNUQsT0FBTyxFQUFFLG9CQUFvQixFQUFFLGtCQUFrQixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDM0YsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBRTVELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUNwRCxPQUFPLEVBQUUsWUFBWSxFQUFFLFdBQVcsRUFBa0IsTUFBTSx5QkFBeUIsQ0FBQztBQUNwRixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNsRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDekQsT0FBTyxFQUFFLFlBQVksRUFBRSxTQUFTLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUNsRixPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFFL0Q7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLHFCQUFxQixHQUErRDtJQUN4RixtQkFBbUIsRUFBRSxDQUFDO0lBQ3RCLFVBQVUsRUFBRSxDQUFDO0NBQ2QsQ0FBQztBQUVGOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUNILE1BQU0s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QUFFLEdBQUcsQ0FBQyxTQUFTLENBQUMsYUFBYSxFQUFFLHFDQUFxQyxDQUFDLENBQUM7UUFDMUYsU0FBUyxDQUNQLEdBQUcsRUFDSCxHQUFHLEVBQ0gscUJBQXFCLFNBQVMsNkNBQTZDLEVBQzNFLFNBQVMsQ0FBQyxtQkFBbUIsQ0FDOUIsQ0FBQztRQUNGLE9BQU87SUFDVCxDQUFDO0lBQ0QsaUJBQWlCLENBQUMsR0FBRyxFQUFFLFNBQVMsRUFBRSxXQUFXLENBQUMsS0FBSyxFQUFFLFdBQVcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7QUFDbEYsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxNQUFNLFVBQVUsY0FBYyxDQUFFLFlBQTBCLEVBQ3hELEtBQWEsRUFDYixTQUFvQixFQUNwQixVQUFrQixFQUNsQixPQUFrRCxFQUNsRCxNQUFNLEdBQVcsQ0FBQyxFQUNsQixlQUF3QixFQUN4QixXQUFtQztJQUVuQyxNQUFNLElBQUksR0FBRyxXQUFXO1FBQ3RCLENBQUMsQ0FBQyxZQUFZLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxlQUFlLEVBQUUsV0FBVyxDQUFDO1FBQzVGLENBQUMsQ0FBQyxZQUFZLENBQUMsU0FBUyxDQUFDLEtBQUssRUFBRSxTQUFTLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxlQUFlLENBQUMsQ0FBQztJQUNsRixJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBWSxFQUFFLEVBQUUsQ0FDMUIsT0FBTyxDQUFDLHVCQUF1QixFQUFFLEVBQUUsS0FBSyxFQUFFLFlBQVksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQy9ELENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCB0eXBlIHsgUmVxdWVzdCwgUmVzcG9uc2UgfSBmcm9tICdleHByZXNzJztcblxuaW1wb3J0IHsgY3VycmVudEF1ZGl0Q29udGV4dCwgc2FuaXRpemVDb3JyZWxhdGlvbklkIH0gZnJvbSAnLi9hdWRpdC1jb250ZXh0LmpzJztcbmltcG9ydCB7IGNyZWF0ZVNhZmVDbGllbnQsIHR5cGUgUmVxdWVzdE9wdGlvbnMgfSBmcm9tICcuL2h0dHAtY2xpZW50LmpzJztcbmltcG9ydCB7IGJhdGNoZXJGb3IsIHR5cGUgTWV0ZXJlZEluY3JlbWVudEdyb3VwIH0gZnJvbSAnLi9xdW90YS1pbmNyZW1lbnQtYmF0Y2hlci5qcyc7XG5pbXBvcnQgeyBvbkJlaGFsZkNhbGxlciB9IGZyb20gJy4uL21pZGRsZXdhcmUvb24tYmVoYWxmLmpzJztcbmltcG9ydCB7IGdldFNlcnZpY2VBdXRoSGVhZGVyLCBpc1NlcnZpY2VQcmluY2lwYWwgfSBmcm9tICcuLi9taWRkbGV3YXJlL3NlcnZpY2UtdG9rZW5zLmpzJztcbmltcG9ydCB7IFNZU1RFTV9PUkdfSUQgfSBmcm9tICcuLi9taWRkbGV3YXJlL3N5c3RlbS1vcmcuanMnO1xuaW1wb3J0IHR5cGUgeyBKd3RQYXlsb2FkLCBQcmluY2lwYWxUeXBlLCBRdW90YVR5cGUsIFF1b3RhQ2hlY2tSZXN1bHQsIFNlcnZpY2VDb25maWcgfSBmcm9tICcuLi90eXBlcy9jb21tb24uanMnO1xuaW1wb3J0IHsgRXJyb3JDb2RlIH0gZnJvbSAnLi4vdHlwZXMvZXJyb3ItY29kZXMuanMnO1xuaW1wb3J0IHsgREVGQVVMVF9USUVSLCBpc1ZhbGlkVGllciwgdHlwZSBRdW90YVRpZXIgfSBmcm9tICcuLi90eXBlcy9xdW90YS10aWVycy5qcyc7XG5pbXBvcnQgeyBlbnZCb29sLCBlbnZJbnQgfSBmcm9tICcuLi91dGlscy9lbnYuanMnO1xuaW1wb3J0IHsgY3JlYXRlTG9nZ2VyIH0gZnJvbSAnLi4vdXRpbHMvbG9nZ2VyLmpzJztcbmltcG9ydCB7IGVtaXRDb3VudGVyIH0gZnJvbSAnLi4vdXRpbHMvbWV0cmljLWVtaXR0ZXIuanMnO1xuaW1wb3J0IHsgZXJyb3JNZXNzYWdlLCBzZW5kRXJyb3IsIHNlbmRRdW90YUV4Y2VlZGVkIH0gZnJvbSAnLi4vdXRpbHMvcmVzcG9uc2UuanMnO1xuaW1wb3J0IHsgc2VydmljZUVuZHBvaW50IH0gZnJvbSAnLi4vdXRpbHMvc2VydmljZS1yZWdpc3RyeS5qcyc7XG5cbi8qKlxuICogUmV0cnkgb3B0aW9ucyBmb3IgcXVvdGEgY2FsbHMg4oCUIGZhaWwgZmFzdCAoYSBzbG93IHF1b3RhIHNlcnZpY2UgbXVzdCBub3Qgc3RhbGwgdGhlIHJlcXVlc3QpLlxuICpcbiAqIE5FVkVSIHJldHJ5IGEgNDI5LiBUaGUgcXVvdGEgc2VydmljZSBhbnN3ZXJzIGFuIG92ZXItbGltaXQgb3JnIHdpdGggNDI5XG4gKiBRVU9UQV9FWENFRURFRCBhbmQgYFJldHJ5LUFmdGVyYCA9IHNlY29uZHMgdW50aWwgdGhlIHBlcmlvZCByZXNldHM7IHRoZSBIVFRQXG4gKiBjbGllbnQgaG9ub3JzIHRoYXQgKGNhcHBlZCBhdCA2MHMpLCBzbyBhIHNpbmdsZSByYXRlLWxpbWl0IHJldHJ5IHN0YWxsZWQgdGhlXG4gKiByZXF1ZXN0IHdlbGwgcGFzdCB0aGUgaGFuZGxlciB0aW1lb3V0LCB3aGljaCB0aGVuIGFuc3dlcmVkIDUwMyBhbmQgdGhlIHJlYWxcbiAqIDQyOSB3YXMgbG9zdC4gQSA0MjkgaXMgYSBmaW5hbCBhbnN3ZXIgaGVyZS5cbiAqL1xuY29uc3QgUVVPVEFfUkVRVUVTVF9PUFRJT05TOiBQaWNrPFJlcXVlc3RPcHRpb25zLCAnbWF4UmF0ZUxpbWl0UmV0cmllcycgfCAnbWF4UmV0cmllcyc+ID0ge1xuICBtYXhSYXRlTGltaXRSZXRyaWVzOiAwLFxuICBtYXhSZXRyaWVzOiAxLFxufTtcblxuLyoqXG4gKiBCdWRnZXQgZm9yIG9uZSBgY2hlY2tgIG9mIGEgQ09VTlRFUiBxdW90YSAoYFFVT1RBX0NIRUNLX1RJTUVPVVRfTVNgLCBkZWZhdWx0XG4gKiAzMDApLCB3aXRoIG5vIHJldHJ5LlxuICpcbiAqIFRoZSBjaGVjayBpcyBhIHJlYWQgZ2F0ZSB0aGF0IEZBSUxTIE9QRU4sIHJ1biBhaGVhZCBvZiB0aGUgcmVxdWVzdCBpdCBnYXRlczpcbiAqIHRoZSBvbGQgNSBzIHRpbWVvdXQgw5cgMiBhdHRlbXB0cyBtZWFudCBhIHNsb3cgcXVvdGEgc2VydmljZSBhZGRlZCB1cCB0byAxMCBzXG4gKiB0byBldmVyeSBtZXRlcmVkIHJlcXVlc3QgYW5kIHRoZW4gbGV0IGl0IHRocm91Z2ggYW55d2F5LiBBIHNob3J0IGJ1ZGdldCB0dXJuc1xuICogdGhlIHNhbWUgaW5jaWRlbnQgaW50byBhIOKJpCAzMDAgbXMgZmFpbC1vcGVuIChjb3VudGVkIG9uXG4gKiBgcXVvdGFfZmFpbF9vcGVuX3RvdGFsYCwgd2hpY2ggYWxlcnRzKSDigJQgYW5kIHdpdGggdGhlIHBlci1wb2QgY2hlY2sgY2FjaGUgaW5cbiAqIGZyb250IChhcGktc2VydmVyIGBjaGVja1F1b3RhYCkgYSBoZWFsdGh5IHNlcnZpY2UgaXMgYXNrZWQgYXQgbW9zdCBvbmNlIHBlclxuICogb3JnL3R5cGUgcGVyIGNhY2hlIFRUTC5cbiAqXG4gKiBgc3RvcmFnZUJ5dGVzYCBrZWVwcyB0aGUgY2xpZW50IHRpbWVvdXQgYW5kIG9uZSByZXRyeTogaXQgaXMgYSBNRUFTVVJFRCByZWFkXG4gKiAodGhlIHF1b3RhIHNlcnZpY2Ugd2Fsa3MgdGhlIG9yZydzIHJlZ2lzdHJ5IG5hbWVzcGFjZSBvbiBhIGNvbGQgY2FjaGUpIGJlaGluZFxuICogdGhlIHJlZ2lzdHJ5J3MgZmFpbC1DTE9TRUQgcHVzaCBnYXRlLCB3aGVyZSBhIHByZW1hdHVyZSB0aW1lb3V0IHJlZnVzZXMgYSBwdXNoLlxuICovXG5leHBvcnQgY29uc3QgUVVPVEFfQ0hFQ0tfVElNRU9VVF9NUyA9IGVudkludCgnUVVPVEFfQ0hFQ0tfVElNRU9VVF9NUycsIDMwMCwgeyBtaW46IDEgfSk7XG5cbmZ1bmN0aW9uIGNoZWNrUmVxdWVzdE9wdGlvbnMocXVvdGFUeXBlOiBRdW90YVR5cGUpOiBQaWNrPFJlcXVlc3RPcHRpb25zLCAnbWF4UmF0ZUxpbWl0UmV0cmllcycgfCAnbWF4UmV0cmllcycgfCAndGltZW91dCc+IHtcbiAgaWYgKHF1b3RhVHlwZSA9PT0gJ3N0b3JhZ2VCeXRlcycpIHJldHVybiBRVU9UQV9SRVFVRVNUX09QVElPTlM7XG4gIHJldHVybiB7IG1heFJhdGVMaW1pdFJldHJpZXM6IDAsIG1heFJldHJpZXM6IDAsIHRpbWVvdXQ6IFFVT1RBX0NIRUNLX1RJTUVPVVRfTVMgfTtcbn1cblxuY29uc3QgbG9nZ2VyID0gY3JlYXRlTG9nZ2VyKCdxdW90YScpO1xuXG4vLyBSRVNFUlZFIEZBSUwgTU9ERSDigJQgZXhwbGljaXQsIHNpbmdsZSBwb2xpY3kuXG4vL1xuLy8gYHJlc2VydmVgIGdhdGVzIEVYUEVOU0lWRSwgYmlsbGFibGUgcmVzb3VyY2VzIChwaXBlbGluZXMsIHBsdWdpbiBidWlsZHMsIEFJXG4vLyBjYWxscywgcGxhdGZvcm0gZmVhdHVyZSBzbG90cykuIEV2ZXJ5IHF1b3RhIHR5cGUgaXMgYSBwZXItcGVyaW9kIEZMT1cgY291bnRlclxuLy8gd2l0aCBubyBhZnRlci10aGUtZmFjdCByZWNvbmNpbGlhdGlvbjogYSB1bml0IGNvbnN1bWVkIHdoaWxlIHRoZSByZXNlcnZhdGlvblxuLy8gY291bGQgbm90IGJlIGNvbmZpcm1lZCBpcyBuZXZlciBjb3VudGVkLCBzbyBmYWlsLW9wZW4gbGV0cyBhbiBvcmcgY29uc3VtZVxuLy8gdW5ib3VuZGVkIHVubWV0ZXJlZCB1bml0cyBmb3IgdGhlIHdob2xlIGxlbmd0aCBvZiBhbiBpbmNpZGVudCDigJQgYW5kIGFuXG4vLyB1bmNvbmZpcm1lZCByZXNlcnZlICh0aW1lb3V0LCBvcGVuIGNpcmN1aXQpIG1heSBldmVuIGhhdmUgbGFuZGVkIHNlcnZlci1zaWRlLlxuLy8gU28gYHJlc2VydmVgIGZhaWxzIENMT1NFRCB3aGVuZXZlciB0aGUgcXVvdGEgc2VydmljZSBkaWQgbm90IENPTkZJUk0gdGhlIHNsb3Q6XG4vLyAgIC0gdW5yZWFjaGFibGUgLyB0aW1lZCBvdXQgLyBjaXJjdWl0IGJyZWFrZXIgb3BlbiAobm8gcmVzcG9uc2UpLFxuLy8gICAtIGEgcmVhY2hhYmxlLWJ1dC1lcnJvcmVkIHJlc3BvbnNlICg1eHgsIDR4eCwgbWFsZm9ybWVkIGJvZHkpLFxuLy8gICAtIGEgNDI5IHRoYXQgaXMgTk9UIGEgZ2VudWluZSBRVU9UQV9FWENFRURFRCAoZ2F0ZXdheSAvIHJhdGUgbGltaXRlcikuXG4vLyBPcGVyYXRvcnMgd2hvIHByZWZlciBhdmFpbGFiaWxpdHkgb3ZlciBlbmZvcmNlbWVudCBvcHQgdGhlIFdIT0xFIHNldCBpbnRvXG4vLyBmYWlsLW9wZW4gd2l0aCBRVU9UQV9SRVNFUlZFX0ZBSUxfT1BFTj10cnVlLiBCb3RoIG91dGNvbWVzIGVtaXQgYSBjb3VudGVyXG4vLyAoYHF1b3RhX2ZhaWxfY2xvc2VkX3RvdGFsYCAvIGBxdW90YV9mYWlsX29wZW5fdG90YWxgKSB0YWdnZWQgd2l0aCB0aGUgcmVhc29uLlxuLy8gYGNoZWNrYCAoYSBjaGVhcCByZWFkIGdhdGUpIHN0YXlzIGZhaWwtb3BlbjsgYGluY3JlbWVudGAgaXMgZmlyZS1hbmQtZm9yZ2V0LlxuY29uc3QgUVVPVEFfUkVTRVJWRV9GQUlMX09QRU4gPSBlbnZCb29sKCdRVU9UQV9SRVNFUlZFX0ZBSUxfT1BFTicsIGZhbHNlKTtcblxuLy8gVVNBR0UgQVRUUklCVVRJT04g4oCUIHdobyBzcGVudCBhIHVuaXQuXG4vL1xuLy8gVGhlIHF1b3RhIHNlcnZpY2Uga2VlcHMgb25lIGFnZ3JlZ2F0ZSBjb3VudGVyIHBlciAob3JnLCB0eXBlKTsgb24gaXRzIG93biB0aGF0XG4vLyBjYW4gc2F5IGFuIG9yZyBpcyBhdCAxMDAlIGJ1dCBuZXZlciBXSElDSCBrZXksIHJvdXRlIG9yIHBpcGVsaW5lIGdvdCBpdCB0aGVyZS5cbi8vIEV2ZXJ5IGluY3JlbWVudCAvIHJlc2VydmUgLyByZWZ1bmQgdGhlcmVmb3JlIGNhcnJpZXMgYW4gYXR0cmlidXRpb24gYmxvY2sgdGhlXG4vLyBxdW90YSBzZXJ2aWNlIHdyaXRlcyBpbnRvIGl0cyB1c2FnZSBsZWRnZXIgKGBHRVQgL3F1b3Rhcy86b3JnSWQvdXNhZ2VgKS4gSXQgaXNcbi8vIG1ldGFkYXRhIG9ubHkg4oCUIGVuZm9yY2VtZW50IG5ldmVyIHJlYWRzIGl0IOKAlCBhbmQgZXZlcnkgZmllbGQgaXMgb3B0aW9uYWwsIHNvIGFcbi8vIGNhbGxlciB0aGF0IGtub3dzIG5vdGhpbmcgc3RpbGwgbWV0ZXJzIGNvcnJlY3RseS5cblxuLyoqIFdobyAvIHdoYXQgc3BlbnQgKG9yIGdvdCBiYWNrKSBhIHF1b3RhIHVuaXQuIEFsbCBmaWVsZHMgb3B0aW9uYWwuICovXG5leHBvcnQgaW50ZXJmYWNlIFF1b3RhVXNhZ2VBdHRyaWJ1dGlvbiB7XG4gIHByaW5jaXBhbFR5cGU/OiBQcmluY2lwYWxUeXBlO1xuICAvKiogVGhlIHVzZXIgaWQgb3Igc2VydmljZS1hY2NvdW50IGlkIGJlaGluZCB0aGUgY2FsbCAodGhlIHRva2VuJ3MgYHN1YmApLiAqL1xuICBwcmluY2lwYWxJZD86IHN0cmluZztcbiAgLyoqIFRoZSByZXZvY2FibGUgY3JlZGVudGlhbDogdGhlIGFjY2VzcyBrZXkgdGhlIHRva2VuIGRlcml2ZXMgZnJvbSwgZWxzZSBpdHMgYGp0aWAuICovXG4gIGtleUlkPzogc3RyaW5nO1xuICAvKiogYE1FVEhPRCAvcm91dGUvOnBhdHRlcm5gIOKAlCB0aGUgbWF0Y2hlZCByb3V0ZSBQQVRURVJOLCBuZXZlciB0aGUgcmF3IFVSTCAobm8gaWRzLCBubyBxdWVyeSkuICovXG4gIHJvdXRlPzogc3RyaW5nO1xuICAvKiogVGhlIHBpcGVsaW5lIHRoZSBjYWxsIHdhcyBtYWRlIGZvciAoYDpwaXBlbGluZUlkYCBwYXJhbSBvciBgWC1QaXBlbGluZS1JZGAgaGVhZGVyKS4gKi9cbiAgcGlwZWxpbmVJZD86IHN0cmluZztcbiAgcmVxdWVzdElkPzogc3RyaW5nO1xuICAvKipcbiAgICogQUkgY2FsbHMgb25seTogd2hpY2ggcHJvZHVjdCBzdXJmYWNlIHNwZW50IHRoZSB1bml0IOKAlCBgYXNrYCwgYGFnZW50YCxcbiAgICogYGFnZW50LXRvb2w6PG5hbWU+YCwgYHBpcGVsaW5lLWdlbmVyYXRlYCwgYHBsdWdpbi1nZW5lcmF0ZWAsXG4gICAqIGByZXBvcnQtc3VtbWFyeWAuIFNldCBieSBhcGktc2VydmVyJ3MgYHdpdGhBaUNhbGxSZXNlcnZhdGlvbmAuXG4gICAqL1xuICBmZWF0dXJlPzogc3RyaW5nO1xuICAvKiogQUkgY2FsbHMgb25seTogdGhlIG1vZGVsIGlkIHRoZSByZXNlcnZhdGlvbiB3YXMgcmVzb2x2ZWQgdG8gKG5ldmVyIGEga2V5KS4gKi9cbiAgbW9kZWw/OiBzdHJpbmc7XG4gIC8qKiBBSSBjYWxscyBvbmx5OiB3aG9zZSBrZXkgc2VydmVkIHRoZSBjYWxsIOKAlCBgcGxhdGZvcm1gLCBgb3JnYCBvciBgcmVxdWVzdGAgKEJZT0spLiAqL1xuICBrZXlTb3VyY2U/OiBBaUtleVNvdXJjZTtcbn1cblxuLyoqIFdob3NlIGtleSBzZXJ2ZXMgYW4gQUkgY2FsbCAobWlycm9ycyBhaS1jb3JlIGBLZXlTb3VyY2VgKS4gT25seSBgcGxhdGZvcm1gIHNwZW5kcyBgYWlDYWxsc2AuICovXG5leHBvcnQgdHlwZSBBaUtleVNvdXJjZSA9ICdwbGF0Zm9ybScgfCAnb3JnJyB8ICdyZXF1ZXN0JztcblxuLyoqIFRva2VuIGNvdW50cyBhbiBBSSBjYWxsIHJlcG9ydHMgYWZ0ZXIgaXQgc2V0dGxlcyAoc2VlIHtAbGluayBRdW90YVNlcnZpY2UucmVwb3J0VXNhZ2V9KS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUXVvdGFUb2tlblVzYWdlIHtcbiAgdG9rZW5zSW46IG51bWJlcjtcbiAgdG9rZW5zT3V0OiBudW1iZXI7XG59XG5cbi8qKiBMb25nZXN0IGF0dHJpYnV0aW9uIHN0cmluZyB0aGUgY2xpZW50IHNlbmRzICh0aGUgcXVvdGEgc2VydmljZSBlbmZvcmNlcyB0aGUgc2FtZSBib3VuZCkuICovXG5jb25zdCBNQVhfQVRUUklCVVRJT05fTEVOID0gMjAwO1xuXG5mdW5jdGlvbiBib3VuZGVkKHZhbHVlOiB1bmtub3duKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgJiYgdmFsdWUubGVuZ3RoID4gMCA/IHZhbHVlLnNsaWNlKDAsIE1BWF9BVFRSSUJVVElPTl9MRU4pIDogdW5kZWZpbmVkO1xufVxuXG4vKiogVGhlIHByaW5jaXBhbCBoYWxmIG9mIGFuIGF0dHJpYnV0aW9uIGJsb2NrLCBmcm9tIGEgVkVSSUZJRUQgdG9rZW4uICovXG5mdW5jdGlvbiBwcmluY2lwYWxBdHRyaWJ1dGlvbih1c2VyOiBKd3RQYXlsb2FkIHwgdW5kZWZpbmVkKTogUXVvdGFVc2FnZUF0dHJpYnV0aW9uIHtcbiAgaWYgKCF1c2VyKSByZXR1cm4ge307XG4gIHJldHVybiB7XG4gICAgcHJpbmNpcGFsVHlwZTogdXNlci5wcmluY2lwYWxUeXBlLFxuICAgIHByaW5jaXBhbElkOiBib3VuZGVkKHVzZXIuc3ViKSxcbiAgICBrZXlJZDogYm91bmRlZCh1c2VyLnBhcmVudEtleUlkID8/IHVzZXIuanRpKSxcbiAgfTtcbn1cblxuLyoqXG4gKiBBdHRyaWJ1dGlvbiBmb3IgdGhlIHJlcXVlc3QgYmVpbmcgc2VydmVkOiB0aGUgdmVyaWZpZWQgcHJpbmNpcGFsLCB0aGUgbWF0Y2hlZFxuICogcm91dGUgcGF0dGVybiwgdGhlIHBpcGVsaW5lIChgOnBpcGVsaW5lSWRgIHBhcmFtIG9yIGEgc2FuaXRpemVkXG4gKiBgWC1QaXBlbGluZS1JZGAgaGVhZGVyKSBhbmQgdGhlIHJlcXVlc3QgaWQuIFJlYWQgb2ZmIGByZXFgIGRpcmVjdGx5IHJhdGhlciB0aGFuXG4gKiB0aGUgYW1iaWVudCBhdWRpdCBjb250ZXh0IGJlY2F1c2UgdGhlIG1ldGVyaW5nIG1pZGRsZXdhcmUgcnVucyBpbiBhIGBmaW5pc2hgXG4gKiBsaXN0ZW5lciwgd2hlcmUgdGhlIHJlcXVlc3QncyBhc3luYyBzY29wZSBpcyBubyBsb25nZXIgZ3VhcmFudGVlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHF1b3RhQXR0cmlidXRpb25Gcm9tUmVxdWVzdChyZXE6IFJlcXVlc3QpOiBRdW90YVVzYWdlQXR0cmlidXRpb24ge1xuICBjb25zdCByb3V0ZVBhdGggPSByZXEucm91dGU/LnBhdGg7XG4gIGNvbnN0IHJvdXRlID0gdHlwZW9mIHJvdXRlUGF0aCA9PT0gJ3N0cmluZycgPyBgJHtyZXEubWV0aG9kfSAkeyhyZXEuYmFzZVVybCA/PyAnJykgKyByb3V0ZVBhdGh9YCA6IHVuZGVmaW5lZDtcbiAgY29uc3QgaGVhZGVyID0gcmVxLmhlYWRlcnNbJ3gtcGlwZWxpbmUtaWQnXTtcbiAgY29uc3QgcGlwZWxpbmVJZCA9IHNhbml0aXplQ29ycmVsYXRpb25JZChyZXEucGFyYW1zPy5waXBlbGluZUlkKSA/PyBzYW5pdGl6ZUNvcnJlbGF0aW9uSWQoQXJyYXkuaXNBcnJheShoZWFkZXIpID8gaGVhZGVyWzBdIDogaGVhZGVyKTtcbiAgY29uc3QgcmVxdWVzdElkSGVhZGVyID0gcmVxLmhlYWRlcnNbJ3gtcmVxdWVzdC1pZCddO1xuICBjb25zdCByZXF1ZXN0SWQgPSAocmVxIGFzIFJlcXVlc3QgJiB7IHJlcXVlc3RJZD86IHN0cmluZyB9KS5yZXF1ZXN0SWRcbiAgICA/PyBzYW5pdGl6ZUNvcnJlbGF0aW9uSWQoQXJyYXkuaXNBcnJheShyZXF1ZXN0SWRIZWFkZXIpID8gcmVxdWVzdElkSGVhZGVyWzBdIDogcmVxdWVzdElkSGVhZGVyKTtcbiAgcmV0dXJuIHtcbiAgICAuLi5wcmluY2lwYWxBdHRyaWJ1dGlvbihyZXEudXNlciksXG4gICAgLi4uKHJvdXRlID8geyByb3V0ZTogcm91dGUuc2xpY2UoMCwgTUFYX0FUVFJJQlVUSU9OX0xFTikgfSA6IHt9KSxcbiAgICAuLi4ocGlwZWxpbmVJZCA/IHsgcGlwZWxpbmVJZCB9IDoge30pLFxuICAgIC4uLihyZXF1ZXN0SWQgPyB7IHJlcXVlc3RJZDogYm91bmRlZChyZXF1ZXN0SWQpIH0gOiB7fSksXG4gIH07XG59XG5cbi8qKlxuICogQXR0cmlidXRpb24gZnJvbSB0aGUgYW1iaWVudCBhdWRpdCBjb250ZXh0LCBmb3IgY2FsbHMgbWFkZSBpbnNpZGUgYSByZXF1ZXN0XG4gKiBzY29wZSB0aGF0IGRpZCBub3QgcGFzcyBvbmUgZXhwbGljaXRseSAodGhlIHJlc2VydmUgLyByZWZ1bmQgaGVscGVycyBldmVyeVxuICogc2VydmljZSB1c2VzKS4gRW1wdHkgb3V0c2lkZSBhbnkgc2NvcGUuXG4gKi9cbmZ1bmN0aW9uIGF0dHJpYnV0aW9uRnJvbUNvbnRleHQoKTogUXVvdGFVc2FnZUF0dHJpYnV0aW9uIHtcbiAgY29uc3QgY3R4ID0gY3VycmVudEF1ZGl0Q29udGV4dCgpO1xuICBpZiAoIWN0eCkgcmV0dXJuIHt9O1xuICByZXR1cm4ge1xuICAgIC4uLnByaW5jaXBhbEF0dHJpYnV0aW9uKGN0eC5wcmluY2lwYWw/LigpKSxcbiAgICAuLi4oY3R4LnJlcXVlc3RJZCA/IHsgcmVxdWVzdElkOiBib3VuZGVkKGN0eC5yZXF1ZXN0SWQpIH0gOiB7fSksXG4gIH07XG59XG5cbi8qKiBUaGUgYXR0cmlidXRpb24gYSBxdW90YSB3cml0ZSBzZW5kczogdGhlIGV4cGxpY2l0IGJsb2NrLCBlbHNlIHRoZSBhbWJpZW50IG9uZS4gKi9cbmZ1bmN0aW9uIHJlc29sdmVBdHRyaWJ1dGlvbihleHBsaWNpdD86IFF1b3RhVXNhZ2VBdHRyaWJ1dGlvbik6IFF1b3RhVXNhZ2VBdHRyaWJ1dGlvbiB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IHJlc29sdmVkID0gZXhwbGljaXQgPz8gYXR0cmlidXRpb25Gcm9tQ29udGV4dCgpO1xuICByZXR1cm4gT2JqZWN0LmtleXMocmVzb2x2ZWQpLmxlbmd0aCA+IDAgPyByZXNvbHZlZCA6IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBUaGUgcXVvdGEgdHlwZSBhIG1ldGVyZWQgcmVxdWVzdCBhY3R1YWxseSBzcGVuZHMuXG4gKlxuICogYGFwaUNhbGxzYCBpcyB0aGUgUEVPUExFJ3MgYnVkZ2V0IOKAlCBhbiBpbnRlcmFjdGl2ZSBzZXNzaW9uLiBBIHJlcXVlc3QgbWFkZSBieVxuICogYSBOT04tSU5URVJBQ1RJVkUgY3JlZGVudGlhbCBzcGVuZHMgYGF1dG9tYXRpb25DYWxsc2AgaW5zdGVhZCwgbmV2ZXIgYm90aCwgc29cbiAqIGEgZmxlZXQgb2Ygc2VsZi1tdXRhdGluZyBwaXBlbGluZXMgY2FuJ3QgZXhoYXVzdCB0aGUgY29uc29sZSBmb3IgdGhlIGh1bWFuc1xuICogaW4gdGhlIHNhbWUgb3JnOlxuICogIC0gYW4gb3JnIFNFUlZJQ0UgQUNDT1VOVCAoYHByaW5jaXBhbFR5cGU6ICdzZXJ2aWNlX2FjY291bnQnYCDigJRcbiAqICAgIHBsYXRmb3JtLWF1dG9tYXRpb24sIHBpcGVsaW5lLXJlZ2lzdGVyLCByZXBvcnRpbmctaW5nZXN0LCByZWdpc3RyeS1wdXNoKTtcbiAqICAtIGEgUEVSU09OQUwgQUNDRVNTIEtFWTogdGhlIGV4Y2hhbmdlZCBrZXkgdG9rZW4gKGB0b2tlbl91c2U6ICdhcGlfa2V5J2ApXG4gKiAgICBhbmQgYW55dGhpbmcgbWludGVkIHdoaWxlIGhvbGRpbmcgb25lIChgcGFyZW50S2V5SWRgKS4gQSBQQVQgaW4gYSBDSSBqb2JcbiAqICAgIGlzIGF1dG9tYXRpb24gd2hvZXZlciBvd25zIGl0IOKAlCBiaWxsaW5nIGl0IGFzIGEgcGVyc29uIGxldCBvbmUgc2NyaXB0XG4gKiAgICBsb2NrIGl0cyBvd25lcidzIHRlYW1tYXRlcyBvdXQgb2YgdGhlIGNvbnNvbGUuIENJIHNob3VsZCBzdGlsbCB1c2UgYVxuICogICAgc2VydmljZS1hY2NvdW50IGtleSAoaXQgc3Vydml2ZXMgdGhlIHBlcnNvbiBsZWF2aW5nKTsgZWl0aGVyIHdheSB0aGVcbiAqICAgIHRyYWZmaWMgbm93IGxhbmRzIG9uIGBhdXRvbWF0aW9uQ2FsbHNgLlxuICogRXZlcnkgb3RoZXIgdHlwZSBpcyByZXR1cm5lZCB1bmNoYW5nZWQ6IGFuIEFJIGNhbGwgb3IgYSBwaXBlbGluZSBjcmVhdGlvblxuICogY29zdHMgdGhlIHNhbWUgd2hvZXZlciBtYWtlcyBpdC5cbiAqXG4gKiBgbWV0ZXJRdW90YU9uU3VjY2Vzc2AgYW5kIGBjaGVja1F1b3RhYCBjYWxsIHRoaXMgdGhlbXNlbHZlcywgc28gYSBzZXJ2aWNlXG4gKiBtb3VudHMgYm90aCB3aXRoIGAnYXBpQ2FsbHMnYCBhbmQgdGhlIHNwbGl0IGhhcHBlbnMgcGVyIHJlcXVlc3QuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtZXRlcmVkUXVvdGFUeXBlRm9yKHJlcTogUGljazxSZXF1ZXN0LCAndXNlcic+LCBxdW90YVR5cGU6IFF1b3RhVHlwZSk6IFF1b3RhVHlwZSB7XG4gIGlmIChxdW90YVR5cGUgIT09ICdhcGlDYWxscycgfHwgIXJlcS51c2VyKSByZXR1cm4gcXVvdGFUeXBlO1xuICBjb25zdCB1ID0gcmVxLnVzZXI7XG4gIGlmICh1LnByaW5jaXBhbFR5cGUgPT09ICdzZXJ2aWNlX2FjY291bnQnIHx8IHUudG9rZW5fdXNlID09PSAnYXBpX2tleScgfHwgdS5wYXJlbnRLZXlJZCkgcmV0dXJuICdhdXRvbWF0aW9uQ2FsbHMnO1xuICByZXR1cm4gcXVvdGFUeXBlO1xufVxuXG4vKiogV2h5IGEgcmVxdWVzdCBpcyBub3QgbWV0ZXJlZC9jaGVja2VkIGFnYWluc3QgYXBpQ2FsbHMgKHNlZSB7QGxpbmsgY2FsbFF1b3RhRXhlbXB0aW9ufSkuICovXG5leHBvcnQgdHlwZSBDYWxsUXVvdGFFeGVtcHRpb24gPSAnc2VydmljZScgfCAnaW1wZXJzb25hdGlvbicgfCAnb25fYmVoYWxmJztcblxuLyoqXG4gKiBXaGV0aGVyIHRoZSBhcGlDYWxscy9hdXRvbWF0aW9uQ2FsbHMgbWV0ZXIgQU5EIGNoZWNrIHNraXAgdGhpcyAodmVyaWZpZWQpXG4gKiByZXF1ZXN0LCBhbmQgd2h5LiBPbmUgZnVuY3Rpb24gZm9yIGJvdGggaGFsdmVzLCBzbyB0aGUgZ2F0ZSBuZXZlciByZWZ1c2VzIGFcbiAqIGNhbGwgdGhlIG1ldGVyIHdvdWxkIG5vdCBiaWxsOlxuICogIC0gYHNlcnZpY2VgIOKAlCBhbiBpbnRlcm5hbCBzZXJ2aWNlIHByaW5jaXBhbDogcGVlciB0cmFmZmljIGlzIGNhdXNlZCBieSBhXG4gKiAgICB1c2VyIGFjdGlvbiB0aGUgb3JpZ2luYXRpbmcgc2VydmljZSBhbHJlYWR5IG1ldGVyZWQ7XG4gKiAgLSBgaW1wZXJzb25hdGlvbmAg4oCUIGEgc3lzYWRtaW4gaW1wZXJzb25hdGlvbiBzZXNzaW9uIChgaW1wZXJzb25hdG9ySWRgKS5cbiAqICAgIFZlbmRvciBzdGFmZiBsb29raW5nIGF0IGEgdGVuYW50J3MgY29uc29sZSBtdXN0IG5laXRoZXIgc3BlbmQgdGhlIHRlbmFudCdzXG4gKiAgICBidWRnZXQgbm9yIGJlIGxvY2tlZCBvdXQgYnkgaXQgd2hpbGUgZGlhZ25vc2luZyBhbiBleGhhdXN0ZWQgb3JnOyB0aGVcbiAqICAgIHNlc3Npb24gaXMgYXVkaXRlZCBvbiBpdHMgb3duIHRyYWlsO1xuICogIC0gYG9uX2JlaGFsZmAg4oCUIGEgdXNlciB0b2tlbiBGT1JXQVJERUQgYnkgYW4gaW50ZXJuYWwgc2VydmljZSBhcyBwYXJ0IG9mIGFcbiAqICAgIHJlcXVlc3QgYWxyZWFkeSBtZXRlcmVkIHdoZXJlIGl0IGFycml2ZWQgKHRoZSBhc2sgYWdlbnQncyB0b29scyxcbiAqICAgIHBpcGVsaW5lJ3MgcGxhY2Vob2xkZXItcGx1Z2luIGNvbmZpcm0pLCBwcm92ZW4gYnkgYSBzaWduZWQgbWFya2VyIHRoZVxuICogICAgdXNlciBjYW5ub3QgZm9yZ2UgKG1pZGRsZXdhcmUvb24tYmVoYWxmLnRzKS5cbiAqIEFwcGxpZXMgdG8gdGhlIENBTEwgYnVkZ2V0cyBvbmx5OiByZXNlcnZhdGlvbi1nYXRlZCBxdW90YXMgKHBpcGVsaW5lcyxcbiAqIHBsdWdpbnMg4oCmKSBhcmUgY2hhcmdlZCB3aG9ldmVyIGFza3MuIGBhaUNhbGxzYCBtaXJyb3JzIHRoZSBpbXBlcnNvbmF0aW9uIGhhbGZcbiAqIG9uIGl0cyBvd24gKGFwaS1zZXJ2ZXIgYHdpdGhBaUNhbGxSZXNlcnZhdGlvbmAgc2tpcHMgdGhlIHNsb3Qgd2hlbiB0aGVcbiAqIHNlc3Npb24gaXMgYW4gaW1wZXJzb25hdGlvbjsgdGhlIGNhbGwgaXMgc3RpbGwgYXVkaXRlZCkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjYWxsUXVvdGFFeGVtcHRpb24ocmVxOiBSZXF1ZXN0KTogQ2FsbFF1b3RhRXhlbXB0aW9uIHwgdW5kZWZpbmVkIHtcbiAgaWYgKCFyZXEudXNlcikgcmV0dXJuIHVuZGVmaW5lZDtcbiAgaWYgKGlzU2VydmljZVByaW5jaXBhbChyZXEpKSByZXR1cm4gJ3NlcnZpY2UnO1xuICBpZiAocmVxLnVzZXIuaW1wZXJzb25hdG9ySWQpIHJldHVybiAnaW1wZXJzb25hdGlvbic7XG4gIGlmIChvbkJlaGFsZkNhbGxlcihyZXEpKSByZXR1cm4gJ29uX2JlaGFsZic7XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogU2VydmljZS1wcmluY2lwYWwgYEF1dGhvcml6YXRpb25gIGhlYWRlciBmb3IgYSBxdW90YSBjYWxsIG1hZGUgb24gYmVoYWxmIG9mXG4gKiBgb3JnSWRgIGJ5IHRoZSBDVVJSRU5UIHNlcnZpY2UgKGBTRVJWSUNFX05BTUVgLCB0aGUgc2FtZSBpZGVudGl0eSB0aGUgaGVhbHRoXG4gKiByb3V0ZXIgcmVwb3J0cykuXG4gKlxuICogVGhlIHF1b3RhIHNlcnZpY2UncyBtdXRhdGlvbiBlbmRwb2ludHMgKGAvOm9yZ0lkL2luY3JlbWVudGAsIGAvZGVjcmVtZW50YClcbiAqIHJlamVjdCBhbnl0aGluZyBidXQgYSBzaWduZWQgc2VydmljZSBwcmluY2lwYWwgb3IgYSBzeXN0ZW0gYWRtaW4sIHNvXG4gKiBmb3J3YXJkaW5nIHRoZSBlbmQgdXNlcidzIGJlYXJlciB0b2tlbiB0aGVyZSBpcyBhbHdheXMgYSA0MDMuIFNlcnZpY2UgdG9rZW5zXG4gKiBhcmUgYWxzbyBleGVtcHQgZnJvbSB0aGUgcXVvdGEgc2VydmljZSdzIHBlci1JUCByYXRlIGxpbWl0ZXIsIHNvIGhvdC1wYXRoXG4gKiBxdW90YSB0cmFmZmljIGZyb20gYSBidXN5IHBvZCBjYW4ndCBleGhhdXN0IHRoYXQgcG9kIElQJ3MgYnVja2V0IGFuZCBzaWxlbnRseVxuICogdHVybiBlbmZvcmNlbWVudCBvZmYuIFNjb3BlZCB0byB0aGUgdGFyZ2V0IG9yZyB3aXRoIHRoZSBsb3dlc3Qgcm9sZSAobWVtYmVyKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFF1b3RhU2VydmljZUF1dGhIZWFkZXIob3JnSWQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBnZXRTZXJ2aWNlQXV0aEhlYWRlcih7IHNlcnZpY2VOYW1lOiBwcm9jZXNzLmVudi5TRVJWSUNFX05BTUUgfHwgJ2FwaScsIG9yZ0lkLCByb2xlOiAnbWVtYmVyJyB9KTtcbn1cblxuLyoqXG4gKiBSZXN1bHQgb2YgYSBzeW5jaHJvbm91cyBxdW90YSByZXNlcnZhdGlvbiAgdGhlIGF0b21pYyBjaGVjaytpbmNyZW1lbnRcbiAqIHZhcmlhbnQuIGBleGNlZWRlZDogdHJ1ZWAgbWVhbnMgdGhlIG9wZXJhdGlvbiB3YXMgcmVqZWN0ZWQgYXQgdGhlIERCXG4gKiBsZXZlbDsgdGhlIGNhbGxlciBzaG91bGQgcmV0dXJuIDQyOSB3aXRob3V0IHJ1bm5pbmcgdGhlIGdhdGVkIGFjdGlvbi5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBRdW90YVJlc2VydmVSZXN1bHQge1xuICAvKiogVHJ1ZSB3aGVuIHRoZSBzbG90IHdhcyBOT1QgcmVzZXJ2ZWQg4oCUIHRoZSBnYXRlZCBhY3Rpb24gbXVzdCBub3QgcnVuLiAqL1xuICBleGNlZWRlZDogYm9vbGVhbjtcbiAgLyoqXG4gICAqIFNldCAodHJ1ZSkgYnkgdGhlIHF1b3RhIENMSUVOVCB3aGVuIHRoZSByZXNlcnZhdGlvbiB3YXMgZGVuaWVkIGJlY2F1c2UgdGhlXG4gICAqIHF1b3RhIHNlcnZpY2UgY291bGQgbm90IENPTkZJUk0gaXQgKHVucmVhY2hhYmxlIC8gdGltZW91dCAvIGNpcmN1aXQgb3BlbiAvXG4gICAqIGVycm9yZWQpIOKAlCBub3QgYmVjYXVzZSB0aGUgb3JnIGlzIG92ZXIgaXRzIGxpbWl0LiBBbHdheXMgcGFpcmVkIHdpdGhcbiAgICogYGV4Y2VlZGVkOiB0cnVlYC4gQW5zd2VyIHdpdGgge0BsaW5rIHNlbmRRdW90YVJlc2VydmVEZW5pZWR9LCB3aGljaCBtYXBzIGl0IHRvXG4gICAqIDUwMyBpbnN0ZWFkIG9mIGEgbWlzbGVhZGluZyA0MjkgXCJxdW90YSBleGNlZWRlZFwiLlxuICAgKi9cbiAgdW5hdmFpbGFibGU/OiBib29sZWFuO1xuICAvKipcbiAgICogU2V0IHdoZW4gYW4gYGFpQ2FsbHNgIHJlc2VydmF0aW9uIHdhcyByZWZ1c2VkIGJ5IG9uZSBvZiB0aGUgb3JnJ3MgT1BUSU9OQUxcbiAgICogQUkgY29udHJvbHMgcmF0aGVyIHRoYW4gdGhlIHBlcmlvZCBjYXA6IHtAbGluayBFcnJvckNvZGUuQUlfTUVNQkVSX1NIQVJFX0VYQ0VFREVEfVxuICAgKiAodGhlIGNhbGxlcidzIHBlci1tZW1iZXIgc2hhcmUgaXMgc3BlbnQpIG9yXG4gICAqIHtAbGluayBFcnJvckNvZGUuQUlfVE9LRU5fQlVER0VUX0VYQ0VFREVEfSAodGhlIG9yZydzIHBlci1wZXJpb2QgdG9rZW5cbiAgICogYnVkZ2V0IGlzIHNwZW50KS4gUGFpcmVkIHdpdGggYGV4Y2VlZGVkOiB0cnVlYCBhbmQgdGhlIHF1b3RhIHNlcnZpY2Unc1xuICAgKiBgbWVzc2FnZWA7IHtAbGluayBzZW5kUXVvdGFSZXNlcnZlRGVuaWVkfSByZWxheXMgYm90aC5cbiAgICovXG4gIGNvZGU/OiBBaUxpbWl0Q29kZTtcbiAgbWVzc2FnZT86IHN0cmluZztcbiAgcXVvdGE6IHtcbiAgICB0eXBlOiBRdW90YVR5cGU7XG4gICAgbGltaXQ6IG51bWJlcjtcbiAgICB1c2VkOiBudW1iZXI7XG4gICAgcmVtYWluaW5nOiBudW1iZXI7XG4gICAgcmVzZXRBdD86IHN0cmluZztcbiAgfTtcbn1cblxuLyoqIFRoZSA0MjkgY29kZXMgYW4gYGFpQ2FsbHNgIHJlc2VydmF0aW9uIGFuc3dlcnMgd2hlbiBhbiBvcHRpb25hbCBvcmcgQUkgY29udHJvbCByZWZ1c2VzIGl0LiAqL1xuZXhwb3J0IHR5cGUgQWlMaW1pdENvZGUgPSBFcnJvckNvZGUuQUlfTUVNQkVSX1NIQVJFX0VYQ0VFREVEIHwgRXJyb3JDb2RlLkFJX1RPS0VOX0JVREdFVF9FWENFRURFRDtcblxuY29uc3QgQUlfTElNSVRfQ09ERVM6IFJlYWRvbmx5U2V0PHN0cmluZz4gPSBuZXcgU2V0KFtFcnJvckNvZGUuQUlfTUVNQkVSX1NIQVJFX0VYQ0VFREVELCBFcnJvckNvZGUuQUlfVE9LRU5fQlVER0VUX0VYQ0VFREVEXSk7XG5cbi8qKlxuICogUXVvdGEgc2VydmljZSBjbGllbnQgaW50ZXJmYWNlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFF1b3RhU2VydmljZSB7XG4gIC8qKiBDaGVjayBpZiBxdW90YSBpcyBhdmFpbGFibGUgKGZhaWwtb3BlbiBvbiBlcnJvcikuICovXG4gIGNoZWNrKG9yZ0lkOiBzdHJpbmcsIHF1b3RhVHlwZTogUXVvdGFUeXBlLCBhdXRoSGVhZGVyOiBzdHJpbmcsIHJlcXVlc3RJZD86IHN0cmluZyk6IFByb21pc2U8UXVvdGFDaGVja1Jlc3VsdD47XG4gIC8qKlxuICAgKiBJbmNyZW1lbnQgcXVvdGEgdXNhZ2UuIFJldHVybnMgYSBwcm9taXNlIHNvIGNhbGxlcnMgY2FuIG9wdGlvbmFsbHkgaGFuZGxlXG4gICAqIGVycm9ycy4gYGF0dHJpYnV0aW9uYCBkZWZhdWx0cyB0byB0aGUgYW1iaWVudCByZXF1ZXN0IGNvbnRleHQuXG4gICAqL1xuICBpbmNyZW1lbnQob3JnSWQ6IHN0cmluZywgcXVvdGFUeXBlOiBRdW90YVR5cGUsIGF1dGhIZWFkZXI6IHN0cmluZywgYW1vdW50PzogbnVtYmVyLCBhdHRyaWJ1dGlvbj86IFF1b3RhVXNhZ2VBdHRyaWJ1dGlvbik6IFByb21pc2U8dm9pZD47XG4gIC8qKlxuICAgKiBNRVRFUkVEIGluY3JlbWVudCBvZiBhIHByZS1hZ2dyZWdhdGVkIGJhdGNoICh0aGUgcGVyLXBvZCBiYXRjaGVyJ3MgZmx1c2gsXG4gICAqIHNlZSBgcXVvdGEtaW5jcmVtZW50LWJhdGNoZXIudHNgKTogdGhlIHN1bSBvZiBgZ3JvdXBzYCBpcyBhcHBsaWVkIHdpdGhcbiAgICogUEFSVElBTCBhZG1pc3Npb24g4oCUIHRoZSBjb3VudGVyIG1vdmVzIGJ5IGFzIG11Y2ggYXMgZml0cyB1bmRlciB0aGUgY2FwIGFuZFxuICAgKiB0aGUgcmVtYWluZGVyIGlzIHJlY29yZGVkIGFzIGBvdmVyc2hvb3RgIOKAlCBhbmQgZWFjaCBncm91cCdzIGF0dHJpYnV0aW9uIGlzXG4gICAqIHdyaXR0ZW4gdG8gdGhlIHVzYWdlIGxlZGdlci4gTmV2ZXIgYSA0MjkuIFJlc29sdmVzIHdpdGggd2hhdCB3YXMgY291bnRlZCxcbiAgICogb3IgYG51bGxgIHdoZW4gdGhlIHF1b3RhIHNlcnZpY2UgZGlkIG5vdCBhbnN3ZXIgb2sgKGNvdW50ZWQgb25cbiAgICogYHF1b3RhX2luY3JlbWVudF9mYWlsdXJlc190b3RhbGApLlxuICAgKi9cbiAgaW5jcmVtZW50TWV0ZXJlZChvcmdJZDogc3RyaW5nLCBxdW90YVR5cGU6IFF1b3RhVHlwZSwgYXV0aEhlYWRlcjogc3RyaW5nLCBncm91cHM6IE1ldGVyZWRJbmNyZW1lbnRHcm91cFtdKTogUHJvbWlzZTx7IGNvdW50ZWQ6IG51bWJlcjsgb3ZlcnNob290OiBudW1iZXIgfSB8IG51bGw+O1xuICAvKipcbiAgICogQXRvbWljIHJlc2VydmUgIHRoZSBzYW1lIGF0b21pYyBjaGVjaytpbmNyZW1lbnQgYXMgYGluY3JlbWVudGAsIGJ1dFxuICAgKiBwYXJzZXMgdGhlIHJlc3BvbnNlIHNvIGNhbGxlcnMgY2FuIHNlZSB3aGV0aGVyIHRoZSBzbG90IHdhcyBhY3R1YWxseVxuICAgKiByZXNlcnZlZC4gVXNlIHRoaXMgZm9yIGV4cGVuc2l2ZSByZXNvdXJjZXMgd2hlcmUgdGhlIHBvc3QtaG9jIGZpcmUtXG4gICAqIGFuZC1mb3JnZXQgcGF0dGVybiBhbGxvd3MgY29uY3VycmVudCBvdmVyLXNwZW5kLlxuICAgKlxuICAgKiBGYWlscyBDTE9TRUQgKGBleGNlZWRlZDogdHJ1ZWApIHdoZW5ldmVyIHRoZSBzbG90IGlzIG5vdCBjb25maXJtZWQg4oCUXG4gICAqIHVucmVhY2hhYmxlLCB0aW1lb3V0LCBvcGVuIGNpcmN1aXQsIG5vbi1vaywgb3IgYSBub24tcXVvdGEgNDI5IOKAlCB1bmxlc3NcbiAgICogYFFVT1RBX1JFU0VSVkVfRkFJTF9PUEVOPXRydWVgIChzZWUgdGhlIHBvbGljeSBub3RlIGF0IHRoZSB0b3Agb2YgdGhpcyBmaWxlKS5cbiAgICovXG4gIHJlc2VydmUob3JnSWQ6IHN0cmluZywgcXVvdGFUeXBlOiBRdW90YVR5cGUsIGF1dGhIZWFkZXI6IHN0cmluZywgYW1vdW50PzogbnVtYmVyLCBhdHRyaWJ1dGlvbj86IFF1b3RhVXNhZ2VBdHRyaWJ1dGlvbik6IFByb21pc2U8UXVvdGFSZXNlcnZlUmVzdWx0PjtcbiAgLyoqXG4gICAqIFJvbGwgYmFjayBhIHByZXZpb3VzbHkgcmVzZXJ2ZWQgc2xvdC4gRmlyZS1hbmQtZm9yZ2V0IOKAlCBuZXZlciB0aHJvd3MuXG4gICAqIFBhc3MgYHJlc2V0QXRTbmFwc2hvdGAgKHRoZSBgcXVvdGEucmVzZXRBdGAgb2JzZXJ2ZWQgd2hlbiB0aGUgc2xvdCB3YXNcbiAgICogcmVzZXJ2ZWQpIHRvIG1ha2UgdGhlIHJvbGxiYWNrIGNvbmRpdGlvbmFsOiBpZiB0aGUgcGVyaW9kIHJvbGxlZCBvdmVyXG4gICAqIGJldHdlZW4gcmVzZXJ2ZSBhbmQgcm9sbGJhY2ssIHRoZSBzZXJ2ZXIgc2tpcHMgdGhlIGRlY3JlbWVudCBzbyBpdCBkb2Vzbid0XG4gICAqIHN0ZWFsIGNhcGFjaXR5IGZyb20gdGhlIG5ldyBwZXJpb2QuXG4gICAqL1xuICBkZWNyZW1lbnQob3JnSWQ6IHN0cmluZywgcXVvdGFUeXBlOiBRdW90YVR5cGUsIGF1dGhIZWFkZXI6IHN0cmluZywgYW1vdW50PzogbnVtYmVyLCByZXNldEF0U25hcHNob3Q/OiBzdHJpbmcsIGF0dHJpYnV0aW9uPzogUXVvdGFVc2FnZUF0dHJpYnV0aW9uKTogUHJvbWlzZTx2b2lkPjtcbiAgLyoqXG4gICAqIFJlY29yZCB3aGF0IGFuIEFJIGNhbGwgQ09TVCBhZnRlciBpdCBzZXR0bGVkIOKAlCBpdHMgdG9rZW4gY291bnRzIOKAlCBpbiB0aGVcbiAgICogdXNhZ2UgbGVkZ2VyLCB3aXRob3V0IG1vdmluZyBhbnkgY291bnRlciAoYSB6ZXJvLXVuaXQgbGVkZ2VyIHJvdyBjYXJyeWluZ1xuICAgKiBgdG9rZW5zSW5gIC8gYHRva2Vuc091dGAgdW5kZXIgdGhlIGNhbGwncyBhdHRyaWJ1dGlvbikuIEFsc28gaG93IGEgY2FsbCB0aGF0XG4gICAqIHNwZW50IE5PIGBhaUNhbGxzYCB1bml0IChhIEJZT0sga2V5LCBhbiBpbXBlcnNvbmF0aW9uIHNlc3Npb24sIGEgd2VpZ2h0LTBcbiAgICogbW9kZWwpIHN0aWxsIHNob3dzIHVwIGluIHRoZSB1c2FnZSBicmVha2Rvd24uIEZpcmUtYW5kLWZvcmdldCDigJQgbmV2ZXIgdGhyb3dzLlxuICAgKiBPcHRpb25hbCBzbyB0ZXN0IGRvdWJsZXMgbmVlZCBub3QgaW1wbGVtZW50IGl0LlxuICAgKi9cbiAgcmVwb3J0VXNhZ2U/KG9yZ0lkOiBzdHJpbmcsIHF1b3RhVHlwZTogUXVvdGFUeXBlLCBhdXRoSGVhZGVyOiBzdHJpbmcsIHRva2VuczogUXVvdGFUb2tlblVzYWdlLCBhdHRyaWJ1dGlvbj86IFF1b3RhVXNhZ2VBdHRyaWJ1dGlvbik6IFByb21pc2U8dm9pZD47XG4gIC8qKlxuICAgKiBHZXQgdGhlIG9yZydzIHF1b3RhIGBRdW90YVRpZXJgLiBVc2VkIGJ5IHRoZSBwbHVnaW4tYnVpbGQgcXVldWUgcGFydGl0aW9uaW5nXG4gICAqIHRvIHJvdXRlIGEgYnVpbGQgdG8gdGhlIHJpZ2h0IHBlci10aWVyIHF1ZXVlLiBGYWlsLW9wZW4gcmV0dXJucyBgREVGQVVMVF9USUVSYFxuICAgKiAoYGRldmVsb3BlcmAgd2hlbiBiaWxsaW5nIGlzIGVuYWJsZWQsIGB1bmxpbWl0ZWRgIHdoZW4gaXQncyBkaXNhYmxlZCk7IGFcbiAgICogbWlzY2xhc3NpZmllZCBvcmcgc3RpbGwgYnVpbGRzIG9uIHRoZSBkZWZhdWx0IHF1ZXVlLCBqdXN0IHdpdGhvdXQgdGhlXG4gICAqIHRpZXItc2NvcGVkIHNjaGVkdWxpbmcgYm9vc3QuXG4gICAqL1xuICBnZXRUaWVyKG9yZ0lkOiBzdHJpbmcsIGF1dGhIZWFkZXI6IHN0cmluZywgcmVxdWVzdElkPzogc3RyaW5nKTogUHJvbWlzZTxRdW90YVRpZXI+O1xuICAvKipcbiAgICogRkFJTC1DTE9TRUQgdHdpbiBvZiB7QGxpbmsgZ2V0VGllcn06IHRoZSBvcmcncyB0aWVyIGFzIHRoZSBxdW90YSBzZXJ2aWNlXG4gICAqIENPTkZJUk1FRCBpdCwgb3IgYG51bGxgIHdoZW4gaXQgY291bGQgbm90IGJlIGNvbmZpcm1lZCAodW5yZWFjaGFibGUsIG5vbi1vayxcbiAgICogbWlzc2luZyBvciB1bnJlY29nbml6ZWQgdGllcikuIEZvciBkZWNpc2lvbnMgdGhhdCBtdXN0IG5ldmVyIGJlIHRha2VuIG9uIGFcbiAgICogZ3Vlc3Mg4oCUIGFueXRoaW5nIHRoYXQgcmV2b2tlcywgZG93bmdyYWRlcyBvciBkZWxldGVzIG9uIHRoZSBzdHJlbmd0aCBvZiBhXG4gICAqIHRpZXIgKGUuZy4gYSB2ZXJpZmllZC1wdWJsaXNoZXIgZ3JhY2Ugc3dlZXApIG11c3Qgc2tpcCB0aGUgb3JnIG9uIGBudWxsYCxcbiAgICogbmV2ZXIgYWN0IG9uIGBERUZBVUxUX1RJRVJgLlxuICAgKi9cbiAgZ2V0VGllclN0cmljdChvcmdJZDogc3RyaW5nLCBhdXRoSGVhZGVyOiBzdHJpbmcsIHJlcXVlc3RJZD86IHN0cmluZyk6IFByb21pc2U8UXVvdGFUaWVyIHwgbnVsbD47XG59XG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBmb3IgcXVvdGEgc2VydmljZSBjbGllbnQuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUXVvdGFTZXJ2aWNlQ29uZmlnIHtcbiAgLyoqIFF1b3RhIHNlcnZpY2UgaG9zdCAoZGVmYXVsdDogZW52IFFVT1RBX1NFUlZJQ0VfSE9TVCBvciAncXVvdGEnKSAqL1xuICBob3N0Pzogc3RyaW5nO1xuICAvKiogUXVvdGEgc2VydmljZSBwb3J0IChkZWZhdWx0OiBlbnYgUVVPVEFfU0VSVklDRV9QT1JUIG9yIDMwMDApICovXG4gIHBvcnQ/OiBudW1iZXI7XG4gIC8qKiBSZXF1ZXN0IHRpbWVvdXQgaW4gbWlsbGlzZWNvbmRzIChkZWZhdWx0OiA1MDAwKSAqL1xuICB0aW1lb3V0PzogbnVtYmVyO1xufVxuXG4vKipcbiAqIEFwcGx5IHRoZSBleHBsaWNpdCByZXNlcnZlIGZhaWwtbW9kZSBwb2xpY3kgdG8gYSByZXNlcnZhdGlvbiB0aGUgcXVvdGEgc2VydmljZVxuICogZGlkIE5PVCBjb25maXJtIChzZWUgUVVPVEFfUkVTRVJWRV9GQUlMX09QRU4gYWJvdmUpLiBEZWZhdWx0OiBkZW55LlxuICovXG5mdW5jdGlvbiB1bmNvbmZpcm1lZFJlc2VydmUoXG4gIG9yZ0lkOiBzdHJpbmcsXG4gIHF1b3RhVHlwZTogUXVvdGFUeXBlLFxuICByZWFzb246ICd1bnJlYWNoYWJsZScgfCAndHJhbnNpZW50LTQyOScgfCAnbm9uLW9rJyxcbiAgc3RhdHVzQ29kZT86IG51bWJlcixcbik6IFF1b3RhUmVzZXJ2ZVJlc3VsdCB7XG4gIGlmIChRVU9UQV9SRVNFUlZFX0ZBSUxfT1BFTikge1xuICAgIGxvZ2dlci53YXJuKCdRVU9UQV9GQUlMX09QRU46IHF1b3RhIHJlc2VydmUgbm90IGNvbmZpcm1lZCwgYWxsb3dpbmcgcmVxdWVzdCcsIHsgb3JnSWQsIHF1b3RhVHlwZSwgcmVhc29uLCBzdGF0dXNDb2RlIH0pO1xuICAgIGVtaXRDb3VudGVyKCdxdW90YV9mYWlsX29wZW5fdG90YWwnLCB7IG9wZXJhdGlvbjogJ3Jlc2VydmUnLCByZWFzb24sIHF1b3RhVHlwZSB9KTtcbiAgICByZXR1cm4geyBleGNlZWRlZDogZmFsc2UsIHF1b3RhOiB7IHR5cGU6IHF1b3RhVHlwZSwgbGltaXQ6IC0xLCB1c2VkOiAwLCByZW1haW5pbmc6IC0xIH0gfTtcbiAgfVxuICBsb2dnZXIud2FybignUVVPVEFfRkFJTF9DTE9TRUQ6IHF1b3RhIHJlc2VydmUgbm90IGNvbmZpcm1lZCwgZGVueWluZyByZXF1ZXN0JywgeyBvcmdJZCwgcXVvdGFUeXBlLCByZWFzb24sIHN0YXR1c0NvZGUgfSk7XG4gIGVtaXRDb3VudGVyKCdxdW90YV9mYWlsX2Nsb3NlZF90b3RhbCcsIHsgb3BlcmF0aW9uOiAncmVzZXJ2ZScsIHJlYXNvbiwgcXVvdGFUeXBlIH0pO1xuICByZXR1cm4geyBleGNlZWRlZDogdHJ1ZSwgdW5hdmFpbGFibGU6IHRydWUsIHF1b3RhOiB7IHR5cGU6IHF1b3RhVHlwZSwgbGltaXQ6IDAsIHVzZWQ6IDAsIHJlbWFpbmluZzogMCB9IH07XG59XG5cbi8qKlxuICogQ3JlYXRlIGEgZmFpbC1vcGVuIHF1b3RhIHJlc3VsdCAoYWxsb3dzIHRoZSByZXF1ZXN0KS5cbiAqL1xuZnVuY3Rpb24gY3JlYXRlRmFpbE9wZW5SZXN1bHQoKTogUXVvdGFDaGVja1Jlc3VsdCB7XG4gIHJldHVybiB7XG4gICAgYWxsb3dlZDogdHJ1ZSxcbiAgICBsaW1pdDogLTEsXG4gICAgdXNlZDogMCxcbiAgICByZW1haW5pbmc6IC0xLFxuICAgIHJlc2V0QXQ6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICB1bmxpbWl0ZWQ6IHRydWUsXG4gICAgLy8gVGFnIHRoZSBzZW50aW5lbCBzbyBmYWlsLWNsb3NlZCBjYWxsZXJzIGNhbiB0ZWxsIGFuIG91dGFnZSBhcGFydCBmcm9tIGFcbiAgICAvLyByZWFsIHVubGltaXRlZCAoLTEpIHJlYWRpbmcuIFJlYWwgcXVvdGEgcmVzdWx0cyBuZXZlciBzZXQgdGhpcy5cbiAgICBmYWlsT3BlbjogdHJ1ZSxcbiAgfTtcbn1cblxuLyoqXG4gKiBCdWlsZCBjb21tb24gcmVxdWVzdCBoZWFkZXJzIHdpdGggb3B0aW9uYWwgcmVxdWVzdCBJRCBmb3IgZGlzdHJpYnV0ZWQgdHJhY2luZy5cbiAqL1xuZnVuY3Rpb24gYnVpbGRIZWFkZXJzKG9yZ0lkOiBzdHJpbmcsIGF1dGhIZWFkZXI/OiBzdHJpbmcsIHJlcXVlc3RJZD86IHN0cmluZyk6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4ge1xuICBjb25zdCBoZWFkZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0geyAneC1vcmctaWQnOiBvcmdJZCB9O1xuICBpZiAoYXV0aEhlYWRlcikgaGVhZGVycy5BdXRob3JpemF0aW9uID0gYXV0aEhlYWRlcjtcbiAgaWYgKHJlcXVlc3RJZCkgaGVhZGVyc1snWC1SZXF1ZXN0LUlkJ10gPSByZXF1ZXN0SWQ7XG4gIHJldHVybiBoZWFkZXJzO1xufVxuXG4vKipcbiAqIENyZWF0ZSBhIHF1b3RhIHNlcnZpY2UgY2xpZW50LlxuICpcbiAqIEBwYXJhbSBjb25maWcgLSBPcHRpb25hbCBzZXJ2aWNlIGNvbmZpZ3VyYXRpb25cbiAqIEByZXR1cm5zIFF1b3RhIHNlcnZpY2UgY2xpZW50XG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IHF1b3RhU2VydmljZSA9IGNyZWF0ZVF1b3RhU2VydmljZSgpO1xuICpcbiAqIC8vIENoZWNrIHF1b3RhIGJlZm9yZSBwcm9jZXNzaW5nXG4gKiBjb25zdCBxdW90YSA9IGF3YWl0IHF1b3RhU2VydmljZS5jaGVjayhvcmdJZCwgJ2FwaUNhbGxzJywgYXV0aEhlYWRlcik7XG4gKiBpZiAoIXF1b3RhLmFsbG93ZWQpIHtcbiAqIHJldHVybiByZXMuc3RhdHVzKDQyOSkuanNvbih7IGVycm9yOiAnUXVvdGEgZXhjZWVkZWQnIH0pO1xuICogfVxuICpcbiAqIC8vIEluY3JlbWVudCBxdW90YSBhZnRlciBzdWNjZXNzXG4gKiBxdW90YVNlcnZpY2UuaW5jcmVtZW50KG9yZ0lkLCAnYXBpQ2FsbHMnLCBhdXRoSGVhZGVyKS5jYXRjaChlcnIgPT4gbG9nZ2VyLndhcm4oJ1F1b3RhIGluY3JlbWVudCBmYWlsZWQnLCB7IGVycm9yOiBlcnIgfSkpO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVRdW90YVNlcnZpY2UoY29uZmlnOiBRdW90YVNlcnZpY2VDb25maWcgPSB7fSk6IFF1b3RhU2VydmljZSB7XG4gIGNvbnN0IHNlcnZpY2VDb25maWc6IFNlcnZpY2VDb25maWcgPSB7XG4gICAgaG9zdDogY29uZmlnLmhvc3QgPz8gc2VydmljZUVuZHBvaW50KCdxdW90YScpLmhvc3QsXG4gICAgcG9ydDogY29uZmlnLnBvcnQgPz8gc2VydmljZUVuZHBvaW50KCdxdW90YScpLnBvcnQsXG4gICAgdGltZW91dDogY29uZmlnLnRpbWVvdXQgPz8gNTAwMCxcbiAgfTtcblxuICBjb25zdCBjbGllbnQgPSBjcmVhdGVTYWZlQ2xpZW50KHNlcnZpY2VDb25maWcpO1xuXG4gIC8qKiBPbmUgdGllciByZWFkOiB0aGUgY29uZmlybWVkIHRpZXIsIG9yIHdoeSB0aGVyZSBpc24ndCBvbmUuICovXG4gIGFzeW5jIGZ1bmN0aW9uIHJlYWRUaWVyKFxuICAgIG9yZ0lkOiBzdHJpbmcsIGF1dGhIZWFkZXI6IHN0cmluZywgcmVxdWVzdElkPzogc3RyaW5nLFxuICApOiBQcm9taXNlPHsgdGllcjogUXVvdGFUaWVyOyByZWFzb24/OiB1bmRlZmluZWQ7IHN0YXR1c0NvZGU/OiBudW1iZXIgfSB8IHsgdGllcjogbnVsbDsgcmVhc29uOiAndW5yZWFjaGFibGUnIHwgJ25vbi1vaycgfCAnaW52YWxpZC10aWVyJzsgc3RhdHVzQ29kZT86IG51bWJlciB9PiB7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBjbGllbnQuZ2V0PHtcbiAgICAgIHN1Y2Nlc3M6IGJvb2xlYW47XG4gICAgICBkYXRhPzogeyBxdW90YT86IHsgdGllcj86IHN0cmluZyB9IH07XG4gICAgICBtZXNzYWdlPzogc3RyaW5nO1xuICAgIH0+KGAvcXVvdGFzLyR7ZW5jb2RlVVJJQ29tcG9uZW50KG9yZ0lkKX1gLCB7IGhlYWRlcnM6IGJ1aWxkSGVhZGVycyhvcmdJZCwgYXV0aEhlYWRlciwgcmVxdWVzdElkKSwgLi4uUVVPVEFfUkVRVUVTVF9PUFRJT05TIH0pO1xuICAgIGlmICghcmVzcG9uc2UpIHJldHVybiB7IHRpZXI6IG51bGwsIHJlYXNvbjogJ3VucmVhY2hhYmxlJyB9O1xuICAgIGlmIChyZXNwb25zZS5zdGF0dXNDb2RlICE9PSAyMDAgfHwgIXJlc3BvbnNlLmJvZHk/LnN1Y2Nlc3MpIHJldHVybiB7IHRpZXI6IG51bGwsIHJlYXNvbjogJ25vbi1vaycsIHN0YXR1c0NvZGU6IHJlc3BvbnNlLnN0YXR1c0NvZGUgfTtcbiAgICBjb25zdCB0aWVyID0gcmVzcG9uc2UuYm9keS5kYXRhPy5xdW90YT8udGllcjtcbiAgICBpZiAoIXRpZXIgfHwgIWlzVmFsaWRUaWVyKHRpZXIpKSByZXR1cm4geyB0aWVyOiBudWxsLCByZWFzb246ICdpbnZhbGlkLXRpZXInLCBzdGF0dXNDb2RlOiByZXNwb25zZS5zdGF0dXNDb2RlIH07XG4gICAgcmV0dXJuIHsgdGllciwgc3RhdHVzQ29kZTogcmVzcG9uc2Uuc3RhdHVzQ29kZSB9O1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBhc3luYyBjaGVjayhvcmdJZDogc3RyaW5nLCBxdW90YVR5cGU6IFF1b3RhVHlwZSwgYXV0aEhlYWRlcjogc3RyaW5nLCByZXF1ZXN0SWQ/OiBzdHJpbmcpOiBQcm9taXNlPFF1b3RhQ2hlY2tSZXN1bHQ+IHtcbiAgICAgIGNvbnN0IHBhdGggPSBgL3F1b3Rhcy8ke2VuY29kZVVSSUNvbXBvbmVudChvcmdJZCl9LyR7ZW5jb2RlVVJJQ29tcG9uZW50KHF1b3RhVHlwZSl9YDtcblxuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBjbGllbnQuZ2V0PHtcbiAgICAgICAgc3VjY2VzczogYm9vbGVhbjtcbiAgICAgICAgZGF0YT86IHsgcXVvdGFUeXBlOiBzdHJpbmc7IHN0YXR1czogUXVvdGFDaGVja1Jlc3VsdCB9O1xuICAgICAgICBtZXNzYWdlPzogc3RyaW5nO1xuICAgICAgfT4ocGF0aCwgeyBoZWFkZXJzOiBidWlsZEhlYWRlcnMob3JnSWQsIGF1dGhIZWFkZXIsIHJlcXVlc3RJZCksIC4uLmNoZWNrUmVxdWVzdE9wdGlvbnMocXVvdGFUeXBlKSB9KTtcblxuICAgICAgaWYgKCFyZXNwb25zZSkge1xuICAgICAgICBsb2dnZXIud2FybignUVVPVEFfRkFJTF9PUEVOOiBRdW90YSBzZXJ2aWNlIHVucmVhY2hhYmxlLCBhbGxvd2luZyByZXF1ZXN0JywgeyBvcmdJZCwgcXVvdGFUeXBlIH0pO1xuICAgICAgICBlbWl0Q291bnRlcigncXVvdGFfZmFpbF9vcGVuX3RvdGFsJywgeyBvcGVyYXRpb246ICdjaGVjaycsIHJlYXNvbjogJ3VucmVhY2hhYmxlJywgcXVvdGFUeXBlIH0pO1xuICAgICAgICByZXR1cm4gY3JlYXRlRmFpbE9wZW5SZXN1bHQoKTtcbiAgICAgIH1cblxuICAgICAgaWYgKHJlc3BvbnNlLnN0YXR1c0NvZGUgIT09IDIwMCB8fCAhcmVzcG9uc2UuYm9keS5zdWNjZXNzIHx8ICFyZXNwb25zZS5ib2R5LmRhdGE/LnN0YXR1cykge1xuICAgICAgICBsb2dnZXIud2FybignUVVPVEFfRkFJTF9PUEVOOiBRdW90YSBjaGVjayByZXR1cm5lZCBub24tb2ssIGFsbG93aW5nIHJlcXVlc3QnLCB7XG4gICAgICAgICAgb3JnSWQsIHF1b3RhVHlwZSwgc3RhdHVzQ29kZTogcmVzcG9uc2Uuc3RhdHVzQ29kZSwgbWVzc2FnZTogcmVzcG9uc2UuYm9keS5tZXNzYWdlLFxuICAgICAgICB9KTtcbiAgICAgICAgZW1pdENvdW50ZXIoJ3F1b3RhX2ZhaWxfb3Blbl90b3RhbCcsIHsgb3BlcmF0aW9uOiAnY2hlY2snLCByZWFzb246ICdub24tb2snLCBxdW90YVR5cGUgfSk7XG4gICAgICAgIHJldHVybiBjcmVhdGVGYWlsT3BlblJlc3VsdCgpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gcmVzcG9uc2UuYm9keS5kYXRhLnN0YXR1cztcbiAgICB9LFxuXG4gICAgYXN5bmMgaW5jcmVtZW50KG9yZ0lkOiBzdHJpbmcsIHF1b3RhVHlwZTogUXVvdGFUeXBlLCBhdXRoSGVhZGVyOiBzdHJpbmcsIGFtb3VudDogbnVtYmVyID0gMSwgYXR0cmlidXRpb24/OiBRdW90YVVzYWdlQXR0cmlidXRpb24pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgIGNvbnN0IHBhdGggPSBgL3F1b3Rhcy8ke2VuY29kZVVSSUNvbXBvbmVudChvcmdJZCl9L2luY3JlbWVudGA7XG4gICAgICBjb25zdCBhdHRyID0gcmVzb2x2ZUF0dHJpYnV0aW9uKGF0dHJpYnV0aW9uKTtcblxuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBjbGllbnRcbiAgICAgICAgLnBvc3QocGF0aCwgeyBxdW90YVR5cGUsIGFtb3VudCwgLi4uKGF0dHIgJiYgeyBhdHRyaWJ1dGlvbjogYXR0ciB9KSB9LCB7IGhlYWRlcnM6IGJ1aWxkSGVhZGVycyhvcmdJZCwgYXV0aEhlYWRlciwgYXR0cj8ucmVxdWVzdElkKSwgLi4uUVVPVEFfUkVRVUVTVF9PUFRJT05TIH0pO1xuXG4gICAgICBpZiAocmVzcG9uc2U/LnN0YXR1c0NvZGUgPT09IDQyOSkge1xuICAgICAgICAvLyBPdmVyIHRoZSBsaW1pdDogdGhlIHF1b3RhIHNlcnZpY2UgcmVmdXNlZCBBTkQgcmVjb3JkZWQgdGhlIGRlbmlhbCBpblxuICAgICAgICAvLyBpdHMgbGVkZ2VyLiBOb3QgYSBmYWlsdXJlIG9mIG1ldGVyaW5nIOKAlCB0aGUgY291bnRlciBpcyBleGFjdGx5IHdoZXJlXG4gICAgICAgIC8vIGl0IHNob3VsZCBiZS5cbiAgICAgICAgbG9nZ2VyLmRlYnVnKCdRdW90YSBpbmNyZW1lbnQgcmVmdXNlZCAob3ZlciBsaW1pdCknLCB7IG9yZ0lkLCBxdW90YVR5cGUsIGFtb3VudCB9KTtcbiAgICAgIH0gZWxzZSBpZiAoIXJlc3BvbnNlIHx8IHJlc3BvbnNlLnN0YXR1c0NvZGUgIT09IDIwMCkge1xuICAgICAgICBsb2dnZXIud2FybignRmFpbGVkIHRvIGluY3JlbWVudCBxdW90YScsIHtcbiAgICAgICAgICBvcmdJZCwgcXVvdGFUeXBlLCBhbW91bnQsIHN0YXR1c0NvZGU6IHJlc3BvbnNlPy5zdGF0dXNDb2RlLFxuICAgICAgICB9KTtcbiAgICAgICAgLy8gQSBsb3N0IG1ldGVyaW5nIGluY3JlbWVudCBpcyBhIHVuaXQgdGhlIG9yZyBjb25zdW1lZCBhbmQgbmV2ZXIgcGFpZFxuICAgICAgICAvLyBmb3IuIENvdW50ZWQgKGxhYmVsbGVkIGJ5IHRoZSBlbWl0dGluZyBgc2VydmljZWApIHNvIGEgc3VzdGFpbmVkIHJhdGVcbiAgICAgICAgLy8gcGFnZXMgaW5zdGVhZCBvZiBzaWxlbnRseSB1bmRlci1iaWxsaW5nIOKAlCBzZWUgUXVvdGFJbmNyZW1lbnRGYWlsdXJlcy5cbiAgICAgICAgZW1pdENvdW50ZXIoJ3F1b3RhX2luY3JlbWVudF9mYWlsdXJlc190b3RhbCcsIHsgcmVhc29uOiByZXNwb25zZSA/ICdub24tb2snIDogJ3VucmVhY2hhYmxlJywgcXVvdGFUeXBlIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbG9nZ2VyLmRlYnVnKCdRdW90YSBpbmNyZW1lbnRlZCcsIHsgb3JnSWQsIHF1b3RhVHlwZSwgYW1vdW50IH0pO1xuICAgICAgfVxuICAgIH0sXG5cbiAgICBhc3luYyBpbmNyZW1lbnRNZXRlcmVkKG9yZ0lkOiBzdHJpbmcsIHF1b3RhVHlwZTogUXVvdGFUeXBlLCBhdXRoSGVhZGVyOiBzdHJpbmcsIGdyb3VwczogTWV0ZXJlZEluY3JlbWVudEdyb3VwW10pOiBQcm9taXNlPHsgY291bnRlZDogbnVtYmVyOyBvdmVyc2hvb3Q6IG51bWJlciB9IHwgbnVsbD4ge1xuICAgICAgY29uc3QgcGF0aCA9IGAvcXVvdGFzLyR7ZW5jb2RlVVJJQ29tcG9uZW50KG9yZ0lkKX0vaW5jcmVtZW50YDtcbiAgICAgIGNvbnN0IGFtb3VudCA9IGdyb3Vwcy5yZWR1Y2UoKHN1bSwgZykgPT4gc3VtICsgZy5hbW91bnQsIDApO1xuICAgICAgaWYgKGFtb3VudCA8PSAwKSByZXR1cm4geyBjb3VudGVkOiAwLCBvdmVyc2hvb3Q6IDAgfTtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgY2xpZW50LnBvc3Q8eyBzdWNjZXNzOiBib29sZWFuOyBkYXRhPzogeyBjb3VudGVkPzogbnVtYmVyOyBvdmVyc2hvb3Q/OiBudW1iZXIgfSB9PihcbiAgICAgICAgcGF0aCxcbiAgICAgICAgeyBxdW90YVR5cGUsIGFtb3VudCwgbWV0ZXI6IHRydWUsIGdyb3VwcyB9LFxuICAgICAgICB7IGhlYWRlcnM6IGJ1aWxkSGVhZGVycyhvcmdJZCwgYXV0aEhlYWRlciksIC4uLlFVT1RBX1JFUVVFU1RfT1BUSU9OUyB9LFxuICAgICAgKTtcbiAgICAgIGlmICghcmVzcG9uc2UgfHwgcmVzcG9uc2Uuc3RhdHVzQ29kZSAhPT0gMjAwIHx8ICFyZXNwb25zZS5ib2R5Py5zdWNjZXNzKSB7XG4gICAgICAgIGxvZ2dlci53YXJuKCdGYWlsZWQgdG8gYXBwbHkgbWV0ZXJlZCBxdW90YSBpbmNyZW1lbnQnLCB7IG9yZ0lkLCBxdW90YVR5cGUsIGFtb3VudCwgc3RhdHVzQ29kZTogcmVzcG9uc2U/LnN0YXR1c0NvZGUgfSk7XG4gICAgICAgIC8vIEV2ZXJ5IHVuaXQgaW4gdGhlIGJhdGNoIHdlbnQgdW5jb3VudGVkIOKAlCBzZWUgUXVvdGFJbmNyZW1lbnRGYWlsdXJlcy5cbiAgICAgICAgZW1pdENvdW50ZXIoJ3F1b3RhX2luY3JlbWVudF9mYWlsdXJlc190b3RhbCcsIHsgcmVhc29uOiByZXNwb25zZSA/ICdub24tb2snIDogJ3VucmVhY2hhYmxlJywgcXVvdGFUeXBlIH0pO1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGNvdW50ZWQgPSByZXNwb25zZS5ib2R5LmRhdGE/LmNvdW50ZWQgPz8gYW1vdW50O1xuICAgICAgY29uc3Qgb3ZlcnNob290ID0gcmVzcG9uc2UuYm9keS5kYXRhPy5vdmVyc2hvb3QgPz8gMDtcbiAgICAgIGxvZ2dlci5kZWJ1ZygnTWV0ZXJlZCBxdW90YSBpbmNyZW1lbnQgYXBwbGllZCcsIHsgb3JnSWQsIHF1b3RhVHlwZSwgYW1vdW50LCBjb3VudGVkLCBvdmVyc2hvb3QgfSk7XG4gICAgICByZXR1cm4geyBjb3VudGVkLCBvdmVyc2hvb3QgfTtcbiAgICB9LFxuXG4gICAgYXN5bmMgcmVzZXJ2ZShvcmdJZDogc3RyaW5nLCBxdW90YVR5cGU6IFF1b3RhVHlwZSwgYXV0aEhlYWRlcjogc3RyaW5nLCBhbW91bnQ6IG51bWJlciA9IDEsIGF0dHJpYnV0aW9uPzogUXVvdGFVc2FnZUF0dHJpYnV0aW9uKTogUHJvbWlzZTxRdW90YVJlc2VydmVSZXN1bHQ+IHtcbiAgICAgIGNvbnN0IHBhdGggPSBgL3F1b3Rhcy8ke2VuY29kZVVSSUNvbXBvbmVudChvcmdJZCl9L2luY3JlbWVudGA7XG4gICAgICBjb25zdCBhdHRyID0gcmVzb2x2ZUF0dHJpYnV0aW9uKGF0dHJpYnV0aW9uKTtcblxuICAgICAgLy8gMjAwIGNhcnJpZXMgYGRhdGEucXVvdGFgOyA0MjkgKFFVT1RBX0VYQ0VFREVEKSBjYXJyaWVzIGBkZXRhaWxzLnF1b3RhYC5cbiAgICAgIC8vIEJvdGggc2hhcGVzIGFyZSBub3JtYWxpemVkIGludG8gUXVvdGFSZXNlcnZlUmVzdWx0LlxuICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBjbGllbnQucG9zdDx7XG4gICAgICAgIHN1Y2Nlc3M6IGJvb2xlYW47XG4gICAgICAgIGRhdGE/OiB7IHF1b3RhPzogUXVvdGFSZXNlcnZlUmVzdWx0WydxdW90YSddIH07XG4gICAgICAgIGRldGFpbHM/OiB7IHF1b3RhPzogUXVvdGFSZXNlcnZlUmVzdWx0WydxdW90YSddIH07XG4gICAgICAgIC8qKiBgc2VuZEVycm9yYCdzIGVycm9yLWNvZGUgZmllbGQuICovXG4gICAgICAgIGNvZGU/OiBzdHJpbmc7XG4gICAgICAgIG1lc3NhZ2U/OiBzdHJpbmc7XG4gICAgICB9PihwYXRoLCB7IHF1b3RhVHlwZSwgYW1vdW50LCAuLi4oYXR0ciAmJiB7IGF0dHJpYnV0aW9uOiBhdHRyIH0pIH0sIHsgaGVhZGVyczogYnVpbGRIZWFkZXJzKG9yZ0lkLCBhdXRoSGVhZGVyLCBhdHRyPy5yZXF1ZXN0SWQpLCAuLi5RVU9UQV9SRVFVRVNUX09QVElPTlMgfSk7XG5cbiAgICAgIGlmICghcmVzcG9uc2UpIHJldHVybiB1bmNvbmZpcm1lZFJlc2VydmUob3JnSWQsIHF1b3RhVHlwZSwgJ3VucmVhY2hhYmxlJyk7XG5cbiAgICAgIGlmIChyZXNwb25zZS5zdGF0dXNDb2RlID09PSA0MjkpIHtcbiAgICAgICAgY29uc3QgcSA9IHJlc3BvbnNlLmJvZHkuZGV0YWlscz8ucXVvdGE7XG4gICAgICAgIC8vIEFuIG9wdGlvbmFsIG9yZyBBSSBjb250cm9sIChwZXItbWVtYmVyIHNoYXJlLCB0b2tlbiBidWRnZXQpIHJlZnVzZWQgdGhlXG4gICAgICAgIC8vIHNsb3Q6IGEgZ2VudWluZSwgZmluYWwgZGVuaWFsIOKAlCByZWxheWVkIHdpdGggaXRzIG93biBjb2RlIGFuZCBtZXNzYWdlLlxuICAgICAgICBpZiAocmVzcG9uc2UuYm9keS5jb2RlICYmIEFJX0xJTUlUX0NPREVTLmhhcyhyZXNwb25zZS5ib2R5LmNvZGUpKSB7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGV4Y2VlZGVkOiB0cnVlLFxuICAgICAgICAgICAgY29kZTogcmVzcG9uc2UuYm9keS5jb2RlIGFzIEFpTGltaXRDb2RlLFxuICAgICAgICAgICAgLi4uKHJlc3BvbnNlLmJvZHkubWVzc2FnZSA/IHsgbWVzc2FnZTogcmVzcG9uc2UuYm9keS5tZXNzYWdlIH0gOiB7fSksXG4gICAgICAgICAgICBxdW90YTogcSA/PyB7IHR5cGU6IHF1b3RhVHlwZSwgbGltaXQ6IDAsIHVzZWQ6IDAsIHJlbWFpbmluZzogMCB9LFxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgLy8gT25seSBhIEdFTlVJTkUgcXVvdGEtZXhjZWVkZWQgNDI5IG1lYW5zIFwib3ZlciBxdW90YVwiLiBBIGdlbmVyaWMgNDI5IOKAlFxuICAgICAgICAvLyBhbiBpbnRlcnZlbmluZyBnYXRld2F5IG9yIHJhdGUgbGltaXRlciDigJQgZGlkIG5vdCBjb25maXJtIGFueXRoaW5nLCBzb1xuICAgICAgICAvLyBpdCBnb2VzIHRocm91Z2ggdGhlIHNhbWUgdW5jb25maXJtZWQtcmVzZXJ2YXRpb24gcG9saWN5IGFzIGFuIG91dGFnZS5cbiAgICAgICAgaWYgKHJlc3BvbnNlLmJvZHkuY29kZSA9PT0gRXJyb3JDb2RlLlFVT1RBX0VYQ0VFREVEIHx8IHEpIHtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZXhjZWVkZWQ6IHRydWUsXG4gICAgICAgICAgICBxdW90YTogcSA/PyB7IHR5cGU6IHF1b3RhVHlwZSwgbGltaXQ6IDAsIHVzZWQ6IDAsIHJlbWFpbmluZzogMCB9LFxuICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVuY29uZmlybWVkUmVzZXJ2ZShvcmdJZCwgcXVvdGFUeXBlLCAndHJhbnNpZW50LTQyOScsIHJlc3BvbnNlLnN0YXR1c0NvZGUpO1xuICAgICAgfVxuXG4gICAgICBpZiAocmVzcG9uc2Uuc3RhdHVzQ29kZSAhPT0gMjAwIHx8ICFyZXNwb25zZS5ib2R5LnN1Y2Nlc3MpIHtcbiAgICAgICAgcmV0dXJuIHVuY29uZmlybWVkUmVzZXJ2ZShvcmdJZCwgcXVvdGFUeXBlLCAnbm9uLW9rJywgcmVzcG9uc2Uuc3RhdHVzQ29kZSk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHEgPSByZXNwb25zZS5ib2R5LmRhdGE/LnF1b3RhO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgZXhjZWVkZWQ6IGZhbHNlLFxuICAgICAgICBxdW90YTogcSA/PyB7IHR5cGU6IHF1b3RhVHlwZSwgbGltaXQ6IC0xLCB1c2VkOiAwLCByZW1haW5pbmc6IC0xIH0sXG4gICAgICB9O1xuICAgIH0sXG5cbiAgICBhc3luYyBkZWNyZW1lbnQob3JnSWQ6IHN0cmluZywgcXVvdGFUeXBlOiBRdW90YVR5cGUsIGF1dGhIZWFkZXI6IHN0cmluZywgYW1vdW50OiBudW1iZXIgPSAxLCByZXNldEF0U25hcHNob3Q/OiBzdHJpbmcsIGF0dHJpYnV0aW9uPzogUXVvdGFVc2FnZUF0dHJpYnV0aW9uKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICBjb25zdCBwYXRoID0gYC9xdW90YXMvJHtlbmNvZGVVUklDb21wb25lbnQob3JnSWQpfS9kZWNyZW1lbnRgO1xuICAgICAgY29uc3QgYXR0ciA9IHJlc29sdmVBdHRyaWJ1dGlvbihhdHRyaWJ1dGlvbik7XG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGNsaWVudFxuICAgICAgICAucG9zdChwYXRoLCB7IHF1b3RhVHlwZSwgYW1vdW50LCAuLi4ocmVzZXRBdFNuYXBzaG90ICYmIHsgcmVzZXRBdFNuYXBzaG90IH0pLCAuLi4oYXR0ciAmJiB7IGF0dHJpYnV0aW9uOiBhdHRyIH0pIH0sIHsgaGVhZGVyczogYnVpbGRIZWFkZXJzKG9yZ0lkLCBhdXRoSGVhZGVyLCBhdHRyPy5yZXF1ZXN0SWQpLCAuLi5RVU9UQV9SRVFVRVNUX09QVElPTlMgfSk7XG5cbiAgICAgIGlmICghcmVzcG9uc2UgfHwgcmVzcG9uc2Uuc3RhdHVzQ29kZSAhPT0gMjAwKSB7XG4gICAgICAgIC8vIFJvbGxiYWNrIGZhaWx1cmUgaXMgbG9nZ2VkIGJ1dCBuZXZlciBwcm9wYWdhdGVkICB0aGUgYWN0aW9uJ3Mgb3duXG4gICAgICAgIC8vIGZhaWx1cmUgaGFzIGFscmVhZHkgYmVlbiBzdXJmYWNlZCB0byB0aGUgY2FsbGVyOyBhIHN0dWNrIGNvdW50ZXJcbiAgICAgICAgLy8gcmVzb2x2ZXMgb24gdGhlIG5leHQgcGVyaW9kIHJlc2V0LlxuICAgICAgICBsb2dnZXIud2FybignRmFpbGVkIHRvIGRlY3JlbWVudCBxdW90YSAoc2xvdCB3aWxsIHJlc2V0IG9uIG5leHQgcGVyaW9kKScsIHtcbiAgICAgICAgICBvcmdJZCwgcXVvdGFUeXBlLCBhbW91bnQsIHN0YXR1c0NvZGU6IHJlc3BvbnNlPy5zdGF0dXNDb2RlLFxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZygnUXVvdGEgZGVjcmVtZW50ZWQnLCB7IG9yZ0lkLCBxdW90YVR5cGUsIGFtb3VudCB9KTtcbiAgICAgIH1cbiAgICB9LFxuXG4gICAgYXN5bmMgcmVwb3J0VXNhZ2Uob3JnSWQ6IHN0cmluZywgcXVvdGFUeXBlOiBRdW90YVR5cGUsIGF1dGhIZWFkZXI6IHN0cmluZywgdG9rZW5zOiBRdW90YVRva2VuVXNhZ2UsIGF0dHJpYnV0aW9uPzogUXVvdGFVc2FnZUF0dHJpYnV0aW9uKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICBjb25zdCB0b2tlbnNJbiA9IE1hdGgubWF4KDAsIE1hdGguZmxvb3IodG9rZW5zLnRva2Vuc0luIHx8IDApKTtcbiAgICAgIGNvbnN0IHRva2Vuc091dCA9IE1hdGgubWF4KDAsIE1hdGguZmxvb3IodG9rZW5zLnRva2Vuc091dCB8fCAwKSk7XG4gICAgICBjb25zdCBhdHRyID0gcmVzb2x2ZUF0dHJpYnV0aW9uKGF0dHJpYnV0aW9uKTtcbiAgICAgIC8vIE5vdGhpbmcgdG8gc2F5OiBubyB0b2tlbnMgYW5kIG5vIGF0dHJpYnV0aW9uIHRvIG1ha2UgYSB6ZXJvIHJvdyB1c2VmdWwuXG4gICAgICBpZiAodG9rZW5zSW4gPT09IDAgJiYgdG9rZW5zT3V0ID09PSAwICYmICFhdHRyKSByZXR1cm47XG4gICAgICBjb25zdCBwYXRoID0gYC9xdW90YXMvJHtlbmNvZGVVUklDb21wb25lbnQob3JnSWQpfS9pbmNyZW1lbnRgO1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBjbGllbnQucG9zdChcbiAgICAgICAgICBwYXRoLFxuICAgICAgICAgIHsgcXVvdGFUeXBlLCByZXBvcnQ6IHRydWUsIHRva2Vuc0luLCB0b2tlbnNPdXQsIC4uLihhdHRyICYmIHsgYXR0cmlidXRpb246IGF0dHIgfSkgfSxcbiAgICAgICAgICB7IGhlYWRlcnM6IGJ1aWxkSGVhZGVycyhvcmdJZCwgYXV0aEhlYWRlciwgYXR0cj8ucmVxdWVzdElkKSwgLi4uUVVPVEFfUkVRVUVTVF9PUFRJT05TIH0sXG4gICAgICAgICk7XG4gICAgICAgIGlmICghcmVzcG9uc2UgfHwgcmVzcG9uc2Uuc3RhdHVzQ29kZSAhPT0gMjAwKSB7XG4gICAgICAgICAgbG9nZ2VyLndhcm4oJ0ZhaWxlZCB0byByZXBvcnQgQUkgdXNhZ2UnLCB7IG9yZ0lkLCBxdW90YVR5cGUsIHN0YXR1c0NvZGU6IHJlc3BvbnNlPy5zdGF0dXNDb2RlIH0pO1xuICAgICAgICAgIGVtaXRDb3VudGVyKCdxdW90YV91c2FnZV9yZXBvcnRfZmFpbHVyZXNfdG90YWwnLCB7IHJlYXNvbjogcmVzcG9uc2UgPyAnbm9uLW9rJyA6ICd1bnJlYWNoYWJsZScsIHF1b3RhVHlwZSB9KTtcbiAgICAgICAgfVxuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGxvZ2dlci53YXJuKCdGYWlsZWQgdG8gcmVwb3J0IEFJIHVzYWdlJywgeyBvcmdJZCwgcXVvdGFUeXBlLCBlcnJvcjogZXJyb3JNZXNzYWdlKGVycikgfSk7XG4gICAgICAgIGVtaXRDb3VudGVyKCdxdW90YV91c2FnZV9yZXBvcnRfZmFpbHVyZXNfdG90YWwnLCB7IHJlYXNvbjogJ2V4Y2VwdGlvbicsIHF1b3RhVHlwZSB9KTtcbiAgICAgIH1cbiAgICB9LFxuXG4gICAgYXN5bmMgZ2V0VGllcihvcmdJZDogc3RyaW5nLCBhdXRoSGVhZGVyOiBzdHJpbmcsIHJlcXVlc3RJZD86IHN0cmluZyk6IFByb21pc2U8UXVvdGFUaWVyPiB7XG4gICAgICBjb25zdCBrbm93biA9IGNvbnN0YW50VGllckZvcihvcmdJZCk7XG4gICAgICBpZiAoa25vd24pIHJldHVybiBrbm93bjtcbiAgICAgIGNvbnN0IHJlYWQgPSBhd2FpdCByZWFkVGllcihvcmdJZCwgYXV0aEhlYWRlciwgcmVxdWVzdElkKTtcbiAgICAgIGlmIChyZWFkLnRpZXIpIHJldHVybiByZWFkLnRpZXI7XG4gICAgICBsb2dnZXIud2FybihgUVVPVEFfRkFJTF9PUEVOOiB0aWVyIGxvb2t1cCBmYWlsZWQsIGRlZmF1bHRpbmcgdG8gJHtERUZBVUxUX1RJRVJ9IHRpZXJgLCB7XG4gICAgICAgIG9yZ0lkLCBzdGF0dXNDb2RlOiByZWFkLnN0YXR1c0NvZGUsIHJlYXNvbjogcmVhZC5yZWFzb24sIGRlZmF1bHRUaWVyOiBERUZBVUxUX1RJRVIsXG4gICAgICB9KTtcbiAgICAgIGVtaXRDb3VudGVyKCdxdW90YV9mYWlsX29wZW5fdG90YWwnLCB7IG9wZXJhdGlvbjogJ3RpZXInLCByZWFzb246IHJlYWQucmVhc29uLCBxdW90YVR5cGU6ICd0aWVyJyB9KTtcbiAgICAgIHJldHVybiBERUZBVUxUX1RJRVI7XG4gICAgfSxcblxuICAgIGFzeW5jIGdldFRpZXJTdHJpY3Qob3JnSWQ6IHN0cmluZywgYXV0aEhlYWRlcjogc3RyaW5nLCByZXF1ZXN0SWQ/OiBzdHJpbmcpOiBQcm9taXNlPFF1b3RhVGllciB8IG51bGw+IHtcbiAgICAgIGNvbnN0IGtub3duID0gY29uc3RhbnRUaWVyRm9yKG9yZ0lkKTtcbiAgICAgIGlmIChrbm93bikgcmV0dXJuIGtub3duO1xuICAgICAgY29uc3QgcmVhZCA9IGF3YWl0IHJlYWRUaWVyKG9yZ0lkLCBhdXRoSGVhZGVyLCByZXF1ZXN0SWQpO1xuICAgICAgaWYgKHJlYWQudGllcikgcmV0dXJuIHJlYWQudGllcjtcbiAgICAgIGxvZ2dlci53YXJuKCdRVU9UQV9GQUlMX0NMT1NFRDogdGllciBjb3VsZCBub3QgYmUgY29uZmlybWVkJywgeyBvcmdJZCwgc3RhdHVzQ29kZTogcmVhZC5zdGF0dXNDb2RlLCByZWFzb246IHJlYWQucmVhc29uIH0pO1xuICAgICAgZW1pdENvdW50ZXIoJ3F1b3RhX2ZhaWxfY2xvc2VkX3RvdGFsJywgeyBvcGVyYXRpb246ICd0aWVyJywgcmVhc29uOiByZWFkLnJlYXNvbiwgcXVvdGFUeXBlOiAndGllcicgfSk7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9LFxuICB9O1xufVxuXG4vKipcbiAqIFRoZSBzeXN0ZW0gb3JnJ3MgdGllciBpcyBhIENPTlNUQU5ULCBub3QgYSBiaWxsaW5nIGZhY3QsIHNvIGl0IGlzIGFuc3dlcmVkXG4gKiB3aXRob3V0IGEgbG9va3VwLlxuICpcbiAqIFRoZSBwbGF0Zm9ybSdzIG93biBvcmcgaXMgYWx3YXlzIGB1bmxpbWl0ZWRgIChwbGF0Zm9ybS9zcmMvc2VydmljZXMvXG4gKiBhdXRoLXNlcnZpY2UudHMgc2VlZHMgaXQgdGhhdCB3YXkpOiBub3RoaW5nIG1ldGVycyBpdCBhbmQgaXQgaXMgbmV2ZXIgc29sZC5cbiAqIEFza2luZyB0aGUgcXVvdGEgc2VydmljZSB3YXMgdGhlcmVmb3JlIGEgbmV0d29yayBob3Agd2hvc2Ugb25seSBwb3NzaWJsZVxuICogb3V0Y29tZXMgd2VyZSB0aGUgYW5zd2VyIHdlIGFscmVhZHkga25ldywgb3IgYSBmYWlsdXJlLlxuICpcbiAqIFRoZSBmYWlsdXJlIGlzIHdoYXQgbWFkZSB0aGlzIHdvcnRoIGZpeGluZy4gYGdldFRpZXJgIGZhaWxzIE9QRU4gdG9cbiAqIERFRkFVTFRfVElFUiwgd2hpY2ggd2l0aCBiaWxsaW5nIGVuYWJsZWQgaXMgYGRldmVsb3BlcmAg4oCUIHRoZSBtb3N0XG4gKiBjb25zdHJhaW5lZCB0aWVyIOKAlCBhbmQgaXRzIGRvY3VtZW50ZWQgam9iIGlzIGJ1aWxkLXF1ZXVlIHBhcnRpdGlvbmluZy4gQVxuICogYmxpcCBpbiB0aGUgcXVvdGEgc2VydmljZSB0aGVyZWZvcmUgcm91dGVkIHRoZSBTWVNURU0gb3JnJ3MgYnVpbGRzIG9udG8gdGhlXG4gKiBkZXZlbG9wZXIgcXVldWU7IHRoZSBPZmZpY2lhbCBjYXRhbG9nIGxvYWQgaXMgMTE5IG9mIHRoZW0uIGBnZXRUaWVyU3RyaWN0YFxuICogZmFpbHMgQ0xPU0VEIHRvIG51bGwsIHNvIGEgc3dlZXAgdGhhdCBtdXN0IG5vdCBndWVzcyB3b3VsZCBza2lwIHRoZVxuICogcGxhdGZvcm0ncyBvd24gb3JnIGluc3RlYWQuXG4gKi9cbmZ1bmN0aW9uIGNvbnN0YW50VGllckZvcihvcmdJZDogc3RyaW5nKTogUXVvdGFUaWVyIHwgbnVsbCB7XG4gIHJldHVybiBvcmdJZC50b0xvd2VyQ2FzZSgpID09PSBTWVNURU1fT1JHX0lEID8gJ3VubGltaXRlZCcgOiBudWxsO1xufVxuXG4vKipcbiAqIEZpcmUtYW5kLWZvcmdldCBxdW90YSBNRVRFUklORyBpbmNyZW1lbnQuXG4gKlxuICogQnVmZmVyZWQ6IHRoZSB1bml0IGpvaW5zIHRoZSBwb2QncyBwZXItKG9yZywgdHlwZSkgYWdncmVnYXRlIGFuZCBpcyBzZW50IHdpdGhcbiAqIHRoZSBuZXh0IGZsdXNoIChgUVVPVEFfSU5DUkVNRU5UX0ZMVVNIX01TYCwgc2VlIHF1b3RhLWluY3JlbWVudC1iYXRjaGVyLnRzKVxuICogYXMgb25lIG1ldGVyZWQgaW5jcmVtZW50IOKAlCBwYXJ0aWFsIGFkbWlzc2lvbiBhZ2FpbnN0IHRoZSBjYXAsIHRoZSBleGNlc3NcbiAqIHJlY29yZGVkIGFzIGBvdmVyc2hvb3RgLiBUaGUgY291bnRlciB0aGVyZWZvcmUgbGFncyBieSBhdCBtb3N0IG9uZSBmbHVzaFxuICogaW50ZXJ2YWwuIE9ubHkgdGhlIHJlcXVlc3QgbWV0ZXIgdXNlcyB0aGlzOyByZXNlcnZhdGlvbnMgc3RheSBzeW5jaHJvbm91cy5cbiAqXG4gKiBBdXRoZW50aWNhdGVzIGFzIHRoZSBjYWxsaW5nIFNFUlZJQ0UgKHtAbGluayBnZXRRdW90YVNlcnZpY2VBdXRoSGVhZGVyfSksIG5ldmVyXG4gKiB3aXRoIHRoZSBlbmQgdXNlcidzIHRva2VuOiBgL3F1b3Rhcy86b3JnSWQvaW5jcmVtZW50YCBpcyBzZXJ2aWNlLXByaW5jaXBhbFxuICogb25seSwgc28gYSBmb3J3YXJkZWQgdXNlciBKV1Qgd2FzIGFsd2F5cyByZWplY3RlZCAoNDAzKSBhbmQgdGhlIG1ldGVyZWQgcXVvdGFcbiAqIChlLmcuIGBhcGlDYWxsc2AsIGFuZCB0aGUgYGFwaV9wYWNrYCBidW5kbGUgcmFpc2luZyBpdCkgbmV2ZXIgbW92ZWQuXG4gKlxuICogQHBhcmFtIHF1b3RhU2VydmljZSAtIFF1b3RhIHNlcnZpY2UgY2xpZW50XG4gKiBAcGFyYW0gb3JnSWQgLSBPcmdhbml6YXRpb24gSUQgd2hvc2UgY291bnRlciBpcyBpbmNyZW1lbnRlZFxuICogQHBhcmFtIHF1b3RhVHlwZSAtIFF1b3RhIHR5cGUgdG8gaW5jcmVtZW50XG4gKiBAcGFyYW0gbG9nV2FybiAtIExvZ2dpbmcgZnVuY3Rpb24gZm9yIHdhcm5pbmdzXG4gKiBAcGFyYW0gYXR0cmlidXRpb24gLSBXaG8gc3BlbnQgdGhlIHVuaXQgKGRlZmF1bHRzIHRvIHRoZSBhbWJpZW50IHJlcXVlc3QgY29udGV4dClcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGluY3JlbWVudFF1b3RhKCBxdW90YVNlcnZpY2U6IFF1b3RhU2VydmljZSxcbiAgb3JnSWQ6IHN0cmluZyxcbiAgcXVvdGFUeXBlOiBRdW90YVR5cGUsXG4gIGxvZ1dhcm46IChtZXNzYWdlOiBzdHJpbmcsIGRhdGE/OiB1bmtub3duKSA9PiB2b2lkLFxuICBhdHRyaWJ1dGlvbj86IFF1b3RhVXNhZ2VBdHRyaWJ1dGlvbixcbik6IHZvaWQge1xuICB0cnkge1xuICAgIGNvbnN0IGJhdGNoZXIgPSBiYXRjaGVyRm9yKHF1b3RhU2VydmljZSwgYXN5bmMgKG9yZywgdHlwZSwgZ3JvdXBzKSA9PiB7XG4gICAgICBhd2FpdCBxdW90YVNlcnZpY2UuaW5jcmVtZW50TWV0ZXJlZChvcmcsIHR5cGUsIGdldFF1b3RhU2VydmljZUF1dGhIZWFkZXIob3JnKSwgZ3JvdXBzKTtcbiAgICB9KTtcbiAgICBiYXRjaGVyLmFkZChvcmdJZCwgcXVvdGFUeXBlLCByZXNvbHZlQXR0cmlidXRpb24oYXR0cmlidXRpb24pKTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgbG9nV2FybignUXVvdGEgaW5jcmVtZW50IGZhaWxlZCcsIHsgZXJyb3I6IGVycm9yTWVzc2FnZShlcnIpIH0pO1xuICAgIGVtaXRDb3VudGVyKCdxdW90YV9pbmNyZW1lbnRfZmFpbHVyZXNfdG90YWwnLCB7IHJlYXNvbjogJ2V4Y2VwdGlvbicsIHF1b3RhVHlwZSB9KTtcbiAgfVxufVxuXG4vKipcbiAqIEF0b21pYyByZXNlcnZlIGhlbHBlciBmb3IgdGhlIFwicmVzZXJ2ZSArIGNvbW1pdCAvIHJvbGxiYWNrXCIgcGF0dGVybi5cbiAqIFVzZSBmb3IgZXhwZW5zaXZlIHJlc291cmNlcyAocGlwZWxpbmVzLCBwbHVnaW5zLCBBSSBjYWxscykgd2hlcmUgdGhlXG4gKiBmaXJlLWFuZC1mb3JnZXQgcG9zdC1ob2MgYGluY3JlbWVudFF1b3RhYCBhbGxvd3MgY29uY3VycmVudCBvdmVyLXNwZW5kLlxuICpcbiAqIFJldHVybnMgdGhlIHN0cnVjdHVyZWQgcmVzdWx0IHNvIHRoZSBjYWxsZXIgY2FuIGRlY2lkZSB3aGV0aGVyIHRvIHJ1blxuICogdGhlIGdhdGVkIGFjdGlvbiBvciA0MjkgdGhlIGNsaWVudC5cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHlwZXNjcmlwdFxuICogY29uc3QgcmVzZXJ2YXRpb24gPSBhd2FpdCByZXNlcnZlUXVvdGEocXVvdGFTZXJ2aWNlLCBvcmdJZCwgJ3BpcGVsaW5lcycsIGF1dGhIZWFkZXIpO1xuICogaWYgKHJlc2VydmF0aW9uLmV4Y2VlZGVkKSByZXR1cm4gc2VuZFF1b3RhUmVzZXJ2ZURlbmllZChyZXMsICdwaXBlbGluZXMnLCByZXNlcnZhdGlvbik7XG4gKiB0cnkge1xuICogYXdhaXQgZG9FeHBlbnNpdmVUaGluZygpO1xuICogfSBjYXRjaCAoZXJyKSB7XG4gKiAvLyBQYXNzIHRoZSByZXNlcnZlZCByZXNldEF0IHNvIGEgcGVyaW9kIHJvbGxvdmVyIGRvZXNuJ3QgZ2V0IGRvdWJsZS1jaGFyZ2VkLlxuICogZGVjcmVtZW50UXVvdGEocXVvdGFTZXJ2aWNlLCBvcmdJZCwgJ3BpcGVsaW5lcycsIGF1dGhIZWFkZXIsIGxvZ1dhcm4sIDEsIHJlc2VydmF0aW9uLnF1b3RhLnJlc2V0QXQpO1xuICogdGhyb3cgZXJyO1xuICogfVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNlcnZlUXVvdGEoIHF1b3RhU2VydmljZTogUXVvdGFTZXJ2aWNlLFxuICBvcmdJZDogc3RyaW5nLFxuICBxdW90YVR5cGU6IFF1b3RhVHlwZSxcbiAgYXV0aEhlYWRlcjogc3RyaW5nLFxuICBhbW91bnQ6IG51bWJlciA9IDEsXG4gIGF0dHJpYnV0aW9uPzogUXVvdGFVc2FnZUF0dHJpYnV0aW9uLFxuKTogUHJvbWlzZTxRdW90YVJlc2VydmVSZXN1bHQ+IHtcbiAgcmV0dXJuIHF1b3RhU2VydmljZS5yZXNlcnZlKG9yZ0lkLCBxdW90YVR5cGUsIGF1dGhIZWFkZXIsIGFtb3VudCwgYXR0cmlidXRpb24pO1xufVxuXG4vKiogU2Vjb25kcyBhIGNsaWVudCBzaG91bGQgd2FpdCBiZWZvcmUgcmV0cnlpbmcgd2hlbiBxdW90YSBjb3VsZG4ndCBiZSBjb25maXJtZWQuICovXG5jb25zdCBRVU9UQV9VTkFWQUlMQUJMRV9SRVRSWV9BRlRFUl9TRUNPTkRTID0gNTtcblxuLyoqXG4gKiBBbnN3ZXIgYSBERU5JRUQgcmVzZXJ2YXRpb24gKGByZXNlcnZhdGlvbi5leGNlZWRlZCA9PT0gdHJ1ZWApLlxuICpcbiAqIC0gYHVuYXZhaWxhYmxlYCAodGhlIHF1b3RhIHNlcnZpY2UgY291bGRuJ3QgY29uZmlybSB0aGUgc2xvdCkg4oaSICoqNTAzKipcbiAqICAgYFNFUlZJQ0VfVU5BVkFJTEFCTEVgIHdpdGggYSBzaG9ydCBgUmV0cnktQWZ0ZXJgOiB0aGUgb3JnIGlzIG5vdCBvdmVyIGl0c1xuICogICBsaW1pdCwgc28gYSA0MjkgXCJxdW90YSBleGNlZWRlZFwiIHdvdWxkIHNlbmQgdXNlcnMgdG8gdXBncmFkZSBmb3IgYW4gb3V0YWdlLlxuICogLSBvdGhlcndpc2Ug4oaSIHRoZSBzdGFuZGFyZCA0MjkgYFFVT1RBX0VYQ0VFREVEYCB3aXRoIHRoZSBYLVF1b3RhLSogaGVhZGVycy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNlbmRRdW90YVJlc2VydmVEZW5pZWQocmVzOiBSZXNwb25zZSwgcXVvdGFUeXBlOiBRdW90YVR5cGUsIHJlc2VydmF0aW9uOiBRdW90YVJlc2VydmVSZXN1bHQpOiB2b2lkIHtcbiAgaWYgKHJlc2VydmF0aW9uLmNvZGUpIHtcbiAgICAvLyBBbiBvcHRpb25hbCBvcmcgQUkgY29udHJvbCAocGVyLW1lbWJlciBzaGFyZSAvIHRva2VuIGJ1ZGdldCk6IGl0cyBvd25cbiAgICAvLyBjb2RlLCBzbyB0aGUgY2xpZW50IGNhbiBzYXkgXCJ5b3VyIHNoYXJlXCIgcmF0aGVyIHRoYW4gXCJ0aGUgb3JnIGlzIG91dFwiLlxuICAgIGNvbnN0IHJlc2V0QXQgPSByZXNlcnZhdGlvbi5xdW90YS5yZXNldEF0O1xuICAgIGlmICghcmVzLmhlYWRlcnNTZW50ICYmIHJlc2V0QXQpIHtcbiAgICAgIHJlcy5zZXRIZWFkZXIoJ1JldHJ5LUFmdGVyJywgTWF0aC5tYXgoMCwgTWF0aC5jZWlsKChuZXcgRGF0ZShyZXNldEF0KS5nZXRUaW1lKCkgLSBEYXRlLm5vdygpKSAvIDEwMDApKSk7XG4gICAgfVxuICAgIGVtaXRDb3VudGVyKCdxdW90YV9kZW5pZWRfdG90YWwnLCB7IHR5cGU6IHF1b3RhVHlwZSB9KTtcbiAgICBzZW5kRXJyb3IoXG4gICAgICByZXMsXG4gICAgICA0MjksXG4gICAgICByZXNlcnZhdGlvbi5tZXNzYWdlID8/IGBZb3VyIG9yZ2FuaXphdGlvbidzICR7cXVvdGFUeXBlfSBsaW1pdCBmb3IgdGhpcyBwZXJpb2QgaGFzIGJlZW4gcmVhY2hlZC5gLFxuICAgICAgcmVzZXJ2YXRpb24uY29kZSxcbiAgICAgIHsgcXVvdGE6IHJlc2VydmF0aW9uLnF1b3RhLCBxdW90YVR5cGUsIC4uLihyZXNldEF0ID8geyByZXNldEF0IH0gOiB7fSkgfSxcbiAgICApO1xuICAgIHJldHVybjtcbiAgfVxuICBpZiAocmVzZXJ2YXRpb24udW5hdmFpbGFibGUpIHtcbiAgICBpZiAoIXJlcy5oZWFkZXJzU2VudCkgcmVzLnNldEhlYWRlcignUmV0cnktQWZ0ZXInLCBRVU9UQV9VTkFWQUlMQUJMRV9SRVRSWV9BRlRFUl9TRUNPTkRTKTtcbiAgICBzZW5kRXJyb3IoXG4gICAgICByZXMsXG4gICAgICA1MDMsXG4gICAgICBgVW5hYmxlIHRvIGNvbmZpcm0gJHtxdW90YVR5cGV9IHF1b3RhIHJpZ2h0IG5vdy4gUGxlYXNlIHRyeSBhZ2FpbiBzaG9ydGx5LmAsXG4gICAgICBFcnJvckNvZGUuU0VSVklDRV9VTkFWQUlMQUJMRSxcbiAgICApO1xuICAgIHJldHVybjtcbiAgfVxuICBzZW5kUXVvdGFFeGNlZWRlZChyZXMsIHF1b3RhVHlwZSwgcmVzZXJ2YXRpb24ucXVvdGEsIHJlc2VydmF0aW9uLnF1b3RhLnJlc2V0QXQpO1xufVxuXG4vKipcbiAqIEZpcmUtYW5kLWZvcmdldCByb2xsYmFjayBmb3IgYSBwcmV2aW91c2x5IHJlc2VydmVkIHF1b3RhIHNsb3QuXG4gKiBMb2dzIG9uIGZhaWx1cmUgYnV0IG5ldmVyIHRocm93cyAgdGhlIGFjdGlvbiB0aGF0IG5lZWRlZCB0aGUgcm9sbGJhY2tcbiAqIGhhcyBhbHJlYWR5IGZhaWxlZCwgbm8gcG9pbnQgY29tcG91bmRpbmcgdGhlIGVycm9yLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZGVjcmVtZW50UXVvdGEoIHF1b3RhU2VydmljZTogUXVvdGFTZXJ2aWNlLFxuICBvcmdJZDogc3RyaW5nLFxuICBxdW90YVR5cGU6IFF1b3RhVHlwZSxcbiAgYXV0aEhlYWRlcjogc3RyaW5nLFxuICBsb2dXYXJuOiAobWVzc2FnZTogc3RyaW5nLCBkYXRhPzogdW5rbm93bikgPT4gdm9pZCxcbiAgYW1vdW50OiBudW1iZXIgPSAxLFxuICByZXNldEF0U25hcHNob3Q/OiBzdHJpbmcsXG4gIGF0dHJpYnV0aW9uPzogUXVvdGFVc2FnZUF0dHJpYnV0aW9uLFxuKTogdm9pZCB7XG4gIGNvbnN0IHNlbnQgPSBhdHRyaWJ1dGlvblxuICAgID8gcXVvdGFTZXJ2aWNlLmRlY3JlbWVudChvcmdJZCwgcXVvdGFUeXBlLCBhdXRoSGVhZGVyLCBhbW91bnQsIHJlc2V0QXRTbmFwc2hvdCwgYXR0cmlidXRpb24pXG4gICAgOiBxdW90YVNlcnZpY2UuZGVjcmVtZW50KG9yZ0lkLCBxdW90YVR5cGUsIGF1dGhIZWFkZXIsIGFtb3VudCwgcmVzZXRBdFNuYXBzaG90KTtcbiAgc2VudC5jYXRjaCgoZXJyOiB1bmtub3duKSA9PlxuICAgIGxvZ1dhcm4oJ1F1b3RhIHJvbGxiYWNrIGZhaWxlZCcsIHsgZXJyb3I6IGVycm9yTWVzc2FnZShlcnIpIH0pLFxuICApO1xufVxuIl19
|