@vcd/sdk 15.0.7 → 17.0.0
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/{esm2020 → esm2022}/client/client/api.result.service.mjs +4 -4
- package/esm2022/client/client/logging.interceptor.mjs +44 -0
- package/esm2022/client/client/request.headers.interceptor.mjs +100 -0
- package/esm2022/client/client/response.normalization.interceptor.mjs +59 -0
- package/esm2022/client/client/vcd.api.client.mjs +603 -0
- package/{esm2020 → esm2022}/client/client/vcd.http.client.mjs +6 -6
- package/esm2022/client/client/vcd.transfer.client.mjs +166 -0
- package/esm2022/client/query/filter.builder.mjs +195 -0
- package/esm2022/client/query/query.builder.mjs +79 -0
- package/esm2022/common/container-hooks.mjs +85 -0
- package/{esm2020 → esm2022}/main.mjs +7 -7
- package/{fesm2020 → fesm2022}/vcd-sdk.mjs +54 -54
- package/{fesm2020 → fesm2022}/vcd-sdk.mjs.map +1 -1
- package/open_source_license_vcd_ui_sdk_17.0.0_ga.txt +393 -0
- package/package.json +8 -14
- package/VMware-vcd_ui_sdk-15.0.7-ODP.tar.gz +0 -0
- package/esm2020/client/client/logging.interceptor.mjs +0 -44
- package/esm2020/client/client/request.headers.interceptor.mjs +0 -100
- package/esm2020/client/client/response.normalization.interceptor.mjs +0 -59
- package/esm2020/client/client/vcd.api.client.mjs +0 -603
- package/esm2020/client/client/vcd.transfer.client.mjs +0 -166
- package/esm2020/client/query/filter.builder.mjs +0 -195
- package/esm2020/client/query/query.builder.mjs +0 -79
- package/esm2020/common/container-hooks.mjs +0 -85
- package/fesm2015/vcd-sdk.mjs +0 -1505
- package/fesm2015/vcd-sdk.mjs.map +0 -1
- package/open_source_license_@vcdsdk_15.0.7_GA.txt +0 -22623
- /package/{esm2020 → esm2022}/client/client/constants.mjs +0 -0
- /package/{esm2020 → esm2022}/client/client/index.mjs +0 -0
- /package/{esm2020 → esm2022}/client/client/types.mjs +0 -0
- /package/{esm2020 → esm2022}/client/index.mjs +0 -0
- /package/{esm2020 → esm2022}/client/openapi.mjs +0 -0
- /package/{esm2020 → esm2022}/client/query/index.mjs +0 -0
- /package/{esm2020 → esm2022}/common/index.mjs +0 -0
- /package/{esm2020 → esm2022}/core/index.mjs +0 -0
- /package/{esm2020 → esm2022}/core/plugin.module.mjs +0 -0
- /package/{esm2020 → esm2022}/public-api.mjs +0 -0
- /package/{esm2020 → esm2022}/vcd-sdk.mjs +0 -0
|
@@ -1,603 +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
|
-
if (response.headers.has('Location') && response.status === 202) {
|
|
423
|
-
return this.http.get(response.headers.get('Location'));
|
|
424
|
-
}
|
|
425
|
-
else if (response.body && response.body.type.startsWith('application/vnd.vmware.vcloud.task+')) {
|
|
426
|
-
const task = Object.assign(new TaskType(), response.body);
|
|
427
|
-
return of(task);
|
|
428
|
-
}
|
|
429
|
-
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));
|
|
430
|
-
}
|
|
431
|
-
getEntity(entityRefOrUrn) {
|
|
432
|
-
const entityResolver = typeof entityRefOrUrn === 'string' ?
|
|
433
|
-
this.http.get(`${this._baseUrl}/api/entity/${entityRefOrUrn}`) :
|
|
434
|
-
this.http.get(`${this._baseUrl}/api/entity/urn:vcloud:${entityRefOrUrn.type}:${entityRefOrUrn.id}`);
|
|
435
|
-
return this.validateRequestContext().pipe(concatMap(() => entityResolver), concatMap(entity => this.http.get(`${entity.link[0].href}`)));
|
|
436
|
-
}
|
|
437
|
-
updateTask(task, options) {
|
|
438
|
-
return this.validateRequestContext().pipe(concatMap(() => this.http.get(task.href, { ...options })));
|
|
439
|
-
}
|
|
440
|
-
isTaskComplete(task) {
|
|
441
|
-
return ['success', 'error', 'canceled', 'aborted'].indexOf(task.status) > -1;
|
|
442
|
-
}
|
|
443
|
-
removeItem(item, options) {
|
|
444
|
-
const link = this.findLink(item, 'remove', null);
|
|
445
|
-
if (!link) {
|
|
446
|
-
return throwError(() => new ClientError(`No 'remove' link for specified resource.`, ClientErrorType.HateoasLinkMissing));
|
|
447
|
-
}
|
|
448
|
-
return this.validateRequestContext().pipe(concatMap(() => this.http.delete(link.href, { ...options })));
|
|
449
|
-
}
|
|
450
|
-
query(builder, multisite, options) {
|
|
451
|
-
return this.getQueryPage(`${this._baseUrl}/api/query${builder.get()}`, multisite, options);
|
|
452
|
-
}
|
|
453
|
-
firstPage(result, multisite, options) {
|
|
454
|
-
const link = this.findLink(result, 'firstPage', result.type);
|
|
455
|
-
if (!link) {
|
|
456
|
-
return throwError(() => new ClientError(`No 'firstPage' link for specified query.`, ClientErrorType.HateoasLinkMissing));
|
|
457
|
-
}
|
|
458
|
-
return this.getQueryPage(link.href, multisite, options);
|
|
459
|
-
}
|
|
460
|
-
hasFirstPage(result) {
|
|
461
|
-
return !!this.findLink(result, 'firstPage', result.type);
|
|
462
|
-
}
|
|
463
|
-
previousPage(result, multisite, options) {
|
|
464
|
-
const link = this.findLink(result, 'previousPage', result.type);
|
|
465
|
-
if (!link) {
|
|
466
|
-
return throwError(() => new ClientError(`No 'previousPage' link for specified query.`, ClientErrorType.HateoasLinkMissing));
|
|
467
|
-
}
|
|
468
|
-
return this.getQueryPage(link.href, multisite, options);
|
|
469
|
-
}
|
|
470
|
-
hasPreviousPage(result) {
|
|
471
|
-
return !!this.findLink(result, 'previousPage', result.type);
|
|
472
|
-
}
|
|
473
|
-
nextPage(result, multisite, options) {
|
|
474
|
-
const link = this.findLink(result, 'nextPage', result.type);
|
|
475
|
-
if (!link) {
|
|
476
|
-
return throwError(() => new ClientError(`No 'nextPage' link for specified query.`, ClientErrorType.HateoasLinkMissing));
|
|
477
|
-
}
|
|
478
|
-
return this.getQueryPage(link.href, multisite, options);
|
|
479
|
-
}
|
|
480
|
-
hasNextPage(result) {
|
|
481
|
-
return !!this.findLink(result, 'nextPage', result.type);
|
|
482
|
-
}
|
|
483
|
-
lastPage(result, multisite, options) {
|
|
484
|
-
const link = this.findLink(result, 'lastPage', result.type);
|
|
485
|
-
if (!link) {
|
|
486
|
-
return throwError(() => new ClientError(`No 'lastPage' link for specified query.`, ClientErrorType.HateoasLinkMissing));
|
|
487
|
-
}
|
|
488
|
-
return this.getQueryPage(link.href, multisite, options);
|
|
489
|
-
}
|
|
490
|
-
hasLastPage(result) {
|
|
491
|
-
return !!this.findLink(result, 'lastPage', result.type);
|
|
492
|
-
}
|
|
493
|
-
getQueryPage(href, multisite, options) {
|
|
494
|
-
if (multisite) {
|
|
495
|
-
if (!options) {
|
|
496
|
-
return this.http.get(href, { headers: new HttpHeaders({ _multisite: this.parseMultisiteValue(multisite) }) });
|
|
497
|
-
}
|
|
498
|
-
else if (options?.headers) {
|
|
499
|
-
options.headers.append("_multisite", this.parseMultisiteValue(multisite));
|
|
500
|
-
return this.http.get(href, { ...options });
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
return this.validateRequestContext().pipe(concatMap(() => this.http.get(href, { ...options })));
|
|
504
|
-
}
|
|
505
|
-
/**
|
|
506
|
-
* Use to perform action availability check before calling the API
|
|
507
|
-
* @param item - the navigable item (containing link collection)
|
|
508
|
-
* @param linkRelType - the link rel type, pass either LinkRelType or string
|
|
509
|
-
* @param entityRefType - the entity reference type
|
|
510
|
-
*/
|
|
511
|
-
canPerformAction(item, linkRelType, entityRefType) {
|
|
512
|
-
return !!this.findLink(item, linkRelType, entityRefType);
|
|
513
|
-
}
|
|
514
|
-
findLink(item, rel, type) {
|
|
515
|
-
if (!item || !item.link) {
|
|
516
|
-
return undefined;
|
|
517
|
-
}
|
|
518
|
-
return item.link.find((link) => {
|
|
519
|
-
if (type) {
|
|
520
|
-
return link.rel.includes(rel) && link.type === type;
|
|
521
|
-
}
|
|
522
|
-
return link.rel.includes(rel);
|
|
523
|
-
});
|
|
524
|
-
}
|
|
525
|
-
parseMultisiteValue(multisite) {
|
|
526
|
-
return typeof multisite === 'boolean' ? (multisite ? 'global' : 'local') : multisite.map(site => site.locationId).join(',');
|
|
527
|
-
}
|
|
528
|
-
/**
|
|
529
|
-
* @deprecated Use cloudApiSession
|
|
530
|
-
*/
|
|
531
|
-
get session() {
|
|
532
|
-
return this.validateRequestContext().pipe(concatMap(() => this._sessionObservable));
|
|
533
|
-
}
|
|
534
|
-
/**
|
|
535
|
-
* Get Session observable
|
|
536
|
-
*/
|
|
537
|
-
get cloudApiSession() {
|
|
538
|
-
return this.validateRequestContextCloudApiOnly().pipe(concatMap(() => this._cloudApiSessionObservable));
|
|
539
|
-
}
|
|
540
|
-
get username() {
|
|
541
|
-
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)));
|
|
542
|
-
}
|
|
543
|
-
get organization() {
|
|
544
|
-
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)));
|
|
545
|
-
}
|
|
546
|
-
/**
|
|
547
|
-
* @deprecated Use cloudApiLocation
|
|
548
|
-
*/
|
|
549
|
-
get location() {
|
|
550
|
-
return this.session.pipe(map(session => session.authorizedLocations.location.find(location => location.locationId === session.locationId)));
|
|
551
|
-
}
|
|
552
|
-
/**
|
|
553
|
-
* Gets the location corresponding to the current session
|
|
554
|
-
*/
|
|
555
|
-
get cloudApiLocation() {
|
|
556
|
-
return this.cloudApiSession.pipe(switchMap(() => {
|
|
557
|
-
if (!this._cloudApiAccessibleLocations) {
|
|
558
|
-
// Ensure caching for getting AccessibleLocations
|
|
559
|
-
this._cloudApiAccessibleLocations = this._cloudApiSessionLinks
|
|
560
|
-
.pipe(
|
|
561
|
-
// Get the AccessibleLocations link
|
|
562
|
-
map((links) => this.findLink({ link: links }, 'down', 'AccessibleLocations')),
|
|
563
|
-
// Fetch AccessibleLocations from the backend
|
|
564
|
-
switchMap((link) => link ? this.http.get(link.href) : of(null)),
|
|
565
|
-
// Get the array with all locations (what if there are many pages)
|
|
566
|
-
map((accessibleLocations) => accessibleLocations && accessibleLocations.values))
|
|
567
|
-
.pipe(share({ connector: () => new ReplaySubject(1), resetOnError: false, resetOnComplete: false, resetOnRefCountZero: false }));
|
|
568
|
-
}
|
|
569
|
-
return this._cloudApiAccessibleLocations;
|
|
570
|
-
}),
|
|
571
|
-
// Need to have the session in order to get its location
|
|
572
|
-
withLatestFrom(this.cloudApiSession),
|
|
573
|
-
// Find the location that corresponds to this session
|
|
574
|
-
map(([accessibleLocations, session]) => {
|
|
575
|
-
if (!accessibleLocations || !session) {
|
|
576
|
-
return null;
|
|
577
|
-
}
|
|
578
|
-
const sessionLocation = session.location;
|
|
579
|
-
if (!sessionLocation) {
|
|
580
|
-
return null;
|
|
581
|
-
}
|
|
582
|
-
return accessibleLocations.find(location => location.locationId === sessionLocation);
|
|
583
|
-
}));
|
|
584
|
-
}
|
|
585
|
-
getLocation(session) {
|
|
586
|
-
return session.authorizedLocations.location.find(location => location.locationId === session.locationId);
|
|
587
|
-
}
|
|
588
|
-
/**
|
|
589
|
-
* Build the endpoint url. If the provided endpoint is already an absolute URL, then return it as it is without
|
|
590
|
-
* any modifications, otherwise consider it as a relative one and prepend the baseUrl as defined by the host application.
|
|
591
|
-
*/
|
|
592
|
-
buildEndpointUrl(endpoint) {
|
|
593
|
-
return endpoint.indexOf('://') > -1 ? endpoint : `${this._baseUrl}/${endpoint}`;
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
VcdApiClient.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: VcdApiClient, deps: [{ token: i1.VcdHttpClient }, { token: i0.Injector }, { token: i2.VcdSdkConfig, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
597
|
-
VcdApiClient.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: VcdApiClient });
|
|
598
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.0", ngImport: i0, type: VcdApiClient, decorators: [{
|
|
599
|
-
type: Injectable
|
|
600
|
-
}], ctorParameters: function () { return [{ type: i1.VcdHttpClient }, { type: i0.Injector }, { type: i2.VcdSdkConfig, decorators: [{
|
|
601
|
-
type: Optional
|
|
602
|
-
}] }]; } });
|
|
603
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmNkLmFwaS5jbGllbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy92Y2Qvc2RrL3NyYy9jbGllbnQvY2xpZW50L3ZjZC5hcGkuY2xpZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBQyxVQUFVLEVBQVksUUFBUSxFQUFDLE1BQU0sZUFBZSxDQUFDO0FBQzdELE9BQU8sRUFBQyxXQUFXLEVBQWUsTUFBTSxzQkFBc0IsQ0FBQztBQUMvRCxPQUFPLEVBQUMsZUFBZSxFQUFFLEtBQUssRUFBYyxFQUFFLEVBQUUsYUFBYSxFQUFFLFVBQVUsRUFBQyxNQUFNLE1BQU0sQ0FBQztBQUN2RixPQUFPLEVBQUMsVUFBVSxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxjQUFjLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUNwSCxPQUFPLEVBT0wsUUFBUSxFQUNULE1BQU0sMkNBQTJDLENBQUM7QUFJbkQsT0FBTyxFQUFDLFlBQVksRUFBRSxzQkFBc0IsRUFBRSxjQUFjLEVBQUUsYUFBYSxFQUFDLE1BQU0sOEJBQThCLENBQUM7QUFFakgsT0FBTyxFQUFDLGlCQUFpQixFQUFDLE1BQU0sdUJBQXVCLENBQUM7QUFDeEQsT0FBTyxFQUFDLFlBQVksRUFBQyxNQUFNLGFBQWEsQ0FBQztBQUV6QyxPQUFPLEVBQUMsV0FBVyxFQUFFLGVBQWUsRUFBQyxNQUFNLFNBQVMsQ0FBQzs7OztBQUVyRCxNQUFNLENBQUMsTUFBTSxpQkFBaUIsR0FBRyxnQkFBZ0IsQ0FBQztBQUdsRCxNQUFNLENBQUMsTUFBTSxjQUFjLEdBQUcsTUFBTSxDQUFDO0FBRXJDLCtCQUErQjtBQUUvQjs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLHVCQUF1QixDQUFDLE1BQWM7SUFDbEQsTUFBTSxPQUFPLEdBQWUsRUFBRSxDQUFDO0lBRS9C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QVEsQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLFVBQVUsS0FBSyxlQUFlLENBQUMsQ0FBQztRQUN6RixDQUFDLENBQUMsQ0FDTCxDQUFDO0lBQ04sQ0FBQztJQUVNLFdBQVcsQ0FBQyxPQUFvQjtRQUNuQyxPQUFPLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLFVBQVUsS0FBSyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDN0csQ0FBQztJQUVEOzs7T0FHRztJQUNLLGdCQUFnQixDQUFDLFFBQWdCO1FBQ3JDLE9BQU8sUUFBUSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxRQUFRLElBQUksUUFBUSxFQUFFLENBQUM7SUFDcEYsQ0FBQzs7eUdBcnpCUSxZQUFZOzZHQUFaLFlBQVk7MkZBQVosWUFBWTtrQkFEeEIsVUFBVTs7MEJBeURFLFFBQVEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0luamVjdGFibGUsIEluamVjdG9yLCBPcHRpb25hbH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge0h0dHBIZWFkZXJzLCBIdHRwUmVzcG9uc2V9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcbmltcG9ydCB7QmVoYXZpb3JTdWJqZWN0LCBtZXJnZSwgT2JzZXJ2YWJsZSwgb2YsIFJlcGxheVN1YmplY3QsIHRocm93RXJyb3J9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtjYXRjaEVycm9yLCBjb25jYXRNYXAsIGZpbHRlciwgbWFwLCBzaGFyZSwgc2tpcFdoaWxlLCBzd2l0Y2hNYXAsIHRhcCwgd2l0aExhdGVzdEZyb219IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7XG4gIEF1dGhvcml6ZWRMb2NhdGlvblR5cGUsXG4gIEVudGl0eVJlZmVyZW5jZVR5cGUsXG4gIEVudGl0eVR5cGUsXG4gIExpbmtUeXBlLFxuICBSZXNvdXJjZVR5cGUsXG4gIFNlc3Npb25UeXBlLFxuICBUYXNrVHlwZVxufSBmcm9tICdAdmNkL2JpbmRpbmdzL3ZjbG91ZC9hcGkvcmVzdC9zY2hlbWFfdjFfNSc7XG5pbXBvcnQge1N1cHBvcnRlZFZlcnNpb25zVHlwZX0gZnJvbSAnQHZjZC9iaW5kaW5ncy92Y2xvdWQvYXBpL3Jlc3Qvc2NoZW1hL3ZlcnNpb25pbmcnO1xuaW1wb3J0IHtBY2Nlc3NpYmxlTG9jYXRpb24sIEFjY2Vzc2libGVMb2NhdGlvbnMsIFNlc3Npb259IGZyb20gJy4uL29wZW5hcGknO1xuaW1wb3J0IHtRdWVyeX0gZnJvbSAnLi4vcXVlcnkvaW5kZXgnO1xuaW1wb3J0IHtBUElfUk9PVF9VUkwsIEF1dGhUb2tlbkhvbGRlclNlcnZpY2UsIFNFU1NJT05fT1JHX0lELCBTRVNTSU9OX1NDT1BFfSBmcm9tICcuLi8uLi9jb21tb24vY29udGFpbmVyLWhvb2tzJztcbmltcG9ydCB7VmNkSHR0cENsaWVudH0gZnJvbSAnLi92Y2QuaHR0cC5jbGllbnQnO1xuaW1wb3J0IHtWY2RUcmFuc2ZlckNsaWVudH0gZnJvbSAnLi92Y2QudHJhbnNmZXIuY2xpZW50JztcbmltcG9ydCB7SFRUUF9IRUFERVJTfSBmcm9tICcuL2NvbnN0YW50cyc7XG5pbXBvcnQge1ZjZFNka0NvbmZpZ30gZnJvbSBcIi4uLy4uL2NvcmUvcGx1Z2luLm1vZHVsZVwiO1xuaW1wb3J0IHtDbGllbnRFcnJvciwgQ2xpZW50RXJyb3JUeXBlfSBmcm9tIFwiLi90eXBlc1wiO1xuXG5leHBvcnQgY29uc3QgVFJBTlNGRVJfTElOS19SRUwgPSAndXBsb2FkOmRlZmF1bHQnO1xuZXhwb3J0IHR5cGUgTmF2aWdhYmxlID0gUmVzb3VyY2VUeXBlIHwgeyBsaW5rPzogTGlua1R5cGVbXSB9O1xuXG5leHBvcnQgY29uc3QgSEFURU9BU19IRUFERVIgPSAnTGluayc7XG5cbi8vIHRzbGludDpkaXNhYmxlOnZhcmlhYmxlLW5hbWVcblxuLyoqXG4gKiBQYXJzZSBvdXQgTGluayBoZWFkZXJzIHVzaW5nIGEgdmVyeSBsYXppbHkgaW1wbGVtZW50ZWQgcHVsbCBwYXJzZXJcbiAqIEBwYXJhbSBoZWFkZXIgJzx1cmwxPjtuYW1lMT1cInZhbHVlMVwiLG5hbWUyPVwidmFsdWUyXCIsPHVybDI+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+IHRoaXMuaHR0cC5kZWxldGUodGhpcy5idWlsZEVuZHBvaW50VXJsKGVuZHBvaW50KSwgeyAuLi5vcHRpb25zLCBvYnNlcnZlOiAncmVzcG9uc2UnIH0pKSxcbiAgICAgICAgICAgIGNvbmNhdE1hcChyZXNwb25zZSA9PiB0aGlzLm1hcFJlc3BvbnNlVG9UYXNrKHJlc3BvbnNlLCAnREVMRVRFJykpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBtYXBSZXNwb25zZVRvVGFzayhyZXNwb25zZTogSHR0cFJlc3BvbnNlPGFueT4sIGh0dHBWZXJiOiBzdHJpbmcpOiBPYnNlcnZhYmxlPFRhc2tUeXBlPiB7XG4gICAgICAgIGlmIChyZXNwb25zZS5oZWFkZXJzLmhhcygnTG9jYXRpb24nKSAmJiByZXNwb25zZS5zdGF0dXMgPT09IDIwMikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaHR0cC5nZXQ8VGFza1R5cGU+KHJlc3BvbnNlLmhlYWRlcnMuZ2V0KCdMb2NhdGlvbicpKTtcbiAgICAgICAgfSBlbHNlIGlmIChyZXNwb25zZS5ib2R5ICYmIHJlc3BvbnNlLmJvZHkudHlwZS5zdGFydHNXaXRoKCdhcHBsaWNhdGlvbi92bmQudm13YXJlLnZjbG91ZC50YXNrKycpKSB7XG4gICAgICAgICAgICBjb25zdCB0YXNrOiBUYXNrVHlwZSA9IE9iamVjdC5hc3NpZ24obmV3IFRhc2tUeXBlKCksIHJlc3BvbnNlLmJvZHkpO1xuICAgICAgICAgICAgcmV0dXJuIG9mKHRhc2spO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRocm93RXJyb3IoKCkgPT4gbmV3IENsaWVudEVycm9yKFxuICAgICAgICAgIGBBbiBhc3luY2hyb25vdXMgcmVxdWVzdCB3YXMgbWFkZSB0byBbJHtodHRwVmVyYn0gJHtyZXNwb25zZS51cmx9XSwgYnV0IG5vIHRhc2sgd2FzIHJldHVybmVkLiAgVGhlIG9wZXJhdGlvbiBtYXkgc3RpbGwgaGF2ZSBiZWVuIHN1Y2Nlc3NmdWwuYCxcbiAgICAgICAgICAgIENsaWVudEVycm9yVHlwZS5UYXNrTGlua01pc3NpbmdcbiAgICAgICAgKSk7XG4gICAgfVxuXG4gICAgcHVibGljIGdldEVudGl0eTxUIGV4dGVuZHMgRW50aXR5UmVmZXJlbmNlVHlwZT4oZW50aXR5UmVmOiBFbnRpdHlSZWZlcmVuY2VUeXBlKTogT2JzZXJ2YWJsZTxUPjtcbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6dW5pZmllZC1zaWduYXR1cmVzXG4gICAgcHVibGljIGdldEVudGl0eTxUIGV4dGVuZHMgRW50aXR5UmVmZXJlbmNlVHlwZT4odXJuOiBzdHJpbmcpOiBPYnNlcnZhYmxlPFQ+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=
|