@vcd/sdk 17.0.3 → 19.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,608 +0,0 @@
1
- import { Injectable, Optional } from '@angular/core';
2
- import { HttpHeaders } from '@angular/common/http';
3
- import { BehaviorSubject, merge, of, ReplaySubject, throwError } from 'rxjs';
4
- import { catchError, concatMap, filter, map, share, skipWhile, switchMap, tap, withLatestFrom } from 'rxjs/operators';
5
- import { TaskType } from '@vcd/bindings/vcloud/api/rest/schema_v1_5';
6
- import { API_ROOT_URL, AuthTokenHolderService, SESSION_ORG_ID, SESSION_SCOPE } from '../../common/container-hooks';
7
- import { VcdTransferClient } from './vcd.transfer.client';
8
- import { HTTP_HEADERS } from './constants';
9
- import { ClientError, ClientErrorType } from "./types";
10
- import * as i0 from "@angular/core";
11
- import * as i1 from "./vcd.http.client";
12
- import * as i2 from "../../core/plugin.module";
13
- export const TRANSFER_LINK_REL = 'upload:default';
14
- export const HATEOAS_HEADER = 'Link';
15
- // tslint:disable:variable-name
16
- /**
17
- * Parse out Link headers using a very lazily implemented pull parser
18
- * @param header '<url1>;name1="value1",name2="value2",<url2>;name3="value3,value4"'
19
- * @returns parsed link headers
20
- */
21
- export function parseHeaderHateoasLinks(header) {
22
- const results = [];
23
- if (!header) {
24
- return results;
25
- }
26
- const headerFieldMappings = {
27
- href: 'href',
28
- model: 'type',
29
- title: 'id',
30
- rel: 'rel'
31
- };
32
- let tokenIndex = -1;
33
- function peek(token) {
34
- return header.indexOf(token, tokenIndex + 1);
35
- }
36
- function next(token) {
37
- const nextIndex = peek(token);
38
- if (nextIndex === -1) {
39
- throw new Error(JSON.stringify({ header, token, tokenIndex }));
40
- }
41
- tokenIndex = nextIndex;
42
- return tokenIndex;
43
- }
44
- while (peek('<') > -1) {
45
- try {
46
- const hrefStart = next('<');
47
- const hrefEnd = next('>');
48
- const href = header.substring(hrefStart + 1, hrefEnd);
49
- const result = { href, type: null, id: null, rel: null, vCloudExtension: [] };
50
- let comma = peek(',');
51
- let semicolon = peek(';');
52
- while ((semicolon > -1 && comma > -1 && semicolon < comma) || (semicolon > -1 && comma === -1)) {
53
- const nameStart = next(';');
54
- const nameEnd = next('=');
55
- const name = header.substring(nameStart + 1, nameEnd).trim().toLowerCase();
56
- const valueStart = next('"');
57
- const valueEnd = next('"');
58
- const value = header.substring(valueStart + 1, valueEnd);
59
- const mappedName = headerFieldMappings[name];
60
- if (mappedName) {
61
- // @ts-ignore
62
- result[mappedName] = decodeURIComponent(value);
63
- }
64
- comma = peek(',');
65
- semicolon = peek(';');
66
- }
67
- results.push(result);
68
- }
69
- catch (error) { // We will try the next one...
70
- console.log(error);
71
- }
72
- }
73
- return results;
74
- }
75
- export var LinkRelType;
76
- (function (LinkRelType) {
77
- LinkRelType["add"] = "add";
78
- LinkRelType["remove"] = "remove";
79
- LinkRelType["edit"] = "edit";
80
- })(LinkRelType || (LinkRelType = {}));
81
- /**
82
- * A basic client for interacting with the VMware Cloud Director APIs.
83
- *
84
- * A VMware Cloud Director plugin can get a reference to this client by using angular injection.
85
- * ```
86
- * constructor(private vcdApi: VcdApiClient) {}
87
- * ```
88
- *
89
- * VcdApiClient reuses the authentication from the VCD platform so in general there is
90
- * no need of an explicit authentication/login.
91
- *
92
- * When dealing with the session management there are two APIs:
93
- * 1. Deprecated legacy API that is using the `api/session` endpoint and the corresponding models
94
- * 2. Newly added API that is using the `cloudapi` endpoint and the corresponding models
95
- *
96
- * Note that if a plugin performs an explicit cloud api authentication call through
97
- * {@link VcdApiClient#setCloudApiAuthentication} or {@link VcdApiClient#cloudApiLogin}
98
- * from that moment on the VcdApiClient uses only cloud api session management.
99
- * This means calls to {@link VcdApiClient#setAuthentication} or {@link VcdApiClient#login} have no effect.
100
- */
101
- export class VcdApiClient {
102
- set baseUrl(_baseUrl) {
103
- this._baseUrl = _baseUrl;
104
- }
105
- get version() {
106
- return this.http.requestHeadersInterceptor.version;
107
- }
108
- constructor(http, injector, config) {
109
- this.http = http;
110
- this.injector = injector;
111
- this.config = config;
112
- /**
113
- * @deprecated Use {@link VcdApiClient#_cloudApiSession}
114
- */
115
- this._session = new BehaviorSubject(null);
116
- this._sessionObservable = this._session.asObservable()
117
- .pipe(skipWhile(session => !session));
118
- /**
119
- * CloudApi Session
120
- */
121
- this._cloudApiSession = new BehaviorSubject(null);
122
- this._cloudApiSessionObservable = this._cloudApiSession.asObservable()
123
- .pipe(skipWhile(session => !session));
124
- this._cloudApiSessionLinks = new BehaviorSubject([]);
125
- /**
126
- * This property determines if it is an explicit cloud api login.
127
- * In this case the old API (/api/session) should not be used at all.
128
- */
129
- this._isCloudApiLogin = false;
130
- this._baseUrl = this.injector.get(API_ROOT_URL);
131
- let negotiatedVersion;
132
- if (this.config?.apiVersion) {
133
- negotiatedVersion = of(this.config.apiVersion).pipe(map((version) => {
134
- this.setVersion(version);
135
- return version;
136
- }));
137
- }
138
- else {
139
- negotiatedVersion = this.http.get(`${this._baseUrl}/api/versions`).pipe(map(versions => this.negotiateVersion(versions)), tap(version => this.setVersion(version)));
140
- }
141
- this._negotiateVersion = negotiatedVersion.pipe(share({ connector: () => new ReplaySubject(1), resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false }));
142
- const tokenHolder = this.injector.get(AuthTokenHolderService, { token: '' });
143
- const token = tokenHolder.jwt ? `Bearer ${tokenHolder.jwt}` : tokenHolder.token;
144
- this._getSession = this.setAuthentication(token)
145
- .pipe(share({ connector: () => new ReplaySubject(1), resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false }));
146
- this._getCloudApiSession = this.setCloudApiAuthentication(token)
147
- .pipe(share({ connector: () => new ReplaySubject(1), resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false }));
148
- // This is not an explicit cloud api login
149
- this._isCloudApiLogin = false;
150
- }
151
- negotiateVersion(serverVersions) {
152
- const supportedVersions = serverVersions.versionInfo.map(versionInfo => versionInfo.version);
153
- // Default API Version used is the Latest API Version in VMware Cloud Director
154
- return supportedVersions[supportedVersions.length - 1];
155
- }
156
- /**
157
- * The purpose of this function is to ensure that prior to sending any call to the backend
158
- * the version has been set and the current session has been retrieved.
159
- * Note that this is important during the automatic authentication that is done during the
160
- * constructor initialization, when the plugin is not required to perform its own explicit authentication
161
- * but rather the ones from the underlying framework is used.
162
- */
163
- validateRequestContext() {
164
- return (this.version ? of(this.version) : this._negotiateVersion)
165
- .pipe(
166
- // In case of a cloud api login we are not interested in the /api/session session
167
- concatMap(() => this._isCloudApiLogin ? of(null) : this._getSession), concatMap(() => this._getCloudApiSession
168
- // In case of cloud api failure we do not want to prevent further execution
169
- // for backward compatibility considerations since this may be a case
170
- // when cloud api is not supported at all for the specified version
171
- .pipe(catchError((e) => of(true)))), map(() => true));
172
- }
173
- /**
174
- *
175
- * For use cases wich solely depends on cloudapi without any backward compatibility
176
- * there should be no dependence on the old /api endpoint at all
177
- */
178
- validateRequestContextCloudApiOnly() {
179
- return (this.version ? of(this.version) : this._negotiateVersion).pipe(concatMap(() => this._getCloudApiSession));
180
- }
181
- setVersion(_version) {
182
- this.http.requestHeadersInterceptor.version = _version;
183
- return this;
184
- }
185
- /**
186
- * Global configuration for the service, that allows a provider user to execute API requests
187
- * in the scope of a specific tenant.
188
- *
189
- * If you want to execute single API request in scope of specific tenant you can do it
190
- * by passing "X-VMWARE-VCLOUD-TENANT-CONTEXT" header to the specific API Request.
191
- *
192
- * This scoping is available to query-based API calls and to bulk GET calls in the
193
- * /cloudapi space.
194
- *
195
- * @param actAs an entityRef of the tenant (organization) to scope subsequent calls to in
196
- * the VcdApiClient, or null/no parameter to remove tenant-specific scoping
197
- * @returns the current VcdApiClient instance (for chaining)
198
- */
199
- actAs(actAs = null) {
200
- this.http.requestHeadersInterceptor.actAs = !actAs ? null : actAs.id;
201
- this.http.requestHeadersInterceptor.actAsOrgName = !actAs ? null : actAs.name;
202
- return this;
203
- }
204
- /**
205
- * @deprecated Use {@link VcdApiClient#setCloudApiAuthentication}
206
- *
207
- * Sets the authentication token to use for the VcdApiClient.
208
- *
209
- * After setting the token, the client will get the current session
210
- * information associated with the authenticated token.
211
- *
212
- * @param authentication the authentication string (to be used in either the 'Authorization'
213
- * or 'x-vcloud-authorization' header)
214
- * @returns the session associated with the authentication token
215
- */
216
- setAuthentication(authentication) {
217
- if (this._isCloudApiLogin) {
218
- return throwError('Only cloud api auth is allowed since it was already used');
219
- }
220
- this.http.requestHeadersInterceptor.authentication = authentication;
221
- return this.http.get(`${this._baseUrl}/api/session`).pipe(tap(session => {
222
- // automatically set actAs for provider in tenant scope
223
- if (session.org === 'System' && this.injector.get(SESSION_SCOPE) === 'tenant') {
224
- // Automatic actAs only works in versions >=9.5
225
- try {
226
- this.actAs({ id: this.injector.get(SESSION_ORG_ID) });
227
- }
228
- catch (e) {
229
- console.warn('No SESSION_ORG_ID set in container. Automatic actAs is disabled.');
230
- }
231
- }
232
- }), tap(session => this._session.next(session)));
233
- }
234
- /**
235
- * Sets the authentication token to use for the VcdApiClient.
236
- *
237
- * After setting the token, the client will get the current session
238
- * information associated with the authenticated token.
239
- *
240
- * @param authentication the authentication string (to be used in either the 'Authorization'
241
- * or 'x-vcloud-authorization' header)
242
- *
243
- * @returns session observable associated with the authentication token
244
- */
245
- setCloudApiAuthentication(authentication) {
246
- this.onBeforeCloudApiAuthentication();
247
- return of(true)
248
- .pipe(
249
- // Set the authentication as part of the observable in order to ensure the caller has subscribed to the observable
250
- tap(() => this.http.requestHeadersInterceptor.authentication = authentication), switchMap(() => this.http.get(`${this._baseUrl}/cloudapi/1.0.0/sessions/current`, { observe: 'response' })))
251
- .pipe(this.onCloudApiAuthentication());
252
- }
253
- enableLogging() {
254
- this.http.loggingInterceptor.enabled = true;
255
- return this;
256
- }
257
- /**
258
- * @deprecated Use {@link VcdApiClient#cloudApiLogin}
259
- *
260
- * Creates an authenticated session for the specified credential data.
261
- *
262
- * @param username the name of the user to authenticate
263
- * @param tenant the organization the user belongs to
264
- * @param password the password for the user
265
- * @returns an authenticated session for the given credentials
266
- */
267
- login(username, tenant, password) {
268
- if (this._isCloudApiLogin) {
269
- return throwError('Only cloud api auth is allowed since it was already used');
270
- }
271
- const authString = btoa(`${username}@${tenant}:${password}`);
272
- return this.http.post(`${this._baseUrl}/api/sessions`, null, {
273
- observe: 'response',
274
- headers: new HttpHeaders({ Authorization: `Basic ${authString}` })
275
- })
276
- .pipe(tap((response) =>
277
- // tslint:disable-next-line:max-line-length
278
- this.http.requestHeadersInterceptor.authentication = `${response.headers.get('x-vmware-vcloud-token-type')} ${response.headers.get('x-vmware-vcloud-access-token')}`), map(response => response.body), tap(session => this._session.next(session)));
279
- }
280
- /**
281
- * Creates an authenticated session for the specified credential data using cloud api endpoint.
282
- *
283
- * @param username the name of the user to authenticate
284
- * @param tenant the organization the user belongs to
285
- * @param password the password for the user
286
- * @returns an authenticated session for the given credentials
287
- */
288
- cloudApiLogin(username, tenant, password) {
289
- this.onBeforeCloudApiAuthentication();
290
- const authString = btoa(`${username}@${tenant}:${password}`);
291
- let url = `${this._baseUrl}/cloudapi/1.0.0/sessions`;
292
- if (tenant.toLowerCase() === 'system') {
293
- url += '/provider';
294
- }
295
- return this.http.post(url, null, {
296
- observe: 'response',
297
- headers: new HttpHeaders({ [HTTP_HEADERS.Authorization]: `Basic ${authString}` })
298
- }).pipe(tap((response) => {
299
- // tslint:disable-next-line:max-line-length
300
- const token = `${response.headers.get('x-vmware-vcloud-token-type')} ${response.headers.get('x-vmware-vcloud-access-token')}`;
301
- this.http.requestHeadersInterceptor.authentication = token;
302
- }), this.onCloudApiAuthentication());
303
- }
304
- /**
305
- * It is necessary to know if an explicit cloud api auth request was done.
306
- * This function handles this by setting the corresponding flags, properties etc.
307
- */
308
- onBeforeCloudApiAuthentication() {
309
- // In case of an explicit cloud api auth request:
310
- // Set the flag _isCloudApiLogin in order to know that explicit cloud api authentication is done
311
- // This will help us skip code related to the old api, i.e. we should not allow explicit mix of both the api-s
312
- this._isCloudApiLogin = true;
313
- // In case of an explicit cloud api auth request:
314
- // There is no need of _getCloudApiSession observable which is needed in the automatic login during the constructor initialization.
315
- // The explicit cloud api auth request will retrieve the session.
316
- this._getCloudApiSession = of(null);
317
- }
318
- /**
319
- * Handle authentication.
320
- * This includes getting HATEOAS links, setting the session, handling errors etc.
321
- */
322
- onCloudApiAuthentication() {
323
- return (source) => source.pipe(tap((resp) => {
324
- // Get HATEOAS links
325
- try {
326
- this.setCloudApiSessionLinks(parseHeaderHateoasLinks(resp.headers.get(HATEOAS_HEADER)));
327
- }
328
- catch (e) {
329
- console.log('Error when parsing session HATEOAS links:', e);
330
- }
331
- }), map(resp => resp.body), tap((session) => {
332
- // Clear previous actAs
333
- this.actAs(null);
334
- // automatically set actAs for provider in tenant scope
335
- if (session.org && session.org.name === 'System' && this.injector.get(SESSION_SCOPE) === 'tenant') {
336
- // Automatic actAs only works in versions >=9.5
337
- try {
338
- this.actAs({ id: this.injector.get(SESSION_ORG_ID) });
339
- }
340
- catch (e) {
341
- console.warn('No SESSION_ORG_ID set in container. Automatic actAs is disabled.');
342
- }
343
- }
344
- }), tap((session) => this._cloudApiSession.next(session)), catchError((e) => {
345
- this.onCloudApiAuthenticationError();
346
- return throwError(e);
347
- }));
348
- }
349
- onCloudApiAuthenticationError() {
350
- // Clear the authentication so that any subsequent backend calls are not authenticated
351
- this.http.requestHeadersInterceptor.authentication = '';
352
- // _getCloudApiSession is in the center of any backend call, nullify it in order not to prevent those calls
353
- // since it is easier to troubleshoot failing backend rather than no call
354
- this._getCloudApiSession = of(null);
355
- // Clear the links
356
- this._cloudApiSessionLinks.next([]);
357
- // Clear the session
358
- this._cloudApiSession.next(null);
359
- }
360
- setCloudApiSessionLinks(links) {
361
- this._cloudApiAccessibleLocations = null;
362
- this._cloudApiSessionLinks.next(links || []);
363
- }
364
- get(endpoint, options) {
365
- return this.validateRequestContext().pipe(concatMap(() => this.http.get(this.buildEndpointUrl(endpoint), { ...options })));
366
- }
367
- list(endpoint, queryBuilder, multisite, options) {
368
- let url = this.buildEndpointUrl(endpoint);
369
- if (queryBuilder) {
370
- url = `${url}${queryBuilder.getCloudAPI()}`;
371
- }
372
- if (multisite) {
373
- if (!options) {
374
- return this.http.get(url, { headers: new HttpHeaders({ _multisite: this.parseMultisiteValue(multisite) }) });
375
- }
376
- else if (options?.headers) {
377
- options.headers.append("_multisite", this.parseMultisiteValue(multisite));
378
- return this.http.get(url, { ...options });
379
- }
380
- }
381
- return this.validateRequestContext().pipe(concatMap(() => this.http.get(url, { ...options })));
382
- }
383
- createSync(endpoint, item, options) {
384
- return this.validateRequestContext().pipe(concatMap(() => this.http.post(this.buildEndpointUrl(endpoint), item, { ...options })));
385
- }
386
- createAsync(endpoint, item, options) {
387
- return this.validateRequestContext().pipe(concatMap(() => this.http.post(this.buildEndpointUrl(endpoint), item, { ...options, observe: 'response' })), concatMap(response => this.mapResponseToTask(response, 'POST')));
388
- }
389
- getTransferLink(endpoint, item, transferRel = TRANSFER_LINK_REL) {
390
- return this.http
391
- .post(this.buildEndpointUrl(endpoint), item, { observe: 'response' })
392
- .pipe(map((res) => {
393
- const headerLinks = res.headers.has(HATEOAS_HEADER)
394
- ? parseHeaderHateoasLinks(res.headers.get(HATEOAS_HEADER))
395
- : [];
396
- const links = res.body ? (res.body.link || []) : [];
397
- const link = [...headerLinks, ...links]
398
- .find((l) => l.rel === transferRel);
399
- if (!link) {
400
- throw new ClientError(`Response from ${endpoint} did not contain a transfer link`, ClientErrorType.HateoasLinkMissing);
401
- }
402
- return link.href;
403
- }));
404
- }
405
- startTransfer(endpoint, item, transferRel = TRANSFER_LINK_REL) {
406
- return this.getTransferLink(endpoint, item, transferRel)
407
- .pipe(map((transferUrl) => new VcdTransferClient(this.http, transferUrl)));
408
- }
409
- updateSync(endpoint, item, options) {
410
- return this.validateRequestContext().pipe(concatMap(() => this.http.put(this.buildEndpointUrl(endpoint), item, { ...options })));
411
- }
412
- updateAsync(endpoint, item, options) {
413
- return this.validateRequestContext().pipe(concatMap(() => this.http.put(this.buildEndpointUrl(endpoint), item, { ...options, observe: 'response' })), concatMap(response => this.mapResponseToTask(response, 'PUT')));
414
- }
415
- deleteSync(endpoint, options) {
416
- return this.validateRequestContext().pipe(concatMap(() => this.http.delete(this.buildEndpointUrl(endpoint), { ...options })));
417
- }
418
- deleteAsync(endpoint, options) {
419
- return this.validateRequestContext().pipe(concatMap(() => this.http.delete(this.buildEndpointUrl(endpoint), { ...options, observe: 'response' })), concatMap(response => this.mapResponseToTask(response, 'DELETE')));
420
- }
421
- mapResponseToTask(response, httpVerb) {
422
- //POST - Task link is returned in 'Location' header
423
- if (response.headers.has('Location') && response.status === 202) {
424
- return this.http.get(response.headers.get('Location'));
425
- //PUT - Task link is returned in 'x-vmware-vcloud-task-location' header
426
- }
427
- else if (response.headers.has('x-vmware-vcloud-task-location') && response.status === 200) {
428
- return this.http.get(response.headers.get('x-vmware-vcloud-task-location'));
429
- }
430
- else if (response.body && response.body.type.startsWith('application/vnd.vmware.vcloud.task+')) {
431
- const task = Object.assign(new TaskType(), response.body);
432
- return of(task);
433
- }
434
- return throwError(() => new ClientError(`An asynchronous request was made to [${httpVerb} ${response.url}], but no task was returned. The operation may still have been successful.`, ClientErrorType.TaskLinkMissing));
435
- }
436
- getEntity(entityRefOrUrn) {
437
- const entityResolver = typeof entityRefOrUrn === 'string' ?
438
- this.http.get(`${this._baseUrl}/api/entity/${entityRefOrUrn}`) :
439
- this.http.get(`${this._baseUrl}/api/entity/urn:vcloud:${entityRefOrUrn.type}:${entityRefOrUrn.id}`);
440
- return this.validateRequestContext().pipe(concatMap(() => entityResolver), concatMap(entity => this.http.get(`${entity.link[0].href}`)));
441
- }
442
- updateTask(task, options) {
443
- return this.validateRequestContext().pipe(concatMap(() => this.http.get(task.href, { ...options })));
444
- }
445
- isTaskComplete(task) {
446
- return ['success', 'error', 'canceled', 'aborted'].indexOf(task.status) > -1;
447
- }
448
- removeItem(item, options) {
449
- const link = this.findLink(item, 'remove', null);
450
- if (!link) {
451
- return throwError(() => new ClientError(`No 'remove' link for specified resource.`, ClientErrorType.HateoasLinkMissing));
452
- }
453
- return this.validateRequestContext().pipe(concatMap(() => this.http.delete(link.href, { ...options })));
454
- }
455
- query(builder, multisite, options) {
456
- return this.getQueryPage(`${this._baseUrl}/api/query${builder.get()}`, multisite, options);
457
- }
458
- firstPage(result, multisite, options) {
459
- const link = this.findLink(result, 'firstPage', result.type);
460
- if (!link) {
461
- return throwError(() => new ClientError(`No 'firstPage' link for specified query.`, ClientErrorType.HateoasLinkMissing));
462
- }
463
- return this.getQueryPage(link.href, multisite, options);
464
- }
465
- hasFirstPage(result) {
466
- return !!this.findLink(result, 'firstPage', result.type);
467
- }
468
- previousPage(result, multisite, options) {
469
- const link = this.findLink(result, 'previousPage', result.type);
470
- if (!link) {
471
- return throwError(() => new ClientError(`No 'previousPage' link for specified query.`, ClientErrorType.HateoasLinkMissing));
472
- }
473
- return this.getQueryPage(link.href, multisite, options);
474
- }
475
- hasPreviousPage(result) {
476
- return !!this.findLink(result, 'previousPage', result.type);
477
- }
478
- nextPage(result, multisite, options) {
479
- const link = this.findLink(result, 'nextPage', result.type);
480
- if (!link) {
481
- return throwError(() => new ClientError(`No 'nextPage' link for specified query.`, ClientErrorType.HateoasLinkMissing));
482
- }
483
- return this.getQueryPage(link.href, multisite, options);
484
- }
485
- hasNextPage(result) {
486
- return !!this.findLink(result, 'nextPage', result.type);
487
- }
488
- lastPage(result, multisite, options) {
489
- const link = this.findLink(result, 'lastPage', result.type);
490
- if (!link) {
491
- return throwError(() => new ClientError(`No 'lastPage' link for specified query.`, ClientErrorType.HateoasLinkMissing));
492
- }
493
- return this.getQueryPage(link.href, multisite, options);
494
- }
495
- hasLastPage(result) {
496
- return !!this.findLink(result, 'lastPage', result.type);
497
- }
498
- getQueryPage(href, multisite, options) {
499
- if (multisite) {
500
- if (!options) {
501
- return this.http.get(href, { headers: new HttpHeaders({ _multisite: this.parseMultisiteValue(multisite) }) });
502
- }
503
- else if (options?.headers) {
504
- options.headers.append("_multisite", this.parseMultisiteValue(multisite));
505
- return this.http.get(href, { ...options });
506
- }
507
- }
508
- return this.validateRequestContext().pipe(concatMap(() => this.http.get(href, { ...options })));
509
- }
510
- /**
511
- * Use to perform action availability check before calling the API
512
- * @param item - the navigable item (containing link collection)
513
- * @param linkRelType - the link rel type, pass either LinkRelType or string
514
- * @param entityRefType - the entity reference type
515
- */
516
- canPerformAction(item, linkRelType, entityRefType) {
517
- return !!this.findLink(item, linkRelType, entityRefType);
518
- }
519
- findLink(item, rel, type) {
520
- if (!item || !item.link) {
521
- return undefined;
522
- }
523
- return item.link.find((link) => {
524
- if (type) {
525
- return link.rel.includes(rel) && link.type === type;
526
- }
527
- return link.rel.includes(rel);
528
- });
529
- }
530
- parseMultisiteValue(multisite) {
531
- return typeof multisite === 'boolean' ? (multisite ? 'global' : 'local') : multisite.map(site => site.locationId).join(',');
532
- }
533
- /**
534
- * @deprecated Use cloudApiSession
535
- */
536
- get session() {
537
- return this.validateRequestContext().pipe(concatMap(() => this._sessionObservable));
538
- }
539
- /**
540
- * Get Session observable
541
- */
542
- get cloudApiSession() {
543
- return this.validateRequestContextCloudApiOnly().pipe(concatMap(() => this._cloudApiSessionObservable));
544
- }
545
- get username() {
546
- return merge(this.cloudApiSession.pipe(filter(() => this._isCloudApiLogin), map(session => session && session.user && session.user.name)), this.session.pipe(filter(() => !this._isCloudApiLogin), map(session => session && session.user)));
547
- }
548
- get organization() {
549
- return merge(this.cloudApiSession.pipe(filter(() => this._isCloudApiLogin), map(session => session && session.org && session.org.name)), this.session.pipe(filter(() => !this._isCloudApiLogin), map(session => session && session.org)));
550
- }
551
- /**
552
- * @deprecated Use cloudApiLocation
553
- */
554
- get location() {
555
- return this.session.pipe(map(session => session.authorizedLocations.location.find(location => location.locationId === session.locationId)));
556
- }
557
- /**
558
- * Gets the location corresponding to the current session
559
- */
560
- get cloudApiLocation() {
561
- return this.cloudApiSession.pipe(switchMap(() => {
562
- if (!this._cloudApiAccessibleLocations) {
563
- // Ensure caching for getting AccessibleLocations
564
- this._cloudApiAccessibleLocations = this._cloudApiSessionLinks
565
- .pipe(
566
- // Get the AccessibleLocations link
567
- map((links) => this.findLink({ link: links }, 'down', 'AccessibleLocations')),
568
- // Fetch AccessibleLocations from the backend
569
- switchMap((link) => link ? this.http.get(link.href) : of(null)),
570
- // Get the array with all locations (what if there are many pages)
571
- map((accessibleLocations) => accessibleLocations && accessibleLocations.values))
572
- .pipe(share({ connector: () => new ReplaySubject(1), resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false }));
573
- }
574
- return this._cloudApiAccessibleLocations;
575
- }),
576
- // Need to have the session in order to get its location
577
- withLatestFrom(this.cloudApiSession),
578
- // Find the location that corresponds to this session
579
- map(([accessibleLocations, session]) => {
580
- if (!accessibleLocations || !session) {
581
- return null;
582
- }
583
- const sessionLocation = session.location;
584
- if (!sessionLocation) {
585
- return null;
586
- }
587
- return accessibleLocations.find(location => location.locationId === sessionLocation);
588
- }));
589
- }
590
- getLocation(session) {
591
- return session.authorizedLocations.location.find(location => location.locationId === session.locationId);
592
- }
593
- /**
594
- * Build the endpoint url. If the provided endpoint is already an absolute URL, then return it as it is without
595
- * any modifications, otherwise consider it as a relative one and prepend the baseUrl as defined by the host application.
596
- */
597
- buildEndpointUrl(endpoint) {
598
- return endpoint.indexOf('://') > -1 ? endpoint : `${this._baseUrl}/${endpoint}`;
599
- }
600
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: VcdApiClient, deps: [{ token: i1.VcdHttpClient }, { token: i0.Injector }, { token: i2.VcdSdkConfig, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
601
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: VcdApiClient }); }
602
- }
603
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.2", ngImport: i0, type: VcdApiClient, decorators: [{
604
- type: Injectable
605
- }], ctorParameters: () => [{ type: i1.VcdHttpClient }, { type: i0.Injector }, { type: i2.VcdSdkConfig, decorators: [{
606
- type: Optional
607
- }] }] });
608
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmNkLmFwaS5jbGllbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy92Y2Qvc2RrL3NyYy9jbGllbnQvY2xpZW50L3ZjZC5hcGkuY2xpZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBQyxVQUFVLEVBQVksUUFBUSxFQUFDLE1BQU0sZUFBZSxDQUFDO0FBQzdELE9BQU8sRUFBQyxXQUFXLEVBQWUsTUFBTSxzQkFBc0IsQ0FBQztBQUMvRCxPQUFPLEVBQUMsZUFBZSxFQUFFLEtBQUssRUFBYyxFQUFFLEVBQUUsYUFBYSxFQUFFLFVBQVUsRUFBQyxNQUFNLE1BQU0sQ0FBQztBQUN2RixPQUFPLEVBQUMsVUFBVSxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxjQUFjLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUNwSCxPQUFPLEVBT0wsUUFBUSxFQUNULE1BQU0sMkNBQTJDLENBQUM7QUFJbkQsT0FBTyxFQUFDLFlBQVksRUFBRSxzQkFBc0IsRUFBRSxjQUFjLEVBQUUsYUFBYSxFQUFDLE1BQU0sOEJBQThCLENBQUM7QUFFakgsT0FBTyxFQUFDLGlCQUFpQixFQUFDLE1BQU0sdUJBQXVCLENBQUM7QUFDeEQsT0FBTyxFQUFDLFlBQVksRUFBQyxNQUFNLGFBQWEsQ0FBQztBQUV6QyxPQUFPLEVBQUMsV0FBVyxFQUFFLGVBQWUsRUFBQyxNQUFNLFNBQVMsQ0FBQzs7OztBQUVyRCxNQUFNLENBQUMsTUFBTSxpQkFBaUIsR0FBRyxnQkFBZ0IsQ0FBQztBQUdsRCxNQUFNLENBQUMsTUFBTSxjQUFjLEdBQUcsTUFBTSxDQUFDO0FBRXJDLCtCQUErQjtBQUUvQjs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLHVCQUF1QixDQUFDLE1BQWM7SUFDbEQsTUFBTSxPQUFPLEdBQWUsRUFBRSxDQUFDO0lBRS9C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Q3JDLE9BQU8sUUFBUSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxRQUFRLElBQUksUUFBUSxFQUFFLENBQUM7SUFDcEYsQ0FBQzs4R0ExekJRLFlBQVk7a0hBQVosWUFBWTs7MkZBQVosWUFBWTtrQkFEeEIsVUFBVTs7MEJBeURFLFFBQVEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0luamVjdGFibGUsIEluamVjdG9yLCBPcHRpb25hbH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge0h0dHBIZWFkZXJzLCBIdHRwUmVzcG9uc2V9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcbmltcG9ydCB7QmVoYXZpb3JTdWJqZWN0LCBtZXJnZSwgT2JzZXJ2YWJsZSwgb2YsIFJlcGxheVN1YmplY3QsIHRocm93RXJyb3J9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtjYXRjaEVycm9yLCBjb25jYXRNYXAsIGZpbHRlciwgbWFwLCBzaGFyZSwgc2tpcFdoaWxlLCBzd2l0Y2hNYXAsIHRhcCwgd2l0aExhdGVzdEZyb219IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7XG4gIEF1dGhvcml6ZWRMb2NhdGlvblR5cGUsXG4gIEVudGl0eVJlZmVyZW5jZVR5cGUsXG4gIEVudGl0eVR5cGUsXG4gIExpbmtUeXBlLFxuICBSZXNvdXJjZVR5cGUsXG4gIFNlc3Npb25UeXBlLFxuICBUYXNrVHlwZVxufSBmcm9tICdAdmNkL2JpbmRpbmdzL3ZjbG91ZC9hcGkvcmVzdC9zY2hlbWFfdjFfNSc7XG5pbXBvcnQge1N1cHBvcnRlZFZlcnNpb25zVHlwZX0gZnJvbSAnQHZjZC9iaW5kaW5ncy92Y2xvdWQvYXBpL3Jlc3Qvc2NoZW1hL3ZlcnNpb25pbmcnO1xuaW1wb3J0IHtBY2Nlc3NpYmxlTG9jYXRpb24sIEFjY2Vzc2libGVMb2NhdGlvbnMsIFNlc3Npb259IGZyb20gJy4uL29wZW5hcGknO1xuaW1wb3J0IHtRdWVyeX0gZnJvbSAnLi4vcXVlcnkvaW5kZXgnO1xuaW1wb3J0IHtBUElfUk9PVF9VUkwsIEF1dGhUb2tlbkhvbGRlclNlcnZpY2UsIFNFU1NJT05fT1JHX0lELCBTRVNTSU9OX1NDT1BFfSBmcm9tICcuLi8uLi9jb21tb24vY29udGFpbmVyLWhvb2tzJztcbmltcG9ydCB7VmNkSHR0cENsaWVudH0gZnJvbSAnLi92Y2QuaHR0cC5jbGllbnQnO1xuaW1wb3J0IHtWY2RUcmFuc2ZlckNsaWVudH0gZnJvbSAnLi92Y2QudHJhbnNmZXIuY2xpZW50JztcbmltcG9ydCB7SFRUUF9IRUFERVJTfSBmcm9tICcuL2NvbnN0YW50cyc7XG5pbXBvcnQge1ZjZFNka0NvbmZpZ30gZnJvbSBcIi4uLy4uL2NvcmUvcGx1Z2luLm1vZHVsZVwiO1xuaW1wb3J0IHtDbGllbnRFcnJvciwgQ2xpZW50RXJyb3JUeXBlfSBmcm9tIFwiLi90eXBlc1wiO1xuXG5leHBvcnQgY29uc3QgVFJBTlNGRVJfTElOS19SRUwgPSAndXBsb2FkOmRlZmF1bHQnO1xuZXhwb3J0IHR5cGUgTmF2aWdhYmxlID0gUmVzb3VyY2VUeXBlIHwgeyBsaW5rPzogTGlua1R5cGVbXSB9O1xuXG5leHBvcnQgY29uc3QgSEFURU9BU19IRUFERVIgPSAnTGluayc7XG5cbi8vIHRzbGludDpkaXNhYmxlOnZhcmlhYmxlLW5hbWVcblxuLyoqXG4gKiBQYXJzZSBvdXQgTGluayBoZWFkZXJzIHVzaW5nIGEgdmVyeSBsYXppbHkgaW1wbGVtZW50ZWQgcHVsbCBwYXJzZXJcbiAqIEBwYXJhbSBoZWFkZXIgJzx1cmwxPjtuYW1lMT1cInZhbHVlMVwiLG5hbWUyPVwidmFsdWUyXCIsPHVybDI+O25hbWUzPVwidmFsdWUzLHZhbHVlNFwiJ1xuICogQHJldHVybnMgcGFyc2VkIGxpbmsgaGVhZGVyc1xuICovXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VIZWFkZXJIYXRlb2FzTGlua3MoaGVhZGVyOiBzdHJpbmcpOiBMaW5rVHlwZVtdIHtcbiAgICBjb25zdCByZXN1bHRzOiBMaW5rVHlwZVtdID0gW107XG5cbiAgICBpZiAoIWhlYWRlcikge1xuICAgICAgICByZXR1cm4gcmVzdWx0cztcbiAgICB9XG5cbiAgICBjb25zdCBoZWFkZXJGaWVsZE1hcHBpbmdzOiB7W2tleTogc3RyaW5nXToga2V5b2YgTGlua1R5cGV9ID0ge1xuICAgICAgICBocmVmOiAnaHJlZicsXG4gICAgICAgIG1vZGVsOiAndHlwZScsXG4gICAgICAgIHRpdGxlOiAnaWQnLFxuICAgICAgICByZWw6ICdyZWwnXG4gICAgfTtcbiAgICBsZXQgdG9rZW5JbmRleCA9IC0xO1xuXG4gICAgZnVuY3Rpb24gcGVlayh0b2tlbjogc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBoZWFkZXIuaW5kZXhPZih0b2tlbiwgdG9rZW5JbmRleCArIDEpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG5leHQodG9rZW46IHN0cmluZykge1xuICAgICAgICBjb25zdCBuZXh0SW5kZXggPSBwZWVrKHRva2VuKTtcbiAgICAgICAgaWYgKG5leHRJbmRleCA9PT0gLTEpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihKU09OLnN0cmluZ2lmeSh7aGVhZGVyLCB0b2tlbiwgdG9rZW5JbmRleH0pKTtcbiAgICAgICAgfVxuICAgICAgICB0b2tlbkluZGV4ID0gbmV4dEluZGV4O1xuICAgICAgICByZXR1cm4gdG9rZW5JbmRleDtcbiAgICB9XG5cbiAgICB3aGlsZSAocGVlaygnPCcpID4gLTEpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IGhyZWZTdGFydCA9IG5leHQoJzwnKTtcbiAgICAgICAgICAgIGNvbnN0IGhyZWZFbmQgPSBuZXh0KCc+Jyk7XG4gICAgICAgICAgICBjb25zdCBocmVmID0gaGVhZGVyLnN1YnN0cmluZyhocmVmU3RhcnQgKyAxLCBocmVmRW5kKTtcbiAgICAgICAgICAgIGNvbnN0IHJlc3VsdDogTGlua1R5cGUgPSB7aHJlZiwgdHlwZTogbnVsbCwgaWQ6IG51bGwsIHJlbDogbnVsbCwgdkNsb3VkRXh0ZW5zaW9uOiBbXX07XG4gICAgICAgICAgICBsZXQgY29tbWEgPSBwZWVrKCcsJyk7XG4gICAgICAgICAgICBsZXQgc2VtaWNvbG9uID0gcGVlaygnOycpO1xuICAgICAgICAgICAgd2hpbGUgKChzZW1pY29sb24gPiAtMSAmJiBjb21tYSA+IC0xICYmIHNlbWljb2xvbiA8IGNvbW1hKSB8fCAoc2VtaWNvbG9uID4gLTEgJiYgY29tbWEgPT09IC0xKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IG5hbWVTdGFydCA9IG5leHQoJzsnKTtcbiAgICAgICAgICAgICAgICBjb25zdCBuYW1lRW5kID0gbmV4dCgnPScpO1xuICAgICAgICAgICAgICAgIGNvbnN0IG5hbWUgPSBoZWFkZXIuc3Vic3RyaW5nKG5hbWVTdGFydCArIDEsIG5hbWVFbmQpLnRyaW0oKS50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlU3RhcnQgPSBuZXh0KCdcIicpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlRW5kID0gbmV4dCgnXCInKTtcbiAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZSA9IGhlYWRlci5zdWJzdHJpbmcodmFsdWVTdGFydCArIDEsIHZhbHVlRW5kKTtcbiAgICAgICAgICAgICAgICBjb25zdCBtYXBwZWROYW1lID0gaGVhZGVyRmllbGRNYXBwaW5nc1tuYW1lXTtcbiAgICAgICAgICAgICAgICBpZiAobWFwcGVkTmFtZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFttYXBwZWROYW1lXSA9IGRlY29kZVVSSUNvbXBvbmVudCh2YWx1ZSkgYXMgYW55O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb21tYSA9IHBlZWsoJywnKTtcbiAgICAgICAgICAgICAgICBzZW1pY29sb24gPSBwZWVrKCc7Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXN1bHRzLnB1c2gocmVzdWx0KTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHsgIC8vIFdlIHdpbGwgdHJ5IHRoZSBuZXh0IG9uZS4uLlxuICAgICAgICAgICAgY29uc29sZS5sb2coZXJyb3IpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdHM7XG59XG5cbmV4cG9ydCBlbnVtIExpbmtSZWxUeXBlIHtcbiAgICBhZGQgPSAnYWRkJyxcbiAgICByZW1vdmUgPSAncmVtb3ZlJyxcbiAgICBlZGl0ID0gJ2VkaXQnLFxufVxuXG4vKipcbiAqIEEgYmFzaWMgY2xpZW50IGZvciBpbnRlcmFjdGluZyB3aXRoIHRoZSBWTXdhcmUgQ2xvdWQgRGlyZWN0b3IgQVBJcy5cbiAqXG4gKiBBIFZNd2FyZSBDbG91ZCBEaXJlY3RvciBwbHVnaW4gY2FuIGdldCBhIHJlZmVyZW5jZSB0byB0aGlzIGNsaWVudCBieSB1c2luZyBhbmd1bGFyIGluamVjdGlvbi5cbiAqIGBgYFxuICogICAgIGNvbnN0cnVjdG9yKHByaXZhdGUgdmNkQXBpOiBWY2RBcGlDbGllbnQpIHt9XG4gKiBgYGBcbiAqXG4gKiBWY2RBcGlDbGllbnQgcmV1c2VzIHRoZSBhdXRoZW50aWNhdGlvbiBmcm9tIHRoZSBWQ0QgcGxhdGZvcm0gc28gaW4gZ2VuZXJhbCB0aGVyZSBpc1xuICogbm8gbmVlZCBvZiBhbiBleHBsaWNpdCBhdXRoZW50aWNhdGlvbi9sb2dpbi5cbiAqXG4gKiBXaGVuIGRlYWxpbmcgd2l0aCB0aGUgc2Vzc2lvbiBtYW5hZ2VtZW50IHRoZXJlIGFyZSB0d28gQVBJczpcbiAqIDEuIERlcHJlY2F0ZWQgbGVnYWN5IEFQSSB0aGF0IGlzIHVzaW5nIHRoZSBgYXBpL3Nlc3Npb25gIGVuZHBvaW50IGFuZCB0aGUgY29ycmVzcG9uZGluZyBtb2RlbHNcbiAqIDIuIE5ld2x5IGFkZGVkIEFQSSB0aGF0IGlzIHVzaW5nIHRoZSBgY2xvdWRhcGlgIGVuZHBvaW50IGFuZCB0aGUgY29ycmVzcG9uZGluZyBtb2RlbHNcbiAqXG4gKiBOb3RlIHRoYXQgaWYgYSBwbHVnaW4gcGVyZm9ybXMgYW4gZXhwbGljaXQgY2xvdWQgYXBpIGF1dGhlbnRpY2F0aW9uIGNhbGwgdGhyb3VnaFxuICoge0BsaW5rIFZjZEFwaUNsaWVudCNzZXRDbG91ZEFwaUF1dGhlbnRpY2F0aW9ufSBvciB7QGxpbmsgVmNkQXBpQ2xpZW50I2Nsb3VkQXBpTG9naW59XG4gKiBmcm9tIHRoYXQgbW9tZW50IG9uIHRoZSBWY2RBcGlDbGllbnQgdXNlcyBvbmx5IGNsb3VkIGFwaSBzZXNzaW9uIG1hbmFnZW1lbnQuXG4gKiBUaGlzIG1lYW5zIGNhbGxzIHRvIHtAbGluayBWY2RBcGlDbGllbnQjc2V0QXV0aGVudGljYXRpb259IG9yIHtAbGluayBWY2RBcGlDbGllbnQjbG9naW59IGhhdmUgbm8gZWZmZWN0LlxuICovXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgVmNkQXBpQ2xpZW50IHtcbiAgICBzZXQgYmFzZVVybChfYmFzZVVybDogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMuX2Jhc2VVcmwgPSBfYmFzZVVybDtcbiAgICB9XG5cbiAgICBnZXQgdmVyc2lvbigpOiBzdHJpbmcge1xuICAgICAgICByZXR1cm4gdGhpcy5odHRwLnJlcXVlc3RIZWFkZXJzSW50ZXJjZXB0b3IudmVyc2lvbjtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9uZWdvdGlhdGVWZXJzaW9uOiBPYnNlcnZhYmxlPHN0cmluZz47XG4gICAgcHJpdmF0ZSBfYmFzZVVybDogc3RyaW5nO1xuXG4gICAgLyoqXG4gICAgICogQGRlcHJlY2F0ZWQgVXNlIHtAbGluayBWY2RBcGlDbGllbnQjX2Nsb3VkQXBpU2Vzc2lvbn1cbiAgICAgKi9cbiAgICBwcml2YXRlIF9zZXNzaW9uOiBCZWhhdmlvclN1YmplY3Q8U2Vzc2lvblR5cGU+ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxTZXNzaW9uVHlwZT4obnVsbCk7XG4gICAgcHJpdmF0ZSBfc2Vzc2lvbk9ic2VydmFibGU6IE9ic2VydmFibGU8U2Vzc2lvblR5cGU+ID0gdGhpcy5fc2Vzc2lvbi5hc09ic2VydmFibGUoKVxuICAgICAgICAucGlwZShcbiAgICAgICAgICAgIHNraXBXaGlsZShzZXNzaW9uID0+ICFzZXNzaW9uKVxuICAgICAgICApO1xuICAgIHByaXZhdGUgX2dldFNlc3Npb246IE9ic2VydmFibGU8U2Vzc2lvblR5cGU+O1xuXG4gICAgLyoqXG4gICAgICogQ2xvdWRBcGkgU2Vzc2lvblxuICAgICAqL1xuICAgIHByaXZhdGUgX2Nsb3VkQXBpU2Vzc2lvbjogQmVoYXZpb3JTdWJqZWN0PFNlc3Npb24+ID0gbmV3IEJlaGF2aW9yU3ViamVjdDxTZXNzaW9uPihudWxsKTtcbiAgICBwcml2YXRlIF9jbG91ZEFwaVNlc3Npb25PYnNlcnZhYmxlOiBPYnNlcnZhYmxlPFNlc3Npb24+ID0gdGhpcy5fY2xvdWRBcGlTZXNzaW9uLmFzT2JzZXJ2YWJsZSgpXG4gICAgICAgIC5waXBlKFxuICAgICAgICAgICAgc2tpcFdoaWxlKHNlc3Npb24gPT4gIXNlc3Npb24pXG4gICAgICAgICk7XG4gICAgLyoqXG4gICAgICogVGhpcyBvYnNlcnZhYmxlIGhhcyBhIHNwZWNpYWwgcHVycG9zZSB3aGVuIGRvaW5nIGF1dG9tYXRpYyBsb2dpbiBkdXJpbmcgdGhlIGNvbnN0cnVjdG9yIGluaXRpYWxpemF0aW9uLlxuICAgICAqIEl0IGFsbG93cyBiYWNrZW5kIGNhbGwgb25seSBhZnRlciBhbiBBUEkgdmVyc2lvbiBpcyBzZXQuXG4gICAgICogSXQgYWxzbyBlbnN1cmVzIHRoYXQgYSBiYWNrZW5kIGNhbGwgdG8gZ2V0IHRoZSBjdXJyZW50IHNlc3Npb24gaXMgZG9uZSBvbmNlIHByaW9yIHRvIGFueSBvdGhlciBjYWxscy5cbiAgICAgKlxuICAgICAqIEluIGNhc2Ugb2YgYW4gZXhwbGljaXQgY2xvdWQgYXBpIGF1dGggcmVxdWVzdCB0aGVyZSBpcyBubyBuZWVkIG9mIHRoaXMgb2JzZXJ2YWJsZVxuICAgICAqIHNpbmNlIHRoaXMgYXV0aCByZXF1ZXN0IHdpbGwgcmV0cmlldmUgdGhlIHNlc3Npb24gaXRzZWxmXG4gICAgICovXG4gICAgcHJpdmF0ZSBfZ2V0Q2xvdWRBcGlTZXNzaW9uOiBPYnNlcnZhYmxlPFNlc3Npb24+O1xuXG4gICAgcHJpdmF0ZSBfY2xvdWRBcGlTZXNzaW9uTGlua3M6IEJlaGF2aW9yU3ViamVjdDxMaW5rVHlwZVtdPiA9IG5ldyBCZWhhdmlvclN1YmplY3Q8TGlua1R5cGVbXT4oW10pO1xuXG4gICAgLyoqXG4gICAgICogQ2FjaGVkLCBsYXp5IGxvYWRlZCBvYnNlcnZhYmxlIG9mIHRoZSBBY2Nlc3NpYmxlTG9jYXRpb24gYXJyYXlcbiAgICAgKi9cbiAgICBwcml2YXRlIF9jbG91ZEFwaUFjY2Vzc2libGVMb2NhdGlvbnM6IE9ic2VydmFibGU8QWNjZXNzaWJsZUxvY2F0aW9uW10+O1xuXG4gICAgLyoqXG4gICAgICogVGhpcyBwcm9wZXJ0eSBkZXRlcm1pbmVzIGlmIGl0IGlzIGFuIGV4cGxpY2l0IGNsb3VkIGFwaSBsb2dpbi5cbiAgICAgKiBJbiB0aGlzIGNhc2UgdGhlIG9sZCBBUEkgKC9hcGkvc2Vzc2lvbikgc2hvdWxkIG5vdCBiZSB1c2VkIGF0IGFsbC5cbiAgICAgKi9cbiAgICBwcml2YXRlIF9pc0Nsb3VkQXBpTG9naW4gPSBmYWxzZTtcblxuICAgIGNvbnN0cnVjdG9yKFxuICAgICAgICAgICAgcHJpdmF0ZSBodHRwOiBWY2RIdHRwQ2xpZW50LFxuICAgICAgICAgICAgcHJpdmF0ZSBpbmplY3RvcjogSW5qZWN0b3IsXG4gICAgICAgICAgICBAT3B0aW9uYWwoKSBwcml2YXRlIGNvbmZpZz86IFZjZFNka0NvbmZpZyxcbiAgICApIHtcbiAgICAgICAgdGhpcy5fYmFzZVVybCA9IHRoaXMuaW5qZWN0b3IuZ2V0KEFQSV9ST09UX1VSTCk7XG5cbiAgICAgICAgbGV0IG5lZ290aWF0ZWRWZXJzaW9uOiBPYnNlcnZhYmxlPHN0cmluZz47XG4gICAgICAgIGlmICh0aGlzLmNvbmZpZz8uYXBpVmVyc2lvbikge1xuICAgICAgICAgICAgbmVnb3RpYXRlZFZlcnNpb24gPSBvZih0aGlzLmNvbmZpZy5hcGlWZXJzaW9uKS5waXBlKFxuICAgICAgICAgICAgICAgIG1hcCgodmVyc2lvbikgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNldFZlcnNpb24odmVyc2lvbik7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2ZXJzaW9uO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbmVnb3RpYXRlZFZlcnNpb24gPSB0aGlzLmh0dHAuZ2V0PFN1cHBvcnRlZFZlcnNpb25zVHlwZT4oYCR7dGhpcy5fYmFzZVVybH0vYXBpL3ZlcnNpb25zYCkucGlwZShcbiAgICAgICAgICAgICAgICBtYXAodmVyc2lvbnMgPT4gdGhpcy5uZWdvdGlhdGVWZXJzaW9uKHZlcnNpb25zKSksXG4gICAgICAgICAgICAgICAgdGFwKHZlcnNpb24gPT4gdGhpcy5zZXRWZXJzaW9uKHZlcnNpb24pKVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9uZWdvdGlhdGVWZXJzaW9uID0gbmVnb3RpYXRlZFZlcnNpb24ucGlwZShcbiAgICAgICAgICAgIHNoYXJlKHsgY29ubmVjdG9yOiAoKSA9PiBuZXcgUmVwbGF5U3ViamVjdCgxKSwgcmVzZXRPbkVycm9yOiBmYWxzZSwgcmVzZXRPbkNvbXBsZXRlOiBmYWxzZSwgcmVzZXRPblJlZkNvdW50WmVybzogZmFsc2UgfSlcbiAgICAgICAgKTtcblxuICAgICAgICBjb25zdCB0b2tlbkhvbGRlcjogQXV0aFRva2VuSG9sZGVyU2VydmljZSA9IHRoaXMuaW5qZWN0b3IuZ2V0KEF1dGhUb2tlbkhvbGRlclNlcnZpY2UsIHsgdG9rZW46ICcnIH0pO1xuICAgICAgICBjb25zdCB0b2tlbiA9IHRva2VuSG9sZGVyLmp3dCA/IGBCZWFyZXIgJHt0b2tlbkhvbGRlci5qd3R9YCA6IHRva2VuSG9sZGVyLnRva2VuO1xuICAgICAgICB0aGlzLl9nZXRTZXNzaW9uID0gdGhpcy5zZXRBdXRoZW50aWNhdGlvbih0b2tlbilcbiAgICAgICAgICAgIC5waXBlKFxuICAgICAgICAgICAgICAgIHNoYXJlKHsgY29ubmVjdG9yOiAoKSA9PiBuZXcgUmVwbGF5U3ViamVjdCgxKSwgcmVzZXRPbkVycm9yOiBmYWxzZSwgcmVzZXRPbkNvbXBsZXRlOiBmYWxzZSwgcmVzZXRPblJlZkNvdW50WmVybzogZmFsc2UgfSlcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgdGhpcy5fZ2V0Q2xvdWRBcGlTZXNzaW9uID0gdGhpcy5zZXRDbG91ZEFwaUF1dGhlbnRpY2F0aW9uKHRva2VuKVxuICAgICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICAgICAgc2hhcmUoeyBjb25uZWN0b3I6ICgpID0+IG5ldyBSZXBsYXlTdWJqZWN0KDEpLCByZXNldE9uRXJyb3I6IGZhbHNlLCByZXNldE9uQ29tcGxldGU6IGZhbHNlLCByZXNldE9uUmVmQ291bnRaZXJvOiBmYWxzZSB9KVxuICAgICAgICAgICAgKTtcbiAgICAgICAgLy8gVGhpcyBpcyBub3QgYW4gZXhwbGljaXQgY2xvdWQgYXBpIGxvZ2luXG4gICAgICAgIHRoaXMuX2lzQ2xvdWRBcGlMb2dpbiA9IGZhbHNlO1xuICAgIH1cblxuICAgIHByaXZhdGUgbmVnb3RpYXRlVmVyc2lvbihzZXJ2ZXJWZXJzaW9uczogU3VwcG9ydGVkVmVyc2lvbnNUeXBlKTogc3RyaW5nIHtcbiAgICAgICAgY29uc3Qgc3VwcG9ydGVkVmVyc2lvbnM6IHN0cmluZ1tdID0gc2VydmVyVmVyc2lvbnMudmVyc2lvbkluZm8ubWFwKHZlcnNpb25JbmZvID0+IHZlcnNpb25JbmZvLnZlcnNpb24pO1xuXG4gICAgICAgIC8vIERlZmF1bHQgQVBJIFZlcnNpb24gdXNlZCBpcyB0aGUgTGF0ZXN0IEFQSSBWZXJzaW9uIGluIFZNd2FyZSBDbG91ZCBEaXJlY3RvclxuICAgICAgICByZXR1cm4gc3VwcG9ydGVkVmVyc2lvbnNbc3VwcG9ydGVkVmVyc2lvbnMubGVuZ3RoIC0gMV07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIHB1cnBvc2Ugb2YgdGhpcyBmdW5jdGlvbiBpcyB0byBlbnN1cmUgdGhhdCBwcmlvciB0byBzZW5kaW5nIGFueSBjYWxsIHRvIHRoZSBiYWNrZW5kXG4gICAgICogdGhlIHZlcnNpb24gaGFzIGJlZW4gc2V0IGFuZCB0aGUgY3VycmVudCBzZXNzaW9uIGhhcyBiZWVuIHJldHJpZXZlZC5cbiAgICAgKiBOb3RlIHRoYXQgdGhpcyBpcyBpbXBvcnRhbnQgZHVyaW5nIHRoZSBhdXRvbWF0aWMgYXV0aGVudGljYXRpb24gdGhhdCBpcyBkb25lIGR1cmluZyB0aGVcbiAgICAgKiBjb25zdHJ1Y3RvciBpbml0aWFsaXphdGlvbiwgd2hlbiB0aGUgcGx1Z2luIGlzIG5vdCByZXF1aXJlZCB0byBwZXJmb3JtIGl0cyBvd24gZXhwbGljaXQgYXV0aGVudGljYXRpb25cbiAgICAgKiBidXQgcmF0aGVyIHRoZSBvbmVzIGZyb20gdGhlIHVuZGVybHlpbmcgZnJhbWV3b3JrIGlzIHVzZWQuXG4gICAgICovXG4gICAgcHJpdmF0ZSB2YWxpZGF0ZVJlcXVlc3RDb250ZXh0KCk6IE9ic2VydmFibGU8dHJ1ZT4ge1xuICAgICAgICByZXR1cm4gKHRoaXMudmVyc2lvbiA/IG9mKHRoaXMudmVyc2lvbikgOiB0aGlzLl9uZWdvdGlhdGVWZXJzaW9uKVxuICAgICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICAgICAgLy8gSW4gY2FzZSBvZiBhIGNsb3VkIGFwaSBsb2dpbiB3ZSBhcmUgbm90IGludGVyZXN0ZWQgaW4gdGhlIC9hcGkvc2Vzc2lvbiBzZXNzaW9uXG4gICAgICAgICAgICAgICAgY29uY2F0TWFwKCgpID0+IHRoaXMuX2lzQ2xvdWRBcGlMb2dpbiA/IG9mKG51bGwpIDogdGhpcy5fZ2V0U2Vzc2lvbiksXG4gICAgICAgICAgICAgICAgY29uY2F0TWFwKCgpID0+IHRoaXMuX2dldENsb3VkQXBpU2Vzc2lvblxuICAgICAgICAgICAgICAgICAgICAvLyBJbiBjYXNlIG9mIGNsb3VkIGFwaSBmYWlsdXJlIHdlIGRvIG5vdCB3YW50IHRvIHByZXZlbnQgZnVydGhlciBleGVjdXRpb25cbiAgICAgICAgICAgICAgICAgICAgLy8gZm9yIGJhY2t3YXJkIGNvbXBhdGliaWxpdHkgY29uc2lkZXJhdGlvbnMgc2luY2UgdGhpcyBtYXkgYmUgYSBjYXNlXG4gICAgICAgICAgICAgICAgICAgIC8vIHdoZW4gY2xvdWQgYXBpIGlzIG5vdCBzdXBwb3J0ZWQgYXQgYWxsIGZvciB0aGUgc3BlY2lmaWVkIHZlcnNpb25cbiAgICAgICAgICAgICAgICAgICAgLnBpcGUoY2F0Y2hFcnJvcigoZSkgPT4gb2YodHJ1ZSkpKVxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgbWFwKCgpID0+IHRydWUpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAvKipcbiAgICAgKlxuICAgICAqIEZvciB1c2UgY2FzZXMgd2ljaCBzb2xlbHkgZGVwZW5kcyBvbiBjbG91ZGFwaSB3aXRob3V0IGFueSBiYWNrd2FyZCBjb21wYXRpYmlsaXR5XG4gICAgICogdGhlcmUgc2hvdWxkIGJlIG5vIGRlcGVuZGVuY2Ugb24gdGhlIG9sZCAvYXBpIGVuZHBvaW50IGF0IGFsbFxuICAgICAqL1xuICAgIHByaXZhdGUgdmFsaWRhdGVSZXF1ZXN0Q29udGV4dENsb3VkQXBpT25seSgpOiBPYnNlcnZhYmxlPFNlc3Npb24+IHtcbiAgICAgICAgcmV0dXJuICh0aGlzLnZlcnNpb24gPyBvZih0aGlzLnZlcnNpb24pIDogdGhpcy5fbmVnb3RpYXRlVmVyc2lvbikucGlwZShcbiAgICAgICAgICAgIGNvbmNhdE1hcCgoKSA9PiB0aGlzLl9nZXRDbG91ZEFwaVNlc3Npb24pXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHVibGljIHNldFZlcnNpb24oX3ZlcnNpb246IHN0cmluZyk6IFZjZEFwaUNsaWVudCB7XG4gICAgICAgIHRoaXMuaHR0cC5yZXF1ZXN0SGVhZGVyc0ludGVyY2VwdG9yLnZlcnNpb24gPSBfdmVyc2lvbjtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2xvYmFsIGNvbmZpZ3VyYXRpb24gZm9yIHRoZSBzZXJ2aWNlLCB0aGF0IGFsbG93cyBhIHByb3ZpZGVyIHVzZXIgdG8gZXhlY3V0ZSBBUEkgcmVxdWVzdHNcbiAgICAgKiBpbiB0aGUgc2NvcGUgb2YgYSBzcGVjaWZpYyB0ZW5hbnQuXG4gICAgICpcbiAgICAgKiBJZiB5b3Ugd2FudCB0byBleGVjdXRlIHNpbmdsZSBBUEkgcmVxdWVzdCBpbiBzY29wZSBvZiBzcGVjaWZpYyB0ZW5hbnQgeW91IGNhbiBkbyBpdFxuICAgICAqIGJ5IHBhc3NpbmcgXCJYLVZNV0FSRS1WQ0xPVUQtVEVOQU5ULUNPTlRFWFRcIiBoZWFkZXIgdG8gdGhlIHNwZWNpZmljIEFQSSBSZXF1ZXN0LlxuICAgICAqXG4gICAgICogVGhpcyBzY29waW5nIGlzIGF2YWlsYWJsZSB0byBxdWVyeS1iYXNlZCBBUEkgY2FsbHMgYW5kIHRvIGJ1bGsgR0VUIGNhbGxzIGluIHRoZVxuICAgICAqIC9jbG91ZGFwaSBzcGFjZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBhY3RBcyBhbiBlbnRpdHlSZWYgb2YgdGhlIHRlbmFudCAob3JnYW5pemF0aW9uKSB0byBzY29wZSBzdWJzZXF1ZW50IGNhbGxzIHRvIGluXG4gICAgICogIHRoZSBWY2RBcGlDbGllbnQsIG9yIG51bGwvbm8gcGFyYW1ldGVyIHRvIHJlbW92ZSB0ZW5hbnQtc3BlY2lmaWMgc2NvcGluZ1xuICAgICAqIEByZXR1cm5zIHRoZSBjdXJyZW50IFZjZEFwaUNsaWVudCBpbnN0YW5jZSAoZm9yIGNoYWluaW5nKVxuICAgICAqL1xuICAgIHB1YmxpYyBhY3RBcyhhY3RBczogRW50aXR5UmVmZXJlbmNlVHlwZSA9IG51bGwpOiBWY2RBcGlDbGllbnQge1xuICAgICAgICB0aGlzLmh0dHAucmVxdWVzdEhlYWRlcnNJbnRlcmNlcHRvci5hY3RBcyA9ICFhY3RBcyA/IG51bGwgOiBhY3RBcy5pZDtcbiAgICAgICAgdGhpcy5odHRwLnJlcXVlc3RIZWFkZXJzSW50ZXJjZXB0b3IuYWN0QXNPcmdOYW1lID0gIWFjdEFzID8gbnVsbCA6IGFjdEFzLm5hbWU7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBkZXByZWNhdGVkIFVzZSB7QGxpbmsgVmNkQXBpQ2xpZW50I3NldENsb3VkQXBpQXV0aGVudGljYXRpb259XG4gICAgICpcbiAgICAgKiBTZXRzIHRoZSBhdXRoZW50aWNhdGlvbiB0b2tlbiB0byB1c2UgZm9yIHRoZSBWY2RBcGlDbGllbnQuXG4gICAgICpcbiAgICAgKiBBZnRlciBzZXR0aW5nIHRoZSB0b2tlbiwgdGhlIGNsaWVudCB3aWxsIGdldCB0aGUgY3VycmVudCBzZXNzaW9uXG4gICAgICogaW5mb3JtYXRpb24gYXNzb2NpYXRlZCB3aXRoIHRoZSBhdXRoZW50aWNhdGVkIHRva2VuLlxuICAgICAqXG4gICAgICogQHBhcmFtIGF1dGhlbnRpY2F0aW9uIHRoZSBhdXRoZW50aWNhdGlvbiBzdHJpbmcgKHRvIGJlIHVzZWQgaW4gZWl0aGVyIHRoZSAnQXV0aG9yaXphdGlvbidcbiAgICAgKiAgb3IgJ3gtdmNsb3VkLWF1dGhvcml6YXRpb24nIGhlYWRlcilcbiAgICAgKiBAcmV0dXJucyB0aGUgc2Vzc2lvbiBhc3NvY2lhdGVkIHdpdGggdGhlIGF1dGhlbnRpY2F0aW9uIHRva2VuXG4gICAgICovXG4gICAgcHVibGljIHNldEF1dGhlbnRpY2F0aW9uKGF1dGhlbnRpY2F0aW9uOiBzdHJpbmcpOiBPYnNlcnZhYmxlPFNlc3Npb25UeXBlPiB7XG4gICAgICAgIGlmICh0aGlzLl9pc0Nsb3VkQXBpTG9naW4pIHtcbiAgICAgICAgICAgIHJldHVybiB0aHJvd0Vycm9yKCdPbmx5IGNsb3VkIGFwaSBhdXRoIGlzIGFsbG93ZWQgc2luY2UgaXQgd2FzIGFscmVhZHkgdXNlZCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5odHRwLnJlcXVlc3RIZWFkZXJzSW50ZXJjZXB0b3IuYXV0aGVudGljYXRpb24gPSBhdXRoZW50aWNhdGlvbjtcbiAgICAgICAgcmV0dXJuIHRoaXMuaHR0cC5nZXQ8U2Vzc2lvblR5cGU+KGAke3RoaXMuX2Jhc2VVcmx9L2FwaS9zZXNzaW9uYCkucGlwZShcbiAgICAgICAgICAgICAgICB0YXAoc2Vzc2lvbiA9PiB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGF1dG9tYXRpY2FsbHkgc2V0IGFjdEFzIGZvciBwcm92aWRlciBpbiB0ZW5hbnQgc2NvcGVcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNlc3Npb24ub3JnID09PSAnU3lzdGVtJyAmJiB0aGlzLmluamVjdG9yLmdldChTRVNTSU9OX1NDT1BFKSA9PT0gJ3RlbmFudCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIEF1dG9tYXRpYyBhY3RBcyBvbmx5IHdvcmtzIGluIHZlcnNpb25zID49OS41XG4gICAgICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYWN0QXMoe2lkOiB0aGlzLmluamVjdG9yLmdldChTRVNTSU9OX09SR19JRCl9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLndhcm4oJ05vIFNFU1NJT05fT1JHX0lEIHNldCBpbiBjb250YWluZXIuIEF1dG9tYXRpYyBhY3RBcyBpcyBkaXNhYmxlZC4nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgIHRhcChzZXNzaW9uID0+IHRoaXMuX3Nlc3Npb24ubmV4dChzZXNzaW9uKSlcbiAgICAgICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgYXV0aGVudGljYXRpb24gdG9rZW4gdG8gdXNlIGZvciB0aGUgVmNkQXBpQ2xpZW50LlxuICAgICAqXG4gICAgICogQWZ0ZXIgc2V0dGluZyB0aGUgdG9rZW4sIHRoZSBjbGllbnQgd2lsbCBnZXQgdGhlIGN1cnJlbnQgc2Vzc2lvblxuICAgICAqIGluZm9ybWF0aW9uIGFzc29jaWF0ZWQgd2l0aCB0aGUgYXV0aGVudGljYXRlZCB0b2tlbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBhdXRoZW50aWNhdGlvbiB0aGUgYXV0aGVudGljYXRpb24gc3RyaW5nICh0byBiZSB1c2VkIGluIGVpdGhlciB0aGUgJ0F1dGhvcml6YXRpb24nXG4gICAgICogIG9yICd4LXZjbG91ZC1hdXRob3JpemF0aW9uJyBoZWFkZXIpXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBzZXNzaW9uIG9ic2VydmFibGUgYXNzb2NpYXRlZCB3aXRoIHRoZSBhdXRoZW50aWNhdGlvbiB0b2tlblxuICAgICAqL1xuICAgIHB1YmxpYyBzZXRDbG91ZEFwaUF1dGhlbnRpY2F0aW9uKGF1dGhlbnRpY2F0aW9uOiBzdHJpbmcpOiBPYnNlcnZhYmxlPFNlc3Npb24+IHtcbiAgICAgICAgdGhpcy5vbkJlZm9yZUNsb3VkQXBpQXV0aGVudGljYXRpb24oKTtcblxuICAgICAgICByZXR1cm4gb2YodHJ1ZSlcbiAgICAgICAgICAgIC5waXBlKFxuICAgICAgICAgICAgICAgIC8vIFNldCB0aGUgYXV0aGVudGljYXRpb24gYXMgcGFydCBvZiB0aGUgb2JzZXJ2YWJsZSBpbiBvcmRlciB0byBlbnN1cmUgdGhlIGNhbGxlciBoYXMgc3Vic2NyaWJlZCB0byB0aGUgb2JzZXJ2YWJsZVxuICAgICAgICAgICAgICAgIHRhcCgoKSA9PiB0aGlzLmh0dHAucmVxdWVzdEhlYWRlcnNJbnRlcmNlcHRvci5hdXRoZW50aWNhdGlvbiA9IGF1dGhlbnRpY2F0aW9uKSxcbiAgICAgICAgICAgICAgICBzd2l0Y2hNYXAoKCkgPT4gdGhpcy5odHRwLmdldDxTZXNzaW9uPihgJHt0aGlzLl9iYXNlVXJsfS9jbG91ZGFwaS8xLjAuMC9zZXNzaW9ucy9jdXJyZW50YCwgeyBvYnNlcnZlOiAncmVzcG9uc2UnIH0pKSxcbiAgICAgICAgICAgIClcbiAgICAgICAgICAgIC5waXBlKFxuICAgICAgICAgICAgICAgIHRoaXMub25DbG91ZEFwaUF1dGhlbnRpY2F0aW9uKClcbiAgICAgICAgICAgICk7XG4gICAgfVxuXG4gICAgcHVibGljIGVuYWJsZUxvZ2dpbmcoKTogVmNkQXBpQ2xpZW50IHtcbiAgICAgICAgdGhpcy5odHRwLmxvZ2dpbmdJbnRlcmNlcHRvci5lbmFibGVkID0gdHJ1ZTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAZGVwcmVjYXRlZCBVc2Uge0BsaW5rIFZjZEFwaUNsaWVudCNjbG91ZEFwaUxvZ2lufVxuICAgICAqXG4gICAgICogQ3JlYXRlcyBhbiBhdXRoZW50aWNhdGVkIHNlc3Npb24gZm9yIHRoZSBzcGVjaWZpZWQgY3JlZGVudGlhbCBkYXRhLlxuICAgICAqXG4gICAgICogQHBhcmFtIHVzZXJuYW1lIHRoZSBuYW1lIG9mIHRoZSB1c2VyIHRvIGF1dGhlbnRpY2F0ZVxuICAgICAqIEBwYXJhbSB0ZW5hbnQgdGhlIG9yZ2FuaXphdGlvbiB0aGUgdXNlciBiZWxvbmdzIHRvXG4gICAgICogQHBhcmFtIHBhc3N3b3JkIHRoZSBwYXNzd29yZCBmb3IgdGhlIHVzZXJcbiAgICAgKiBAcmV0dXJucyBhbiBhdXRoZW50aWNhdGVkIHNlc3Npb24gZm9yIHRoZSBnaXZlbiBjcmVkZW50aWFsc1xuICAgICAqL1xuICAgIHB1YmxpYyBsb2dpbih1c2VybmFtZTogc3RyaW5nLCB0ZW5hbnQ6IHN0cmluZywgcGFzc3dvcmQ6IHN0cmluZyk6IE9ic2VydmFibGU8U2Vzc2lvblR5cGU+IHtcbiAgICAgICAgaWYgKHRoaXMuX2lzQ2xvdWRBcGlMb2dpbikge1xuICAgICAgICAgICAgcmV0dXJuIHRocm93RXJyb3IoJ09ubHkgY2xvdWQgYXBpIGF1dGggaXMgYWxsb3dlZCBzaW5jZSBpdCB3YXMgYWxyZWFkeSB1c2VkJyk7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgYXV0aFN0cmluZzogc3RyaW5nID0gYnRvYShgJHt1c2VybmFtZX1AJHt0ZW5hbnR9OiR7cGFzc3dvcmR9YCk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuaHR0cC5wb3N0PFNlc3Npb25UeXBlPihcbiAgICAgICAgICAgIGAke3RoaXMuX2Jhc2VVcmx9L2FwaS9zZXNzaW9uc2AsXG4gICAgICAgICAgICBudWxsLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIG9ic2VydmU6ICdyZXNwb25zZScsXG4gICAgICAgICAgICAgICAgaGVhZGVyczogbmV3IEh0dHBIZWFkZXJzKHsgQXV0aG9yaXphdGlvbjogYEJhc2ljICR7YXV0aFN0cmluZ31gfSlcbiAgICAgICAgICAgIH1cbiAgICAgICAgKVxuICAgICAgICAucGlwZShcbiAgICAgICAgICAgIHRhcCgocmVzcG9uc2U6IEh0dHBSZXNwb25zZTxhbnk+KSA9PlxuICAgICAgICAgICAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTptYXgtbGluZS1sZW5ndGhcbiAgICAgICAgICAgICAgICB0aGlzLmh0dHAucmVxdWVzdEhlYWRlcnNJbnRlcmNlcHRvci5hdXRoZW50aWNhdGlvbiA9IGAke3Jlc3BvbnNlLmhlYWRlcnMuZ2V0KCd4LXZtd2FyZS12Y2xvdWQtdG9rZW4tdHlwZScpfSAke3Jlc3BvbnNlLmhlYWRlcnMuZ2V0KCd4LXZtd2FyZS12Y2xvdWQtYWNjZXNzLXRva2VuJyl9YFxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIG1hcChyZXNwb25zZSA9PiByZXNwb25zZS5ib2R5KSxcbiAgICAgICAgICAgIHRhcChzZXNzaW9uID0+IHRoaXMuX3Nlc3Npb24ubmV4dChzZXNzaW9uKSlcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGF1dGhlbnRpY2F0ZWQgc2Vzc2lvbiBmb3IgdGhlIHNwZWNpZmllZCBjcmVkZW50aWFsIGRhdGEgdXNpbmcgY2xvdWQgYXBpIGVuZHBvaW50LlxuICAgICAqXG4gICAgICogQHBhcmFtIHVzZXJuYW1lIHRoZSBuYW1lIG9mIHRoZSB1c2VyIHRvIGF1dGhlbnRpY2F0ZVxuICAgICAqIEBwYXJhbSB0ZW5hbnQgdGhlIG9yZ2FuaXphdGlvbiB0aGUgdXNlciBiZWxvbmdzIHRvXG4gICAgICogQHBhcmFtIHBhc3N3b3JkIHRoZSBwYXNzd29yZCBmb3IgdGhlIHVzZXJcbiAgICAgKiBAcmV0dXJucyBhbiBhdXRoZW50aWNhdGVkIHNlc3Npb24gZm9yIHRoZSBnaXZlbiBjcmVkZW50aWFsc1xuICAgICAqL1xuICAgIHB1YmxpYyBjbG91ZEFwaUxvZ2luKHVzZXJuYW1lOiBzdHJpbmcsIHRlbmFudDogc3RyaW5nLCBwYXNzd29yZDogc3RyaW5nKTogT2JzZXJ2YWJsZTxTZXNzaW9uPiB7XG4gICAgICAgIHRoaXMub25CZWZvcmVDbG91ZEFwaUF1dGhlbnRpY2F0aW9uKCk7XG5cbiAgICAgICAgY29uc3QgYXV0aFN0cmluZzogc3RyaW5nID0gYnRvYShgJHt1c2VybmFtZX1AJHt0ZW5hbnR9OiR7cGFzc3dvcmR9YCk7XG4gICAgICAgIGxldCB1cmwgPSBgJHt0aGlzLl9iYXNlVXJsfS9jbG91ZGFwaS8xLjAuMC9zZXNzaW9uc2A7XG4gICAgICAgIGlmICh0ZW5hbnQudG9Mb3dlckNhc2UoKSA9PT0gJ3N5c3RlbScpIHtcbiAgICAgICAgICAgIHVybCArPSAnL3Byb3ZpZGVyJztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5odHRwLnBvc3Q8U2Vzc2lvbj4oXG4gICAgICAgICAgICB1cmwsXG4gICAgICAgICAgICBudWxsLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIG9ic2VydmU6ICdyZXNwb25zZScsXG4gICAgICAgICAgICAgICAgaGVhZGVyczogbmV3IEh0dHBIZWFkZXJzKHsgW0hUVFBfSEVBREVSUy5BdXRob3JpemF0aW9uXTogYEJhc2ljICR7YXV0aFN0cmluZ31gIH0pXG4gICAgICAgICAgICB9XG4gICAgICAgICkucGlwZShcbiAgICAgICAgICAgIHRhcCgocmVzcG9uc2U6IEh0dHBSZXNwb25zZTxTZXNzaW9uPikgPT4ge1xuICAgICAgICAgICAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTptYXgtbGluZS1sZW5ndGhcbiAgICAgICAgICAgICAgICBjb25zdCB0b2tlbiA9IGAke3Jlc3BvbnNlLmhlYWRlcnMuZ2V0KCd4LXZtd2FyZS12Y2xvdWQtdG9rZW4tdHlwZScpfSAke3Jlc3BvbnNlLmhlYWRlcnMuZ2V0KCd4LXZtd2FyZS12Y2xvdWQtYWNjZXNzLXRva2VuJyl9YDtcbiAgICAgICAgICAgICAgICB0aGlzLmh0dHAucmVxdWVzdEhlYWRlcnNJbnRlcmNlcHRvci5hdXRoZW50aWNhdGlvbiA9IHRva2VuO1xuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICB0aGlzLm9uQ2xvdWRBcGlBdXRoZW50aWNhdGlvbigpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSXQgaXMgbmVjZXNzYXJ5IHRvIGtub3cgaWYgYW4gZXhwbGljaXQgY2xvdWQgYXBpIGF1dGggcmVxdWVzdCB3YXMgZG9uZS5cbiAgICAgKiBUaGlzIGZ1bmN0aW9uIGhhbmRsZXMgdGhpcyBieSBzZXR0aW5nIHRoZSBjb3JyZXNwb25kaW5nIGZsYWdzLCBwcm9wZXJ0aWVzIGV0Yy5cbiAgICAgKi9cbiAgICBwcml2YXRlIG9uQmVmb3JlQ2xvdWRBcGlBdXRoZW50aWNhdGlvbigpIHtcbiAgICAgICAgLy8gSW4gY2FzZSBvZiBhbiBleHBsaWNpdCBjbG91ZCBhcGkgYXV0aCByZXF1ZXN0OlxuICAgICAgICAvLyBTZXQgdGhlIGZsYWcgX2lzQ2xvdWRBcGlMb2dpbiBpbiBvcmRlciB0byBrbm93IHRoYXQgZXhwbGljaXQgY2xvdWQgYXBpIGF1dGhlbnRpY2F0aW9uIGlzIGRvbmVcbiAgICAgICAgLy8gVGhpcyB3aWxsIGhlbHAgdXMgc2tpcCBjb2RlIHJlbGF0ZWQgdG8gdGhlIG9sZCBhcGksIGkuZS4gd2Ugc2hvdWxkIG5vdCBhbGxvdyBleHBsaWNpdCBtaXggb2YgYm90aCB0aGUgYXBpLXNcbiAgICAgICAgdGhpcy5faXNDbG91ZEFwaUxvZ2luID0gdHJ1ZTtcbiAgICAgICAgLy8gSW4gY2FzZSBvZiBhbiBleHBsaWNpdCBjbG91ZCBhcGkgYXV0aCByZXF1ZXN0OlxuICAgICAgICAvLyBUaGVyZSBpcyBubyBuZWVkIG9mIF9nZXRDbG91ZEFwaVNlc3Npb24gb2JzZXJ2YWJsZSB3aGljaCBpcyBuZWVkZWQgaW4gdGhlIGF1dG9tYXRpYyBsb2dpbiBkdXJpbmcgdGhlIGNvbnN0cnVjdG9yIGluaXRpYWxpemF0aW9uLlxuICAgICAgICAvLyBUaGUgZXhwbGljaXQgY2xvdWQgYXBpIGF1dGggcmVxdWVzdCB3aWxsIHJldHJpZXZlIHRoZSBzZXNzaW9uLlxuICAgICAgICB0aGlzLl9nZXRDbG91ZEFwaVNlc3Npb24gPSBvZihudWxsKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGUgYXV0aGVudGljYXRpb24uXG4gICAgICogVGhpcyBpbmNsdWRlcyBnZXR0aW5nIEhBVEVPQVMgbGlua3MsIHNldHRpbmcgdGhlIHNlc3Npb24sIGhhbmRsaW5nIGVycm9ycyBldGMuXG4gICAgICovXG4gICAgcHJpdmF0ZSBvbkNsb3VkQXBpQXV0aGVudGljYXRpb24oKTogKHNvdXJjZTogT2JzZXJ2YWJsZTxIdHRwUmVzcG9uc2U8U2Vzc2lvbj4+KSA9PiBPYnNlcnZhYmxlPFNlc3Npb24+IHtcbiAgICAgICAgcmV0dXJuIChzb3VyY2UpID0+IHNvdXJjZS5waXBlKFxuICAgICAgICAgICAgdGFwKChyZXNwOiBIdHRwUmVzcG9uc2U8U2Vzc2lvbj4pID0+IHtcbiAgICAgICAgICAgICAgICAvLyBHZXQgSEFURU9BUyBsaW5rc1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0Q2xvdWRBcGlTZXNzaW9uTGlua3MocGFyc2VIZWFkZXJIYXRlb2FzTGlua3MocmVzcC5oZWFkZXJzLmdldChIQVRFT0FTX0hFQURFUikpKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCdFcnJvciB3aGVuIHBhcnNpbmcgc2Vzc2lvbiBIQVRFT0FTIGxpbmtzOicsIGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgbWFwKHJlc3AgPT4gcmVzcC5ib2R5KSxcbiAgICAgICAgICAgIHRhcCgoc2Vzc2lvbjogU2Vzc2lvbikgPT4ge1xuICAgICAgICAgICAgICAgIC8vIENsZWFyIHByZXZpb3VzIGFjdEFzXG4gICAgICAgICAgICAgICAgdGhpcy5hY3RBcyhudWxsKTtcbiAgICAgICAgICAgICAgICAvLyBhdXRvbWF0aWNhbGx5IHNldCBhY3RBcyBmb3IgcHJvdmlkZXIgaW4gdGVuYW50IHNjb3BlXG4gICAgICAgICAgICAgICAgaWYgKHNlc3Npb24ub3JnICYmIHNlc3Npb24ub3JnLm5hbWUgPT09ICdTeXN0ZW0nICYmIHRoaXMuaW5qZWN0b3IuZ2V0KFNFU1NJT05fU0NPUEUpID09PSAndGVuYW50Jykge1xuICAgICAgICAgICAgICAgICAgICAvLyBBdXRvbWF0aWMgYWN0QXMgb25seSB3b3JrcyBpbiB2ZXJzaW9ucyA+PTkuNVxuICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5hY3RBcyh7IGlkOiB0aGlzLmluamVjdG9yLmdldChTRVNTSU9OX09SR19JRCkgfSk7XG4gICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignTm8gU0VTU0lPTl9PUkdfSUQgc2V0IGluIGNvbnRhaW5lci4gQXV0b21hdGljIGFjdEFzIGlzIGRpc2FibGVkLicpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICB0YXAoKHNlc3Npb246IFNlc3Npb24pID0+IHRoaXMuX2Nsb3VkQXBpU2Vzc2lvbi5uZXh0KHNlc3Npb24pKSxcbiAgICAgICAgICAgIGNhdGNoRXJyb3IoKGUpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLm9uQ2xvdWRBcGlBdXRoZW50aWNhdGlvbkVycm9yKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRocm93RXJyb3IoZSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICApO1xuICAgIH1cblxuICAgIHByaXZhdGUgb25DbG91ZEFwaUF1dGhlbnRpY2F0aW9uRXJyb3IoKSB7XG4gICAgICAgIC8vIENsZWFyIHRoZSBhdXRoZW50aWNhdGlvbiBzbyB0aGF0IGFueSBzdWJzZXF1ZW50IGJhY2tlbmQgY2FsbHMgYXJlIG5vdCBhdXRoZW50aWNhdGVkXG4gICAgICAgIHRoaXMuaHR0cC5yZXF1ZXN0SGVhZGVyc0ludGVyY2VwdG9yLmF1dGhlbnRpY2F0aW9uID0gJyc7XG4gICAgICAgIC8vIF9nZXRDbG91ZEFwaVNlc3Npb24gaXMgaW4gdGhlIGNlbnRlciBvZiBhbnkgYmFja2VuZCBjYWxsLCBudWxsaWZ5IGl0IGluIG9yZGVyIG5vdCB0byBwcmV2ZW50IHRob3NlIGNhbGxzXG4gICAgICAgIC8vIHNpbmNlIGl0IGlzIGVhc2llciB0byB0cm91Ymxlc2hvb3QgZmFpbGluZyBiYWNrZW5kIHJhdGhlciB0aGFuIG5vIGNhbGxcbiAgICAgICAgdGhpcy5fZ2V0Q2xvdWRBcGlTZXNzaW9uID0gb2YobnVsbCk7XG4gICAgICAgIC8vIENsZWFyIHRoZSBsaW5rc1xuICAgICAgICB0aGlzLl9jbG91ZEFwaVNlc3Npb25MaW5rcy5uZXh0KFtdKTtcbiAgICAgICAgLy8gQ2xlYXIgdGhlIHNlc3Npb25cbiAgICAgICAgdGhpcy5fY2xvdWRBcGlTZXNzaW9uLm5leHQobnVsbCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBzZXRDbG91ZEFwaVNlc3Npb25MaW5rcyhsaW5rczogTGlua1R5cGVbXSkge1xuICAgICAgICB0aGlzLl9jbG91ZEFwaUFjY2Vzc2libGVMb2NhdGlvbnMgPSBudWxsO1xuICAgICAgICB0aGlzLl9jbG91ZEFwaVNlc3Npb25MaW5rcy5uZXh0KGxpbmtzIHx8IFtdKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0PFQ+KGVuZHBvaW50OiBzdHJpbmcsICBvcHRpb25zPzogeyBoZWFkZXJzPzogSHR0cEhlYWRlcnMgfSk6IE9ic2VydmFibGU8VD4ge1xuICAgICAgICByZXR1cm4gdGhpcy52YWxpZGF0ZVJlcXVlc3RDb250ZXh0KCkucGlwZShcbiAgICAgICAgICAgIGNvbmNhdE1hcCgoKSA9PiB0aGlzLmh0dHAuZ2V0PFQ+KHRoaXMuYnVpbGRFbmRwb2ludFVybChlbmRwb2ludCksIHsuLi5vcHRpb25zfSkpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHVibGljIGxpc3Q8VD4oZW5kcG9pbnQ6IHN0cmluZywgcXVlcnlCdWlsZGVyPzogUXVlcnkuQnVpbGRlciwgbXVsdGlzaXRlPzogYm9vbGVhbiB8IEF1dGhvcml6ZWRMb2NhdGlvblR5cGVbXSwgb3B0aW9ucz86IHsgaGVhZGVycz86IEh0dHBIZWFkZXJzIH0pIHtcbiAgICAgICAgbGV0IHVybCA9IHRoaXMuYnVpbGRFbmRwb2ludFVybChlbmRwb2ludCk7XG5cbiAgICAgICAgaWYgKHF1ZXJ5QnVpbGRlcikge1xuICAgICAgICAgICAgdXJsID0gYCR7dXJsfSR7cXVlcnlCdWlsZGVyLmdldENsb3VkQVBJKCl9YDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChtdWx0aXNpdGUpIHtcbiAgICAgICAgICAgIGlmICghb3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmh0dHAuZ2V0PFQ+KHVybCwgeyBoZWFkZXJzOiBuZXcgSHR0cEhlYWRlcnMoeyBfbXVsdGlzaXRlOiB0aGlzLnBhcnNlTXVsdGlzaXRlVmFsdWUobXVsdGlzaXRlKSB9KSB9KTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAob3B0aW9ucz8uaGVhZGVycykge1xuICAgICAgICAgICAgICAgIG9wdGlvbnMuaGVhZGVycy5hcHBlbmQoXCJfbXVsdGlzaXRlXCIsIHRoaXMucGFyc2VNdWx0aXNpdGVWYWx1ZShtdWx0aXNpdGUpKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5odHRwLmdldDxUPih1cmwsIHsgLi4ub3B0aW9ucyB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLnZhbGlkYXRlUmVxdWVzdENvbnRleHQoKS5waXBlKFxuICAgICAgICAgICAgY29uY2F0TWFwKCgpID0+IHRoaXMuaHR0cC5nZXQ8VD4odXJsLCB7IC4uLm9wdGlvbnMgfSkpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHVibGljIGNyZWF0ZVN5bmM8VD4oZW5kcG9pbnQ6IHN0cmluZywgaXRlbTogVCwgb3B0aW9ucz86IHsgaGVhZGVycz86IEh0dHBIZWFkZXJzIH0pOiBPYnNlcnZhYmxlPFQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMudmFsaWRhdGVSZXF1ZXN0Q29udGV4dCgpLnBpcGUoXG4gICAgICAgICAgICBjb25jYXRNYXAoKCkgPT4gdGhpcy5odHRwLnBvc3Q8VD4oXG4gICAgICAgICAgICAgICAgdGhpcy5idWlsZEVuZHBvaW50VXJsKGVuZHBvaW50KSxcbiAgICAgICAgICAgICAgICBpdGVtLFxuICAgICAgICAgICAgICAgIHsuLi5vcHRpb25zfVxuICAgICAgICAgICAgKSlcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgY3JlYXRlQXN5bmM8VD4oZW5kcG9pbnQ6IHN0cmluZywgaXRlbTogVCwgb3B0aW9ucz86IHsgaGVhZGVycz86IEh0dHBIZWFkZXJzIH0pOiBPYnNlcnZhYmxlPFRhc2tUeXBlPiB7XG4gICAgICAgIHJldHVybiB0aGlzLnZhbGlkYXRlUmVxdWVzdENvbnRleHQoKS5waXBlKFxuICAgICAgICAgICAgY29uY2F0TWFwKCgpID0+IHRoaXMuaHR0cC5wb3N0KFxuICAgICAgICAgICAgICAgIHRoaXMuYnVpbGRFbmRwb2ludFVybChlbmRwb2ludCksXG4gICAgICAgICAgICAgICAgaXRlbSxcbiAgICAgICAgICAgICAgICB7IC4uLm9wdGlvbnMsIG9ic2VydmU6ICdyZXNwb25zZScgfVxuICAgICAgICAgICAgKSksXG4gICAgICAgICAgICBjb25jYXRNYXAocmVzcG9uc2UgPT4gdGhpcy5tYXBSZXNwb25zZVRvVGFzayhyZXNwb25zZSwgJ1BPU1QnKSlcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0VHJhbnNmZXJMaW5rPFQ+KGVuZHBvaW50OiBzdHJpbmcsIGl0ZW06IFQsIHRyYW5zZmVyUmVsOiBzdHJpbmcgPSBUUkFOU0ZFUl9MSU5LX1JFTCk6IE9ic2VydmFibGU8c3RyaW5nPiB7XG4gICAgICAgIHJldHVybiB0aGlzLmh0dHBcbiAgICAgICAgICAgIC5wb3N0KHRoaXMuYnVpbGRFbmRwb2ludFVybChlbmRwb2ludCksIGl0ZW0sIHsgb2JzZXJ2ZTogJ3Jlc3BvbnNlJyB9KVxuICAgICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICAgICAgbWFwKChyZXM6IEh0dHBSZXNwb25zZTxUICYgTmF2aWdhYmxlPikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBoZWFkZXJMaW5rczogTGlua1R5cGVbXSA9IHJlcy5oZWFkZXJzLmhhcyhIQVRFT0FTX0hFQURFUilcbiAgICAgICAgICAgICAgICAgICAgICAgID8gcGFyc2VIZWFkZXJIYXRlb2FzTGlua3MocmVzLmhlYWRlcnMuZ2V0KEhBVEVPQVNfSEVBREVSKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIDogW107XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGxpbmtzOiBMaW5rVHlwZVtdID0gcmVzLmJvZHkgPyAocmVzLmJvZHkubGluayB8fCBbXSkgOiBbXTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbGluayA9IFsuLi5oZWFkZXJMaW5rcywgLi4ubGlua3NdXG4gICAgICAgICAgICAgICAgICAgICAgICAuZmluZCgobCkgPT4gbC5yZWwgPT09IHRyYW5zZmVyUmVsKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFsaW5rKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgQ2xpZW50RXJyb3IoXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGBSZXNwb25zZSBmcm9tICR7ZW5kcG9pbnR9IGRpZCBub3QgY29udGFpbiBhIHRyYW5zZmVyIGxpbmtgLFxuICAgICAgICAgICAgICAgICAgICAgICAgICBDbGllbnRFcnJvclR5cGUuSGF0ZW9hc0xpbmtNaXNzaW5nXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBsaW5rLmhyZWY7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICk7XG4gICAgfVxuXG4gICAgcHVibGljIHN0YXJ0VHJhbnNmZXI8VD4oZW5kcG9pbnQ6IHN0cmluZywgaXRlbTogVCwgdHJhbnNmZXJSZWw6IHN0cmluZyA9IFRSQU5TRkVSX0xJTktfUkVMKTogT2JzZXJ2YWJsZTxWY2RUcmFuc2ZlckNsaWVudD4ge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRUcmFuc2ZlckxpbmsoZW5kcG9pbnQsIGl0ZW0sIHRyYW5zZmVyUmVsKVxuICAgICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICAgICAgbWFwKCh0cmFuc2ZlclVybCkgPT4gbmV3IFZjZFRyYW5zZmVyQ2xpZW50KHRoaXMuaHR0cCwgdHJhbnNmZXJVcmwpKVxuICAgICAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgdXBkYXRlU3luYzxUPihlbmRwb2ludDogc3RyaW5nLCBpdGVtOiBULCBvcHRpb25zPzogeyBoZWFkZXJzPzogSHR0cEhlYWRlcnMgfSk6IE9ic2VydmFibGU8VD4ge1xuICAgICAgICByZXR1cm4gdGhpcy52YWxpZGF0ZVJlcXVlc3RDb250ZXh0KCkucGlwZShcbiAgICAgICAgICAgIGNvbmNhdE1hcCgoKSA9PiB0aGlzLmh0dHAucHV0PFQ+KFxuICAgICAgICAgICAgICAgIHRoaXMuYnVpbGRFbmRwb2ludFVybChlbmRwb2ludCksXG4gICAgICAgICAgICAgICAgaXRlbSxcbiAgICAgICAgICAgICAgICB7IC4uLm9wdGlvbnMgfVxuICAgICAgICAgICAgKSlcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgdXBkYXRlQXN5bmM8VD4oZW5kcG9pbnQ6IHN0cmluZywgaXRlbTogVCwgb3B0aW9ucz86IHsgaGVhZGVycz86IEh0dHBIZWFkZXJzIH0pOiBPYnNlcnZhYmxlPFRhc2tUeXBlPiB7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMudmFsaWRhdGVSZXF1ZXN0Q29udGV4dCgpLnBpcGUoXG4gICAgICAgICAgICBjb25jYXRNYXAoKCkgPT4gdGhpcy5odHRwLnB1dChcbiAgICAgICAgICAgICAgICB0aGlzLmJ1aWxkRW5kcG9pbnRVcmwoZW5kcG9pbnQpLFxuICAgICAgICAgICAgICAgIGl0ZW0sXG4gICAgICAgICAgICAgICAgeyAuLi5vcHRpb25zLCBvYnNlcnZlOiAncmVzcG9uc2UnIH1cbiAgICAgICAgICAgICkpLFxuICAgICAgICAgICAgY29uY2F0TWFwKHJlc3BvbnNlID0+IHRoaXMubWFwUmVzcG9uc2VUb1Rhc2socmVzcG9uc2UsICdQVVQnKSlcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZGVsZXRlU3luYyhlbmRwb2ludDogc3RyaW5nLCBvcHRpb25zPzogeyBoZWFkZXJzPzogSHR0cEhlYWRlcnMgfSk6IE9ic2VydmFibGU8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpcy52YWxpZGF0ZVJlcXVlc3RDb250ZXh0KCkucGlwZShcbiAgICAgICAgICAgIGNvbmNhdE1hcCgoKSA9PiB0aGlzLmh0dHAuZGVsZXRlPHZvaWQ+KHRoaXMuYnVpbGRFbmRwb2ludFVybChlbmRwb2ludCksIHsgLi4ub3B0aW9ucyB9KSlcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZGVsZXRlQXN5bmMoZW5kcG9pbnQ6IHN0cmluZywgb3B0aW9ucz86IHsgaGVhZGVycz86IEh0dHBIZWFkZXJzIH0pOiBPYnNlcnZhYmxlPFRhc2tUeXBlPiB7XG4gICAgICAgIHJldHVybiB0aGlzLnZhbGlkYXRlUmVxdWVzdENvbnRleHQoKS5waXBlKFxuICAgICAgICAgICAgY29uY2F0TWFwKCgpID0+IHRoaXMuaHR0cC5kZWxldGUodGhpcy5idWlsZEVuZHBvaW50VXJsKGVuZHBvaW50KSwgeyAuLi5vcHRpb25zLCBvYnNlcnZlOiAncmVzcG9uc2UnIH0pKSxcbiAgICAgICAgICAgIGNvbmNhdE1hcChyZXNwb25zZSA9PiB0aGlzLm1hcFJlc3BvbnNlVG9UYXNrKHJlc3BvbnNlLCAnREVMRVRFJykpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBtYXBSZXNwb25zZVRvVGFzayhyZXNwb25zZTogSHR0cFJlc3BvbnNlPGFueT4sIGh0dHBWZXJiOiBzdHJpbmcpOiBPYnNlcnZhYmxlPFRhc2tUeXBlPiB7XG5cbiAgICAgICAgLy9QT1NUIC0gVGFzayBsaW5rIGlzIHJldHVybmVkIGluICdMb2NhdGlvbicgaGVhZGVyXG4gICAgICAgIGlmIChyZXNwb25zZS5oZWFkZXJzLmhhcygnTG9jYXRpb24nKSAmJiByZXNwb25zZS5zdGF0dXMgPT09IDIwMikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaHR0cC5nZXQ8VGFza1R5cGU+KHJlc3BvbnNlLmhlYWRlcnMuZ2V0KCdMb2NhdGlvbicpKTtcbiAgICAgICAgLy9QVVQgLSBUYXNrIGxpbmsgaXMgcmV0dXJuZWQgaW4gJ3gtdm13YXJlLXZjbG91ZC10YXNrLWxvY2F0aW9uJyBoZWFkZXJcbiAgICAgICAgfSBlbHNlIGlmIChyZXNwb25zZS5oZWFkZXJzLmhhcygneC12bXdhcmUtdmNsb3VkLXRhc2stbG9jYXRpb24nKSAmJiByZXNwb25zZS5zdGF0dXMgPT09IDIwMCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaHR0cC5nZXQ8VGFza1R5cGU+KHJlc3BvbnNlLmhlYWRlcnMuZ2V0KCd4LXZtd2FyZS12Y2xvdWQtdGFzay1sb2NhdGlvbicpKTtcbiAgICAgICAgfSBlbHNlIGlmIChyZXNwb25zZS5ib2R5ICYmIHJlc3BvbnNlLmJvZHkudHlwZS5zdGFydHNXaXRoKCdhcHBsaWNhdGlvbi92bmQudm13YXJlLnZjbG91ZC50YXNrKycpKSB7XG4gICAgICAgICAgICBjb25zdCB0YXNrOiBUYXNrVHlwZSA9IE9iamVjdC5hc3NpZ24obmV3IFRhc2tUeXBlKCksIHJlc3BvbnNlLmJvZHkpO1xuICAgICAgICAgICAgcmV0dXJuIG9mKHRhc2spO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRocm93RXJyb3IoKCkgPT4gbmV3IENsaWVudEVycm9yKFxuICAgICAgICAgIGBBbiBhc3luY2hyb25vdXMgcmVxdWVzdCB3YXMgbWFkZSB0byBbJHtodHRwVmVyYn0gJHtyZXNwb25zZS51cmx9XSwgYnV0IG5vIHRhc2sgd2FzIHJldHVybmVkLiAgVGhlIG9wZXJhdGlvbiBtYXkgc3RpbGwgaGF2ZSBiZWVuIHN1Y2Nlc3NmdWwuYCxcbiAgICAgICAgICAgIENsaWVudEVycm9yVHlwZS5UYXNrTGlua01pc3NpbmdcbiAgICAgICAgKSk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldEVudGl0eTxUIGV4dGVuZHMgRW50aXR5UmVmZXJlbmNlVHlwZT4oZW50aXR5UmVmOiBFbnRpdHlSZWZlcmVuY2VUeXBlKTogT2JzZXJ2YWJsZTxUPjtcbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6dW5pZmllZC1zaWduYXR1cmVzXG4gICAgcHVibGljIGdldEVudGl0eTxUIGV4dGVuZHMgRW50aXR5UmVmZXJlbmNlVHlwZT4odXJuOiBzdHJpbmcpOiBPYnNlcnZhYmxlPFQ+O1xuICAgIHB1YmxpYyBnZXRFbnRpdHk8VCBleHRlbmRzIEVudGl0eVJlZmVyZW5jZVR5cGU+KGVudGl0eVJlZk9yVXJuOiBFbnRpdHlSZWZlcmVuY2VUeXBlIHwgc3RyaW5nKTogT2JzZXJ2YWJsZTxUPiB7XG4gICAgICAgIGNvbnN0IGVudGl0eVJlc29sdmVyOiBPYnNlcnZhYmxlPEVudGl0eVR5cGU+ID0gdHlwZW9mIGVudGl0eVJlZk9yVXJuID09PSAnc3RyaW5nJyA/XG4gICAgICAgICAgICB0aGlzLmh0dHAuZ2V0PEVudGl0eVR5cGU+KGAke3RoaXMuX2Jhc2VVcmx9L2FwaS9lbnRpdHkvJHtlbnRpdHlSZWZPclVybn1gKSA6XG4gICAgICAgICAgICB0aGlzLmh0dHAuZ2V0PEVudGl0eVR5cGU+KGAke3RoaXMuX2Jhc2VVcmx9L2FwaS9lbnRpdHkvdXJuOnZjbG91ZDoke2VudGl0eVJlZk9yVXJuLnR5cGV9OiR7ZW50aXR5UmVmT3JVcm4uaWR9YCk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXMudmFsaWRhdGVSZXF1ZXN0Q29udGV4dCgpLnBpcGUoXG4gICAgICAgICAgICBjb25jYXRNYXAoKCkgPT4gZW50aXR5UmVzb2x2ZXIpLFxuICAgICAgICAgICAgY29uY2F0TWFwKGVudGl0eSA9PiB0aGlzLmh0dHAuZ2V0PFQ+KGAke2VudGl0eS5saW5rWzBdLmhyZWZ9YCkpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHVibGljIHVwZGF0ZVRhc2sodGFzazogVGFza1R5cGUsIG9wdGlvbnM/OiB7IGhlYWRlcnM/OiBIdHRwSGVhZGVycyB9KTogT2JzZXJ2YWJsZTxUYXNrVHlwZT4ge1xuICAgICAgICByZXR1cm4gdGhpcy52YWxpZGF0ZVJlcXVlc3RDb250ZXh0KCkucGlwZShcbiAgICAgICAgICAgIGNvbmNhdE1hcCgoKSA9PiB0aGlzLmh0dHAuZ2V0PFRhc2tUeXBlPih0YXNrLmhyZWYsIHsgLi4ub3B0aW9ucyB9KSlcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgaXNUYXNrQ29tcGxldGUodGFzazogVGFza1R5cGUpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIFsnc3VjY2VzcycsICdlcnJvcicsICdjYW5jZWxlZCcsICdhYm9ydGVkJ10uaW5kZXhPZih0YXNrLnN0YXR1cykgPiAtMTtcbiAgICB9XG5cbiAgICBwdWJsaWMgcmVtb3ZlSXRlbShpdGVtOiBOYXZpZ2FibGUsIG9wdGlvbnM/OiB7IGhlYWRlcnM/OiBIdHRwSGVhZGVycyB9KTogT2JzZXJ2YWJsZTxUYXNrVHlwZT4ge1xuICAgICAgICBjb25zdCBsaW5rOiBMaW5rVHlwZSA9IHRoaXMuZmluZExpbmsoaXRlbSwgJ3JlbW92ZScsIG51bGwpO1xuICAgICAgICBpZiAoIWxpbmspIHtcbiAgICAgICAgICAgIHJldHVybiB0aHJvd0Vycm9yKCgpID0+IG5ldyBDbGllbnRFcnJvcihcbiAgICAgICAgICAgICAgYE5vICdyZW1vdmUnIGxpbmsgZm9yIHNwZWNpZmllZCByZXNvdXJjZS5gLFxuICAgICAgICAgICAgICBDbGllbnRFcnJvclR5cGUuSGF0ZW9hc0xpbmtNaXNzaW5nXG4gICAgICAgICAgICApKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLnZhbGlkYXRlUmVxdWVzdENvbnRleHQoKS5waXBlKFxuICAgICAgICAgICAgY29uY2F0TWFwKCgpID0+IHRoaXMuaHR0cC5kZWxldGU8VGFza1R5cGU+KGxpbmsuaHJlZiwgeyAuLi5vcHRpb25zIH0pKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFF1ZXJpZXMgdGhlIFZNd2FyZSBDbG91ZCBEaXJlY3RvciBBUEkgYmFzZWQgb24gdGhlIHNwZWNpZmllZCBRdWVyeS5CdWlsZGVyIGluc3RhbmNlLlxuICAgICAqXG4gICAgICogQHBhcmFtIGJ1aWxkZXIgQW4gZGVmaW5pdGlvbiBvZiB0aGUgcXVlcnkgdG8gY29uc3RydWN0ICh0eXBlLCBmaWx0ZXIsIHBhZ2Ugc2l6ZSwgZXRjLilcbiAgICAgKiBAcGFyYW0gbXVsdGlzaXRlIGEgZmxhZyBpbmRpY2F0aW5nIHdoZXRoZXIgb3Igbm90IHRvIGZhbiB0aGUgcXVlcnkgb3V0IHRvIGFsbCBhdmFpbGFibGUgc2l0ZXNcbiAgICAgKiBAcmV0dXJucyBhIHF1ZXJ5IHJlc3VsdCBmb3IgdGhlIHNwZWNpZmllZCBxdWVyeVxuICAgICAqL1xuICAgIHB1YmxpYyBxdWVyeTxUPihidWlsZGVyOiBRdWVyeS5CdWlsZGVyLCBtdWx0aXNpdGU/OiBib29sZWFuLCBvcHRpb25zPzogeyBoZWFkZXJzPzogSHR0cEhlYWRlcnMgfSk6IE9ic2VydmFibGU8VD47XG4gICAgLyoqXG4gICAgICogUXVlcmllcyB0aGUgVk13YXJlIENsb3VkIERpcmVjdG9yIEFQSSBiYXNlZCBvbiB0aGUgc3BlY2lmaWVkIFF1ZXJ5LkJ1aWxkZXIgaW5zdGFuY2UuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gYnVpbGRlciBBbiBkZWZpbml0aW9uIG9mIHRoZSBxdWVyeSB0byBjb25zdHJ1Y3QgKHR5cGUsIGZpbHRlciwgcGFnZSBzaXplLCBldGMuKVxuICAgICAqIEBwYXJhbSBtdWx0aXNpdGUgdGhlIHNldCBvZiBzaXRlIGxvY2F0aW9ucyB0byBpbmNsdWRlIGluIHRoZSBxdWVyeSBmYW5vdXRcbiAgICAgKiBAcmV0dXJucyBhIHF1ZXJ5IHJlc3VsdCBmb3IgdGhlIHNwZWNpZmllZCBxdWVyeVxuICAgICAqL1xuICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTp1bmlmaWVkLXNpZ25hdHVyZXNcbiAgICBwdWJsaWMgcXVlcnk8VD4oYnVpbGRlcjogUXVlcnkuQnVpbGRlciwgbXVsdGlzaXRlPzogQXV0aG9yaXplZExvY2F0aW9uVHlwZVtdLCBvcHRpb25zPzogeyBoZWFkZXJzPzogSHR0cEhlYWRlcnMgfSk6IE9ic2VydmFibGU8VD47XG4gICAgcHVibGljIHF1ZXJ5PFQ+KGJ1aWxkZXI6IFF1ZXJ5LkJ1aWxkZXIsIG11bHRpc2l0ZT86IGFueSwgb3B0aW9ucz86IHsgaGVhZGVycz86IEh0dHBIZWFkZXJzIH0pOiBPYnNlcnZhYmxlPFQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UXVlcnlQYWdlKGAke3RoaXMuX2Jhc2VVcmx9L2FwaS9xdWVyeSR7YnVpbGRlci5nZXQoKX1gLCBtdWx0aXNpdGUsIG9wdGlvbnMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFF1ZXJpZXMgdGhlIFZNd2FyZSBDbG91ZCBEaXJlY3RvciBBUEkgZm9yIHRoZSBmaXJzdCBwYWdlIG9mIHRoZSBwcm92aWRlZCByZXN1bHQgc2V0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHJlc3VsdCB0aGUgcmVzdWx0IHNldCB0byByZXRyaWV2ZSB0aGUgZmlyc3QgcGFnZSBvZiByZWNvcmRzIGZvclxuICAgICAqIEBwYXJhbSBtdWx0aXNpdGUgYSBmbGFnIGluZGljYXRpbmcgd2hldGhlciBvciBub3QgdG8gZmFuIHRoZSBxdWVyeSBvdXQgdG8gYWxsIGF2YWlsYWJsZSBzaXRlc1xuICAgICAqIEByZXR1cm5zIHRoZSByZWNvcmRzIGZvciB0aGUgZmlyc3QgcGFnZSBvZiB0aGUgcXVlcnlcbiAgICAgKi9cbiAgICBwdWJsaWMgZmlyc3RQYWdlPFQ+KHJlc3VsdDogVCwgbXVsdGlzaXRlPzogYm9vbGVhbiwgb3B0aW9ucz86IHsgaGVhZGVycz86IEh0dHBIZWFkZXJzIH0pOiBPYnNlcnZhYmxlPFQ+O1xuICAgIC8qKlxuICAgICAqIFF1ZXJpZXMgdGhlIFZNd2FyZSBDbG91ZCBEaXJlY3RvciBBUEkgZm9yIHRoZSBmaXJzdCBwYWdlIG9mIHRoZSBwcm92aWRlZCByZXN1bHQgc2V0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHJlc3VsdCB0aGUgcmVzdWx0IHNldCB0byByZXRyaWV2ZSB0aGUgZmlyc3QgcGFnZSBvZiByZWNvcmRzIGZvclxuICAgICAqIEBwYXJhbSBtdWx0aXNpdGUgdGhlIHNldCBvZiBzaXRlIGxvY2F0aW9ucyB0byBpbmNsdWRlIGluIHRoZSBxdWVyeSBmYW5vdXRcbiAgICAgKiBAcmV0dXJucyB0aGUgcmVjb3JkcyBmb3IgdGhlIGZpcnN0IHBhZ2Ugb2YgdGhlIHF1ZXJ5XG4gICAgICovXG4gICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOnVuaWZpZWQtc2lnbmF0dXJlc1xuICAgIHB1YmxpYyBmaXJzdFBhZ2U8VD4ocmVzdWx0OiBULCBtdWx0aXNpdGU/OiBBdXRob3JpemVkTG9jYXRpb25UeXBlW10sIG9wdGlvbnM/OiB7IGhlYWRlcnM/OiBIdHRwSGVhZGVycyB9KTogT2JzZXJ2YWJsZTxUPjtcbiAgICBwdWJsaWMgZmlyc3RQYWdlPFQ+KHJlc3VsdDogVCwgbXVsdGlzaXRlPzogYW55LCBvcHRpb25zPzogeyBoZWFkZXJzPzogSHR0cEhlYWRlcnMgfSk6IE9ic2VydmFibGU8VD4ge1xuICAgICAgICBjb25zdCBsaW5rOiBMaW5rVHlwZSA9IHRoaXMuZmluZExpbmsocmVzdWx0LCAnZmlyc3RQYWdlJywgKHJlc3VsdCBhcyBSZXNvdXJjZVR5cGUpLnR5cGUpO1xuICAgICAgICBpZiAoIWxpbmspIHtcbiAgICAgICAgICAgIHJldHVybiB0aHJvd0Vycm9yKCgpID0+IG5ldyBDbGllbnRFcnJvcihcbiAgICAgICAgICAgICAgYE5vICdmaXJzdFBhZ2UnIGxpbmsgZm9yIHNwZWNpZmllZCBxdWVyeS5gLFxuICAgICAgICAgICAgICBDbGllbnRFcnJvclR5cGUuSGF0ZW9hc0xpbmtNaXNzaW5nXG4gICAgICAgICAgICApKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLmdldFF1ZXJ5UGFnZShsaW5rLmhyZWYsIG11bHRpc2l0ZSwgb3B0aW9ucyk7XG4gICAgfVxuXG4gICAgcHVibGljIGhhc0ZpcnN0UGFnZTxUPihyZXN1bHQ6IFQpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICEhdGhpcy5maW5kTGluayhyZXN1bHQsICdmaXJzdFBhZ2UnLCAocmVzdWx0IGFzIFJlc291cmNlVHlwZSkudHlwZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUXVlcmllcyB0aGUgVk13YXJlIENsb3VkIERpcmVjdG9yIEFQSSBmb3IgdGhlIHByZXZpb3VzIHBhZ2Ugb2YgdGhlIHByb3ZpZGVkIHJlc3VsdCBzZXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gcmVzdWx0IHRoZSByZXN1bHQgc2V0IHRvIHJldHJpZXZlIHRoZSBwcmV2aW91cyBwYWdlIG9mIHJlY29yZHMgZm9yXG4gICAgICogQHBhcmFtIG11bHRpc2l0ZSBhIGZsYWcgaW5kaWNhdGluZyB3aGV0aGVyIG9yIG5vdCB0byBmYW4gdGhlIHF1ZXJ5IG91dCB0byBhbGwgYXZhaWxhYmxlIHNpdGVzXG4gICAgICogQHJldHVybnMgdGhlIHJlY29yZHMgZm9yIHRoZSBwcmV2aW91cyBwYWdlIG9mIHRoZSBxdWVyeVxuICAgICAqL1xuICAgIHB1YmxpYyBwcmV2aW91c1BhZ2U8VD4ocmVzdWx0OiBULCBtdWx0aXNpdGU/OiBib29sZWFuLCBvcHRpb25zPzogeyBoZWFkZXJzPzogSHR0cEhlYWRlcnMgfSk6IE9ic2VydmFibGU8VD47XG4gICAgLyoqXG4gICAgICogUXVlcmllcyB0aGUgVk13YXJlIENsb3VkIERpcmVjdG9yIEFQSSBmb3IgdGhlIHByZXZpb3VzIHBhZ2Ugb2YgdGhlIHByb3ZpZGVkIHJlc3VsdCBzZXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gcmVzdWx0IHRoZSByZXN1bHQgc2V0IHRvIHJldHJpZXZlIHRoZSBwcmV2aW91cyBwYWdlIG9mIHJlY29yZHMgZm9yXG4gICAgICogQHBhcmFtIG11bHRpc2l0ZSB0aGUgc2V0IG9mIHNpdGUgbG9jYXRpb25zIHRvIGluY2x1ZGUgaW4gdGhlIHF1ZXJ5IGZhbm91dFxuICAgICAqIEByZXR1cm5zIHRoZSByZWNvcmRzIGZvciB0aGUgcHJldmlvdXMgcGFnZSBvZiB0aGUgcXVlcnlcbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6dW5pZmllZC1zaWduYXR1cmVzXG4gICAgcHVibGljIHByZXZpb3VzUGFnZTxUPihyZXN1bHQ6IFQsIG11bHRpc2l0ZT86IEF1dGhvcml6ZWRMb2NhdGlvblR5cGVbXSwgb3B0aW9ucz86IHsgaGVhZGVycz86IEh0dHBIZWFkZXJzIH0pOiBPYnNlcnZhYmxlPFQ+O1xuICAgIHB1YmxpYyBwcmV2aW91c1BhZ2U8VD4ocmVzdWx0OiBULCBtdWx0aXNpdGU/OiBhbnksIG9wdGlvbnM/OiB7IGhlYWRlcnM/OiBIdHRwSGVhZGVycyB9KTogT2JzZXJ2YWJsZTxUPiB7XG4gICAgICAgIGNvbnN0IGxpbms6IExpbmtUeXBlID0gdGhpcy5maW5kTGluayhyZXN1bHQsICdwcmV2aW91c1BhZ2UnLCAocmVzdWx0IGFzIFJlc291cmNlVHlwZSkudHlwZSk7XG4gICAgICAgIGlmICghbGluaykge1xuICAgICAgICAgICAgcmV0dXJuIHRocm93RXJyb3IoKCkgPT4gbmV3IENsaWVudEVycm9yKFxuICAgICAgICAgICAgICBgTm8gJ3ByZXZpb3VzUGFnZScgbGluayBmb3Igc3BlY2lmaWVkIHF1ZXJ5LmAsXG4gICAgICAgICAgICAgIENsaWVudEVycm9yVHlwZS5IYXRlb2FzTGlua01pc3NpbmdcbiAgICAgICAgICAgICAgKSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5nZXRRdWVyeVBhZ2UobGluay5ocmVmLCBtdWx0aXNpdGUsIG9wdGlvbnMpO1xuICAgIH1cblxuICAgIHB1YmxpYyBoYXNQcmV2aW91c1BhZ2U8VD4ocmVzdWx0OiBUKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiAhIXRoaXMuZmluZExpbmsocmVzdWx0LCAncHJldmlvdXNQYWdlJywgKHJlc3VsdCBhcyBSZXNvdXJjZVR5cGUpLnR5cGUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFF1ZXJpZXMgdGhlIFZNd2FyZSBDbG91ZCBEaXJlY3RvciBBUEkgZm9yIHRoZSBuZXh0IHBhZ2Ugb2YgdGhlIHByb3ZpZGVkIHJlc3VsdCBzZXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gcmVzdWx0IHRoZSByZXN1bHQgc2V0IHRvIHJldHJpZXZlIHRoZSBuZXh0IHBhZ2Ugb2YgcmVjb3JkcyBmb3JcbiAgICAgKiBAcGFyYW0gbXVsdGlzaXRlIGEgZmxhZyBpbmRpY2F0aW5nIHdoZXRoZXIgb3Igbm90IHRvIGZhbiB0aGUgcXVlcnkgb3V0IHRvIGFsbCBhdmFpbGFibGUgc2l0ZXNcbiAgICAgKiBAcmV0dXJucyB0aGUgcmVjb3JkcyBmb3IgdGhlIG5leHQgcGFnZSBvZiB0aGUgcXVlcnlcbiAgICAgKi9cbiAgICBwdWJsaWMgbmV4dFBhZ2U8VD4ocmVzdWx0OiBULCBtdWx0aXNpdGU/OiBib29sZWFuLCBvcHRpb25zPzogeyBoZWFkZXJzPzogSHR0cEhlYWRlcnMgfSk6IE9ic2VydmFibGU8VD47XG4gICAgLyoqXG4gICAgICogUXVlcmllcyB0aGUgVk13YXJlIENsb3VkIERpcmVjdG9yIEFQSSBmb3IgdGhlIG5leHQgcGFnZSBvZiB0aGUgcHJvdmlkZWQgcmVzdWx0IHNldC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSByZXN1bHQgdGhlIHJlc3VsdCBzZXQgdG8gcmV0cmlldmUgdGhlIG5leHQgcGFnZSBvZiByZWNvcmRzIGZvclxuICAgICAqIEBwYXJhbSBtdWx0aXNpdGUgdGhlIHNldCBvZiBzaXRlIGxvY2F0aW9ucyB0byBpbmNsdWRlIGluIHRoZSBxdWVyeSBmYW5vdXRcbiAgICAgKiBAcmV0dXJucyB0aGUgcmVjb3JkcyBmb3IgdGhlIG5leHQgcGFnZSBvZiB0aGUgcXVlcnlcbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6dW5pZmllZC1zaWduYXR1cmVzXG4gICAgcHVibGljIG5leHRQYWdlPFQ+KHJlc3VsdDogVCwgbXVsdGlzaXRlPzogQXV0aG9yaXplZExvY2F0aW9uVHlwZVtdLCBvcHRpb25zPzogeyBoZWFkZXJzPzogSHR0cEhlYWRlcnMgfSk6IE9ic2VydmFibGU8VD47XG4gICAgcHVibGljIG5leHRQYWdlPFQ+KHJlc3VsdDogVCwgbXVsdGlzaXRlPzogYW55LCBvcHRpb25zPzogeyBoZWFkZXJzPzogSHR0cEhlYWRlcnMgfSk6IE9ic2VydmFibGU8VD4ge1xuICAgICAgICBjb25zdCBsaW5rOiBMaW5rVHlwZSA9IHRoaXMuZmluZExpbmsocmVzdWx0LCAnbmV4dFBhZ2UnLCAocmVzdWx0IGFzIFJlc291cmNlVHlwZSkudHlwZSk7XG4gICAgICAgIGlmICghbGluaykge1xuICAgICAgICAgICAgcmV0dXJuIHRocm93RXJyb3IoKCkgPT4gbmV3IENsaWVudEVycm9yKFxuICAgICAgICAgICAgICBgTm8gJ25leHRQYWdlJyBsaW5rIGZvciBzcGVjaWZpZWQgcXVlcnkuYCxcbiAgICAgICAgICAgICAgQ2xpZW50RXJyb3JUeXBlLkhhdGVvYXNMaW5rTWlzc2luZ1xuICAgICAgICAgICAgICApKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLmdldFF1ZXJ5UGFnZTxUPihsaW5rLmhyZWYsIG11bHRpc2l0ZSwgb3B0aW9ucyk7XG4gICAgfVxuXG4gICAgcHVibGljIGhhc05leHRQYWdlPFQ+KHJlc3VsdDogVCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gISF0aGlzLmZpbmRMaW5rKHJlc3VsdCwgJ25leHRQYWdlJywgKHJlc3VsdCBhcyBSZXNvdXJjZVR5cGUpLnR5cGUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFF1ZXJpZXMgdGhlIFZNd2FyZSBDbG91ZCBEaXJlY3RvciBBUEkgZm9yIHRoZSBsYXN0IHBhZ2Ugb2YgdGhlIHByb3ZpZGVkIHJlc3VsdCBzZXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gcmVzdWx0IHRoZSByZXN1bHQgc2V0IHRvIHJldHJpZXZlIHRoZSBsYXN0IHBhZ2Ugb2YgcmVjb3JkcyBmb3JcbiAgICAgKiBAcGFyYW0gbXVsdGlzaXRlIGEgZmxhZyBpbmRpY2F0aW5nIHdoZXRoZXIgb3Igbm90IHRvIGZhbiB0aGUgcXVlcnkgb3V0IHRvIGFsbCBhdmFpbGFibGUgc2l0ZXNcbiAgICAgKiBAcmV0dXJucyB0aGUgcmVjb3JkcyBmb3IgdGhlIGxhc3QgcGFnZSBvZiB0aGUgcXVlcnlcbiAgICAgKi9cbiAgICBwdWJsaWMgbGFzdFBhZ2U8VD4ocmVzdWx0OiBULCBtdWx0aXNpdGU/OiBib29sZWFuLCBvcHRpb25zPzogeyBoZWFkZXJzPzogSHR0cEhlYWRlcnMgfSk6IE9ic2VydmFibGU8VD47XG4gICAgLyoqXG4gICAgICogUXVlcmllcyB0aGUgVk13YXJlIENsb3VkIERpcmVjdG9yIEFQSSBmb3IgdGhlIGxhc3QgcGFnZSBvZiB0aGUgcHJvdmlkZWQgcmVzdWx0IHNldC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSByZXN1bHQgdGhlIHJlc3VsdCBzZXQgdG8gcmV0cmlldmUgdGhlIGxhc3QgcGFnZSBvZiByZWNvcmRzIGZvclxuICAgICAqIEBwYXJhbSBtdWx0aXNpdGUgdGhlIHNldCBvZiBzaXRlIGxvY2F0aW9ucyB0byBpbmNsdWRlIGluIHRoZSBxdWVyeSBmYW5vdXRcbiAgICAgKiBAcmV0dXJucyB0aGUgcmVjb3JkcyBmb3IgdGhlIGxhc3QgcGFnZSBvZiB0aGUgcXVlcnlcbiAgICAgKi9cbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6dW5pZmllZC1zaWduYXR1cmVzXG4gICAgcHVibGljIGxhc3RQYWdlPFQ+KHJlc3VsdDogVCwgbXVsdGlzaXRlPzogQXV0aG9yaXplZExvY2F0aW9uVHlwZVtdLCBvcHRpb25zPzogeyBoZWFkZXJzPzogSHR0cEhlYWRlcnMgfSk6IE9ic2VydmFibGU8VD47XG4gICAgcHVibGljIGxhc3RQYWdlPFQ+KHJlc3VsdDogVCwgbXVsdGlzaXRlPzogYW55LCBvcHRpb25zPzogeyBoZWFkZXJzPzogSHR0cEhlYWRlcnMgfSk6IE9ic2VydmFibGU8VD4ge1xuICAgICAgICBjb25zdCBsaW5rOiBMaW5rVHlwZSA9IHRoaXMuZmluZExpbmsocmVzdWx0LCAnbGFzdFBhZ2UnLCAocmVzdWx0IGFzIFJlc291cmNlVHlwZSkudHlwZSk7XG4gICAgICAgIGlmICghbGluaykge1xuICAgICAgICAgICAgcmV0dXJuIHRocm93RXJyb3IoKCkgPT4gbmV3IENsaWVudEVycm9yKFxuICAgICAgICAgICAgICBgTm8gJ2xhc3RQYWdlJyBsaW5rIGZvciBzcGVjaWZpZWQgcXVlcnkuYCxcbiAgICAgICAgICAgICAgQ2xpZW50RXJyb3JUeXBlLkhhdGVvYXNMaW5rTWlzc2luZ1xuICAgICAgICAgICAgKSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5nZXRRdWVyeVBhZ2UobGluay5ocmVmLCBtdWx0aXNpdGUsIG9wdGlvbnMpO1xuICAgIH1cblxuICAgIHB1YmxpYyBoYXNMYXN0UGFnZTxUPihyZXN1bHQ6IFQpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICEhdGhpcy5maW5kTGluayhyZXN1bHQsICdsYXN0UGFnZScsIChyZXN1bHQgYXMgUmVzb3VyY2VUeXBlKS50eXBlKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldFF1ZXJ5UGFnZTxUPihocmVmOiBzdHJpbmcsIG11bHRpc2l0ZT86IGFueSwgb3B0aW9ucz86IHsgaGVhZGVycz86IEh0dHBIZWFkZXJzIH0pOiBPYnNlcnZhYmxlPFQ+IHtcbiAgICAgICAgaWYgKG11bHRpc2l0ZSkge1xuICAgICAgICAgICAgaWYgKCFvcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuaHR0cC5nZXQ8VD4oaHJlZiwgeyBoZWFkZXJzOiBuZXcgSHR0cEhlYWRlcnMoeyBfbXVsdGlzaXRlOiB0aGlzLnBhcnNlTXVsdGlzaXRlVmFsdWUobXVsdGlzaXRlKSB9KSB9KVxuICAgICAgICAgICAgfSBlbHNlIGlmIChvcHRpb25zPy5oZWFkZXJzKSB7XG4gICAgICAgICAgICAgICAgb3B0aW9ucy5oZWFkZXJzLmFwcGVuZChcIl9tdWx0aXNpdGVcIiwgdGhpcy5wYXJzZU11bHRpc2l0ZVZhbHVlKG11bHRpc2l0ZSkpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmh0dHAuZ2V0PFQ+KGhyZWYsIHsgLi4ub3B0aW9ucyB9KVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMudmFsaWRhdGVSZXF1ZXN0Q29udGV4dCgpLnBpcGUoXG4gICAgICAgICAgICBjb25jYXRNYXAoKCkgPT4gdGhpcy5odHRwLmdldDxUPihocmVmLCB7IC4uLm9wdGlvbnMgfSkpXG4gICAgICAgICk7XG4gICAgfVxuXG4gIC8qKlxuICAgKiBVc2UgdG8gcGVyZm9ybSBhY3Rpb24gYXZhaWxhYmlsaXR5IGNoZWNrIGJlZm9yZSBjYWxsaW5nIHRoZSBBUElcbiAgICogQHBhcmFtIGl0ZW0gLSB0aGUgbmF2aWdhYmxlIGl0ZW0gKGNvbnRhaW5pbmcgbGluayBjb2xsZWN0aW9uKVxuICAgKiBAcGFyYW0gbGlua1JlbFR5cGUgLSB0aGUgbGluayByZWwgdHlwZSwgcGFzcyBlaXRoZXIgTGlua1JlbFR5cGUgb3Igc3RyaW5nXG4gICAqIEBwYXJhbSBlbnRpdHlSZWZUeXBlIC0gdGhlIGVudGl0eSByZWZlcmVuY2UgdHlwZVxuICAgKi9cbiAgICBwdWJsaWMgY2FuUGVyZm9ybUFjdGlvbihpdGVtOiBOYXZpZ2FibGUsIGxpbmtSZWxUeXBlOiBMaW5rUmVsVHlwZSB8IHN0cmluZywgZW50aXR5UmVmVHlwZT86IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gISF0aGlzLmZpbmRMaW5rKGl0ZW0sIGxpbmtSZWxUeXBlLCBlbnRpdHlSZWZUeXBlKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGZpbmRMaW5rKGl0ZW06IE5hdmlnYWJsZSwgcmVsOiBzdHJpbmcsIHR5cGU6IHN0cmluZyk6IExpbmtUeXBlIHtcbiAgICAgICAgaWYgKCFpdGVtIHx8ICFpdGVtLmxpbmspIHtcbiAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gaXRlbS5saW5rLmZpbmQoKGxpbmspID0+IHtcbiAgICAgICAgICAgIGlmICh0eXBlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGxpbmsucmVsLmluY2x1ZGVzKHJlbCkgJiYgbGluay50eXBlID09PSB0eXBlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gbGluay5yZWwuaW5jbHVkZXMocmVsKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBwYXJzZU11bHRpc2l0ZVZhbHVlKG11bHRpc2l0ZTogYm9vbGVhbiB8IEF1dGhvcml6ZWRMb2NhdGlvblR5cGVbXSk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0eXBlb2YgbXVsdGlzaXRlID09PSAnYm9vbGVhbicgPyAobXVsdGlzaXRlID8gJ2dsb2JhbCcgOiAnbG9jYWwnKSA6IG11bHRpc2l0ZS5tYXAoc2l0ZSA9PiBzaXRlLmxvY2F0aW9uSWQpLmpvaW4oJywnKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAZGVwcmVjYXRlZCBVc2UgY2xvdWRBcGlTZXNzaW9uXG4gICAgICovXG4gICAgcHVibGljIGdldCBzZXNzaW9uKCk6IE9ic2VydmFibGU8U2Vzc2lvblR5cGU+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMudmFsaWRhdGVSZXF1ZXN0Q29udGV4dCgpLnBpcGUoXG4gICAgICAgICAgICBjb25jYXRNYXAoKCkgPT4gdGhpcy5fc2Vzc2lvbk9ic2VydmFibGUpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2V0IFNlc3Npb24gb2JzZXJ2YWJsZVxuICAgICAqL1xuICAgIHB1YmxpYyBnZXQgY2xvdWRBcGlTZXNzaW9uKCk6IE9ic2VydmFibGU8U2Vzc2lvbj4ge1xuICAgICAgICByZXR1cm4gdGhpcy52YWxpZGF0ZVJlcXVlc3RDb250ZXh0Q2xvdWRBcGlPbmx5KCkucGlwZShcbiAgICAgICAgICAgIGNvbmNhdE1hcCgoKSA9PiB0aGlzLl9jbG91ZEFwaVNlc3Npb25PYnNlcnZhYmxlKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXQgdXNlcm5hbWUoKTogT2JzZXJ2YWJsZTxzdHJpbmc+IHtcbiAgICAgICAgcmV0dXJuIG1lcmdlKFxuICAgICAgICAgICAgICAgIHRoaXMuY2xvdWRBcGlTZXNzaW9uLnBpcGUoXG4gICAgICAgICAgICAgICAgICAgIGZpbHRlcigoKSA9PiB0aGlzLl9pc0Nsb3VkQXBpTG9naW4pLFxuICAgICAgICAgICAgICAgICAgICBtYXAoc2Vzc2lvbiA9PiBzZXNzaW9uICYmIHNlc3Npb24udXNlciAmJiBzZXNzaW9uLnVzZXIubmFtZSlcbiAgICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgICAgIHRoaXMuc2Vzc2lvbi5waXBlKFxuICAgICAgICAgICAgICAgICAgICBmaWx0ZXIoKCkgPT4gIXRoaXMuX2lzQ2xvdWRBcGlMb2dpbiksXG4gICAgICAgICAgICAgICAgICAgIG1hcChzZXNzaW9uID0+IHNlc3Npb24gJiYgc2Vzc2lvbi51c2VyKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldCBvcmdhbml6YXRpb24oKTogT2JzZXJ2YWJsZTxzdHJpbmc+IHtcbiAgICAgICAgcmV0dXJuIG1lcmdlKFxuICAgICAgICAgICAgdGhpcy5jbG91ZEFwaVNlc3Npb24ucGlwZShcbiAgICAgICAgICAgICAgICBmaWx0ZXIoKCkgPT4gdGhpcy5faXNDbG91ZEFwaUxvZ2luKSxcbiAgICAgICAgICAgICAgICBtYXAoc2Vzc2lvbiA9PiBzZXNzaW9uICYmIHNlc3Npb24ub3JnICYmIHNlc3Npb24ub3JnLm5hbWUpXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgdGhpcy5zZXNzaW9uLnBpcGUoXG4gICAgICAgICAgICAgICAgZmlsdGVyKCgpID0+ICF0aGlzLl9pc0Nsb3VkQXBpTG9naW4pLFxuICAgICAgICAgICAgICAgIG1hcChzZXNzaW9uID0+IHNlc3Npb24gJiYgc2Vzc2lvbi5vcmcpXG4gICAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQGRlcHJlY2F0ZWQgVXNlIGNsb3VkQXBpTG9jYXRpb25cbiAgICAgKi9cbiAgICBwdWJsaWMgZ2V0IGxvY2F0aW9uKCk6IE9ic2VydmFibGU8QXV0aG9yaXplZExvY2F0aW9uVHlwZT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5zZXNzaW9uLnBpcGUoXG4gICAgICAgICAgICBtYXAoc2Vzc2lvbiA9PiBzZXNzaW9uLmF1dGhvcml6ZWRMb2NhdGlvbnMubG9jYXRpb24uZmluZChsb2NhdGlvbiA9PiBsb2NhdGlvbi5sb2NhdGlvbklkID09PSBzZXNzaW9uLmxvY2F0aW9uSWQpKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdldHMgdGhlIGxvY2F0aW9uIGNvcnJlc3BvbmRpbmcgdG8gdGhlIGN1cnJlbnQgc2Vzc2lvblxuICAgICAqL1xuICAgIHB1YmxpYyBnZXQgY2xvdWRBcGlMb2NhdGlvbigpOiBPYnNlcnZhYmxlPEFjY2Vzc2libGVMb2NhdGlvbj4ge1xuICAgICAgICByZXR1cm4gdGhpcy5jbG91ZEFwaVNlc3Npb24ucGlwZShcbiAgICAgICAgICAgIHN3aXRjaE1hcCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLl9jbG91ZEFwaUFjY2Vzc2libGVMb2NhdGlvbnMpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gRW5zdXJlIGNhY2hpbmcgZm9yIGdldHRpbmcgQWNjZXNzaWJsZUxvY2F0aW9uc1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9jbG91ZEFwaUFjY2Vzc2libGVMb2NhdGlvbnMgPSB0aGlzLl9jbG91ZEFwaVNlc3Npb25MaW5rc1xuICAgICAgICAgICAgICAgICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gR2V0IHRoZSBBY2Nlc3NpYmxlTG9jYXRpb25zIGxpbmtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXAoKGxpbmtzKSA9PiB0aGlzLmZpbmRMaW5rKHsgbGluazogbGlua3MgfSwgJ2Rvd24nLCAnQWNjZXNzaWJsZUxvY2F0aW9ucycpKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGZXRjaCBBY2Nlc3NpYmxlTG9jYXRpb25zIGZyb20gdGhlIGJhY2tlbmRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2hNYXAoKGxpbms6IExpbmtUeXBlKSA9PiBsaW5rID8gdGhpcy5odHRwLmdldDxBY2Nlc3NpYmxlTG9jYXRpb25zPihsaW5rLmhyZWYpIDogb2YobnVsbCkpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEdldCB0aGUgYXJyYXkgd2l0aCBhbGwgbG9jYXRpb25zICh3aGF0IGlmIHRoZXJlIGFyZSBtYW55IHBhZ2VzKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcCgoYWNjZXNzaWJsZUxvY2F0aW9uczogQWNjZXNzaWJsZUxvY2F0aW9ucykgPT4gYWNjZXNzaWJsZUxvY2F0aW9ucyAmJiBhY2Nlc3NpYmxlTG9jYXRpb25zLnZhbHVlcylcbiAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICAgIC5waXBlKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNoYXJlKHsgY29ubmVjdG9yOiAoKSA9PiBuZXcgUmVwbGF5U3ViamVjdCgxKSwgcmVzZXRPbkVycm9yOiBmYWxzZSwgcmVzZXRPbkNvbXBsZXRlOiBmYWxzZSwgcmVzZXRPblJlZkNvdW50WmVybzogZmFsc2UgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9jbG91ZEFwaUFjY2Vzc2libGVMb2NhdGlvbnM7XG4gICAgICAgICAgICB9KSxcblxuICAgICAgICAgICAgLy8gTmVlZCB0byBoYXZlIHRoZSBzZXNzaW9uIGluIG9yZGVyIHRvIGdldCBpdHMgbG9jYXRpb25cbiAgICAgICAgICAgIHdpdGhMYXRlc3RGcm9tKHRoaXMuY2xvdWRBcGlTZXNzaW9uKSxcbiAgICAgICAgICAgIC8vIEZpbmQgdGhlIGxvY2F0aW9uIHRoYXQgY29ycmVzcG9uZHMgdG8gdGhpcyBzZXNzaW9uXG4gICAgICAgICAgICBtYXAoKFthY2Nlc3NpYmxlTG9jYXRpb25zLCBzZXNzaW9uXSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmICghYWNjZXNzaWJsZUxvY2F0aW9ucyB8fCAhc2Vzc2lvbikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29uc3Qgc2Vzc2lvbkxvY2F0aW9uID0gc2Vzc2lvbi5sb2NhdGlvbjtcbiAgICAgICAgICAgICAgICBpZiAoIXNlc3Npb25Mb2NhdGlvbikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGFjY2Vzc2libGVMb2NhdGlvbnMuZmluZChsb2NhdGlvbiA9PiBsb2NhdGlvbi5sb2NhdGlvbklkID09PSBzZXNzaW9uTG9jYXRpb24pO1xuICAgICAgICAgICAgfSksXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldExvY2F0aW9uKHNlc3Npb246IFNlc3Npb25UeXBlKTogQXV0aG9yaXplZExvY2F0aW9uVHlwZSB7XG4gICAgICAgIHJldHVybiBzZXNzaW9uLmF1dGhvcml6ZWRMb2NhdGlvbnMubG9jYXRpb24uZmluZChsb2NhdGlvbiA9PiBsb2NhdGlvbi5sb2NhdGlvbklkID09PSBzZXNzaW9uLmxvY2F0aW9uSWQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEJ1aWxkIHRoZSBlbmRwb2ludCB1cmwuIElmIHRoZSBwcm92aWRlZCBlbmRwb2ludCBpcyBhbHJlYWR5IGFuIGFic29sdXRlIFVSTCwgdGhlbiByZXR1cm4gaXQgYXMgaXQgaXMgd2l0aG91dFxuICAgICAqIGFueSBtb2RpZmljYXRpb25zLCBvdGhlcndpc2UgY29uc2lkZXIgaXQgYXMgYSByZWxhdGl2ZSBvbmUgYW5kIHByZXBlbmQgdGhlIGJhc2VVcmwgYXMgZGVmaW5lZCBieSB0aGUgaG9zdCBhcHBsaWNhdGlvbi5cbiAgICAgKi9cbiAgICBwcml2YXRlIGJ1aWxkRW5kcG9pbnRVcmwoZW5kcG9pbnQ6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiBlbmRwb2ludC5pbmRleE9mKCc6Ly8nKSA+IC0xID8gZW5kcG9pbnQgOiBgJHt0aGlzLl9iYXNlVXJsfS8ke2VuZHBvaW50fWA7XG4gICAgfVxuXG59XG4iXX0=