@angular/common
Version:
Angular - commonly needed directives and services
326 lines (325 loc) • 175 kB
JavaScript
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import { Injectable } from '@angular/core';
import { of } from 'rxjs';
import { concatMap, filter, map } from 'rxjs/operators';
import { HttpHandler } from './backend';
import { HttpHeaders } from './headers';
import { HttpParams } from './params';
import { HttpRequest } from './request';
import { HttpResponse } from './response';
import * as i0 from "@angular/core";
import * as i1 from "./backend";
/**
* Constructs an instance of `HttpRequestOptions<T>` from a source `HttpMethodOptions` and
* the given `body`. This function clones the object and adds the body.
*
* Note that the `responseType` *options* value is a String that identifies the
* single data type of the response.
* A single overload version of the method handles each response type.
* The value of `responseType` cannot be a union, as the combined signature could imply.
*
*/
function addBody(options, body) {
return {
body,
headers: options.headers,
context: options.context,
observe: options.observe,
params: options.params,
reportProgress: options.reportProgress,
responseType: options.responseType,
withCredentials: options.withCredentials,
transferCache: options.transferCache,
};
}
/**
* Performs HTTP requests.
* This service is available as an injectable class, with methods to perform HTTP requests.
* Each request method has multiple signatures, and the return type varies based on
* the signature that is called (mainly the values of `observe` and `responseType`).
*
* Note that the `responseType` *options* value is a String that identifies the
* single data type of the response.
* A single overload version of the method handles each response type.
* The value of `responseType` cannot be a union, as the combined signature could imply.
*
* @usageNotes
* Sample HTTP requests for the [Tour of Heroes](/tutorial/tour-of-heroes/toh-pt0) application.
*
* ### HTTP Request Example
*
* ```
* // GET heroes whose name contains search term
* searchHeroes(term: string): observable<Hero[]>{
*
* const params = new HttpParams({fromString: 'name=term'});
* return this.httpClient.request('GET', this.heroesUrl, {responseType:'json', params});
* }
* ```
*
* Alternatively, the parameter string can be used without invoking HttpParams
* by directly joining to the URL.
* ```
* this.httpClient.request('GET', this.heroesUrl + '?' + 'name=term', {responseType:'json'});
* ```
*
*
* ### JSONP Example
* ```
* requestJsonp(url, callback = 'callback') {
* return this.httpClient.jsonp(this.heroesURL, callback);
* }
* ```
*
* ### PATCH Example
* ```
* // PATCH one of the heroes' name
* patchHero (id: number, heroName: string): Observable<{}> {
* const url = `${this.heroesUrl}/${id}`; // PATCH api/heroes/42
* return this.httpClient.patch(url, {name: heroName}, httpOptions)
* .pipe(catchError(this.handleError('patchHero')));
* }
* ```
*
* @see [HTTP Guide](guide/understanding-communicating-with-http)
* @see [HTTP Request](api/common/http/HttpRequest)
*
* @publicApi
*/
export class HttpClient {
constructor(handler) {
this.handler = handler;
}
/**
* Constructs an observable for a generic HTTP request that, when subscribed,
* fires the request through the chain of registered interceptors and on to the
* server.
*
* You can pass an `HttpRequest` directly as the only parameter. In this case,
* the call returns an observable of the raw `HttpEvent` stream.
*
* Alternatively you can pass an HTTP method as the first parameter,
* a URL string as the second, and an options hash containing the request body as the third.
* See `addBody()`. In this case, the specified `responseType` and `observe` options determine the
* type of returned observable.
* * The `responseType` value determines how a successful response body is parsed.
* * If `responseType` is the default `json`, you can pass a type interface for the resulting
* object as a type parameter to the call.
*
* The `observe` value determines the return type, according to what you are interested in
* observing.
* * An `observe` value of events returns an observable of the raw `HttpEvent` stream, including
* progress events by default.
* * An `observe` value of response returns an observable of `HttpResponse<T>`,
* where the `T` parameter depends on the `responseType` and any optionally provided type
* parameter.
* * An `observe` value of body returns an observable of `<T>` with the same `T` body type.
*
*/
request(first, url, options = {}) {
let req;
// First, check whether the primary argument is an instance of `HttpRequest`.
if (first instanceof HttpRequest) {
// It is. The other arguments must be undefined (per the signatures) and can be
// ignored.
req = first;
}
else {
// It's a string, so it represents a URL. Construct a request based on it,
// and incorporate the remaining arguments (assuming `GET` unless a method is
// provided.
// Figure out the headers.
let headers = undefined;
if (options.headers instanceof HttpHeaders) {
headers = options.headers;
}
else {
headers = new HttpHeaders(options.headers);
}
// Sort out parameters.
let params = undefined;
if (!!options.params) {
if (options.params instanceof HttpParams) {
params = options.params;
}
else {
params = new HttpParams({ fromObject: options.params });
}
}
// Construct the request.
req = new HttpRequest(first, url, (options.body !== undefined ? options.body : null), {
headers,
context: options.context,
params,
reportProgress: options.reportProgress,
// By default, JSON is assumed to be returned for all calls.
responseType: options.responseType || 'json',
withCredentials: options.withCredentials,
transferCache: options.transferCache,
});
}
// Start with an Observable.of() the initial request, and run the handler (which
// includes all interceptors) inside a concatMap(). This way, the handler runs
// inside an Observable chain, which causes interceptors to be re-run on every
// subscription (this also makes retries re-run the handler, including interceptors).
const events$ = of(req).pipe(concatMap((req) => this.handler.handle(req)));
// If coming via the API signature which accepts a previously constructed HttpRequest,
// the only option is to get the event stream. Otherwise, return the event stream if
// that is what was requested.
if (first instanceof HttpRequest || options.observe === 'events') {
return events$;
}
// The requested stream contains either the full response or the body. In either
// case, the first step is to filter the event stream to extract a stream of
// responses(s).
const res$ = events$.pipe(filter((event) => event instanceof HttpResponse));
// Decide which stream to return.
switch (options.observe || 'body') {
case 'body':
// The requested stream is the body. Map the response stream to the response
// body. This could be done more simply, but a misbehaving interceptor might
// transform the response body into a different format and ignore the requested
// responseType. Guard against this by validating that the response is of the
// requested type.
switch (req.responseType) {
case 'arraybuffer':
return res$.pipe(map((res) => {
// Validate that the body is an ArrayBuffer.
if (res.body !== null && !(res.body instanceof ArrayBuffer)) {
throw new Error('Response is not an ArrayBuffer.');
}
return res.body;
}));
case 'blob':
return res$.pipe(map((res) => {
// Validate that the body is a Blob.
if (res.body !== null && !(res.body instanceof Blob)) {
throw new Error('Response is not a Blob.');
}
return res.body;
}));
case 'text':
return res$.pipe(map((res) => {
// Validate that the body is a string.
if (res.body !== null && typeof res.body !== 'string') {
throw new Error('Response is not a string.');
}
return res.body;
}));
case 'json':
default:
// No validation needed for JSON responses, as they can be of any type.
return res$.pipe(map((res) => res.body));
}
case 'response':
// The response stream was requested directly, so return it.
return res$;
default:
// Guard against new future observe types being added.
throw new Error(`Unreachable: unhandled observe type ${options.observe}}`);
}
}
/**
* Constructs an observable that, when subscribed, causes the configured
* `DELETE` request to execute on the server. See the individual overloads for
* details on the return type.
*
* @param url The endpoint URL.
* @param options The HTTP options to send with the request.
*
*/
delete(url, options = {}) {
return this.request('DELETE', url, options);
}
/**
* Constructs an observable that, when subscribed, causes the configured
* `GET` request to execute on the server. See the individual overloads for
* details on the return type.
*/
get(url, options = {}) {
return this.request('GET', url, options);
}
/**
* Constructs an observable that, when subscribed, causes the configured
* `HEAD` request to execute on the server. The `HEAD` method returns
* meta information about the resource without transferring the
* resource itself. See the individual overloads for
* details on the return type.
*/
head(url, options = {}) {
return this.request('HEAD', url, options);
}
/**
* Constructs an `Observable` that, when subscribed, causes a request with the special method
* `JSONP` to be dispatched via the interceptor pipeline.
* The [JSONP pattern](https://en.wikipedia.org/wiki/JSONP) works around limitations of certain
* API endpoints that don't support newer,
* and preferable [CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) protocol.
* JSONP treats the endpoint API as a JavaScript file and tricks the browser to process the
* requests even if the API endpoint is not located on the same domain (origin) as the client-side
* application making the request.
* The endpoint API must support JSONP callback for JSONP requests to work.
* The resource API returns the JSON response wrapped in a callback function.
* You can pass the callback function name as one of the query parameters.
* Note that JSONP requests can only be used with `GET` requests.
*
* @param url The resource URL.
* @param callbackParam The callback function name.
*
*/
jsonp(url, callbackParam) {
return this.request('JSONP', url, {
params: new HttpParams().append(callbackParam, 'JSONP_CALLBACK'),
observe: 'body',
responseType: 'json',
});
}
/**
* Constructs an `Observable` that, when subscribed, causes the configured
* `OPTIONS` request to execute on the server. This method allows the client
* to determine the supported HTTP methods and other capabilities of an endpoint,
* without implying a resource action. See the individual overloads for
* details on the return type.
*/
options(url, options = {}) {
return this.request('OPTIONS', url, options);
}
/**
* Constructs an observable that, when subscribed, causes the configured
* `PATCH` request to execute on the server. See the individual overloads for
* details on the return type.
*/
patch(url, body, options = {}) {
return this.request('PATCH', url, addBody(options, body));
}
/**
* Constructs an observable that, when subscribed, causes the configured
* `POST` request to execute on the server. The server responds with the location of
* the replaced resource. See the individual overloads for
* details on the return type.
*/
post(url, body, options = {}) {
return this.request('POST', url, addBody(options, body));
}
/**
* Constructs an observable that, when subscribed, causes the configured
* `PUT` request to execute on the server. The `PUT` method replaces an existing resource
* with a new set of values.
* See the individual overloads for details on the return type.
*/
put(url, body, options = {}) {
return this.request('PUT', url, addBody(options, body));
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.1", ngImport: i0, type: HttpClient, deps: [{ token: i1.HttpHandler }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.1.1", ngImport: i0, type: HttpClient }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.1", ngImport: i0, type: HttpClient, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: i1.HttpHandler }] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvY29tbW9uL2h0dHAvc3JjL2NsaWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFFSCxPQUFPLEVBQUMsVUFBVSxFQUFDLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sRUFBYSxFQUFFLEVBQUMsTUFBTSxNQUFNLENBQUM7QUFDcEMsT0FBTyxFQUFDLFNBQVMsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFFdEQsT0FBTyxFQUFDLFdBQVcsRUFBQyxNQUFNLFdBQVcsQ0FBQztBQUV0QyxPQUFPLEVBQUMsV0FBVyxFQUFDLE1BQU0sV0FBVyxDQUFDO0FBQ3RDLE9BQU8sRUFBQyxVQUFVLEVBQW9CLE1BQU0sVUFBVSxDQUFDO0FBQ3ZELE9BQU8sRUFBQyxXQUFXLEVBQUMsTUFBTSxXQUFXLENBQUM7QUFDdEMsT0FBTyxFQUFZLFlBQVksRUFBQyxNQUFNLFlBQVksQ0FBQzs7O0FBR25EOzs7Ozs7Ozs7R0FTRztBQUNILFNBQVMsT0FBTyxDQUNaLE9BVUMsRUFDRCxJQUFZO0lBQ2QsT0FBTztRQUNMLElBQUk7UUFDSixPQUFPLEVBQUUsT0FBTyxDQUFDLE9BQU87UUFDeEIsT0FBTyxFQUFFLE9BQU8sQ0FBQyxPQUFPO1FBQ3hCLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTztRQUN4QixNQUFNLEVBQUUsT0FBTyxDQUFDLE1BQU07UUFDdEIsY0FBYyxFQUFFLE9BQU8sQ0FBQyxjQUFjO1FBQ3RDLFlBQVksRUFBRSxPQUFPLENBQUMsWUFBWTtRQUNsQyxlQUFlLEVBQUUsT0FBTyxDQUFDLGVBQWU7UUFDeEMsYUFBYSxFQUFFLE9BQU8sQ0FBQyxhQUFhO0tBQ3JDLENBQUM7QUFDSixDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7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QUFFLElBQUksVUFBVSxFQUFFLENBQUMsTUFBTSxDQUFDLGFBQWEsRUFBRSxnQkFBZ0IsQ0FBQztZQUNoRSxPQUFPLEVBQUUsTUFBTTtZQUNmLFlBQVksRUFBRSxNQUFNO1NBQ3JCLENBQUMsQ0FBQztJQUNMLENBQUM7SUFzU0Q7Ozs7OztPQU1HO0lBQ0gsT0FBTyxDQUFDLEdBQVcsRUFBRSxVQVNqQixFQUFFO1FBQ0osT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFNLFNBQVMsRUFBRSxHQUFHLEVBQUUsT0FBYyxDQUFDLENBQUM7SUFDM0QsQ0FBQztJQXVURDs7OztPQUlHO0lBQ0gsS0FBSyxDQUFDLEdBQVcsRUFBRSxJQUFjLEVBQUUsVUFTL0IsRUFBRTtRQUNKLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBTSxPQUFPLEVBQUUsR0FBRyxFQUFFLE9BQU8sQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNqRSxDQUFDO0lBb1VEOzs7OztPQUtHO0lBQ0gsSUFBSSxDQUFDLEdBQVcsRUFBRSxJQUFjLEVBQUUsVUFVOUIsRUFBRTtRQUNKLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBTSxNQUFNLEVBQUUsR0FBRyxFQUFFLE9BQU8sQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNoRSxDQUFDO0lBb1REOzs7OztPQUtHO0lBQ0gsR0FBRyxDQUFDLEdBQVcsRUFBRSxJQUFjLEVBQUUsVUFTN0IsRUFBRTtRQUNKLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBTSxLQUFLLEVBQUUsR0FBRyxFQUFFLE9BQU8sQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUMvRCxDQUFDO3lIQTd4RlUsVUFBVTs2SEFBVixVQUFVOztzR0FBVixVQUFVO2tCQUR0QixVQUFVIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5cbmltcG9ydCB7SW5qZWN0YWJsZX0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge09ic2VydmFibGUsIG9mfSBmcm9tICdyeGpzJztcbmltcG9ydCB7Y29uY2F0TWFwLCBmaWx0ZXIsIG1hcH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQge0h0dHBIYW5kbGVyfSBmcm9tICcuL2JhY2tlbmQnO1xuaW1wb3J0IHtIdHRwQ29udGV4dH0gZnJvbSAnLi9jb250ZXh0JztcbmltcG9ydCB7SHR0cEhlYWRlcnN9IGZyb20gJy4vaGVhZGVycyc7XG5pbXBvcnQge0h0dHBQYXJhbXMsIEh0dHBQYXJhbXNPcHRpb25zfSBmcm9tICcuL3BhcmFtcyc7XG5pbXBvcnQge0h0dHBSZXF1ZXN0fSBmcm9tICcuL3JlcXVlc3QnO1xuaW1wb3J0IHtIdHRwRXZlbnQsIEh0dHBSZXNwb25zZX0gZnJvbSAnLi9yZXNwb25zZSc7XG5cblxuLyoqXG4gKiBDb25zdHJ1Y3RzIGFuIGluc3RhbmNlIG9mIGBIdHRwUmVxdWVzdE9wdGlvbnM8VD5gIGZyb20gYSBzb3VyY2UgYEh0dHBNZXRob2RPcHRpb25zYCBhbmRcbiAqIHRoZSBnaXZlbiBgYm9keWAuIFRoaXMgZnVuY3Rpb24gY2xvbmVzIHRoZSBvYmplY3QgYW5kIGFkZHMgdGhlIGJvZHkuXG4gKlxuICogTm90ZSB0aGF0IHRoZSBgcmVzcG9uc2VUeXBlYCAqb3B0aW9ucyogdmFsdWUgaXMgYSBTdHJpbmcgdGhhdCBpZGVudGlmaWVzIHRoZVxuICogc2luZ2xlIGRhdGEgdHlwZSBvZiB0aGUgcmVzcG9uc2UuXG4gKiBBIHNpbmdsZSBvdmVybG9hZCB2ZXJzaW9uIG9mIHRoZSBtZXRob2QgaGFuZGxlcyBlYWNoIHJlc3BvbnNlIHR5cGUuXG4gKiBUaGUgdmFsdWUgb2YgYHJlc3BvbnNlVHlwZWAgY2Fubm90IGJlIGEgdW5pb24sIGFzIHRoZSBjb21iaW5lZCBzaWduYXR1cmUgY291bGQgaW1wbHkuXG4gKlxuICovXG5mdW5jdGlvbiBhZGRCb2R5PFQ+KFxuICAgIG9wdGlvbnM6IHtcbiAgICAgIGhlYWRlcnM/OiBIdHRwSGVhZGVyc3x7W2hlYWRlcjogc3RyaW5nXTogc3RyaW5nIHwgc3RyaW5nW119LFxuICAgICAgY29udGV4dD86IEh0dHBDb250ZXh0LFxuICAgICAgb2JzZXJ2ZT86ICdib2R5J3wnZXZlbnRzJ3wncmVzcG9uc2UnLFxuICAgICAgcGFyYW1zPzogSHR0cFBhcmFtc3xcbiAgICAgICAgICAgIHtbcGFyYW06IHN0cmluZ106IHN0cmluZyB8IG51bWJlciB8IGJvb2xlYW4gfCBSZWFkb25seUFycmF5PHN0cmluZ3xudW1iZXJ8Ym9vbGVhbj59LFxuICAgICAgcmVwb3J0UHJvZ3Jlc3M/OiBib29sZWFuLFxuICAgICAgcmVzcG9uc2VUeXBlPzogJ2FycmF5YnVmZmVyJ3wnYmxvYid8J2pzb24nfCd0ZXh0JyxcbiAgICAgIHdpdGhDcmVkZW50aWFscz86IGJvb2xlYW4sXG4gICAgICB0cmFuc2ZlckNhY2hlPzoge2luY2x1ZGVIZWFkZXJzPzogc3RyaW5nW119fGJvb2xlYW4sXG4gICAgfSxcbiAgICBib2R5OiBUfG51bGwpOiBhbnkge1xuICByZXR1cm4ge1xuICAgIGJvZHksXG4gICAgaGVhZGVyczogb3B0aW9ucy5oZWFkZXJzLFxuICAgIGNvbnRleHQ6IG9wdGlvbnMuY29udGV4dCxcbiAgICBvYnNlcnZlOiBvcHRpb25zLm9ic2VydmUsXG4gICAgcGFyYW1zOiBvcHRpb25zLnBhcmFtcyxcbiAgICByZXBvcnRQcm9ncmVzczogb3B0aW9ucy5yZXBvcnRQcm9ncmVzcyxcbiAgICByZXNwb25zZVR5cGU6IG9wdGlvbnMucmVzcG9uc2VUeXBlLFxuICAgIHdpdGhDcmVkZW50aWFsczogb3B0aW9ucy53aXRoQ3JlZGVudGlhbHMsXG4gICAgdHJhbnNmZXJDYWNoZTogb3B0aW9ucy50cmFuc2ZlckNhY2hlLFxuICB9O1xufVxuXG4vKipcbiAqIFBlcmZvcm1zIEhUVFAgcmVxdWVzdHMuXG4gKiBUaGlzIHNlcnZpY2UgaXMgYXZhaWxhYmxlIGFzIGFuIGluamVjdGFibGUgY2xhc3MsIHdpdGggbWV0aG9kcyB0byBwZXJmb3JtIEhUVFAgcmVxdWVzdHMuXG4gKiBFYWNoIHJlcXVlc3QgbWV0aG9kIGhhcyBtdWx0aXBsZSBzaWduYXR1cmVzLCBhbmQgdGhlIHJldHVybiB0eXBlIHZhcmllcyBiYXNlZCBvblxuICogdGhlIHNpZ25hdHVyZSB0aGF0IGlzIGNhbGxlZCAobWFpbmx5IHRoZSB2YWx1ZXMgb2YgYG9ic2VydmVgIGFuZCBgcmVzcG9uc2VUeXBlYCkuXG4gKlxuICogTm90ZSB0aGF0IHRoZSBgcmVzcG9uc2VUeXBlYCAqb3B0aW9ucyogdmFsdWUgaXMgYSBTdHJpbmcgdGhhdCBpZGVudGlmaWVzIHRoZVxuICogc2luZ2xlIGRhdGEgdHlwZSBvZiB0aGUgcmVzcG9uc2UuXG4gKiBBIHNpbmdsZSBvdmVybG9hZCB2ZXJzaW9uIG9mIHRoZSBtZXRob2QgaGFuZGxlcyBlYWNoIHJlc3BvbnNlIHR5cGUuXG4gKiBUaGUgdmFsdWUgb2YgYHJlc3BvbnNlVHlwZWAgY2Fubm90IGJlIGEgdW5pb24sIGFzIHRoZSBjb21iaW5lZCBzaWduYXR1cmUgY291bGQgaW1wbHkuXG5cbiAqXG4gKiBAdXNhZ2VOb3Rlc1xuICogU2FtcGxlIEhUVFAgcmVxdWVzdHMgZm9yIHRoZSBbVG91ciBvZiBIZXJvZXNdKC90dXRvcmlhbC90b3VyLW9mLWhlcm9lcy90b2gtcHQwKSBhcHBsaWNhdGlvbi5cbiAqXG4gKiAjIyMgSFRUUCBSZXF1ZXN0IEV4YW1wbGVcbiAqXG4gKiBgYGBcbiAqICAvLyBHRVQgaGVyb2VzIHdob3NlIG5hbWUgY29udGFpbnMgc2VhcmNoIHRlcm1cbiAqIHNlYXJjaEhlcm9lcyh0ZXJtOiBzdHJpbmcpOiBvYnNlcnZhYmxlPEhlcm9bXT57XG4gKlxuICogIGNvbnN0IHBhcmFtcyA9IG5ldyBIdHRwUGFyYW1zKHtmcm9tU3RyaW5nOiAnbmFtZT10ZXJtJ30pO1xuICogICAgcmV0dXJuIHRoaXMuaHR0cENsaWVudC5yZXF1ZXN0KCdHRVQnLCB0aGlzLmhlcm9lc1VybCwge3Jlc3BvbnNlVHlwZTonanNvbicsIHBhcmFtc30pO1xuICogfVxuICogYGBgXG4gKlxuICogQWx0ZXJuYXRpdmVseSwgdGhlIHBhcmFtZXRlciBzdHJpbmcgY2FuIGJlIHVzZWQgd2l0aG91dCBpbnZva2luZyBIdHRwUGFyYW1zXG4gKiBieSBkaXJlY3RseSBqb2luaW5nIHRvIHRoZSBVUkwuXG4gKiBgYGBcbiAqIHRoaXMuaHR0cENsaWVudC5yZXF1ZXN0KCdHRVQnLCB0aGlzLmhlcm9lc1VybCArICc/JyArICduYW1lPXRlcm0nLCB7cmVzcG9uc2VUeXBlOidqc29uJ30pO1xuICogYGBgXG4gKlxuICpcbiAqICMjIyBKU09OUCBFeGFtcGxlXG4gKiBgYGBcbiAqIHJlcXVlc3RKc29ucCh1cmwsIGNhbGxiYWNrID0gJ2NhbGxiYWNrJykge1xuICogIHJldHVybiB0aGlzLmh0dHBDbGllbnQuanNvbnAodGhpcy5oZXJvZXNVUkwsIGNhbGxiYWNrKTtcbiAqIH1cbiAqIGBgYFxuICpcbiAqICMjIyBQQVRDSCBFeGFtcGxlXG4gKiBgYGBcbiAqIC8vIFBBVENIIG9uZSBvZiB0aGUgaGVyb2VzJyBuYW1lXG4gKiBwYXRjaEhlcm8gKGlkOiBudW1iZXIsIGhlcm9OYW1lOiBzdHJpbmcpOiBPYnNlcnZhYmxlPHt9PiB7XG4gKiBjb25zdCB1cmwgPSBgJHt0aGlzLmhlcm9lc1VybH0vJHtpZH1gOyAgIC8vIFBBVENIIGFwaS9oZXJvZXMvNDJcbiAqICByZXR1cm4gdGhpcy5odHRwQ2xpZW50LnBhdGNoKHVybCwge25hbWU6IGhlcm9OYW1lfSwgaHR0cE9wdGlvbnMpXG4gKiAgICAucGlwZShjYXRjaEVycm9yKHRoaXMuaGFuZGxlRXJyb3IoJ3BhdGNoSGVybycpKSk7XG4gKiB9XG4gKiBgYGBcbiAqXG4gKiBAc2VlIFtIVFRQIEd1aWRlXShndWlkZS91bmRlcnN0YW5kaW5nLWNvbW11bmljYXRpbmctd2l0aC1odHRwKVxuICogQHNlZSBbSFRUUCBSZXF1ZXN0XShhcGkvY29tbW9uL2h0dHAvSHR0cFJlcXVlc3QpXG4gKlxuICogQHB1YmxpY0FwaVxuICovXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgSHR0cENsaWVudCB7XG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgaGFuZGxlcjogSHR0cEhhbmRsZXIpIHt9XG5cbiAgLyoqXG4gICAqIFNlbmRzIGFuIGBIdHRwUmVxdWVzdGAgYW5kIHJldHVybnMgYSBzdHJlYW0gb2YgYEh0dHBFdmVudGBzLlxuICAgKlxuICAgKiBAcmV0dXJuIEFuIGBPYnNlcnZhYmxlYCBvZiB0aGUgcmVzcG9uc2UsIHdpdGggdGhlIHJlc3BvbnNlIGJvZHkgYXMgYSBzdHJlYW0gb2YgYEh0dHBFdmVudGBzLlxuICAgKi9cbiAgcmVxdWVzdDxSPihyZXE6IEh0dHBSZXF1ZXN0PGFueT4pOiBPYnNlcnZhYmxlPEh0dHBFdmVudDxSPj47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdHMgYSByZXF1ZXN0IHRoYXQgaW50ZXJwcmV0cyB0aGUgYm9keSBhcyBhbiBgQXJyYXlCdWZmZXJgIGFuZCByZXR1cm5zIHRoZSByZXNwb25zZSBpblxuICAgKiBhbiBgQXJyYXlCdWZmZXJgLlxuICAgKlxuICAgKiBAcGFyYW0gbWV0aG9kICBUaGUgSFRUUCBtZXRob2QuXG4gICAqIEBwYXJhbSB1cmwgICAgIFRoZSBlbmRwb2ludCBVUkwuXG4gICAqIEBwYXJhbSBvcHRpb25zIFRoZSBIVFRQIG9wdGlvbnMgdG8gc2VuZCB3aXRoIHRoZSByZXF1ZXN0LlxuICAgKlxuICAgKlxuICAgKiBAcmV0dXJuIEFuIGBPYnNlcnZhYmxlYCBvZiB0aGUgcmVzcG9uc2UsIHdpdGggdGhlIHJlc3BvbnNlIGJvZHkgYXMgYW4gYEFycmF5QnVmZmVyYC5cbiAgICovXG4gIHJlcXVlc3QobWV0aG9kOiBzdHJpbmcsIHVybDogc3RyaW5nLCBvcHRpb25zOiB7XG4gICAgYm9keT86IGFueSxcbiAgICBoZWFkZXJzPzogSHR0cEhlYWRlcnN8e1toZWFkZXI6IHN0cmluZ106IHN0cmluZyB8IHN0cmluZ1tdfSxcbiAgICBjb250ZXh0PzogSHR0cENvbnRleHQsXG4gICAgb2JzZXJ2ZT86ICdib2R5JyxcbiAgICBwYXJhbXM/OiBIdHRwUGFyYW1zfFxuICAgICAgICAgIHtbcGFyYW06IHN0cmluZ106IHN0cmluZyB8IG51bWJlciB8IGJvb2xlYW4gfCBSZWFkb25seUFycmF5PHN0cmluZ3xudW1iZXJ8Ym9vbGVhbj59LFxuICAgIHJlcG9ydFByb2dyZXNzPzogYm9vbGVhbiwgcmVzcG9uc2VUeXBlOiAnYXJyYXlidWZmZXInLFxuICAgIHdpdGhDcmVkZW50aWFscz86IGJvb2xlYW4sXG4gICAgdHJhbnNmZXJDYWNoZT86IHtpbmNsdWRlSGVhZGVycz86IHN0cmluZ1tdfXxib29sZWFuXG4gIH0pOiBPYnNlcnZhYmxlPEFycmF5QnVmZmVyPjtcblxuICAvKipcbiAgICogQ29uc3RydWN0cyBhIHJlcXVlc3QgdGhhdCBpbnRlcnByZXRzIHRoZSBib2R5IGFzIGEgYmxvYiBhbmQgcmV0dXJuc1xuICAgKiB0aGUgcmVzcG9uc2UgYXMgYSBibG9iLlxuICAgKlxuICAgKiBAcGFyYW0gbWV0aG9kICBUaGUgSFRUUCBtZXRob2QuXG4gICAqIEBwYXJhbSB1cmwgICAgIFRoZSBlbmRwb2ludCBVUkwuXG4gICAqIEBwYXJhbSBvcHRpb25zIFRoZSBIVFRQIG9wdGlvbnMgdG8gc2VuZCB3aXRoIHRoZSByZXF1ZXN0LlxuICAgKlxuICAgKiBAcmV0dXJuIEFuIGBPYnNlcnZhYmxlYCBvZiB0aGUgcmVzcG9uc2UsIHdpdGggdGhlIHJlc3BvbnNlIGJvZHkgb2YgdHlwZSBgQmxvYmAuXG4gICAqL1xuICByZXF1ZXN0KG1ldGhvZDogc3RyaW5nLCB1cmw6IHN0cmluZywgb3B0aW9uczoge1xuICAgIGJvZHk/OiBhbnksXG4gICAgaGVhZGVycz86IEh0dHBIZWFkZXJzfHtbaGVhZGVyOiBzdHJpbmddOiBzdHJpbmcgfCBzdHJpbmdbXX0sXG4gICAgY29udGV4dD86IEh0dHBDb250ZXh0LFxuICAgIG9ic2VydmU/OiAnYm9keScsXG4gICAgcGFyYW1zPzogSHR0cFBhcmFtc3xcbiAgICAgICAgICB7W3BhcmFtOiBzdHJpbmddOiBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuIHwgUmVhZG9ubHlBcnJheTxzdHJpbmd8bnVtYmVyfGJvb2xlYW4+fSxcbiAgICByZXBvcnRQcm9ncmVzcz86IGJvb2xlYW4sIHJlc3BvbnNlVHlwZTogJ2Jsb2InLFxuICAgIHdpdGhDcmVkZW50aWFscz86IGJvb2xlYW4sXG4gICAgdHJhbnNmZXJDYWNoZT86IHtpbmNsdWRlSGVhZGVycz86IHN0cmluZ1tdfXxib29sZWFuXG4gIH0pOiBPYnNlcnZhYmxlPEJsb2I+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIGEgcmVxdWVzdCB0aGF0IGludGVycHJldHMgdGhlIGJvZHkgYXMgYSB0ZXh0IHN0cmluZyBhbmRcbiAgICogcmV0dXJucyBhIHN0cmluZyB2YWx1ZS5cbiAgICpcbiAgICogQHBhcmFtIG1ldGhvZCAgVGhlIEhUVFAgbWV0aG9kLlxuICAgKiBAcGFyYW0gdXJsICAgICBUaGUgZW5kcG9pbnQgVVJMLlxuICAgKiBAcGFyYW0gb3B0aW9ucyBUaGUgSFRUUCBvcHRpb25zIHRvIHNlbmQgd2l0aCB0aGUgcmVxdWVzdC5cbiAgICpcbiAgICogQHJldHVybiBBbiBgT2JzZXJ2YWJsZWAgb2YgdGhlIHJlc3BvbnNlLCB3aXRoIHRoZSByZXNwb25zZSBib2R5IG9mIHR5cGUgc3RyaW5nLlxuICAgKi9cbiAgcmVxdWVzdChtZXRob2Q6IHN0cmluZywgdXJsOiBzdHJpbmcsIG9wdGlvbnM6IHtcbiAgICBib2R5PzogYW55LFxuICAgIGhlYWRlcnM/OiBIdHRwSGVhZGVyc3x7W2hlYWRlcjogc3RyaW5nXTogc3RyaW5nIHwgc3RyaW5nW119LFxuICAgIGNvbnRleHQ/OiBIdHRwQ29udGV4dCxcbiAgICBvYnNlcnZlPzogJ2JvZHknLFxuICAgIHBhcmFtcz86IEh0dHBQYXJhbXN8XG4gICAgICAgICAge1twYXJhbTogc3RyaW5nXTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IFJlYWRvbmx5QXJyYXk8c3RyaW5nfG51bWJlcnxib29sZWFuPn0sXG4gICAgcmVwb3J0UHJvZ3Jlc3M/OiBib29sZWFuLCByZXNwb25zZVR5cGU6ICd0ZXh0JyxcbiAgICB3aXRoQ3JlZGVudGlhbHM/OiBib29sZWFuLFxuICAgIHRyYW5zZmVyQ2FjaGU/OiB7aW5jbHVkZUhlYWRlcnM/OiBzdHJpbmdbXX18Ym9vbGVhblxuICB9KTogT2JzZXJ2YWJsZTxzdHJpbmc+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIGEgcmVxdWVzdCB0aGF0IGludGVycHJldHMgdGhlIGJvZHkgYXMgYW4gYEFycmF5QnVmZmVyYCBhbmQgcmV0dXJucyB0aGVcbiAgICogdGhlIGZ1bGwgZXZlbnQgc3RyZWFtLlxuICAgKlxuICAgKiBAcGFyYW0gbWV0aG9kICBUaGUgSFRUUCBtZXRob2QuXG4gICAqIEBwYXJhbSB1cmwgICAgIFRoZSBlbmRwb2ludCBVUkwuXG4gICAqIEBwYXJhbSBvcHRpb25zIFRoZSBIVFRQIG9wdGlvbnMgdG8gc2VuZCB3aXRoIHRoZSByZXF1ZXN0LlxuICAgKlxuICAgKiBAcmV0dXJuIEFuIGBPYnNlcnZhYmxlYCBvZiB0aGUgcmVzcG9uc2UsIHdpdGggdGhlIHJlc3BvbnNlIGJvZHkgYXMgYW4gYXJyYXkgb2YgYEh0dHBFdmVudGBzIGZvclxuICAgKiB0aGUgcmVxdWVzdC5cbiAgICovXG4gIHJlcXVlc3QobWV0aG9kOiBzdHJpbmcsIHVybDogc3RyaW5nLCBvcHRpb25zOiB7XG4gICAgYm9keT86IGFueSxcbiAgICBoZWFkZXJzPzogSHR0cEhlYWRlcnN8e1toZWFkZXI6IHN0cmluZ106IHN0cmluZyB8IHN0cmluZ1tdfSxcbiAgICBjb250ZXh0PzogSHR0cENvbnRleHQsXG4gICAgcGFyYW1zPzogSHR0cFBhcmFtc3xcbiAgICAgICAgICB7W3BhcmFtOiBzdHJpbmddOiBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuIHwgUmVhZG9ubHlBcnJheTxzdHJpbmd8bnVtYmVyfGJvb2xlYW4+fSxcbiAgICAgICAgICBvYnNlcnZlOiAnZXZlbnRzJyxcbiAgICByZXBvcnRQcm9ncmVzcz86IGJvb2xlYW4sIHJlc3BvbnNlVHlwZTogJ2FycmF5YnVmZmVyJyxcbiAgICB3aXRoQ3JlZGVudGlhbHM/OiBib29sZWFuLFxuICAgIHRyYW5zZmVyQ2FjaGU/OiB7aW5jbHVkZUhlYWRlcnM/OiBzdHJpbmdbXX18Ym9vbGVhblxuICB9KTogT2JzZXJ2YWJsZTxIdHRwRXZlbnQ8QXJyYXlCdWZmZXI+PjtcblxuICAvKipcbiAgICogQ29uc3RydWN0cyBhIHJlcXVlc3QgdGhhdCBpbnRlcnByZXRzIHRoZSBib2R5IGFzIGEgYEJsb2JgIGFuZCByZXR1cm5zXG4gICAqIHRoZSBmdWxsIGV2ZW50IHN0cmVhbS5cbiAgICpcbiAgICogQHBhcmFtIG1ldGhvZCAgVGhlIEhUVFAgbWV0aG9kLlxuICAgKiBAcGFyYW0gdXJsICAgICBUaGUgZW5kcG9pbnQgVVJMLlxuICAgKiBAcGFyYW0gb3B0aW9ucyBUaGUgSFRUUCBvcHRpb25zIHRvIHNlbmQgd2l0aCB0aGUgcmVxdWVzdC5cbiAgICpcbiAgICogQHJldHVybiBBbiBgT2JzZXJ2YWJsZWAgb2YgYWxsIGBIdHRwRXZlbnRgcyBmb3IgdGhlIHJlcXVlc3QsXG4gICAqIHdpdGggdGhlIHJlc3BvbnNlIGJvZHkgb2YgdHlwZSBgQmxvYmAuXG4gICAqL1xuICByZXF1ZXN0KG1ldGhvZDogc3RyaW5nLCB1cmw6IHN0cmluZywgb3B0aW9uczoge1xuICAgIGJvZHk/OiBhbnksXG4gICAgaGVhZGVycz86IEh0dHBIZWFkZXJzfHtbaGVhZGVyOiBzdHJpbmddOiBzdHJpbmcgfCBzdHJpbmdbXX0sIG9ic2VydmU6ICdldmVudHMnLFxuICAgIGNvbnRleHQ/OiBIdHRwQ29udGV4dCxcbiAgICBwYXJhbXM/OiBIdHRwUGFyYW1zfFxuICAgICAgICAgIHtbcGFyYW06IHN0cmluZ106IHN0cmluZyB8IG51bWJlciB8IGJvb2xlYW4gfCBSZWFkb25seUFycmF5PHN0cmluZ3xudW1iZXJ8Ym9vbGVhbj59LFxuICAgIHJlcG9ydFByb2dyZXNzPzogYm9vbGVhbiwgcmVzcG9uc2VUeXBlOiAnYmxvYicsXG4gICAgd2l0aENyZWRlbnRpYWxzPzogYm9vbGVhbixcbiAgICB0cmFuc2ZlckNhY2hlPzoge2luY2x1ZGVIZWFkZXJzPzogc3RyaW5nW119fGJvb2xlYW5cbiAgfSk6IE9ic2VydmFibGU8SHR0cEV2ZW50PEJsb2I+PjtcblxuICAvKipcbiAgICogQ29uc3RydWN0cyBhIHJlcXVlc3Qgd2hpY2ggaW50ZXJwcmV0cyB0aGUgYm9keSBhcyBhIHRleHQgc3RyaW5nIGFuZCByZXR1cm5zIHRoZSBmdWxsIGV2ZW50XG4gICAqIHN0cmVhbS5cbiAgICpcbiAgICogQHBhcmFtIG1ldGhvZCAgVGhlIEhUVFAgbWV0aG9kLlxuICAgKiBAcGFyYW0gdXJsICAgICBUaGUgZW5kcG9pbnQgVVJMLlxuICAgKiBAcGFyYW0gb3B0aW9ucyBUaGUgSFRUUCBvcHRpb25zIHRvIHNlbmQgd2l0aCB0aGUgcmVxdWVzdC5cbiAgICpcbiAgICogQHJldHVybiBBbiBgT2JzZXJ2YWJsZWAgb2YgYWxsIGBIdHRwRXZlbnRgcyBmb3IgdGhlIHJlcXVlc3QsXG4gICAqIHdpdGggdGhlIHJlc3BvbnNlIGJvZHkgb2YgdHlwZSBzdHJpbmcuXG4gICAqL1xuICByZXF1ZXN0KG1ldGhvZDogc3RyaW5nLCB1cmw6IHN0cmluZywgb3B0aW9uczoge1xuICAgIGJvZHk/OiBhbnksXG4gICAgaGVhZGVycz86IEh0dHBIZWFkZXJzfHtbaGVhZGVyOiBzdHJpbmddOiBzdHJpbmcgfCBzdHJpbmdbXX0sIG9ic2VydmU6ICdldmVudHMnLFxuICAgIGNvbnRleHQ/OiBIdHRwQ29udGV4dCxcbiAgICBwYXJhbXM/OiBIdHRwUGFyYW1zfFxuICAgICAgICAgIHtbcGFyYW06IHN0cmluZ106IHN0cmluZyB8IG51bWJlciB8IGJvb2xlYW4gfCBSZWFkb25seUFycmF5PHN0cmluZ3xudW1iZXJ8Ym9vbGVhbj59LFxuICAgIHJlcG9ydFByb2dyZXNzPzogYm9vbGVhbiwgcmVzcG9uc2VUeXBlOiAndGV4dCcsXG4gICAgd2l0aENyZWRlbnRpYWxzPzogYm9vbGVhbixcbiAgICB0cmFuc2ZlckNhY2hlPzoge2luY2x1ZGVIZWFkZXJzPzogc3RyaW5nW119fGJvb2xlYW5cbiAgfSk6IE9ic2VydmFibGU8SHR0cEV2ZW50PHN0cmluZz4+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIGEgcmVxdWVzdCB3aGljaCBpbnRlcnByZXRzIHRoZSBib2R5IGFzIGEgSmF2YVNjcmlwdCBvYmplY3QgYW5kIHJldHVybnMgdGhlIGZ1bGxcbiAgICogZXZlbnQgc3RyZWFtLlxuICAgKlxuICAgKiBAcGFyYW0gbWV0aG9kICBUaGUgSFRUUCBtZXRob2QuXG4gICAqIEBwYXJhbSB1cmwgICAgIFRoZSBlbmRwb2ludCBVUkwuXG4gICAqIEBwYXJhbSBvcHRpb25zIFRoZSBIVFRQIG9wdGlvbnMgdG8gc2VuZCB3aXRoIHRoZSAgcmVxdWVzdC5cbiAgICpcbiAgICogQHJldHVybiBBbiBgT2JzZXJ2YWJsZWAgb2YgYWxsIGBIdHRwRXZlbnRgcyBmb3IgdGhlIHJlcXVlc3QsXG4gICAqIHdpdGggdGhlIHJlc3BvbnNlIGJvZHkgb2YgdHlwZSBgT2JqZWN0YC5cbiAgICovXG4gIHJlcXVlc3QobWV0aG9kOiBzdHJpbmcsIHVybDogc3RyaW5nLCBvcHRpb25zOiB7XG4gICAgYm9keT86IGFueSxcbiAgICBoZWFkZXJzPzogSHR0cEhlYWRlcnN8e1toZWFkZXI6IHN0cmluZ106IHN0cmluZyB8IHN0cmluZ1tdfSxcbiAgICBjb250ZXh0PzogSHR0cENvbnRleHQsXG4gICAgcmVwb3J0UHJvZ3Jlc3M/OiBib29sZWFuLCBvYnNlcnZlOiAnZXZlbnRzJyxcbiAgICBwYXJhbXM/OiBIdHRwUGFyYW1zfFxuICAgICAgICAgIHtbcGFyYW06IHN0cmluZ106IHN0cmluZyB8IG51bWJlciB8IGJvb2xlYW4gfCBSZWFkb25seUFycmF5PHN0cmluZ3xudW1iZXJ8Ym9vbGVhbj59LFxuICAgIHJlc3BvbnNlVHlwZT86ICdqc29uJyxcbiAgICB3aXRoQ3JlZGVudGlhbHM/OiBib29sZWFuLFxuICAgIHRyYW5zZmVyQ2FjaGU/OiB7aW5jbHVkZUhlYWRlcnM/OiBzdHJpbmdbXX18Ym9vbGVhblxuICB9KTogT2JzZXJ2YWJsZTxIdHRwRXZlbnQ8YW55Pj47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdHMgYSByZXF1ZXN0IHdoaWNoIGludGVycHJldHMgdGhlIGJvZHkgYXMgYSBKYXZhU2NyaXB0IG9iamVjdCBhbmQgcmV0dXJucyB0aGUgZnVsbFxuICAgKiBldmVudCBzdHJlYW0uXG4gICAqXG4gICAqIEBwYXJhbSBtZXRob2QgIFRoZSBIVFRQIG1ldGhvZC5cbiAgICogQHBhcmFtIHVybCAgICAgVGhlIGVuZHBvaW50IFVSTC5cbiAgICogQHBhcmFtIG9wdGlvbnMgVGhlIEhUVFAgb3B0aW9ucyB0byBzZW5kIHdpdGggdGhlIHJlcXVlc3QuXG4gICAqXG4gICAqIEByZXR1cm4gQW4gYE9ic2VydmFibGVgIG9mIGFsbCBgSHR0cEV2ZW50YHMgZm9yIHRoZSByZXF1ZXN0LFxuICAgKiB3aXRoIHRoZSByZXNwb25zZSBib2R5IG9mIHR5cGUgYFJgLlxuICAgKi9cbiAgcmVxdWVzdDxSPihtZXRob2Q6IHN0cmluZywgdXJsOiBzdHJpbmcsIG9wdGlvbnM6IHtcbiAgICBib2R5PzogYW55LFxuICAgIGhlYWRlcnM/OiBIdHRwSGVhZGVyc3x7W2hlYWRlcjogc3RyaW5nXTogc3RyaW5nIHwgc3RyaW5nW119LFxuICAgIGNvbnRleHQ/OiBIdHRwQ29udGV4dCxcbiAgICByZXBvcnRQcm9ncmVzcz86IGJvb2xlYW4sIG9ic2VydmU6ICdldmVudHMnLFxuICAgIHBhcmFtcz86IEh0dHBQYXJhbXN8XG4gICAgICAgICAge1twYXJhbTogc3RyaW5nXTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IFJlYWRvbmx5QXJyYXk8c3RyaW5nfG51bWJlcnxib29sZWFuPn0sXG4gICAgcmVzcG9uc2VUeXBlPzogJ2pzb24nLFxuICAgIHdpdGhDcmVkZW50aWFscz86IGJvb2xlYW4sXG4gICAgdHJhbnNmZXJDYWNoZT86IHtpbmNsdWRlSGVhZGVycz86IHN0cmluZ1tdfXxib29sZWFuXG4gIH0pOiBPYnNlcnZhYmxlPEh0dHBFdmVudDxSPj47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdHMgYSByZXF1ZXN0IHdoaWNoIGludGVycHJldHMgdGhlIGJvZHkgYXMgYW4gYEFycmF5QnVmZmVyYFxuICAgKiBhbmQgcmV0dXJucyB0aGUgZnVsbCBgSHR0cFJlc3BvbnNlYC5cbiAgICpcbiAgICogQHBhcmFtIG1ldGhvZCAgVGhlIEhUVFAgbWV0aG9kLlxuICAgKiBAcGFyYW0gdXJsICAgICBUaGUgZW5kcG9pbnQgVVJMLlxuICAgKiBAcGFyYW0gb3B0aW9ucyBUaGUgSFRUUCBvcHRpb25zIHRvIHNlbmQgd2l0aCB0aGUgcmVxdWVzdC5cbiAgICpcbiAgICogQHJldHVybiBBbiBgT2JzZXJ2YWJsZWAgb2YgdGhlIGBIdHRwUmVzcG9uc2VgLCB3aXRoIHRoZSByZXNwb25zZSBib2R5IGFzIGFuIGBBcnJheUJ1ZmZlcmAuXG4gICAqL1xuICByZXF1ZXN0KG1ldGhvZDogc3RyaW5nLCB1cmw6IHN0cmluZywgb3B0aW9uczoge1xuICAgIGJvZHk/OiBhbnksXG4gICAgaGVhZGVycz86IEh0dHBIZWFkZXJzfHtbaGVhZGVyOiBzdHJpbmddOiBzdHJpbmcgfCBzdHJpbmdbXX0sIG9ic2VydmU6ICdyZXNwb25zZScsXG4gICAgY29udGV4dD86IEh0dHBDb250ZXh0LFxuICAgIHBhcmFtcz86IEh0dHBQYXJhbXN8XG4gICAgICAgICAge1twYXJhbTogc3RyaW5nXTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IFJlYWRvbmx5QXJyYXk8c3RyaW5nfG51bWJlcnxib29sZWFuPn0sXG4gICAgcmVwb3J0UHJvZ3Jlc3M/OiBib29sZWFuLCByZXNwb25zZVR5cGU6ICdhcnJheWJ1ZmZlcicsXG4gICAgd2l0aENyZWRlbnRpYWxzPzogYm9vbGVhbixcbiAgICB0cmFuc2ZlckNhY2hlPzoge2luY2x1ZGVIZWFkZXJzPzogc3RyaW5nW119fGJvb2xlYW5cbiAgfSk6IE9ic2VydmFibGU8SHR0cFJlc3BvbnNlPEFycmF5QnVmZmVyPj47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdHMgYSByZXF1ZXN0IHdoaWNoIGludGVycHJldHMgdGhlIGJvZHkgYXMgYSBgQmxvYmAgYW5kIHJldHVybnMgdGhlIGZ1bGwgYEh0dHBSZXNwb25zZWAuXG4gICAqXG4gICAqIEBwYXJhbSBtZXRob2QgIFRoZSBIVFRQIG1ldGhvZC5cbiAgICogQHBhcmFtIHVybCAgICAgVGhlIGVuZHBvaW50IFVSTC5cbiAgICogQHBhcmFtIG9wdGlvbnMgVGhlIEhUVFAgb3B0aW9ucyB0byBzZW5kIHdpdGggdGhlIHJlcXVlc3QuXG4gICAqXG4gICAqIEByZXR1cm4gQW4gYE9ic2VydmFibGVgIG9mIHRoZSBgSHR0cFJlc3BvbnNlYCwgd2l0aCB0aGUgcmVzcG9uc2UgYm9keSBvZiB0eXBlIGBCbG9iYC5cbiAgICovXG4gIHJlcXVlc3QobWV0aG9kOiBzdHJpbmcsIHVybDogc3RyaW5nLCBvcHRpb25zOiB7XG4gICAgYm9keT86IGFueSxcbiAgICBoZWFkZXJzPzogSHR0cEhlYWRlcnN8e1toZWFkZXI6IHN0cmluZ106IHN0cmluZyB8IHN0cmluZ1tdfSwgb2JzZXJ2ZTogJ3Jlc3BvbnNlJyxcbiAgICBjb250ZXh0PzogSHR0cENvbnRleHQsXG4gICAgcGFyYW1zPzogSHR0cFBhcmFtc3xcbiAgICAgICAgICB7W3BhcmFtOiBzdHJpbmddOiBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuIHwgUmVhZG9ubHlBcnJheTxzdHJpbmd8bnVtYmVyfGJvb2xlYW4+fSxcbiAgICByZXBvcnRQcm9ncmVzcz86IGJvb2xlYW4sIHJlc3BvbnNlVHlwZTogJ2Jsb2InLFxuICAgIHdpdGhDcmVkZW50aWFscz86IGJvb2xlYW4sXG4gICAgdHJhbnNmZXJDYWNoZT86IHtpbmNsdWRlSGVhZGVycz86IHN0cmluZ1tdfXxib29sZWFuXG4gIH0pOiBPYnNlcnZhYmxlPEh0dHBSZXNwb25zZTxCbG9iPj47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdHMgYSByZXF1ZXN0IHdoaWNoIGludGVycHJldHMgdGhlIGJvZHkgYXMgYSB0ZXh0IHN0cmVhbSBhbmQgcmV0dXJucyB0aGUgZnVsbFxuICAgKiBgSHR0cFJlc3BvbnNlYC5cbiAgICpcbiAgICogQHBhcmFtIG1ldGhvZCAgVGhlIEhUVFAgbWV0aG9kLlxuICAgKiBAcGFyYW0gdXJsICAgICBUaGUgZW5kcG9pbnQgVVJMLlxuICAgKiBAcGFyYW0gb3B0aW9ucyBUaGUgSFRUUCBvcHRpb25zIHRvIHNlbmQgd2l0aCB0aGUgcmVxdWVzdC5cbiAgICpcbiAgICogQHJldHVybiBBbiBgT2JzZXJ2YWJsZWAgb2YgdGhlIEhUVFAgcmVzcG9uc2UsIHdpdGggdGhlIHJlc3BvbnNlIGJvZHkgb2YgdHlwZSBzdHJpbmcuXG4gICAqL1xuICByZXF1ZXN0KG1ldGhvZDogc3RyaW5nLCB1cmw6IHN0cmluZywgb3B0aW9uczoge1xuICAgIGJvZHk/OiBhbnksXG4gICAgaGVhZGVycz86IEh0dHBIZWFkZXJzfHtbaGVhZGVyOiBzdHJpbmddOiBzdHJpbmcgfCBzdHJpbmdbXX0sIG9ic2VydmU6ICdyZXNwb25zZScsXG4gICAgY29udGV4dD86IEh0dHBDb250ZXh0LFxuICAgIHBhcmFtcz86IEh0dHBQYXJhbXN8XG4gICAgICAgICAge1twYXJhbTogc3RyaW5nXTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IFJlYWRvbmx5QXJyYXk8c3RyaW5nfG51bWJlcnxib29sZWFuPn0sXG4gICAgcmVwb3J0UHJvZ3Jlc3M/OiBib29sZWFuLCByZXNwb25zZVR5cGU6ICd0ZXh0JyxcbiAgICB3aXRoQ3JlZGVudGlhbHM/OiBib29sZWFuLFxuICAgIHRyYW5zZmVyQ2FjaGU/OiB7aW5jbHVkZUhlYWRlcnM/OiBzdHJpbmdbXX18Ym9vbGVhblxuICB9KTogT2JzZXJ2YWJsZTxIdHRwUmVzcG9uc2U8c3RyaW5nPj47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdHMgYSByZXF1ZXN0IHdoaWNoIGludGVycHJldHMgdGhlIGJvZHkgYXMgYSBKYXZhU2NyaXB0IG9iamVjdCBhbmQgcmV0dXJucyB0aGUgZnVsbFxuICAgKiBgSHR0cFJlc3BvbnNlYC5cbiAgICpcbiAgICogQHBhcmFtIG1ldGhvZCAgVGhlIEhUVFAgbWV0aG9kLlxuICAgKiBAcGFyYW0gdXJsICAgICBUaGUgZW5kcG9pbnQgVVJMLlxuICAgKiBAcGFyYW0gb3B0aW9ucyBUaGUgSFRUUCBvcHRpb25zIHRvIHNlbmQgd2l0aCB0aGUgcmVxdWVzdC5cbiAgICpcbiAgICogQHJldHVybiBBbiBgT2JzZXJ2YWJsZWAgb2YgdGhlIGZ1bGwgYEh0dHBSZXNwb25zZWAsXG4gICAqIHdpdGggdGhlIHJlc3BvbnNlIGJvZHkgb2YgdHlwZSBgT2JqZWN0YC5cbiAgICovXG4gIHJlcXVlc3QobWV0aG9kOiBzdHJpbmcsIHVybDogc3RyaW5nLCBvcHRpb25zOiB7XG4gICAgYm9keT86IGFueSxcbiAgICBoZWFkZXJzPzogSHR0cEhlYWRlcnN8e1toZWFkZXI6IHN0cmluZ106IHN0cmluZyB8IHN0cmluZ1tdfSxcbiAgICBjb250ZXh0PzogSHR0cENvbnRleHQsXG4gICAgcmVwb3J0UHJvZ3Jlc3M/OiBib29sZWFuLCBvYnNlcnZlOiAncmVzcG9uc2UnLFxuICAgIHBhcmFtcz86IEh0dHBQYXJhbXN8XG4gICAgICAgICAge1twYXJhbTogc3RyaW5nXTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IFJlYWRvbmx5QXJyYXk8c3RyaW5nfG51bWJlcnxib29sZWFuPn0sXG4gICAgcmVzcG9uc2VUeXBlPzogJ2pzb24nLFxuICAgIHdpdGhDcmVkZW50aWFscz86IGJvb2xlYW4sXG4gIH0pOiBPYnNlcnZhYmxlPEh0dHBSZXNwb25zZTxPYmplY3Q+PjtcblxuICAvKipcbiAgICogQ29uc3RydWN0cyBhIHJlcXVlc3Qgd2hpY2ggaW50ZXJwcmV0cyB0aGUgYm9keSBhcyBhIEphdmFTY3JpcHQgb2JqZWN0IGFuZCByZXR1cm5zXG4gICAqIHRoZSBmdWxsIGBIdHRwUmVzcG9uc2VgIHdpdGggdGhlIHJlc3BvbnNlIGJvZHkgaW4gdGhlIHJlcXVlc3RlZCB0eXBlLlxuICAgKlxuICAgKiBAcGFyYW0gbWV0aG9kICBUaGUgSFRUUCBtZXRob2QuXG4gICAqIEBwYXJhbSB1cmwgICAgIFRoZSBlbmRwb2ludCBVUkwuXG4gICAqIEBwYXJhbSBvcHRpb25zIFRoZSBIVFRQIG9wdGlvbnMgdG8gc2VuZCB3aXRoIHRoZSByZXF1ZXN0LlxuICAgKlxuICAgKiBAcmV0dXJuICBBbiBgT2JzZXJ2YWJsZWAgb2YgdGhlIGZ1bGwgYEh0dHBSZXNwb25zZWAsIHdpdGggdGhlIHJlc3BvbnNlIGJvZHkgb2YgdHlwZSBgUmAuXG4gICAqL1xuICByZXF1ZXN0PFI+KG1ldGhvZDogc3RyaW5nLCB1cmw6IHN0cmluZywgb3B0aW9uczoge1xuICAgIGJvZHk/OiBhbnksXG4gICAgaGVhZGVycz86IEh0dHBIZWFkZXJzfHtbaGVhZGVyOiBzdHJpbmddOiBzdHJpbmcgfCBzdHJpbmdbXX0sXG4gICAgY29udGV4dD86IEh0dHBDb250ZXh0LFxuICAgIHJlcG9ydFByb2dyZXNzPzogYm9vbGVhbiwgb2JzZXJ2ZTogJ3Jlc3BvbnNlJyxcbiAgICBwYXJhbXM/OiBIdHRwUGFyYW1zfFxuICAgICAgICAgIHtbcGFyYW06IHN0cmluZ106IHN0cmluZyB8IG51bWJlciB8IGJvb2xlYW4gfCBSZWFkb25seUFycmF5PHN0cmluZ3xudW1iZXJ8Ym9vbGVhbj59LFxuICAgIHJlc3BvbnNlVHlwZT86ICdqc29uJyxcbiAgICB3aXRoQ3JlZGVudGlhbHM/OiBib29sZWFuLFxuICAgIHRyYW5zZmVyQ2FjaGU/OiB7aW5jbHVkZUhlYWRlcnM/OiBzdHJpbmdbXX18Ym9vbGVhblxuICB9KTogT2JzZXJ2YWJsZTxIdHRwUmVzcG9uc2U8Uj4+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIGEgcmVxdWVzdCB3aGljaCBpbnRlcnByZXRzIHRoZSBib2R5IGFzIGEgSmF2YVNjcmlwdCBvYmplY3QgYW5kIHJldHVybnMgdGhlIGZ1bGxcbiAgICogYEh0dHBSZXNwb25zZWAgYXMgYSBKYXZhU2NyaXB0IG9iamVjdC5cbiAgICpcbiAgICogQHBhcmFtIG1ldGhvZCAgVGhlIEhUVFAgbWV0aG9kLlxuICAgKiBAcGFyYW0gdXJsICAgICBUaGUgZW5kcG9pbnQgVVJMLlxuICAgKiBAcGFyYW0gb3B0aW9ucyBUaGUgSFRUUCBvcHRpb25zIHRvIHNlbmQgd2l0aCB0aGUgcmVxdWVzdC5cbiAgICpcbiAgICogQHJldHVybiBBbiBgT2JzZXJ2YWJsZWAgb2YgdGhlIGBIdHRwUmVzcG9uc2VgLCB3aXRoIHRoZSByZXNwb25zZSBib2R5IG9mIHR5cGUgYE9iamVjdGAuXG4gICAqL1xuICByZXF1ZXN0KG1ldGhvZDogc3RyaW5nLCB1cmw6IHN0cmluZywgb3B0aW9ucz86IHtcbiAgICBib2R5PzogYW55LFxuICAgIGhlYWRlcnM/OiBIdHRwSGVhZGVyc3x7W2hlYWRlcjogc3RyaW5nXTogc3RyaW5nIHwgc3RyaW5nW119LFxuICAgIGNvbnRleHQ/OiBIdHRwQ29udGV4dCxcbiAgICBvYnNlcnZlPzogJ2JvZHknLFxuICAgIHBhcmFtcz86IEh0dHBQYXJhbXN8XG4gICAgICAgICAge1twYXJhbTogc3RyaW5nXTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IFJlYWRvbmx5QXJyYXk8c3RyaW5nfG51bWJlcnxib29sZWFuPn0sXG4gICAgcmVzcG9uc2VUeXBlPzogJ2pzb24nLFxuICAgIHJlcG9ydFByb2dyZXNzPzogYm9vbGVhbixcbiAgICB3aXRoQ3JlZGVudGlhbHM/OiBib29sZWFuLFxuICAgIHRyYW5zZmVyQ2FjaGU/OiB7aW5jbHVkZUhlYWRlcnM/OiBzdHJpbmdbXX18Ym9vbGVhblxuICB9KTogT2JzZXJ2YWJsZTxPYmplY3Q+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIGEgcmVxdWVzdCB3aGljaCBpbnRlcnByZXRzIHRoZSBib2R5IGFzIGEgSmF2YVNjcmlwdCBvYmplY3RcbiAgICogd2l0aCB0aGUgcmVzcG9uc2UgYm9keSBvZiB0aGUgcmVxdWVzdGVkIHR5cGUuXG4gICAqXG4gICAqIEBwYXJhbSBtZXRob2QgIFRoZSBIVFRQIG1ldGhvZC5cbiAgICogQHBhcmFtIHVybCAgICAgVGhlIGVuZHBvaW50IFVSTC5cbiAgICogQHBhcmFtIG9wdGlvbnMgVGhlIEhUVFAgb3B0aW9ucyB0byBzZW5kIHdpdGggdGhlIHJlcXVlc3QuXG4gICAqXG4gICAqIEByZXR1cm4gQW4gYE9ic2VydmFibGVgIG9mIHRoZSBgSHR0cFJlc3BvbnNlYCwgd2l0aCB0aGUgcmVzcG9uc2UgYm9keSBvZiB0eXBlIGBSYC5cbiAgICovXG4gIHJlcXVlc3Q8Uj4obWV0aG9kOiBzdHJpbmcsIHVybDogc3RyaW5nLCBvcHRpb25zPzoge1xuICAgIGJvZHk/OiBhbnksXG4gICAgaGVhZGVycz86IEh0dHBIZWFkZXJzfHtbaGVhZGVyOiBzdHJpbmddOiBzdHJpbmcgfCBzdHJpbmdbXX0sXG4gICAgY29udGV4dD86IEh0dHBDb250ZXh0LFxuICAgIG9ic2VydmU/OiAnYm9keScsXG4gICAgcGFyYW1zPzogSHR0cFBhcmFtc3xcbiAgICAgICAgICB7W3BhcmFtOiBzdHJpbmddOiBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuIHwgUmVhZG9ubHlBcnJheTxzdHJpbmd8bnVtYmVyfGJvb2xlYW4+fSxcbiAgICByZXNwb25zZVR5cGU/OiAnanNvbicsXG4gICAgcmVwb3J0UHJvZ3Jlc3M/OiBib29sZWFuLFxuICAgIHdpdGhDcmVkZW50aWFscz86IGJvb2xlYW4sXG4gICAgdHJhbnNmZXJDYWNoZT86IHtpbmNsdWRlSGVhZGVycz86IHN0cmluZ1tdfXxib29sZWFuXG4gIH0pOiBPYnNlcnZhYmxlPFI+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIGEgcmVxdWVzdCB3aGVyZSByZXNwb25zZSB0eXBlIGFuZCByZXF1ZXN0ZWQgb2JzZXJ2YWJsZSBhcmUgbm90IGtub3duIHN0YXRpY2FsbHkuXG4gICAqXG4gICAqIEBwYXJhbSBtZXRob2QgIFRoZSBIVFRQIG1ldGhvZC5cbiAgICogQHBhcmFtIHVybCAgICAgVGhlIGVuZHBvaW50IFVSTC5cbiAgICogQHBhcmFtIG9wdGlvbnMgVGhlIEhUVFAgb3B0aW9ucyB0byBzZW5kIHdpdGggdGhlIHJlcXVlc3QuXG4gICAqXG4gICAqIEByZXR1cm4gQW4gYE9ic2VydmFibGVgIG9mIHRoZSByZXF1ZXN0ZWQgcmVzcG9uc2UsIHdpdGggYm9keSBvZiB0eXBlIGBhbnlgLlxuICAgKi9cbiAgcmVxdWVzdChtZXRob2Q6IHN0cmluZywgdXJsOiBzdHJpbmcsIG9wdGlvbnM/OiB7XG4gICAgYm9keT86IGFueSxcbiAgICBoZWFkZXJzPzogSHR0cEhlYWRlcnN8e1toZWFkZXI6IHN0cmluZ106IHN0cmluZyB8IHN0cmluZ1tdfSxcbiAgICBjb250ZXh0PzogSHR0cENvbnRleHQsXG4gICAgcGFyYW1zPzogSHR0cFBhcmFtc3xcbiAgICAgICAgICB7W3BhcmFtOiBzdHJpbmddOiBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuIHwgUmVhZG9ubHlBcnJheTxzdHJpbmd8bnVtYmVyfGJvb2xlYW4+fSxcbiAgICBvYnNlcnZlPzogJ2JvZHknfCdldmVudHMnfCdyZXNwb25zZScsXG4gICAgcmVwb3J0UHJvZ3Jlc3M/OiBib29sZWFuLFxuICAgIHJlc3BvbnNlVHlwZT86ICdhcnJheWJ1ZmZlcid8J2Jsb2InfCdqc29uJ3wndGV4dCcsXG4gICAgd2l0aENyZWRlbnRpYWxzPzogYm9vbGVhbixcbiAgICB0cmFuc2ZlckNhY2hlPzoge2luY2x1ZGVIZWFkZXJzPzogc3RyaW5nW119fGJvb2xlYW5cbiAgfSk6IE9ic2VydmFibGU8YW55PjtcblxuICAvKipcbiAgICogQ29uc3RydWN0cyBhbiBvYnNlcnZhYmxlIGZvciBhIGdlbmVyaWMgSFRUUCByZXF1ZXN0IHRoYXQsIHdoZW4gc3Vic2NyaWJlZCxcbiAgICogZmlyZXMgdGhlIHJlcXVlc3QgdGhyb3VnaCB0aGUgY2hhaW4gb2YgcmVnaXN0ZXJlZCBpbnRlcmNlcHRvcnMgYW5kIG9uIHRvIHRoZVxuICAgKiBzZXJ2ZXIuXG4gICAqXG4gICAqIFlvdSBjYW4gcGFzcyBhbiBgSHR0cFJlcXVlc3RgIGRpcmVjdGx5IGFzIHRoZSBvbmx5IHBhcmFtZXRlci4gSW4gdGhpcyBjYXNlLFxuICAgKiB0aGUgY2FsbCByZXR1cm5zIGFuIG9ic2VydmFibGUgb2YgdGhlIHJhdyBgSHR0cEV2ZW50YCBzdHJlYW0uXG4gICAqXG4gICAqIEFsdGVybmF0aXZlbHkgeW91IGNhbiBwYXNzIGFuIEhUVFAgbWV0aG9kIGFzIHRoZSBmaXJzdCBwYXJhbWV0ZXIsXG4gICAqIGEgVVJMIHN0cmluZyBhcyB0aGUgc2Vjb25kLCBhbmQgYW4gb3B0aW9ucyBoYXNoIGNvbnRhaW5pbmcgdGhlIHJlcXVlc3QgYm9keSBhcyB0aGUgdGhpcmQuXG4gICAqIFNlZSBgYWRkQm9keSgpYC4gSW4gdGhpcyBjYXNlLCB0aGUgc3BlY2lmaWVkIGByZXNwb25zZVR5cGVgIGFuZCBgb2JzZXJ2ZWAgb3B0aW9ucyBkZXRlcm1pbmUgdGhlXG4gICAqIHR5cGUgb2YgcmV0dXJuZWQgb2JzZXJ2YWJsZS5cbiAgICogICAqIFRoZSBgcmVzcG9uc2VUeXBlYCB2YWx1ZSBkZXRlcm1pbmVzIGhvdyBhIHN1Y2Nlc3NmdWwgcmVzcG9uc2UgYm9keSBpcyBwYXJzZWQuXG4gICAqICAgKiBJZiBgcmVzcG9uc2VUeXBlYCBpcyB0aGUgZGVmYXVsdCBganNvbmAsIHlvdSBjYW4gcGFzcyBhIHR5cGUgaW50ZXJmYWNlIGZvciB0aGUgcmVzdWx0aW5nXG4gICAqIG9iamVjdCBhcyBhIHR5cGUgcGFyYW1ldGVyIHRvIHRoZSBjYWxsLlxuICAgKlxuICAgKiBUaGUgYG9ic2VydmVgIHZhbHVlIGRldGVybWluZXMgdGhlIHJldHVybiB0eXBlLCBhY2NvcmRpbmcgdG8gd2hhdCB5b3UgYXJlIGludGVyZXN0ZWQgaW5cbiAgICogb2JzZXJ2aW5nLlxuICAgKiAgICogQW4gYG9ic2VydmVgIHZhbHVlIG9mIGV2ZW50cyByZXR1cm5zIGFuIG9ic2VydmFibGUgb2YgdGhlIHJhdyBgSHR0cEV2ZW50YCBzdHJlYW0sIGluY2x1ZGluZ1xuICAgKiBwcm9ncmVzcyBldmVudHMgYnkgZGVmYXVsdC5cbiAgICogICAqIEFuIGBvYnNlcnZlYCB2YWx1ZSBvZiByZXNwb25zZSByZXR1cm5zIGFuIG9ic2VydmFibGUgb2YgYEh0dHBSZXNwb25zZTxUPmAsXG4gICAqIHdoZXJlIHRoZSBgVGAgcGFyYW1ldGVyIGRlcGVuZHMgb24gdGhlIGByZXNwb25zZVR5cGVgIGFuZCBhbnkgb3B0aW9uYWxseSBwcm92aWRlZCB0eXBlXG4gICAqIHBhcmFtZXRlci5cbiAgICogICAqIEFuIGBvYnNlcnZlYCB2YWx1ZSBvZiBib2R5IHJldHVybnMgYW4gb2JzZXJ2YWJsZSBvZiBgPFQ+YCB3aXRoIHRoZSBzYW1lIGBUYCBib2R5IHR5cGUuXG4gICAqXG4gICAqL1xuICByZXF1ZXN0KGZpcnN0OiBzdHJpbmd8SHR0cFJlcXVlc3Q8YW55PiwgdXJsPzogc3RyaW5nLCBvcHRpb25zOiB7XG4gICAgYm9keT86IGFueSxcbiAgICBoZWFkZXJzPzogSHR0cEhlYWRlcnN8e1toZWFkZXI6IHN0cmluZ106IHN0cmluZyB8IHN0cmluZ1tdfSxcbiAgICBjb250ZXh0PzogSHR0cENvbnRleHQsXG4gICAgb2JzZXJ2ZT86ICdib2R5J3wnZXZlbnRzJ3wncmVzcG9uc2UnLFxuICAgIHBhcmFtcz86IEh0dHBQYXJhbXN8XG4gICAgICAgICAge1twYXJhbTogc3RyaW5nXTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IFJlYWRvbmx5QXJyYXk8c3RyaW5nfG51bWJlcnxib29sZWFuPn0sXG4gICAgcmVwb3J0UHJvZ3Jlc3M/OiBib29sZWFuLFxuICAgIHJlc3BvbnNlVHlwZT86ICdhcnJheWJ1ZmZlcid8J2Jsb2InfCdqc29uJ3wndGV4dCcsXG4gICAgd2l0aENyZWRlbnRpYWxzPzogYm9vbGVhbixcbiAgICB0cmFuc2ZlckNhY2hlPzoge2luY2x1ZGVIZWFkZXJzPzogc3RyaW5nW119fGJvb2xlYW5cbiAgfSA9IHt9KTogT2JzZXJ2YWJsZTxhbnk+IHtcbiAgICBsZXQgcmVxOiBIdHRwUmVxdWVzdDxhbnk+O1xuICAgIC8vIEZpcnN0LCBjaGVjayB3aGV0aGVyIHRoZSBwcmltYXJ5IGFyZ3VtZW50IGlzIGFuIGluc3RhbmNlIG9mIGBIdHRwUmVxdWVzdGAuXG4gICAgaWYgKGZpcnN0IGluc3RhbmNlb2YgSHR0cFJlcXVlc3QpIHtcbiAgICAgIC8vIEl0IGlzLiBUaGUgb3RoZXIgYXJndW1lbnRzIG11c3QgYmUgdW5kZWZpbmVkIChwZXIgdGhlIHNpZ25hdHVyZXMpIGFuZCBjYW4gYmVcbiAgICAgIC8vIGlnbm9yZWQuXG4gICAgICByZXEgPSBmaXJzdDtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gSXQncyBhIHN0cmluZywgc28gaXQgcmVwcmVzZW50cyBhIFVSTC4gQ29uc3RydWN0IGEgcmVxdWVzdCBiYXNlZCBvbiBpdCxcbiAgICAgIC8vIGFuZCBpbmNvcnBvcmF0ZSB0aGUgcmVtYWluaW5nIGFyZ3VtZW50cyAoYXNzdW1pbmcgYEdFVGAgdW5sZXNzIGEgbWV0aG9kIGlzXG4gICAgICAvLyBwcm92aWRlZC5cblxuICAgICAgLy8gRmlndXJlIG91dCB0aGUgaGVhZGVycy5cbiAgICAgIGxldCBoZWFkZXJzOiBIdHRwSGVhZGVyc3x1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG4gICAgICBpZiAob3B0aW9ucy5oZWFkZXJzIGluc3RhbmNlb2YgSHR0cEhlYWRlcnMpIHtcbiAgICAgICAgaGVhZGVycyA9IG9wdGlvbnMuaGVhZGVycztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGhlYWRlcnMgPSBuZXcgSHR0cEhlYWRlcnMob3B0aW9ucy5oZWFkZXJzKTtcbiAgICAgIH1cblxuICAgICAgLy8gU29ydCBvdXQgcGFyYW1ldGVycy5cbiAgICAgIGxldCBwYXJhbXM6IEh0dHBQYXJhbXN8dW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuICAgICAgaWYgKCEhb3B0aW9ucy5wYXJhbXMpIHtcbiAgICAgICAgaWYgKG9wdGlvbnMucGFyYW1zIGluc3RhbmNlb2YgSHR0cFBhcmFtcykge1xuICAgICAgICAgIHBhcmFtcyA9IG9wdGlvbnMucGFyYW1zO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHBhcmFtcyA9IG5ldyBIdHRwUGFyYW1zKHtmcm9tT2JqZWN0OiBvcHRpb25zLnBh