@angular/common
Version:
Angular - commonly needed directives and services
326 lines (325 loc) • 186 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.3.9", ngImport: i0, type: HttpClient, deps: [{ token: i1.HttpHandler }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: HttpClient }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.9", ngImport: i0, type: HttpClient, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: i1.HttpHandler }] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvY29tbW9uL2h0dHAvc3JjL2NsaWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFFSCxPQUFPLEVBQUMsVUFBVSxFQUFDLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sRUFBYSxFQUFFLEVBQUMsTUFBTSxNQUFNLENBQUM7QUFDcEMsT0FBTyxFQUFDLFNBQVMsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFFdEQsT0FBTyxFQUFDLFdBQVcsRUFBQyxNQUFNLFdBQVcsQ0FBQztBQUV0QyxPQUFPLEVBQUMsV0FBVyxFQUFDLE1BQU0sV0FBVyxDQUFDO0FBQ3RDLE9BQU8sRUFBQyxVQUFVLEVBQW9CLE1BQU0sVUFBVSxDQUFDO0FBQ3ZELE9BQU8sRUFBQyxXQUFXLEVBQUMsTUFBTSxXQUFXLENBQUM7QUFDdEMsT0FBTyxFQUFZLFlBQVksRUFBQyxNQUFNLFlBQVksQ0FBQzs7O0FBRW5EOzs7Ozs7Ozs7R0FTRztBQUNILFNBQVMsT0FBTyxDQUNkLE9BV0MsRUFDRCxJQUFjO0lBRWQsT0FBTztRQUNMLElBQUk7UUFDSixPQUFPLEVBQUUsT0FBTyxDQUFDLE9BQU87UUFDeEIsT0FBTyxFQUFFLE9BQU8sQ0FBQyxPQUFPO1FBQ3hCLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTztRQUN4QixNQUFNLEVBQUUsT0FBTyxDQUFDLE1BQU07UUFDdEIsY0FBYyxFQUFFLE9BQU8sQ0FBQyxjQUFjO1FBQ3RDLFlBQVksRUFBRSxPQUFPLENBQUMsWUFBWTtRQUNsQyxlQUFlLEVBQUUsT0FBTyxDQUFDLGVBQWU7UUFDeEMsYUFBYSxFQUFFLE9BQU8sQ0FBQyxhQUFhO0tBQ3JDLENBQUM7QUFDSixDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7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RUFBRSxJQUFJLFVBQVUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxhQUFhLEVBQUUsZ0JBQWdCLENBQUM7WUFDaEUsT0FBTyxFQUFFLE1BQU07WUFDZixZQUFZLEVBQUUsTUFBTTtTQUNyQixDQUFDLENBQUM7SUFDTCxDQUFDO0lBcVhEOzs7Ozs7T0FNRztJQUNILE9BQU8sQ0FDTCxHQUFXLEVBQ1gsVUFVSSxFQUFFO1FBRU4sT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFNLFNBQVMsRUFBRSxHQUFHLEVBQUUsT0FBYyxDQUFDLENBQUM7SUFDM0QsQ0FBQztJQXFaRDs7OztPQUlHO0lBQ0gsS0FBSyxDQUNILEdBQVcsRUFDWCxJQUFnQixFQUNoQixVQVVJLEVBQUU7UUFFTixPQUFPLElBQUksQ0FBQyxPQUFPLENBQU0sT0FBTyxFQUFFLEdBQUcsRUFBRSxPQUFPLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDakUsQ0FBQztJQWthRDs7Ozs7T0FLRztJQUNILElBQUksQ0FDRixHQUFXLEVBQ1gsSUFBZ0IsRUFDaEIsVUFXSSxFQUFFO1FBRU4sT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFNLE1BQU0sRUFBRSxHQUFHLEVBQUUsT0FBTyxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ2hFLENBQUM7SUFrWkQ7Ozs7O09BS0c7SUFDSCxHQUFHLENBQ0QsR0FBVyxFQUNYLElBQWdCLEVBQ2hCLFVBVUksRUFBRTtRQUVOLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBTSxLQUFLLEVBQUUsR0FBRyxFQUFFLE9BQU8sQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUMvRCxDQUFDO3lIQTkvR1UsVUFBVTs2SEFBVixVQUFVOztzR0FBVixVQUFVO2tCQUR0QixVQUFVIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiBVc2Ugb2YgdGhpcyBzb3VyY2UgY29kZSBpcyBnb3Zlcm5lZCBieSBhbiBNSVQtc3R5bGUgbGljZW5zZSB0aGF0IGNhbiBiZVxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxuICovXG5cbmltcG9ydCB7SW5qZWN0YWJsZX0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge09ic2VydmFibGUsIG9mfSBmcm9tICdyeGpzJztcbmltcG9ydCB7Y29uY2F0TWFwLCBmaWx0ZXIsIG1hcH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQge0h0dHBIYW5kbGVyfSBmcm9tICcuL2JhY2tlbmQnO1xuaW1wb3J0IHtIdHRwQ29udGV4dH0gZnJvbSAnLi9jb250ZXh0JztcbmltcG9ydCB7SHR0cEhlYWRlcnN9IGZyb20gJy4vaGVhZGVycyc7XG5pbXBvcnQge0h0dHBQYXJhbXMsIEh0dHBQYXJhbXNPcHRpb25zfSBmcm9tICcuL3BhcmFtcyc7XG5pbXBvcnQge0h0dHBSZXF1ZXN0fSBmcm9tICcuL3JlcXVlc3QnO1xuaW1wb3J0IHtIdHRwRXZlbnQsIEh0dHBSZXNwb25zZX0gZnJvbSAnLi9yZXNwb25zZSc7XG5cbi8qKlxuICogQ29uc3RydWN0cyBhbiBpbnN0YW5jZSBvZiBgSHR0cFJlcXVlc3RPcHRpb25zPFQ+YCBmcm9tIGEgc291cmNlIGBIdHRwTWV0aG9kT3B0aW9uc2AgYW5kXG4gKiB0aGUgZ2l2ZW4gYGJvZHlgLiBUaGlzIGZ1bmN0aW9uIGNsb25lcyB0aGUgb2JqZWN0IGFuZCBhZGRzIHRoZSBib2R5LlxuICpcbiAqIE5vdGUgdGhhdCB0aGUgYHJlc3BvbnNlVHlwZWAgKm9wdGlvbnMqIHZhbHVlIGlzIGEgU3RyaW5nIHRoYXQgaWRlbnRpZmllcyB0aGVcbiAqIHNpbmdsZSBkYXRhIHR5cGUgb2YgdGhlIHJlc3BvbnNlLlxuICogQSBzaW5nbGUgb3ZlcmxvYWQgdmVyc2lvbiBvZiB0aGUgbWV0aG9kIGhhbmRsZXMgZWFjaCByZXNwb25zZSB0eXBlLlxuICogVGhlIHZhbHVlIG9mIGByZXNwb25zZVR5cGVgIGNhbm5vdCBiZSBhIHVuaW9uLCBhcyB0aGUgY29tYmluZWQgc2lnbmF0dXJlIGNvdWxkIGltcGx5LlxuICpcbiAqL1xuZnVuY3Rpb24gYWRkQm9keTxUPihcbiAgb3B0aW9uczoge1xuICAgIGhlYWRlcnM/OiBIdHRwSGVhZGVycyB8IHtbaGVhZGVyOiBzdHJpbmddOiBzdHJpbmcgfCBzdHJpbmdbXX07XG4gICAgY29udGV4dD86IEh0dHBDb250ZXh0O1xuICAgIG9ic2VydmU/OiAnYm9keScgfCAnZXZlbnRzJyB8ICdyZXNwb25zZSc7XG4gICAgcGFyYW1zPzpcbiAgICAgIHwgSHR0cFBhcmFtc1xuICAgICAgfCB7W3BhcmFtOiBzdHJpbmddOiBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuIHwgUmVhZG9ubHlBcnJheTxzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuPn07XG4gICAgcmVwb3J0UHJvZ3Jlc3M/OiBib29sZWFuO1xuICAgIHJlc3BvbnNlVHlwZT86ICdhcnJheWJ1ZmZlcicgfCAnYmxvYicgfCAnanNvbicgfCAndGV4dCc7XG4gICAgd2l0aENyZWRlbnRpYWxzPzogYm9vbGVhbjtcbiAgICB0cmFuc2ZlckNhY2hlPzoge2luY2x1ZGVIZWFkZXJzPzogc3RyaW5nW119IHwgYm9vbGVhbjtcbiAgfSxcbiAgYm9keTogVCB8IG51bGwsXG4pOiBhbnkge1xuICByZXR1cm4ge1xuICAgIGJvZHksXG4gICAgaGVhZGVyczogb3B0aW9ucy5oZWFkZXJzLFxuICAgIGNvbnRleHQ6IG9wdGlvbnMuY29udGV4dCxcbiAgICBvYnNlcnZlOiBvcHRpb25zLm9ic2VydmUsXG4gICAgcGFyYW1zOiBvcHRpb25zLnBhcmFtcyxcbiAgICByZXBvcnRQcm9ncmVzczogb3B0aW9ucy5yZXBvcnRQcm9ncmVzcyxcbiAgICByZXNwb25zZVR5cGU6IG9wdGlvbnMucmVzcG9uc2VUeXBlLFxuICAgIHdpdGhDcmVkZW50aWFsczogb3B0aW9ucy53aXRoQ3JlZGVudGlhbHMsXG4gICAgdHJhbnNmZXJDYWNoZTogb3B0aW9ucy50cmFuc2ZlckNhY2hlLFxuICB9O1xufVxuXG4vKipcbiAqIFBlcmZvcm1zIEhUVFAgcmVxdWVzdHMuXG4gKiBUaGlzIHNlcnZpY2UgaXMgYXZhaWxhYmxlIGFzIGFuIGluamVjdGFibGUgY2xhc3MsIHdpdGggbWV0aG9kcyB0byBwZXJmb3JtIEhUVFAgcmVxdWVzdHMuXG4gKiBFYWNoIHJlcXVlc3QgbWV0aG9kIGhhcyBtdWx0aXBsZSBzaWduYXR1cmVzLCBhbmQgdGhlIHJldHVybiB0eXBlIHZhcmllcyBiYXNlZCBvblxuICogdGhlIHNpZ25hdHVyZSB0aGF0IGlzIGNhbGxlZCAobWFpbmx5IHRoZSB2YWx1ZXMgb2YgYG9ic2VydmVgIGFuZCBgcmVzcG9uc2VUeXBlYCkuXG4gKlxuICogTm90ZSB0aGF0IHRoZSBgcmVzcG9uc2VUeXBlYCAqb3B0aW9ucyogdmFsdWUgaXMgYSBTdHJpbmcgdGhhdCBpZGVudGlmaWVzIHRoZVxuICogc2luZ2xlIGRhdGEgdHlwZSBvZiB0aGUgcmVzcG9uc2UuXG4gKiBBIHNpbmdsZSBvdmVybG9hZCB2ZXJzaW9uIG9mIHRoZSBtZXRob2QgaGFuZGxlcyBlYWNoIHJlc3BvbnNlIHR5cGUuXG4gKiBUaGUgdmFsdWUgb2YgYHJlc3BvbnNlVHlwZWAgY2Fubm90IGJlIGEgdW5pb24sIGFzIHRoZSBjb21iaW5lZCBzaWduYXR1cmUgY291bGQgaW1wbHkuXG5cbiAqXG4gKiBAdXNhZ2VOb3Rlc1xuICogU2FtcGxlIEhUVFAgcmVxdWVzdHMgZm9yIHRoZSBbVG91ciBvZiBIZXJvZXNdKC90dXRvcmlhbC90b3VyLW9mLWhlcm9lcy90b2gtcHQwKSBhcHBsaWNhdGlvbi5cbiAqXG4gKiAjIyMgSFRUUCBSZXF1ZXN0IEV4YW1wbGVcbiAqXG4gKiBgYGBcbiAqICAvLyBHRVQgaGVyb2VzIHdob3NlIG5hbWUgY29udGFpbnMgc2VhcmNoIHRlcm1cbiAqIHNlYXJjaEhlcm9lcyh0ZXJtOiBzdHJpbmcpOiBvYnNlcnZhYmxlPEhlcm9bXT57XG4gKlxuICogIGNvbnN0IHBhcmFtcyA9IG5ldyBIdHRwUGFyYW1zKHtmcm9tU3RyaW5nOiAnbmFtZT10ZXJtJ30pO1xuICogICAgcmV0dXJuIHRoaXMuaHR0cENsaWVudC5yZXF1ZXN0KCdHRVQnLCB0aGlzLmhlcm9lc1VybCwge3Jlc3BvbnNlVHlwZTonanNvbicsIHBhcmFtc30pO1xuICogfVxuICogYGBgXG4gKlxuICogQWx0ZXJuYXRpdmVseSwgdGhlIHBhcmFtZXRlciBzdHJpbmcgY2FuIGJlIHVzZWQgd2l0aG91dCBpbnZva2luZyBIdHRwUGFyYW1zXG4gKiBieSBkaXJlY3RseSBqb2luaW5nIHRvIHRoZSBVUkwuXG4gKiBgYGBcbiAqIHRoaXMuaHR0cENsaWVudC5yZXF1ZXN0KCdHRVQnLCB0aGlzLmhlcm9lc1VybCArICc/JyArICduYW1lPXRlcm0nLCB7cmVzcG9uc2VUeXBlOidqc29uJ30pO1xuICogYGBgXG4gKlxuICpcbiAqICMjIyBKU09OUCBFeGFtcGxlXG4gKiBgYGBcbiAqIHJlcXVlc3RKc29ucCh1cmwsIGNhbGxiYWNrID0gJ2NhbGxiYWNrJykge1xuICogIHJldHVybiB0aGlzLmh0dHBDbGllbnQuanNvbnAodGhpcy5oZXJvZXNVUkwsIGNhbGxiYWNrKTtcbiAqIH1cbiAqIGBgYFxuICpcbiAqICMjIyBQQVRDSCBFeGFtcGxlXG4gKiBgYGBcbiAqIC8vIFBBVENIIG9uZSBvZiB0aGUgaGVyb2VzJyBuYW1lXG4gKiBwYXRjaEhlcm8gKGlkOiBudW1iZXIsIGhlcm9OYW1lOiBzdHJpbmcpOiBPYnNlcnZhYmxlPHt9PiB7XG4gKiBjb25zdCB1cmwgPSBgJHt0aGlzLmhlcm9lc1VybH0vJHtpZH1gOyAgIC8vIFBBVENIIGFwaS9oZXJvZXMvNDJcbiAqICByZXR1cm4gdGhpcy5odHRwQ2xpZW50LnBhdGNoKHVybCwge25hbWU6IGhlcm9OYW1lfSwgaHR0cE9wdGlvbnMpXG4gKiAgICAucGlwZShjYXRjaEVycm9yKHRoaXMuaGFuZGxlRXJyb3IoJ3BhdGNoSGVybycpKSk7XG4gKiB9XG4gKiBgYGBcbiAqXG4gKiBAc2VlIFtIVFRQIEd1aWRlXShndWlkZS91bmRlcnN0YW5kaW5nLWNvbW11bmljYXRpbmctd2l0aC1odHRwKVxuICogQHNlZSBbSFRUUCBSZXF1ZXN0XShhcGkvY29tbW9uL2h0dHAvSHR0cFJlcXVlc3QpXG4gKlxuICogQHB1YmxpY0FwaVxuICovXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgSHR0cENsaWVudCB7XG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgaGFuZGxlcjogSHR0cEhhbmRsZXIpIHt9XG5cbiAgLyoqXG4gICAqIFNlbmRzIGFuIGBIdHRwUmVxdWVzdGAgYW5kIHJldHVybnMgYSBzdHJlYW0gb2YgYEh0dHBFdmVudGBzLlxuICAgKlxuICAgKiBAcmV0dXJuIEFuIGBPYnNlcnZhYmxlYCBvZiB0aGUgcmVzcG9uc2UsIHdpdGggdGhlIHJlc3BvbnNlIGJvZHkgYXMgYSBzdHJlYW0gb2YgYEh0dHBFdmVudGBzLlxuICAgKi9cbiAgcmVxdWVzdDxSPihyZXE6IEh0dHBSZXF1ZXN0PGFueT4pOiBPYnNlcnZhYmxlPEh0dHBFdmVudDxSPj47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdHMgYSByZXF1ZXN0IHRoYXQgaW50ZXJwcmV0cyB0aGUgYm9keSBhcyBhbiBgQXJyYXlCdWZmZXJgIGFuZCByZXR1cm5zIHRoZSByZXNwb25zZSBpblxuICAgKiBhbiBgQXJyYXlCdWZmZXJgLlxuICAgKlxuICAgKiBAcGFyYW0gbWV0aG9kICBUaGUgSFRUUCBtZXRob2QuXG4gICAqIEBwYXJhbSB1cmwgICAgIFRoZSBlbmRwb2ludCBVUkwuXG4gICAqIEBwYXJhbSBvcHRpb25zIFRoZSBIVFRQIG9wdGlvbnMgdG8gc2VuZCB3aXRoIHRoZSByZXF1ZXN0LlxuICAgKlxuICAgKlxuICAgKiBAcmV0dXJuIEFuIGBPYnNlcnZhYmxlYCBvZiB0aGUgcmVzcG9uc2UsIHdpdGggdGhlIHJlc3BvbnNlIGJvZHkgYXMgYW4gYEFycmF5QnVmZmVyYC5cbiAgICovXG4gIHJlcXVlc3QoXG4gICAgbWV0aG9kOiBzdHJpbmcsXG4gICAgdXJsOiBzdHJpbmcsXG4gICAgb3B0aW9uczoge1xuICAgICAgYm9keT86IGFueTtcbiAgICAgIGhlYWRlcnM/OiBIdHRwSGVhZGVycyB8IHtbaGVhZGVyOiBzdHJpbmddOiBzdHJpbmcgfCBzdHJpbmdbXX07XG4gICAgICBjb250ZXh0PzogSHR0cENvbnRleHQ7XG4gICAgICBvYnNlcnZlPzogJ2JvZHknO1xuICAgICAgcGFyYW1zPzpcbiAgICAgICAgfCBIdHRwUGFyYW1zXG4gICAgICAgIHwge1twYXJhbTogc3RyaW5nXTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IFJlYWRvbmx5QXJyYXk8c3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbj59O1xuICAgICAgcmVwb3J0UHJvZ3Jlc3M/OiBib29sZWFuO1xuICAgICAgcmVzcG9uc2VUeXBlOiAnYXJyYXlidWZmZXInO1xuICAgICAgd2l0aENyZWRlbnRpYWxzPzogYm9vbGVhbjtcbiAgICAgIHRyYW5zZmVyQ2FjaGU/OiB7aW5jbHVkZUhlYWRlcnM/OiBzdHJpbmdbXX0gfCBib29sZWFuO1xuICAgIH0sXG4gICk6IE9ic2VydmFibGU8QXJyYXlCdWZmZXI+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIGEgcmVxdWVzdCB0aGF0IGludGVycHJldHMgdGhlIGJvZHkgYXMgYSBibG9iIGFuZCByZXR1cm5zXG4gICAqIHRoZSByZXNwb25zZSBhcyBhIGJsb2IuXG4gICAqXG4gICAqIEBwYXJhbSBtZXRob2QgIFRoZSBIVFRQIG1ldGhvZC5cbiAgICogQHBhcmFtIHVybCAgICAgVGhlIGVuZHBvaW50IFVSTC5cbiAgICogQHBhcmFtIG9wdGlvbnMgVGhlIEhUVFAgb3B0aW9ucyB0byBzZW5kIHdpdGggdGhlIHJlcXVlc3QuXG4gICAqXG4gICAqIEByZXR1cm4gQW4gYE9ic2VydmFibGVgIG9mIHRoZSByZXNwb25zZSwgd2l0aCB0aGUgcmVzcG9uc2UgYm9keSBvZiB0eXBlIGBCbG9iYC5cbiAgICovXG4gIHJlcXVlc3QoXG4gICAgbWV0aG9kOiBzdHJpbmcsXG4gICAgdXJsOiBzdHJpbmcsXG4gICAgb3B0aW9uczoge1xuICAgICAgYm9keT86IGFueTtcbiAgICAgIGhlYWRlcnM/OiBIdHRwSGVhZGVycyB8IHtbaGVhZGVyOiBzdHJpbmddOiBzdHJpbmcgfCBzdHJpbmdbXX07XG4gICAgICBjb250ZXh0PzogSHR0cENvbnRleHQ7XG4gICAgICBvYnNlcnZlPzogJ2JvZHknO1xuICAgICAgcGFyYW1zPzpcbiAgICAgICAgfCBIdHRwUGFyYW1zXG4gICAgICAgIHwge1twYXJhbTogc3RyaW5nXTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IFJlYWRvbmx5QXJyYXk8c3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbj59O1xuICAgICAgcmVwb3J0UHJvZ3Jlc3M/OiBib29sZWFuO1xuICAgICAgcmVzcG9uc2VUeXBlOiAnYmxvYic7XG4gICAgICB3aXRoQ3JlZGVudGlhbHM/OiBib29sZWFuO1xuICAgICAgdHJhbnNmZXJDYWNoZT86IHtpbmNsdWRlSGVhZGVycz86IHN0cmluZ1tdfSB8IGJvb2xlYW47XG4gICAgfSxcbiAgKTogT2JzZXJ2YWJsZTxCbG9iPjtcblxuICAvKipcbiAgICogQ29uc3RydWN0cyBhIHJlcXVlc3QgdGhhdCBpbnRlcnByZXRzIHRoZSBib2R5IGFzIGEgdGV4dCBzdHJpbmcgYW5kXG4gICAqIHJldHVybnMgYSBzdHJpbmcgdmFsdWUuXG4gICAqXG4gICAqIEBwYXJhbSBtZXRob2QgIFRoZSBIVFRQIG1ldGhvZC5cbiAgICogQHBhcmFtIHVybCAgICAgVGhlIGVuZHBvaW50IFVSTC5cbiAgICogQHBhcmFtIG9wdGlvbnMgVGhlIEhUVFAgb3B0aW9ucyB0byBzZW5kIHdpdGggdGhlIHJlcXVlc3QuXG4gICAqXG4gICAqIEByZXR1cm4gQW4gYE9ic2VydmFibGVgIG9mIHRoZSByZXNwb25zZSwgd2l0aCB0aGUgcmVzcG9uc2UgYm9keSBvZiB0eXBlIHN0cmluZy5cbiAgICovXG4gIHJlcXVlc3QoXG4gICAgbWV0aG9kOiBzdHJpbmcsXG4gICAgdXJsOiBzdHJpbmcsXG4gICAgb3B0aW9uczoge1xuICAgICAgYm9keT86IGFueTtcbiAgICAgIGhlYWRlcnM/OiBIdHRwSGVhZGVycyB8IHtbaGVhZGVyOiBzdHJpbmddOiBzdHJpbmcgfCBzdHJpbmdbXX07XG4gICAgICBjb250ZXh0PzogSHR0cENvbnRleHQ7XG4gICAgICBvYnNlcnZlPzogJ2JvZHknO1xuICAgICAgcGFyYW1zPzpcbiAgICAgICAgfCBIdHRwUGFyYW1zXG4gICAgICAgIHwge1twYXJhbTogc3RyaW5nXTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IFJlYWRvbmx5QXJyYXk8c3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbj59O1xuICAgICAgcmVwb3J0UHJvZ3Jlc3M/OiBib29sZWFuO1xuICAgICAgcmVzcG9uc2VUeXBlOiAndGV4dCc7XG4gICAgICB3aXRoQ3JlZGVudGlhbHM/OiBib29sZWFuO1xuICAgICAgdHJhbnNmZXJDYWNoZT86IHtpbmNsdWRlSGVhZGVycz86IHN0cmluZ1tdfSB8IGJvb2xlYW47XG4gICAgfSxcbiAgKTogT2JzZXJ2YWJsZTxzdHJpbmc+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIGEgcmVxdWVzdCB0aGF0IGludGVycHJldHMgdGhlIGJvZHkgYXMgYW4gYEFycmF5QnVmZmVyYCBhbmQgcmV0dXJucyB0aGVcbiAgICogdGhlIGZ1bGwgZXZlbnQgc3RyZWFtLlxuICAgKlxuICAgKiBAcGFyYW0gbWV0aG9kICBUaGUgSFRUUCBtZXRob2QuXG4gICAqIEBwYXJhbSB1cmwgICAgIFRoZSBlbmRwb2ludCBVUkwuXG4gICAqIEBwYXJhbSBvcHRpb25zIFRoZSBIVFRQIG9wdGlvbnMgdG8gc2VuZCB3aXRoIHRoZSByZXF1ZXN0LlxuICAgKlxuICAgKiBAcmV0dXJuIEFuIGBPYnNlcnZhYmxlYCBvZiB0aGUgcmVzcG9uc2UsIHdpdGggdGhlIHJlc3BvbnNlIGJvZHkgYXMgYW4gYXJyYXkgb2YgYEh0dHBFdmVudGBzIGZvclxuICAgKiB0aGUgcmVxdWVzdC5cbiAgICovXG4gIHJlcXVlc3QoXG4gICAgbWV0aG9kOiBzdHJpbmcsXG4gICAgdXJsOiBzdHJpbmcsXG4gICAgb3B0aW9uczoge1xuICAgICAgYm9keT86IGFueTtcbiAgICAgIGhlYWRlcnM/OiBIdHRwSGVhZGVycyB8IHtbaGVhZGVyOiBzdHJpbmddOiBzdHJpbmcgfCBzdHJpbmdbXX07XG4gICAgICBjb250ZXh0PzogSHR0cENvbnRleHQ7XG4gICAgICBwYXJhbXM/OlxuICAgICAgICB8IEh0dHBQYXJhbXNcbiAgICAgICAgfCB7W3BhcmFtOiBzdHJpbmddOiBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuIHwgUmVhZG9ubHlBcnJheTxzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuPn07XG4gICAgICBvYnNlcnZlOiAnZXZlbnRzJztcbiAgICAgIHJlcG9ydFByb2dyZXNzPzogYm9vbGVhbjtcbiAgICAgIHJlc3BvbnNlVHlwZTogJ2FycmF5YnVmZmVyJztcbiAgICAgIHdpdGhDcmVkZW50aWFscz86IGJvb2xlYW47XG4gICAgICB0cmFuc2ZlckNhY2hlPzoge2luY2x1ZGVIZWFkZXJzPzogc3RyaW5nW119IHwgYm9vbGVhbjtcbiAgICB9LFxuICApOiBPYnNlcnZhYmxlPEh0dHBFdmVudDxBcnJheUJ1ZmZlcj4+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIGEgcmVxdWVzdCB0aGF0IGludGVycHJldHMgdGhlIGJvZHkgYXMgYSBgQmxvYmAgYW5kIHJldHVybnNcbiAgICogdGhlIGZ1bGwgZXZlbnQgc3RyZWFtLlxuICAgKlxuICAgKiBAcGFyYW0gbWV0aG9kICBUaGUgSFRUUCBtZXRob2QuXG4gICAqIEBwYXJhbSB1cmwgICAgIFRoZSBlbmRwb2ludCBVUkwuXG4gICAqIEBwYXJhbSBvcHRpb25zIFRoZSBIVFRQIG9wdGlvbnMgdG8gc2VuZCB3aXRoIHRoZSByZXF1ZXN0LlxuICAgKlxuICAgKiBAcmV0dXJuIEFuIGBPYnNlcnZhYmxlYCBvZiBhbGwgYEh0dHBFdmVudGBzIGZvciB0aGUgcmVxdWVzdCxcbiAgICogd2l0aCB0aGUgcmVzcG9uc2UgYm9keSBvZiB0eXBlIGBCbG9iYC5cbiAgICovXG4gIHJlcXVlc3QoXG4gICAgbWV0aG9kOiBzdHJpbmcsXG4gICAgdXJsOiBzdHJpbmcsXG4gICAgb3B0aW9uczoge1xuICAgICAgYm9keT86IGFueTtcbiAgICAgIGhlYWRlcnM/OiBIdHRwSGVhZGVycyB8IHtbaGVhZGVyOiBzdHJpbmddOiBzdHJpbmcgfCBzdHJpbmdbXX07XG4gICAgICBvYnNlcnZlOiAnZXZlbnRzJztcbiAgICAgIGNvbnRleHQ/OiBIdHRwQ29udGV4dDtcbiAgICAgIHBhcmFtcz86XG4gICAgICAgIHwgSHR0cFBhcmFtc1xuICAgICAgICB8IHtbcGFyYW06IHN0cmluZ106IHN0cmluZyB8IG51bWJlciB8IGJvb2xlYW4gfCBSZWFkb25seUFycmF5PHN0cmluZyB8IG51bWJlciB8IGJvb2xlYW4+fTtcbiAgICAgIHJlcG9ydFByb2dyZXNzPzogYm9vbGVhbjtcbiAgICAgIHJlc3BvbnNlVHlwZTogJ2Jsb2InO1xuICAgICAgd2l0aENyZWRlbnRpYWxzPzogYm9vbGVhbjtcbiAgICAgIHRyYW5zZmVyQ2FjaGU/OiB7aW5jbHVkZUhlYWRlcnM/OiBzdHJpbmdbXX0gfCBib29sZWFuO1xuICAgIH0sXG4gICk6IE9ic2VydmFibGU8SHR0cEV2ZW50PEJsb2I+PjtcblxuICAvKipcbiAgICogQ29uc3RydWN0cyBhIHJlcXVlc3Qgd2hpY2ggaW50ZXJwcmV0cyB0aGUgYm9keSBhcyBhIHRleHQgc3RyaW5nIGFuZCByZXR1cm5zIHRoZSBmdWxsIGV2ZW50XG4gICAqIHN0cmVhbS5cbiAgICpcbiAgICogQHBhcmFtIG1ldGhvZCAgVGhlIEhUVFAgbWV0aG9kLlxuICAgKiBAcGFyYW0gdXJsICAgICBUaGUgZW5kcG9pbnQgVVJMLlxuICAgKiBAcGFyYW0gb3B0aW9ucyBUaGUgSFRUUCBvcHRpb25zIHRvIHNlbmQgd2l0aCB0aGUgcmVxdWVzdC5cbiAgICpcbiAgICogQHJldHVybiBBbiBgT2JzZXJ2YWJsZWAgb2YgYWxsIGBIdHRwRXZlbnRgcyBmb3IgdGhlIHJlcXVlc3QsXG4gICAqIHdpdGggdGhlIHJlc3BvbnNlIGJvZHkgb2YgdHlwZSBzdHJpbmcuXG4gICAqL1xuICByZXF1ZXN0KFxuICAgIG1ldGhvZDogc3RyaW5nLFxuICAgIHVybDogc3RyaW5nLFxuICAgIG9wdGlvbnM6IHtcbiAgICAgIGJvZHk/OiBhbnk7XG4gICAgICBoZWFkZXJzPzogSHR0cEhlYWRlcnMgfCB7W2hlYWRlcjogc3RyaW5nXTogc3RyaW5nIHwgc3RyaW5nW119O1xuICAgICAgb2JzZXJ2ZTogJ2V2ZW50cyc7XG4gICAgICBjb250ZXh0PzogSHR0cENvbnRleHQ7XG4gICAgICBwYXJhbXM/OlxuICAgICAgICB8IEh0dHBQYXJhbXNcbiAgICAgICAgfCB7W3BhcmFtOiBzdHJpbmddOiBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuIHwgUmVhZG9ubHlBcnJheTxzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuPn07XG4gICAgICByZXBvcnRQcm9ncmVzcz86IGJvb2xlYW47XG4gICAgICByZXNwb25zZVR5cGU6ICd0ZXh0JztcbiAgICAgIHdpdGhDcmVkZW50aWFscz86IGJvb2xlYW47XG4gICAgICB0cmFuc2ZlckNhY2hlPzoge2luY2x1ZGVIZWFkZXJzPzogc3RyaW5nW119IHwgYm9vbGVhbjtcbiAgICB9LFxuICApOiBPYnNlcnZhYmxlPEh0dHBFdmVudDxzdHJpbmc+PjtcblxuICAvKipcbiAgICogQ29uc3RydWN0cyBhIHJlcXVlc3Qgd2hpY2ggaW50ZXJwcmV0cyB0aGUgYm9keSBhcyBhIEphdmFTY3JpcHQgb2JqZWN0IGFuZCByZXR1cm5zIHRoZSBmdWxsXG4gICAqIGV2ZW50IHN0cmVhbS5cbiAgICpcbiAgICogQHBhcmFtIG1ldGhvZCAgVGhlIEhUVFAgbWV0aG9kLlxuICAgKiBAcGFyYW0gdXJsICAgICBUaGUgZW5kcG9pbnQgVVJMLlxuICAgKiBAcGFyYW0gb3B0aW9ucyBUaGUgSFRUUCBvcHRpb25zIHRvIHNlbmQgd2l0aCB0aGUgIHJlcXVlc3QuXG4gICAqXG4gICAqIEByZXR1cm4gQW4gYE9ic2VydmFibGVgIG9mIGFsbCBgSHR0cEV2ZW50YHMgZm9yIHRoZSByZXF1ZXN0LFxuICAgKiB3aXRoIHRoZSByZXNwb25zZSBib2R5IG9mIHR5cGUgYE9iamVjdGAuXG4gICAqL1xuICByZXF1ZXN0KFxuICAgIG1ldGhvZDogc3RyaW5nLFxuICAgIHVybDogc3RyaW5nLFxuICAgIG9wdGlvbnM6IHtcbiAgICAgIGJvZHk/OiBhbnk7XG4gICAgICBoZWFkZXJzPzogSHR0cEhlYWRlcnMgfCB7W2hlYWRlcjogc3RyaW5nXTogc3RyaW5nIHwgc3RyaW5nW119O1xuICAgICAgY29udGV4dD86IEh0dHBDb250ZXh0O1xuICAgICAgcmVwb3J0UHJvZ3Jlc3M/OiBib29sZWFuO1xuICAgICAgb2JzZXJ2ZTogJ2V2ZW50cyc7XG4gICAgICBwYXJhbXM/OlxuICAgICAgICB8IEh0dHBQYXJhbXNcbiAgICAgICAgfCB7W3BhcmFtOiBzdHJpbmddOiBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuIHwgUmVhZG9ubHlBcnJheTxzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuPn07XG4gICAgICByZXNwb25zZVR5cGU/OiAnanNvbic7XG4gICAgICB3aXRoQ3JlZGVudGlhbHM/OiBib29sZWFuO1xuICAgICAgdHJhbnNmZXJDYWNoZT86IHtpbmNsdWRlSGVhZGVycz86IHN0cmluZ1tdfSB8IGJvb2xlYW47XG4gICAgfSxcbiAgKTogT2JzZXJ2YWJsZTxIdHRwRXZlbnQ8YW55Pj47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdHMgYSByZXF1ZXN0IHdoaWNoIGludGVycHJldHMgdGhlIGJvZHkgYXMgYSBKYXZhU2NyaXB0IG9iamVjdCBhbmQgcmV0dXJucyB0aGUgZnVsbFxuICAgKiBldmVudCBzdHJlYW0uXG4gICAqXG4gICAqIEBwYXJhbSBtZXRob2QgIFRoZSBIVFRQIG1ldGhvZC5cbiAgICogQHBhcmFtIHVybCAgICAgVGhlIGVuZHBvaW50IFVSTC5cbiAgICogQHBhcmFtIG9wdGlvbnMgVGhlIEhUVFAgb3B0aW9ucyB0byBzZW5kIHdpdGggdGhlIHJlcXVlc3QuXG4gICAqXG4gICAqIEByZXR1cm4gQW4gYE9ic2VydmFibGVgIG9mIGFsbCBgSHR0cEV2ZW50YHMgZm9yIHRoZSByZXF1ZXN0LFxuICAgKiB3aXRoIHRoZSByZXNwb25zZSBib2R5IG9mIHR5cGUgYFJgLlxuICAgKi9cbiAgcmVxdWVzdDxSPihcbiAgICBtZXRob2Q6IHN0cmluZyxcbiAgICB1cmw6IHN0cmluZyxcbiAgICBvcHRpb25zOiB7XG4gICAgICBib2R5PzogYW55O1xuICAgICAgaGVhZGVycz86IEh0dHBIZWFkZXJzIHwge1toZWFkZXI6IHN0cmluZ106IHN0cmluZyB8IHN0cmluZ1tdfTtcbiAgICAgIGNvbnRleHQ/OiBIdHRwQ29udGV4dDtcbiAgICAgIHJlcG9ydFByb2dyZXNzPzogYm9vbGVhbjtcbiAgICAgIG9ic2VydmU6ICdldmVudHMnO1xuICAgICAgcGFyYW1zPzpcbiAgICAgICAgfCBIdHRwUGFyYW1zXG4gICAgICAgIHwge1twYXJhbTogc3RyaW5nXTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IFJlYWRvbmx5QXJyYXk8c3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbj59O1xuICAgICAgcmVzcG9uc2VUeXBlPzogJ2pzb24nO1xuICAgICAgd2l0aENyZWRlbnRpYWxzPzogYm9vbGVhbjtcbiAgICAgIHRyYW5zZmVyQ2FjaGU/OiB7aW5jbHVkZUhlYWRlcnM/OiBzdHJpbmdbXX0gfCBib29sZWFuO1xuICAgIH0sXG4gICk6IE9ic2VydmFibGU8SHR0cEV2ZW50PFI+PjtcblxuICAvKipcbiAgICogQ29uc3RydWN0cyBhIHJlcXVlc3Qgd2hpY2ggaW50ZXJwcmV0cyB0aGUgYm9keSBhcyBhbiBgQXJyYXlCdWZmZXJgXG4gICAqIGFuZCByZXR1cm5zIHRoZSBmdWxsIGBIdHRwUmVzcG9uc2VgLlxuICAgKlxuICAgKiBAcGFyYW0gbWV0aG9kICBUaGUgSFRUUCBtZXRob2QuXG4gICAqIEBwYXJhbSB1cmwgICAgIFRoZSBlbmRwb2ludCBVUkwuXG4gICAqIEBwYXJhbSBvcHRpb25zIFRoZSBIVFRQIG9wdGlvbnMgdG8gc2VuZCB3aXRoIHRoZSByZXF1ZXN0LlxuICAgKlxuICAgKiBAcmV0dXJuIEFuIGBPYnNlcnZhYmxlYCBvZiB0aGUgYEh0dHBSZXNwb25zZWAsIHdpdGggdGhlIHJlc3BvbnNlIGJvZHkgYXMgYW4gYEFycmF5QnVmZmVyYC5cbiAgICovXG4gIHJlcXVlc3QoXG4gICAgbWV0aG9kOiBzdHJpbmcsXG4gICAgdXJsOiBzdHJpbmcsXG4gICAgb3B0aW9uczoge1xuICAgICAgYm9keT86IGFueTtcbiAgICAgIGhlYWRlcnM/OiBIdHRwSGVhZGVycyB8IHtbaGVhZGVyOiBzdHJpbmddOiBzdHJpbmcgfCBzdHJpbmdbXX07XG4gICAgICBvYnNlcnZlOiAncmVzcG9uc2UnO1xuICAgICAgY29udGV4dD86IEh0dHBDb250ZXh0O1xuICAgICAgcGFyYW1zPzpcbiAgICAgICAgfCBIdHRwUGFyYW1zXG4gICAgICAgIHwge1twYXJhbTogc3RyaW5nXTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IFJlYWRvbmx5QXJyYXk8c3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbj59O1xuICAgICAgcmVwb3J0UHJvZ3Jlc3M/OiBib29sZWFuO1xuICAgICAgcmVzcG9uc2VUeXBlOiAnYXJyYXlidWZmZXInO1xuICAgICAgd2l0aENyZWRlbnRpYWxzPzogYm9vbGVhbjtcbiAgICAgIHRyYW5zZmVyQ2FjaGU/OiB7aW5jbHVkZUhlYWRlcnM/OiBzdHJpbmdbXX0gfCBib29sZWFuO1xuICAgIH0sXG4gICk6IE9ic2VydmFibGU8SHR0cFJlc3BvbnNlPEFycmF5QnVmZmVyPj47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdHMgYSByZXF1ZXN0IHdoaWNoIGludGVycHJldHMgdGhlIGJvZHkgYXMgYSBgQmxvYmAgYW5kIHJldHVybnMgdGhlIGZ1bGwgYEh0dHBSZXNwb25zZWAuXG4gICAqXG4gICAqIEBwYXJhbSBtZXRob2QgIFRoZSBIVFRQIG1ldGhvZC5cbiAgICogQHBhcmFtIHVybCAgICAgVGhlIGVuZHBvaW50IFVSTC5cbiAgICogQHBhcmFtIG9wdGlvbnMgVGhlIEhUVFAgb3B0aW9ucyB0byBzZW5kIHdpdGggdGhlIHJlcXVlc3QuXG4gICAqXG4gICAqIEByZXR1cm4gQW4gYE9ic2VydmFibGVgIG9mIHRoZSBgSHR0cFJlc3BvbnNlYCwgd2l0aCB0aGUgcmVzcG9uc2UgYm9keSBvZiB0eXBlIGBCbG9iYC5cbiAgICovXG4gIHJlcXVlc3QoXG4gICAgbWV0aG9kOiBzdHJpbmcsXG4gICAgdXJsOiBzdHJpbmcsXG4gICAgb3B0aW9uczoge1xuICAgICAgYm9keT86IGFueTtcbiAgICAgIGhlYWRlcnM/OiBIdHRwSGVhZGVycyB8IHtbaGVhZGVyOiBzdHJpbmddOiBzdHJpbmcgfCBzdHJpbmdbXX07XG4gICAgICBvYnNlcnZlOiAncmVzcG9uc2UnO1xuICAgICAgY29udGV4dD86IEh0dHBDb250ZXh0O1xuICAgICAgcGFyYW1zPzpcbiAgICAgICAgfCBIdHRwUGFyYW1zXG4gICAgICAgIHwge1twYXJhbTogc3RyaW5nXTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IFJlYWRvbmx5QXJyYXk8c3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbj59O1xuICAgICAgcmVwb3J0UHJvZ3Jlc3M/OiBib29sZWFuO1xuICAgICAgcmVzcG9uc2VUeXBlOiAnYmxvYic7XG4gICAgICB3aXRoQ3JlZGVudGlhbHM/OiBib29sZWFuO1xuICAgICAgdHJhbnNmZXJDYWNoZT86IHtpbmNsdWRlSGVhZGVycz86IHN0cmluZ1tdfSB8IGJvb2xlYW47XG4gICAgfSxcbiAgKTogT2JzZXJ2YWJsZTxIdHRwUmVzcG9uc2U8QmxvYj4+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIGEgcmVxdWVzdCB3aGljaCBpbnRlcnByZXRzIHRoZSBib2R5IGFzIGEgdGV4dCBzdHJlYW0gYW5kIHJldHVybnMgdGhlIGZ1bGxcbiAgICogYEh0dHBSZXNwb25zZWAuXG4gICAqXG4gICAqIEBwYXJhbSBtZXRob2QgIFRoZSBIVFRQIG1ldGhvZC5cbiAgICogQHBhcmFtIHVybCAgICAgVGhlIGVuZHBvaW50IFVSTC5cbiAgICogQHBhcmFtIG9wdGlvbnMgVGhlIEhUVFAgb3B0aW9ucyB0byBzZW5kIHdpdGggdGhlIHJlcXVlc3QuXG4gICAqXG4gICAqIEByZXR1cm4gQW4gYE9ic2VydmFibGVgIG9mIHRoZSBIVFRQIHJlc3BvbnNlLCB3aXRoIHRoZSByZXNwb25zZSBib2R5IG9mIHR5cGUgc3RyaW5nLlxuICAgKi9cbiAgcmVxdWVzdChcbiAgICBtZXRob2Q6IHN0cmluZyxcbiAgICB1cmw6IHN0cmluZyxcbiAgICBvcHRpb25zOiB7XG4gICAgICBib2R5PzogYW55O1xuICAgICAgaGVhZGVycz86IEh0dHBIZWFkZXJzIHwge1toZWFkZXI6IHN0cmluZ106IHN0cmluZyB8IHN0cmluZ1tdfTtcbiAgICAgIG9ic2VydmU6ICdyZXNwb25zZSc7XG4gICAgICBjb250ZXh0PzogSHR0cENvbnRleHQ7XG4gICAgICBwYXJhbXM/OlxuICAgICAgICB8IEh0dHBQYXJhbXNcbiAgICAgICAgfCB7W3BhcmFtOiBzdHJpbmddOiBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuIHwgUmVhZG9ubHlBcnJheTxzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuPn07XG4gICAgICByZXBvcnRQcm9ncmVzcz86IGJvb2xlYW47XG4gICAgICByZXNwb25zZVR5cGU6ICd0ZXh0JztcbiAgICAgIHdpdGhDcmVkZW50aWFscz86IGJvb2xlYW47XG4gICAgICB0cmFuc2ZlckNhY2hlPzoge2luY2x1ZGVIZWFkZXJzPzogc3RyaW5nW119IHwgYm9vbGVhbjtcbiAgICB9LFxuICApOiBPYnNlcnZhYmxlPEh0dHBSZXNwb25zZTxzdHJpbmc+PjtcblxuICAvKipcbiAgICogQ29uc3RydWN0cyBhIHJlcXVlc3Qgd2hpY2ggaW50ZXJwcmV0cyB0aGUgYm9keSBhcyBhIEphdmFTY3JpcHQgb2JqZWN0IGFuZCByZXR1cm5zIHRoZSBmdWxsXG4gICAqIGBIdHRwUmVzcG9uc2VgLlxuICAgKlxuICAgKiBAcGFyYW0gbWV0aG9kICBUaGUgSFRUUCBtZXRob2QuXG4gICAqIEBwYXJhbSB1cmwgICAgIFRoZSBlbmRwb2ludCBVUkwuXG4gICAqIEBwYXJhbSBvcHRpb25zIFRoZSBIVFRQIG9wdGlvbnMgdG8gc2VuZCB3aXRoIHRoZSByZXF1ZXN0LlxuICAgKlxuICAgKiBAcmV0dXJuIEFuIGBPYnNlcnZhYmxlYCBvZiB0aGUgZnVsbCBgSHR0cFJlc3BvbnNlYCxcbiAgICogd2l0aCB0aGUgcmVzcG9uc2UgYm9keSBvZiB0eXBlIGBPYmplY3RgLlxuICAgKi9cbiAgcmVxdWVzdChcbiAgICBtZXRob2Q6IHN0cmluZyxcbiAgICB1cmw6IHN0cmluZyxcbiAgICBvcHRpb25zOiB7XG4gICAgICBib2R5PzogYW55O1xuICAgICAgaGVhZGVycz86IEh0dHBIZWFkZXJzIHwge1toZWFkZXI6IHN0cmluZ106IHN0cmluZyB8IHN0cmluZ1tdfTtcbiAgICAgIGNvbnRleHQ/OiBIdHRwQ29udGV4dDtcbiAgICAgIHJlcG9ydFByb2dyZXNzPzogYm9vbGVhbjtcbiAgICAgIG9ic2VydmU6ICdyZXNwb25zZSc7XG4gICAgICBwYXJhbXM/OlxuICAgICAgICB8IEh0dHBQYXJhbXNcbiAgICAgICAgfCB7W3BhcmFtOiBzdHJpbmddOiBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuIHwgUmVhZG9ubHlBcnJheTxzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuPn07XG4gICAgICByZXNwb25zZVR5cGU/OiAnanNvbic7XG4gICAgICB3aXRoQ3JlZGVudGlhbHM/OiBib29sZWFuO1xuICAgIH0sXG4gICk6IE9ic2VydmFibGU8SHR0cFJlc3BvbnNlPE9iamVjdD4+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIGEgcmVxdWVzdCB3aGljaCBpbnRlcnByZXRzIHRoZSBib2R5IGFzIGEgSmF2YVNjcmlwdCBvYmplY3QgYW5kIHJldHVybnNcbiAgICogdGhlIGZ1bGwgYEh0dHBSZXNwb25zZWAgd2l0aCB0aGUgcmVzcG9uc2UgYm9keSBpbiB0aGUgcmVxdWVzdGVkIHR5cGUuXG4gICAqXG4gICAqIEBwYXJhbSBtZXRob2QgIFRoZSBIVFRQIG1ldGhvZC5cbiAgICogQHBhcmFtIHVybCAgICAgVGhlIGVuZHBvaW50IFVSTC5cbiAgICogQHBhcmFtIG9wdGlvbnMgVGhlIEhUVFAgb3B0aW9ucyB0byBzZW5kIHdpdGggdGhlIHJlcXVlc3QuXG4gICAqXG4gICAqIEByZXR1cm4gIEFuIGBPYnNlcnZhYmxlYCBvZiB0aGUgZnVsbCBgSHR0cFJlc3BvbnNlYCwgd2l0aCB0aGUgcmVzcG9uc2UgYm9keSBvZiB0eXBlIGBSYC5cbiAgICovXG4gIHJlcXVlc3Q8Uj4oXG4gICAgbWV0aG9kOiBzdHJpbmcsXG4gICAgdXJsOiBzdHJpbmcsXG4gICAgb3B0aW9uczoge1xuICAgICAgYm9keT86IGFueTtcbiAgICAgIGhlYWRlcnM/OiBIdHRwSGVhZGVycyB8IHtbaGVhZGVyOiBzdHJpbmddOiBzdHJpbmcgfCBzdHJpbmdbXX07XG4gICAgICBjb250ZXh0PzogSHR0cENvbnRleHQ7XG4gICAgICByZXBvcnRQcm9ncmVzcz86IGJvb2xlYW47XG4gICAgICBvYnNlcnZlOiAncmVzcG9uc2UnO1xuICAgICAgcGFyYW1zPzpcbiAgICAgICAgfCBIdHRwUGFyYW1zXG4gICAgICAgIHwge1twYXJhbTogc3RyaW5nXTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IFJlYWRvbmx5QXJyYXk8c3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbj59O1xuICAgICAgcmVzcG9uc2VUeXBlPzogJ2pzb24nO1xuICAgICAgd2l0aENyZWRlbnRpYWxzPzogYm9vbGVhbjtcbiAgICAgIHRyYW5zZmVyQ2FjaGU/OiB7aW5jbHVkZUhlYWRlcnM/OiBzdHJpbmdbXX0gfCBib29sZWFuO1xuICAgIH0sXG4gICk6IE9ic2VydmFibGU8SHR0cFJlc3BvbnNlPFI+PjtcblxuICAvKipcbiAgICogQ29uc3RydWN0cyBhIHJlcXVlc3Qgd2hpY2ggaW50ZXJwcmV0cyB0aGUgYm9keSBhcyBhIEphdmFTY3JpcHQgb2JqZWN0IGFuZCByZXR1cm5zIHRoZSBmdWxsXG4gICAqIGBIdHRwUmVzcG9uc2VgIGFzIGEgSmF2YVNjcmlwdCBvYmplY3QuXG4gICAqXG4gICAqIEBwYXJhbSBtZXRob2QgIFRoZSBIVFRQIG1ldGhvZC5cbiAgICogQHBhcmFtIHVybCAgICAgVGhlIGVuZHBvaW50IFVSTC5cbiAgICogQHBhcmFtIG9wdGlvbnMgVGhlIEhUVFAgb3B0aW9ucyB0byBzZW5kIHdpdGggdGhlIHJlcXVlc3QuXG4gICAqXG4gICAqIEByZXR1cm4gQW4gYE9ic2VydmFibGVgIG9mIHRoZSBgSHR0cFJlc3BvbnNlYCwgd2l0aCB0aGUgcmVzcG9uc2UgYm9keSBvZiB0eXBlIGBPYmplY3RgLlxuICAgKi9cbiAgcmVxdWVzdChcbiAgICBtZXRob2Q6IHN0cmluZyxcbiAgICB1cmw6IHN0cmluZyxcbiAgICBvcHRpb25zPzoge1xuICAgICAgYm9keT86IGFueTtcbiAgICAgIGhlYWRlcnM/OiBIdHRwSGVhZGVycyB8IHtbaGVhZGVyOiBzdHJpbmddOiBzdHJpbmcgfCBzdHJpbmdbXX07XG4gICAgICBjb250ZXh0PzogSHR0cENvbnRleHQ7XG4gICAgICBvYnNlcnZlPzogJ2JvZHknO1xuICAgICAgcGFyYW1zPzpcbiAgICAgICAgfCBIdHRwUGFyYW1zXG4gICAgICAgIHwge1twYXJhbTogc3RyaW5nXTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IFJlYWRvbmx5QXJyYXk8c3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbj59O1xuICAgICAgcmVzcG9uc2VUeXBlPzogJ2pzb24nO1xuICAgICAgcmVwb3J0UHJvZ3Jlc3M/OiBib29sZWFuO1xuICAgICAgd2l0aENyZWRlbnRpYWxzPzogYm9vbGVhbjtcbiAgICAgIHRyYW5zZmVyQ2FjaGU/OiB7aW5jbHVkZUhlYWRlcnM/OiBzdHJpbmdbXX0gfCBib29sZWFuO1xuICAgIH0sXG4gICk6IE9ic2VydmFibGU8T2JqZWN0PjtcblxuICAvKipcbiAgICogQ29uc3RydWN0cyBhIHJlcXVlc3Qgd2hpY2ggaW50ZXJwcmV0cyB0aGUgYm9keSBhcyBhIEphdmFTY3JpcHQgb2JqZWN0XG4gICAqIHdpdGggdGhlIHJlc3BvbnNlIGJvZHkgb2YgdGhlIHJlcXVlc3RlZCB0eXBlLlxuICAgKlxuICAgKiBAcGFyYW0gbWV0aG9kICBUaGUgSFRUUCBtZXRob2QuXG4gICAqIEBwYXJhbSB1cmwgICAgIFRoZSBlbmRwb2ludCBVUkwuXG4gICAqIEBwYXJhbSBvcHRpb25zIFRoZSBIVFRQIG9wdGlvbnMgdG8gc2VuZCB3aXRoIHRoZSByZXF1ZXN0LlxuICAgKlxuICAgKiBAcmV0dXJuIEFuIGBPYnNlcnZhYmxlYCBvZiB0aGUgYEh0dHBSZXNwb25zZWAsIHdpdGggdGhlIHJlc3BvbnNlIGJvZHkgb2YgdHlwZSBgUmAuXG4gICAqL1xuICByZXF1ZXN0PFI+KFxuICAgIG1ldGhvZDogc3RyaW5nLFxuICAgIHVybDogc3RyaW5nLFxuICAgIG9wdGlvbnM/OiB7XG4gICAgICBib2R5PzogYW55O1xuICAgICAgaGVhZGVycz86IEh0dHBIZWFkZXJzIHwge1toZWFkZXI6IHN0cmluZ106IHN0cmluZyB8IHN0cmluZ1tdfTtcbiAgICAgIGNvbnRleHQ/OiBIdHRwQ29udGV4dDtcbiAgICAgIG9ic2VydmU/OiAnYm9keSc7XG4gICAgICBwYXJhbXM/OlxuICAgICAgICB8IEh0dHBQYXJhbXNcbiAgICAgICAgfCB7W3BhcmFtOiBzdHJpbmddOiBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuIHwgUmVhZG9ubHlBcnJheTxzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuPn07XG4gICAgICByZXNwb25zZVR5cGU/OiAnanNvbic7XG4gICAgICByZXBvcnRQcm9ncmVzcz86IGJvb2xlYW47XG4gICAgICB3aXRoQ3JlZGVudGlhbHM/OiBib29sZWFuO1xuICAgICAgdHJhbnNmZXJDYWNoZT86IHtpbmNsdWRlSGVhZGVycz86IHN0cmluZ1tdfSB8IGJvb2xlYW47XG4gICAgfSxcbiAgKTogT2JzZXJ2YWJsZTxSPjtcblxuICAvKipcbiAgICogQ29uc3RydWN0cyBhIHJlcXVlc3Qgd2hlcmUgcmVzcG9uc2UgdHlwZSBhbmQgcmVxdWVzdGVkIG9ic2VydmFibGUgYXJlIG5vdCBrbm93biBzdGF0aWNhbGx5LlxuICAgKlxuICAgKiBAcGFyYW0gbWV0aG9kICBUaGUgSFRUUCBtZXRob2QuXG4gICAqIEBwYXJhbSB1cmwgICAgIFRoZSBlbmRwb2ludCBVUkwuXG4gICAqIEBwYXJhbSBvcHRpb25zIFRoZSBIVFRQIG9wdGlvbnMgdG8gc2VuZCB3aXRoIHRoZSByZXF1ZXN0LlxuICAgKlxuICAgKiBAcmV0dXJuIEFuIGBPYnNlcnZhYmxlYCBvZiB0aGUgcmVxdWVzdGVkIHJlc3BvbnNlLCB3aXRoIGJvZHkgb2YgdHlwZSBgYW55YC5cbiAgICovXG4gIHJlcXVlc3QoXG4gICAgbWV0aG9kOiBzdHJpbmcsXG4gICAgdXJsOiBzdHJpbmcsXG4gICAgb3B0aW9ucz86IHtcbiAgICAgIGJvZHk/OiBhbnk7XG4gICAgICBoZWFkZXJzPzogSHR0cEhlYWRlcnMgfCB7W2hlYWRlcjogc3RyaW5nXTogc3RyaW5nIHwgc3RyaW5nW119O1xuICAgICAgY29udGV4dD86IEh0dHBDb250ZXh0O1xuICAgICAgcGFyYW1zPzpcbiAgICAgICAgfCBIdHRwUGFyYW1zXG4gICAgICAgIHwge1twYXJhbTogc3RyaW5nXTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IFJlYWRvbmx5QXJyYXk8c3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbj59O1xuICAgICAgb2JzZXJ2ZT86ICdib2R5JyB8ICdldmVudHMnIHwgJ3Jlc3BvbnNlJztcbiAgICAgIHJlcG9ydFByb2dyZXNzPzogYm9vbGVhbjtcbiAgICAgIHJlc3BvbnNlVHlwZT86ICdhcnJheWJ1ZmZlcicgfCAnYmxvYicgfCAnanNvbicgfCAndGV4dCc7XG4gICAgICB3aXRoQ3JlZGVudGlhbHM/OiBib29sZWFuO1xuICAgICAgdHJhbnNmZXJDYWNoZT86IHtpbmNsdWRlSGVhZGVycz86IHN0cmluZ1tdfSB8IGJvb2xlYW47XG4gICAgfSxcbiAgKTogT2JzZXJ2YWJsZTxhbnk+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIGFuIG9ic2VydmFibGUgZm9yIGEgZ2VuZXJpYyBIVFRQIHJlcXVlc3QgdGhhdCwgd2hlbiBzdWJzY3JpYmVkLFxuICAgKiBmaXJlcyB0aGUgcmVxdWVzdCB0aHJvdWdoIHRoZSBjaGFpbiBvZiByZWdpc3RlcmVkIGludGVyY2VwdG9ycyBhbmQgb24gdG8gdGhlXG4gICAqIHNlcnZlci5cbiAgICpcbiAgICogWW91IGNhbiBwYXNzIGFuIGBIdHRwUmVxdWVzdGAgZGlyZWN0bHkgYXMgdGhlIG9ubHkgcGFyYW1ldGVyLiBJbiB0aGlzIGNhc2UsXG4gICAqIHRoZSBjYWxsIHJldHVybnMgYW4gb2JzZXJ2YWJsZSBvZiB0aGUgcmF3IGBIdHRwRXZlbnRgIHN0cmVhbS5cbiAgICpcbiAgICogQWx0ZXJuYXRpdmVseSB5b3UgY2FuIHBhc3MgYW4gSFRUUCBtZXRob2QgYXMgdGhlIGZpcnN0IHBhcmFtZXRlcixcbiAgICogYSBVUkwgc3RyaW5nIGFzIHRoZSBzZWNvbmQsIGFuZCBhbiBvcHRpb25zIGhhc2ggY29udGFpbmluZyB0aGUgcmVxdWVzdCBib2R5IGFzIHRoZSB0aGlyZC5cbiAgICogU2VlIGBhZGRCb2R5KClgLiBJbiB0aGlzIGNhc2UsIHRoZSBzcGVjaWZpZWQgYHJlc3BvbnNlVHlwZWAgYW5kIGBvYnNlcnZlYCBvcHRpb25zIGRldGVybWluZSB0aGVcbiAgICogdHlwZSBvZiByZXR1cm5lZCBvYnNlcnZhYmxlLlxuICAgKiAgICogVGhlIGByZXNwb25zZVR5cGVgIHZhbHVlIGRldGVybWluZXMgaG93IGEgc3VjY2Vzc2Z1bCByZXNwb25zZSBib2R5IGlzIHBhcnNlZC5cbiAgICogICAqIElmIGByZXNwb25zZVR5cGVgIGlzIHRoZSBkZWZhdWx0IGBqc29uYCwgeW91IGNhbiBwYXNzIGEgdHlwZSBpbnRlcmZhY2UgZm9yIHRoZSByZXN1bHRpbmdcbiAgICogb2JqZWN0IGFzIGEgdHlwZSBwYXJhbWV0ZXIgdG8gdGhlIGNhbGwuXG4gICAqXG4gICAqIFRoZSBgb2JzZXJ2ZWAgdmFsdWUgZGV0ZXJtaW5lcyB0aGUgcmV0dXJuIHR5cGUsIGFjY29yZGluZyB0byB3aGF0IHlvdSBhcmUgaW50ZXJlc3RlZCBpblxuICAgKiBvYnNlcnZpbmcuXG4gICAqICAgKiBBbiBgb2JzZXJ2ZWAgdmFsdWUgb2YgZXZlbnRzIHJldHVybnMgYW4gb2JzZXJ2YWJsZSBvZiB0aGUgcmF3IGBIdHRwRXZlbnRgIHN0cmVhbSwgaW5jbHVkaW5nXG4gICAqIHByb2dyZXNzIGV2ZW50cyBieSBkZWZhdWx0LlxuICAgKiAgICogQW4gYG9ic2VydmVgIHZhbHVlIG9mIHJlc3BvbnNlIHJldHVybnMgYW4gb2JzZXJ2YWJsZSBvZiBgSHR0cFJlc3BvbnNlPFQ+YCxcbiAgICogd2hlcmUgdGhlIGBUYCBwYXJhbWV0ZXIgZGVwZW5kcyBvbiB0aGUgYHJlc3BvbnNlVHlwZWAgYW5kIGFueSBvcHRpb25hbGx5IHByb3ZpZGVkIHR5cGVcbiAgICogcGFyYW1ldGVyLlxuICAgKiAgICogQW4gYG9ic2VydmVgIHZhbHVlIG9mIGJvZHkgcmV0dXJucyBhbiBvYnNlcnZhYmxlIG9mIGA8VD5gIHdpdGggdGhlIHNhbWUgYFRgIGJvZHkgdHlwZS5cbiAgICpcbiAgICovXG4gIHJlcXVlc3QoXG4gICAgZmlyc3Q6IHN0cmluZyB8IEh0dHBSZXF1ZXN0PGFueT4sXG4gICAgdXJsPzogc3RyaW5nLFxuICAgIG9wdGlvbnM6IHtcbiAgICAgIGJvZHk/OiBhbnk7XG4gICAgICBoZWFkZXJzPzogSHR0cEhlYWRlcnMgfCB7W2hlYWRlcjogc3RyaW5nXTogc3RyaW5nIHwgc3RyaW5nW119O1xuICAgICAgY29udGV4dD86IEh0dHBDb250ZXh0O1xuICAgICAgb2JzZXJ2ZT86ICdib2R5JyB8ICdldmVudHMnIHwgJ3Jlc3BvbnNlJztcbiAgICAgIHBhcmFtcz86XG4gICAgICAgIHwgSHR0cFBhcmFtc1xuICAgICAgICB8IHtbcGFyYW06IHN0cmluZ106IHN0cmluZyB8IG51bWJlciB8IGJvb2xlYW4gfCBSZWFkb25seUFycmF5PHN0cmluZyB8IG51bWJlciB8IGJvb2xlYW4+fTtcbiAgICAgIHJlcG9ydFByb2dyZXNzPzogYm9vbGVhbjtcbiAgICAgIHJlc3BvbnNlVHlwZT86ICdhcnJheWJ1ZmZlcicgfCAnYmxvYicgfCAnanNvbicgfCAndGV4dCc7XG4gICAgICB3aXRoQ3JlZGVudGlhbHM/OiBib29s