@angular/common
Version:
Angular - commonly needed directives and services
325 lines (324 loc) • 170 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,
};
}
/**
* 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/http)
* @see [HTTP Request](api/common/http/HttpRequest)
*
* @publicApi
*/
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,
});
}
// 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: "16.0.3", ngImport: i0, type: HttpClient, deps: [{ token: i1.HttpHandler }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.3", ngImport: i0, type: HttpClient }); }
}
export { HttpClient };
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.3", ngImport: i0, type: HttpClient, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: i1.HttpHandler }]; } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvY29tbW9uL2h0dHAvc3JjL2NsaWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0dBTUc7QUFFSCxPQUFPLEVBQUMsVUFBVSxFQUFDLE1BQU0sZUFBZSxDQUFDO0FBQ3pDLE9BQU8sRUFBYSxFQUFFLEVBQUMsTUFBTSxNQUFNLENBQUM7QUFDcEMsT0FBTyxFQUFDLFNBQVMsRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFFdEQsT0FBTyxFQUFDLFdBQVcsRUFBQyxNQUFNLFdBQVcsQ0FBQztBQUV0QyxPQUFPLEVBQUMsV0FBVyxFQUFDLE1BQU0sV0FBVyxDQUFDO0FBQ3RDLE9BQU8sRUFBQyxVQUFVLEVBQW9CLE1BQU0sVUFBVSxDQUFDO0FBQ3ZELE9BQU8sRUFBQyxXQUFXLEVBQUMsTUFBTSxXQUFXLENBQUM7QUFDdEMsT0FBTyxFQUFZLFlBQVksRUFBQyxNQUFNLFlBQVksQ0FBQzs7O0FBR25EOzs7Ozs7Ozs7R0FTRztBQUNILFNBQVMsT0FBTyxDQUNaLE9BU0MsRUFDRCxJQUFZO0lBQ2QsT0FBTztRQUNMLElBQUk7UUFDSixPQUFPLEVBQUUsT0FBTyxDQUFDLE9BQU87UUFDeEIsT0FBTyxFQUFFLE9BQU8sQ0FBQyxPQUFPO1FBQ3hCLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTztRQUN4QixNQUFNLEVBQUUsT0FBTyxDQUFDLE1BQU07UUFDdEIsY0FBYyxFQUFFLE9BQU8sQ0FBQyxjQUFjO1FBQ3RDLFlBQVksRUFBRSxPQUFPLENBQUMsWUFBWTtRQUNsQyxlQUFlLEVBQUUsT0FBTyxDQUFDLGVBQWU7S0FDekMsQ0FBQztBQUNKLENBQUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBc0RHO0FBQ0gsTUFDYSxVQUFVO0lB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TyxDQUFNLFNBQVMsRUFBRSxHQUFHLEVBQUUsT0FBYyxDQUFDLENBQUM7SUFDM0QsQ0FBQztJQXVURDs7OztPQUlHO0lBQ0gsS0FBSyxDQUFDLEdBQVcsRUFBRSxJQUFjLEVBQUUsVUFTL0IsRUFBRTtRQUNKLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBTSxPQUFPLEVBQUUsR0FBRyxFQUFFLE9BQU8sQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNqRSxDQUFDO0lBcVREOzs7OztPQUtHO0lBQ0gsSUFBSSxDQUFDLEdBQVcsRUFBRSxJQUFjLEVBQUUsVUFTOUIsRUFBRTtRQUNKLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBTSxNQUFNLEVBQUUsR0FBRyxFQUFFLE9BQU8sQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUNoRSxDQUFDO0lBb1REOzs7OztPQUtHO0lBQ0gsR0FBRyxDQUFDLEdBQVcsRUFBRSxJQUFjLEVBQUUsVUFTN0IsRUFBRTtRQUNKLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBTSxLQUFLLEVBQUUsR0FBRyxFQUFFLE9BQU8sQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUMvRCxDQUFDO3lIQTV0RlUsVUFBVTs2SEFBVixVQUFVOztTQUFWLFVBQVU7c0dBQVYsVUFBVTtrQkFEdEIsVUFBVSIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCBHb29nbGUgTExDIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9hbmd1bGFyLmlvL2xpY2Vuc2VcbiAqL1xuXG5pbXBvcnQge0luamVjdGFibGV9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtPYnNlcnZhYmxlLCBvZn0gZnJvbSAncnhqcyc7XG5pbXBvcnQge2NvbmNhdE1hcCwgZmlsdGVyLCBtYXB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuaW1wb3J0IHtIdHRwSGFuZGxlcn0gZnJvbSAnLi9iYWNrZW5kJztcbmltcG9ydCB7SHR0cENvbnRleHR9IGZyb20gJy4vY29udGV4dCc7XG5pbXBvcnQge0h0dHBIZWFkZXJzfSBmcm9tICcuL2hlYWRlcnMnO1xuaW1wb3J0IHtIdHRwUGFyYW1zLCBIdHRwUGFyYW1zT3B0aW9uc30gZnJvbSAnLi9wYXJhbXMnO1xuaW1wb3J0IHtIdHRwUmVxdWVzdH0gZnJvbSAnLi9yZXF1ZXN0JztcbmltcG9ydCB7SHR0cEV2ZW50LCBIdHRwUmVzcG9uc2V9IGZyb20gJy4vcmVzcG9uc2UnO1xuXG5cbi8qKlxuICogQ29uc3RydWN0cyBhbiBpbnN0YW5jZSBvZiBgSHR0cFJlcXVlc3RPcHRpb25zPFQ+YCBmcm9tIGEgc291cmNlIGBIdHRwTWV0aG9kT3B0aW9uc2AgYW5kXG4gKiB0aGUgZ2l2ZW4gYGJvZHlgLiBUaGlzIGZ1bmN0aW9uIGNsb25lcyB0aGUgb2JqZWN0IGFuZCBhZGRzIHRoZSBib2R5LlxuICpcbiAqIE5vdGUgdGhhdCB0aGUgYHJlc3BvbnNlVHlwZWAgKm9wdGlvbnMqIHZhbHVlIGlzIGEgU3RyaW5nIHRoYXQgaWRlbnRpZmllcyB0aGVcbiAqIHNpbmdsZSBkYXRhIHR5cGUgb2YgdGhlIHJlc3BvbnNlLlxuICogQSBzaW5nbGUgb3ZlcmxvYWQgdmVyc2lvbiBvZiB0aGUgbWV0aG9kIGhhbmRsZXMgZWFjaCByZXNwb25zZSB0eXBlLlxuICogVGhlIHZhbHVlIG9mIGByZXNwb25zZVR5cGVgIGNhbm5vdCBiZSBhIHVuaW9uLCBhcyB0aGUgY29tYmluZWQgc2lnbmF0dXJlIGNvdWxkIGltcGx5LlxuICpcbiAqL1xuZnVuY3Rpb24gYWRkQm9keTxUPihcbiAgICBvcHRpb25zOiB7XG4gICAgICBoZWFkZXJzPzogSHR0cEhlYWRlcnN8e1toZWFkZXI6IHN0cmluZ106IHN0cmluZyB8IHN0cmluZ1tdfSxcbiAgICAgIGNvbnRleHQ/OiBIdHRwQ29udGV4dCxcbiAgICAgIG9ic2VydmU/OiAnYm9keSd8J2V2ZW50cyd8J3Jlc3BvbnNlJyxcbiAgICAgIHBhcmFtcz86IEh0dHBQYXJhbXN8XG4gICAgICAgICAgICB7W3BhcmFtOiBzdHJpbmddOiBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuIHwgUmVhZG9ubHlBcnJheTxzdHJpbmd8bnVtYmVyfGJvb2xlYW4+fSxcbiAgICAgIHJlcG9ydFByb2dyZXNzPzogYm9vbGVhbixcbiAgICAgIHJlc3BvbnNlVHlwZT86ICdhcnJheWJ1ZmZlcid8J2Jsb2InfCdqc29uJ3wndGV4dCcsXG4gICAgICB3aXRoQ3JlZGVudGlhbHM/OiBib29sZWFuLFxuICAgIH0sXG4gICAgYm9keTogVHxudWxsKTogYW55IHtcbiAgcmV0dXJuIHtcbiAgICBib2R5LFxuICAgIGhlYWRlcnM6IG9wdGlvbnMuaGVhZGVycyxcbiAgICBjb250ZXh0OiBvcHRpb25zLmNvbnRleHQsXG4gICAgb2JzZXJ2ZTogb3B0aW9ucy5vYnNlcnZlLFxuICAgIHBhcmFtczogb3B0aW9ucy5wYXJhbXMsXG4gICAgcmVwb3J0UHJvZ3Jlc3M6IG9wdGlvbnMucmVwb3J0UHJvZ3Jlc3MsXG4gICAgcmVzcG9uc2VUeXBlOiBvcHRpb25zLnJlc3BvbnNlVHlwZSxcbiAgICB3aXRoQ3JlZGVudGlhbHM6IG9wdGlvbnMud2l0aENyZWRlbnRpYWxzLFxuICB9O1xufVxuXG4vKipcbiAqIFBlcmZvcm1zIEhUVFAgcmVxdWVzdHMuXG4gKiBUaGlzIHNlcnZpY2UgaXMgYXZhaWxhYmxlIGFzIGFuIGluamVjdGFibGUgY2xhc3MsIHdpdGggbWV0aG9kcyB0byBwZXJmb3JtIEhUVFAgcmVxdWVzdHMuXG4gKiBFYWNoIHJlcXVlc3QgbWV0aG9kIGhhcyBtdWx0aXBsZSBzaWduYXR1cmVzLCBhbmQgdGhlIHJldHVybiB0eXBlIHZhcmllcyBiYXNlZCBvblxuICogdGhlIHNpZ25hdHVyZSB0aGF0IGlzIGNhbGxlZCAobWFpbmx5IHRoZSB2YWx1ZXMgb2YgYG9ic2VydmVgIGFuZCBgcmVzcG9uc2VUeXBlYCkuXG4gKlxuICogTm90ZSB0aGF0IHRoZSBgcmVzcG9uc2VUeXBlYCAqb3B0aW9ucyogdmFsdWUgaXMgYSBTdHJpbmcgdGhhdCBpZGVudGlmaWVzIHRoZVxuICogc2luZ2xlIGRhdGEgdHlwZSBvZiB0aGUgcmVzcG9uc2UuXG4gKiBBIHNpbmdsZSBvdmVybG9hZCB2ZXJzaW9uIG9mIHRoZSBtZXRob2QgaGFuZGxlcyBlYWNoIHJlc3BvbnNlIHR5cGUuXG4gKiBUaGUgdmFsdWUgb2YgYHJlc3BvbnNlVHlwZWAgY2Fubm90IGJlIGEgdW5pb24sIGFzIHRoZSBjb21iaW5lZCBzaWduYXR1cmUgY291bGQgaW1wbHkuXG5cbiAqXG4gKiBAdXNhZ2VOb3Rlc1xuICogU2FtcGxlIEhUVFAgcmVxdWVzdHMgZm9yIHRoZSBbVG91ciBvZiBIZXJvZXNdKC90dXRvcmlhbC90b3VyLW9mLWhlcm9lcy90b2gtcHQwKSBhcHBsaWNhdGlvbi5cbiAqXG4gKiAjIyMgSFRUUCBSZXF1ZXN0IEV4YW1wbGVcbiAqXG4gKiBgYGBcbiAqICAvLyBHRVQgaGVyb2VzIHdob3NlIG5hbWUgY29udGFpbnMgc2VhcmNoIHRlcm1cbiAqIHNlYXJjaEhlcm9lcyh0ZXJtOiBzdHJpbmcpOiBvYnNlcnZhYmxlPEhlcm9bXT57XG4gKlxuICogIGNvbnN0IHBhcmFtcyA9IG5ldyBIdHRwUGFyYW1zKHtmcm9tU3RyaW5nOiAnbmFtZT10ZXJtJ30pO1xuICogICAgcmV0dXJuIHRoaXMuaHR0cENsaWVudC5yZXF1ZXN0KCdHRVQnLCB0aGlzLmhlcm9lc1VybCwge3Jlc3BvbnNlVHlwZTonanNvbicsIHBhcmFtc30pO1xuICogfVxuICogYGBgXG4gKlxuICogQWx0ZXJuYXRpdmVseSwgdGhlIHBhcmFtZXRlciBzdHJpbmcgY2FuIGJlIHVzZWQgd2l0aG91dCBpbnZva2luZyBIdHRwUGFyYW1zXG4gKiBieSBkaXJlY3RseSBqb2luaW5nIHRvIHRoZSBVUkwuXG4gKiBgYGBcbiAqIHRoaXMuaHR0cENsaWVudC5yZXF1ZXN0KCdHRVQnLCB0aGlzLmhlcm9lc1VybCArICc/JyArICduYW1lPXRlcm0nLCB7cmVzcG9uc2VUeXBlOidqc29uJ30pO1xuICogYGBgXG4gKlxuICpcbiAqICMjIyBKU09OUCBFeGFtcGxlXG4gKiBgYGBcbiAqIHJlcXVlc3RKc29ucCh1cmwsIGNhbGxiYWNrID0gJ2NhbGxiYWNrJykge1xuICogIHJldHVybiB0aGlzLmh0dHBDbGllbnQuanNvbnAodGhpcy5oZXJvZXNVUkwsIGNhbGxiYWNrKTtcbiAqIH1cbiAqIGBgYFxuICpcbiAqICMjIyBQQVRDSCBFeGFtcGxlXG4gKiBgYGBcbiAqIC8vIFBBVENIIG9uZSBvZiB0aGUgaGVyb2VzJyBuYW1lXG4gKiBwYXRjaEhlcm8gKGlkOiBudW1iZXIsIGhlcm9OYW1lOiBzdHJpbmcpOiBPYnNlcnZhYmxlPHt9PiB7XG4gKiBjb25zdCB1cmwgPSBgJHt0aGlzLmhlcm9lc1VybH0vJHtpZH1gOyAgIC8vIFBBVENIIGFwaS9oZXJvZXMvNDJcbiAqICByZXR1cm4gdGhpcy5odHRwQ2xpZW50LnBhdGNoKHVybCwge25hbWU6IGhlcm9OYW1lfSwgaHR0cE9wdGlvbnMpXG4gKiAgICAucGlwZShjYXRjaEVycm9yKHRoaXMuaGFuZGxlRXJyb3IoJ3BhdGNoSGVybycpKSk7XG4gKiB9XG4gKiBgYGBcbiAqXG4gKiBAc2VlIFtIVFRQIEd1aWRlXShndWlkZS9odHRwKVxuICogQHNlZSBbSFRUUCBSZXF1ZXN0XShhcGkvY29tbW9uL2h0dHAvSHR0cFJlcXVlc3QpXG4gKlxuICogQHB1YmxpY0FwaVxuICovXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgSHR0cENsaWVudCB7XG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgaGFuZGxlcjogSHR0cEhhbmRsZXIpIHt9XG5cbiAgLyoqXG4gICAqIFNlbmRzIGFuIGBIdHRwUmVxdWVzdGAgYW5kIHJldHVybnMgYSBzdHJlYW0gb2YgYEh0dHBFdmVudGBzLlxuICAgKlxuICAgKiBAcmV0dXJuIEFuIGBPYnNlcnZhYmxlYCBvZiB0aGUgcmVzcG9uc2UsIHdpdGggdGhlIHJlc3BvbnNlIGJvZHkgYXMgYSBzdHJlYW0gb2YgYEh0dHBFdmVudGBzLlxuICAgKi9cbiAgcmVxdWVzdDxSPihyZXE6IEh0dHBSZXF1ZXN0PGFueT4pOiBPYnNlcnZhYmxlPEh0dHBFdmVudDxSPj47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdHMgYSByZXF1ZXN0IHRoYXQgaW50ZXJwcmV0cyB0aGUgYm9keSBhcyBhbiBgQXJyYXlCdWZmZXJgIGFuZCByZXR1cm5zIHRoZSByZXNwb25zZSBpblxuICAgKiBhbiBgQXJyYXlCdWZmZXJgLlxuICAgKlxuICAgKiBAcGFyYW0gbWV0aG9kICBUaGUgSFRUUCBtZXRob2QuXG4gICAqIEBwYXJhbSB1cmwgICAgIFRoZSBlbmRwb2ludCBVUkwuXG4gICAqIEBwYXJhbSBvcHRpb25zIFRoZSBIVFRQIG9wdGlvbnMgdG8gc2VuZCB3aXRoIHRoZSByZXF1ZXN0LlxuICAgKlxuICAgKlxuICAgKiBAcmV0dXJuIEFuIGBPYnNlcnZhYmxlYCBvZiB0aGUgcmVzcG9uc2UsIHdpdGggdGhlIHJlc3BvbnNlIGJvZHkgYXMgYW4gYEFycmF5QnVmZmVyYC5cbiAgICovXG4gIHJlcXVlc3QobWV0aG9kOiBzdHJpbmcsIHVybDogc3RyaW5nLCBvcHRpb25zOiB7XG4gICAgYm9keT86IGFueSxcbiAgICBoZWFkZXJzPzogSHR0cEhlYWRlcnN8e1toZWFkZXI6IHN0cmluZ106IHN0cmluZyB8IHN0cmluZ1tdfSxcbiAgICBjb250ZXh0PzogSHR0cENvbnRleHQsXG4gICAgb2JzZXJ2ZT86ICdib2R5JyxcbiAgICBwYXJhbXM/OiBIdHRwUGFyYW1zfFxuICAgICAgICAgIHtbcGFyYW06IHN0cmluZ106IHN0cmluZyB8IG51bWJlciB8IGJvb2xlYW4gfCBSZWFkb25seUFycmF5PHN0cmluZ3xudW1iZXJ8Ym9vbGVhbj59LFxuICAgIHJlcG9ydFByb2dyZXNzPzogYm9vbGVhbiwgcmVzcG9uc2VUeXBlOiAnYXJyYXlidWZmZXInLFxuICAgIHdpdGhDcmVkZW50aWFscz86IGJvb2xlYW4sXG4gIH0pOiBPYnNlcnZhYmxlPEFycmF5QnVmZmVyPjtcblxuICAvKipcbiAgICogQ29uc3RydWN0cyBhIHJlcXVlc3QgdGhhdCBpbnRlcnByZXRzIHRoZSBib2R5IGFzIGEgYmxvYiBhbmQgcmV0dXJuc1xuICAgKiB0aGUgcmVzcG9uc2UgYXMgYSBibG9iLlxuICAgKlxuICAgKiBAcGFyYW0gbWV0aG9kICBUaGUgSFRUUCBtZXRob2QuXG4gICAqIEBwYXJhbSB1cmwgICAgIFRoZSBlbmRwb2ludCBVUkwuXG4gICAqIEBwYXJhbSBvcHRpb25zIFRoZSBIVFRQIG9wdGlvbnMgdG8gc2VuZCB3aXRoIHRoZSByZXF1ZXN0LlxuICAgKlxuICAgKiBAcmV0dXJuIEFuIGBPYnNlcnZhYmxlYCBvZiB0aGUgcmVzcG9uc2UsIHdpdGggdGhlIHJlc3BvbnNlIGJvZHkgb2YgdHlwZSBgQmxvYmAuXG4gICAqL1xuICByZXF1ZXN0KG1ldGhvZDogc3RyaW5nLCB1cmw6IHN0cmluZywgb3B0aW9uczoge1xuICAgIGJvZHk/OiBhbnksXG4gICAgaGVhZGVycz86IEh0dHBIZWFkZXJzfHtbaGVhZGVyOiBzdHJpbmddOiBzdHJpbmcgfCBzdHJpbmdbXX0sXG4gICAgY29udGV4dD86IEh0dHBDb250ZXh0LFxuICAgIG9ic2VydmU/OiAnYm9keScsXG4gICAgcGFyYW1zPzogSHR0cFBhcmFtc3xcbiAgICAgICAgICB7W3BhcmFtOiBzdHJpbmddOiBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuIHwgUmVhZG9ubHlBcnJheTxzdHJpbmd8bnVtYmVyfGJvb2xlYW4+fSxcbiAgICByZXBvcnRQcm9ncmVzcz86IGJvb2xlYW4sIHJlc3BvbnNlVHlwZTogJ2Jsb2InLFxuICAgIHdpdGhDcmVkZW50aWFscz86IGJvb2xlYW4sXG4gIH0pOiBPYnNlcnZhYmxlPEJsb2I+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIGEgcmVxdWVzdCB0aGF0IGludGVycHJldHMgdGhlIGJvZHkgYXMgYSB0ZXh0IHN0cmluZyBhbmRcbiAgICogcmV0dXJucyBhIHN0cmluZyB2YWx1ZS5cbiAgICpcbiAgICogQHBhcmFtIG1ldGhvZCAgVGhlIEhUVFAgbWV0aG9kLlxuICAgKiBAcGFyYW0gdXJsICAgICBUaGUgZW5kcG9pbnQgVVJMLlxuICAgKiBAcGFyYW0gb3B0aW9ucyBUaGUgSFRUUCBvcHRpb25zIHRvIHNlbmQgd2l0aCB0aGUgcmVxdWVzdC5cbiAgICpcbiAgICogQHJldHVybiBBbiBgT2JzZXJ2YWJsZWAgb2YgdGhlIHJlc3BvbnNlLCB3aXRoIHRoZSByZXNwb25zZSBib2R5IG9mIHR5cGUgc3RyaW5nLlxuICAgKi9cbiAgcmVxdWVzdChtZXRob2Q6IHN0cmluZywgdXJsOiBzdHJpbmcsIG9wdGlvbnM6IHtcbiAgICBib2R5PzogYW55LFxuICAgIGhlYWRlcnM/OiBIdHRwSGVhZGVyc3x7W2hlYWRlcjogc3RyaW5nXTogc3RyaW5nIHwgc3RyaW5nW119LFxuICAgIGNvbnRleHQ/OiBIdHRwQ29udGV4dCxcbiAgICBvYnNlcnZlPzogJ2JvZHknLFxuICAgIHBhcmFtcz86IEh0dHBQYXJhbXN8XG4gICAgICAgICAge1twYXJhbTogc3RyaW5nXTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IFJlYWRvbmx5QXJyYXk8c3RyaW5nfG51bWJlcnxib29sZWFuPn0sXG4gICAgcmVwb3J0UHJvZ3Jlc3M/OiBib29sZWFuLCByZXNwb25zZVR5cGU6ICd0ZXh0JyxcbiAgICB3aXRoQ3JlZGVudGlhbHM/OiBib29sZWFuLFxuICB9KTogT2JzZXJ2YWJsZTxzdHJpbmc+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIGEgcmVxdWVzdCB0aGF0IGludGVycHJldHMgdGhlIGJvZHkgYXMgYW4gYEFycmF5QnVmZmVyYCBhbmQgcmV0dXJucyB0aGVcbiAgICogdGhlIGZ1bGwgZXZlbnQgc3RyZWFtLlxuICAgKlxuICAgKiBAcGFyYW0gbWV0aG9kICBUaGUgSFRUUCBtZXRob2QuXG4gICAqIEBwYXJhbSB1cmwgICAgIFRoZSBlbmRwb2ludCBVUkwuXG4gICAqIEBwYXJhbSBvcHRpb25zIFRoZSBIVFRQIG9wdGlvbnMgdG8gc2VuZCB3aXRoIHRoZSByZXF1ZXN0LlxuICAgKlxuICAgKiBAcmV0dXJuIEFuIGBPYnNlcnZhYmxlYCBvZiB0aGUgcmVzcG9uc2UsIHdpdGggdGhlIHJlc3BvbnNlIGJvZHkgYXMgYW4gYXJyYXkgb2YgYEh0dHBFdmVudGBzIGZvclxuICAgKiB0aGUgcmVxdWVzdC5cbiAgICovXG4gIHJlcXVlc3QobWV0aG9kOiBzdHJpbmcsIHVybDogc3RyaW5nLCBvcHRpb25zOiB7XG4gICAgYm9keT86IGFueSxcbiAgICBoZWFkZXJzPzogSHR0cEhlYWRlcnN8e1toZWFkZXI6IHN0cmluZ106IHN0cmluZyB8IHN0cmluZ1tdfSxcbiAgICBjb250ZXh0PzogSHR0cENvbnRleHQsXG4gICAgcGFyYW1zPzogSHR0cFBhcmFtc3xcbiAgICAgICAgICB7W3BhcmFtOiBzdHJpbmddOiBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuIHwgUmVhZG9ubHlBcnJheTxzdHJpbmd8bnVtYmVyfGJvb2xlYW4+fSxcbiAgICAgICAgICBvYnNlcnZlOiAnZXZlbnRzJyxcbiAgICByZXBvcnRQcm9ncmVzcz86IGJvb2xlYW4sIHJlc3BvbnNlVHlwZTogJ2FycmF5YnVmZmVyJyxcbiAgICB3aXRoQ3JlZGVudGlhbHM/OiBib29sZWFuLFxuICB9KTogT2JzZXJ2YWJsZTxIdHRwRXZlbnQ8QXJyYXlCdWZmZXI+PjtcblxuICAvKipcbiAgICogQ29uc3RydWN0cyBhIHJlcXVlc3QgdGhhdCBpbnRlcnByZXRzIHRoZSBib2R5IGFzIGEgYEJsb2JgIGFuZCByZXR1cm5zXG4gICAqIHRoZSBmdWxsIGV2ZW50IHN0cmVhbS5cbiAgICpcbiAgICogQHBhcmFtIG1ldGhvZCAgVGhlIEhUVFAgbWV0aG9kLlxuICAgKiBAcGFyYW0gdXJsICAgICBUaGUgZW5kcG9pbnQgVVJMLlxuICAgKiBAcGFyYW0gb3B0aW9ucyBUaGUgSFRUUCBvcHRpb25zIHRvIHNlbmQgd2l0aCB0aGUgcmVxdWVzdC5cbiAgICpcbiAgICogQHJldHVybiBBbiBgT2JzZXJ2YWJsZWAgb2YgYWxsIGBIdHRwRXZlbnRgcyBmb3IgdGhlIHJlcXVlc3QsXG4gICAqIHdpdGggdGhlIHJlc3BvbnNlIGJvZHkgb2YgdHlwZSBgQmxvYmAuXG4gICAqL1xuICByZXF1ZXN0KG1ldGhvZDogc3RyaW5nLCB1cmw6IHN0cmluZywgb3B0aW9uczoge1xuICAgIGJvZHk/OiBhbnksXG4gICAgaGVhZGVycz86IEh0dHBIZWFkZXJzfHtbaGVhZGVyOiBzdHJpbmddOiBzdHJpbmcgfCBzdHJpbmdbXX0sIG9ic2VydmU6ICdldmVudHMnLFxuICAgIGNvbnRleHQ/OiBIdHRwQ29udGV4dCxcbiAgICBwYXJhbXM/OiBIdHRwUGFyYW1zfFxuICAgICAgICAgIHtbcGFyYW06IHN0cmluZ106IHN0cmluZyB8IG51bWJlciB8IGJvb2xlYW4gfCBSZWFkb25seUFycmF5PHN0cmluZ3xudW1iZXJ8Ym9vbGVhbj59LFxuICAgIHJlcG9ydFByb2dyZXNzPzogYm9vbGVhbiwgcmVzcG9uc2VUeXBlOiAnYmxvYicsXG4gICAgd2l0aENyZWRlbnRpYWxzPzogYm9vbGVhbixcbiAgfSk6IE9ic2VydmFibGU8SHR0cEV2ZW50PEJsb2I+PjtcblxuICAvKipcbiAgICogQ29uc3RydWN0cyBhIHJlcXVlc3Qgd2hpY2ggaW50ZXJwcmV0cyB0aGUgYm9keSBhcyBhIHRleHQgc3RyaW5nIGFuZCByZXR1cm5zIHRoZSBmdWxsIGV2ZW50XG4gICAqIHN0cmVhbS5cbiAgICpcbiAgICogQHBhcmFtIG1ldGhvZCAgVGhlIEhUVFAgbWV0aG9kLlxuICAgKiBAcGFyYW0gdXJsICAgICBUaGUgZW5kcG9pbnQgVVJMLlxuICAgKiBAcGFyYW0gb3B0aW9ucyBUaGUgSFRUUCBvcHRpb25zIHRvIHNlbmQgd2l0aCB0aGUgcmVxdWVzdC5cbiAgICpcbiAgICogQHJldHVybiBBbiBgT2JzZXJ2YWJsZWAgb2YgYWxsIGBIdHRwRXZlbnRgcyBmb3IgdGhlIHJlcXVlc3QsXG4gICAqIHdpdGggdGhlIHJlc3BvbnNlIGJvZHkgb2YgdHlwZSBzdHJpbmcuXG4gICAqL1xuICByZXF1ZXN0KG1ldGhvZDogc3RyaW5nLCB1cmw6IHN0cmluZywgb3B0aW9uczoge1xuICAgIGJvZHk/OiBhbnksXG4gICAgaGVhZGVycz86IEh0dHBIZWFkZXJzfHtbaGVhZGVyOiBzdHJpbmddOiBzdHJpbmcgfCBzdHJpbmdbXX0sIG9ic2VydmU6ICdldmVudHMnLFxuICAgIGNvbnRleHQ/OiBIdHRwQ29udGV4dCxcbiAgICBwYXJhbXM/OiBIdHRwUGFyYW1zfFxuICAgICAgICAgIHtbcGFyYW06IHN0cmluZ106IHN0cmluZyB8IG51bWJlciB8IGJvb2xlYW4gfCBSZWFkb25seUFycmF5PHN0cmluZ3xudW1iZXJ8Ym9vbGVhbj59LFxuICAgIHJlcG9ydFByb2dyZXNzPzogYm9vbGVhbiwgcmVzcG9uc2VUeXBlOiAndGV4dCcsXG4gICAgd2l0aENyZWRlbnRpYWxzPzogYm9vbGVhbixcbiAgfSk6IE9ic2VydmFibGU8SHR0cEV2ZW50PHN0cmluZz4+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIGEgcmVxdWVzdCB3aGljaCBpbnRlcnByZXRzIHRoZSBib2R5IGFzIGEgSmF2YVNjcmlwdCBvYmplY3QgYW5kIHJldHVybnMgdGhlIGZ1bGxcbiAgICogZXZlbnQgc3RyZWFtLlxuICAgKlxuICAgKiBAcGFyYW0gbWV0aG9kICBUaGUgSFRUUCBtZXRob2QuXG4gICAqIEBwYXJhbSB1cmwgICAgIFRoZSBlbmRwb2ludCBVUkwuXG4gICAqIEBwYXJhbSBvcHRpb25zIFRoZSBIVFRQIG9wdGlvbnMgdG8gc2VuZCB3aXRoIHRoZSAgcmVxdWVzdC5cbiAgICpcbiAgICogQHJldHVybiBBbiBgT2JzZXJ2YWJsZWAgb2YgYWxsIGBIdHRwRXZlbnRgcyBmb3IgdGhlIHJlcXVlc3QsXG4gICAqIHdpdGggdGhlIHJlc3BvbnNlIGJvZHkgb2YgdHlwZSBgT2JqZWN0YC5cbiAgICovXG4gIHJlcXVlc3QobWV0aG9kOiBzdHJpbmcsIHVybDogc3RyaW5nLCBvcHRpb25zOiB7XG4gICAgYm9keT86IGFueSxcbiAgICBoZWFkZXJzPzogSHR0cEhlYWRlcnN8e1toZWFkZXI6IHN0cmluZ106IHN0cmluZyB8IHN0cmluZ1tdfSxcbiAgICBjb250ZXh0PzogSHR0cENvbnRleHQsXG4gICAgcmVwb3J0UHJvZ3Jlc3M/OiBib29sZWFuLCBvYnNlcnZlOiAnZXZlbnRzJyxcbiAgICBwYXJhbXM/OiBIdHRwUGFyYW1zfFxuICAgICAgICAgIHtbcGFyYW06IHN0cmluZ106IHN0cmluZyB8IG51bWJlciB8IGJvb2xlYW4gfCBSZWFkb25seUFycmF5PHN0cmluZ3xudW1iZXJ8Ym9vbGVhbj59LFxuICAgIHJlc3BvbnNlVHlwZT86ICdqc29uJyxcbiAgICB3aXRoQ3JlZGVudGlhbHM/OiBib29sZWFuLFxuICB9KTogT2JzZXJ2YWJsZTxIdHRwRXZlbnQ8YW55Pj47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdHMgYSByZXF1ZXN0IHdoaWNoIGludGVycHJldHMgdGhlIGJvZHkgYXMgYSBKYXZhU2NyaXB0IG9iamVjdCBhbmQgcmV0dXJucyB0aGUgZnVsbFxuICAgKiBldmVudCBzdHJlYW0uXG4gICAqXG4gICAqIEBwYXJhbSBtZXRob2QgIFRoZSBIVFRQIG1ldGhvZC5cbiAgICogQHBhcmFtIHVybCAgICAgVGhlIGVuZHBvaW50IFVSTC5cbiAgICogQHBhcmFtIG9wdGlvbnMgVGhlIEhUVFAgb3B0aW9ucyB0byBzZW5kIHdpdGggdGhlIHJlcXVlc3QuXG4gICAqXG4gICAqIEByZXR1cm4gQW4gYE9ic2VydmFibGVgIG9mIGFsbCBgSHR0cEV2ZW50YHMgZm9yIHRoZSByZXF1ZXN0LFxuICAgKiB3aXRoIHRoZSByZXNwb25zZSBib2R5IG9mIHR5cGUgYFJgLlxuICAgKi9cbiAgcmVxdWVzdDxSPihtZXRob2Q6IHN0cmluZywgdXJsOiBzdHJpbmcsIG9wdGlvbnM6IHtcbiAgICBib2R5PzogYW55LFxuICAgIGhlYWRlcnM/OiBIdHRwSGVhZGVyc3x7W2hlYWRlcjogc3RyaW5nXTogc3RyaW5nIHwgc3RyaW5nW119LFxuICAgIGNvbnRleHQ/OiBIdHRwQ29udGV4dCxcbiAgICByZXBvcnRQcm9ncmVzcz86IGJvb2xlYW4sIG9ic2VydmU6ICdldmVudHMnLFxuICAgIHBhcmFtcz86IEh0dHBQYXJhbXN8XG4gICAgICAgICAge1twYXJhbTogc3RyaW5nXTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IFJlYWRvbmx5QXJyYXk8c3RyaW5nfG51bWJlcnxib29sZWFuPn0sXG4gICAgcmVzcG9uc2VUeXBlPzogJ2pzb24nLFxuICAgIHdpdGhDcmVkZW50aWFscz86IGJvb2xlYW4sXG4gIH0pOiBPYnNlcnZhYmxlPEh0dHBFdmVudDxSPj47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdHMgYSByZXF1ZXN0IHdoaWNoIGludGVycHJldHMgdGhlIGJvZHkgYXMgYW4gYEFycmF5QnVmZmVyYFxuICAgKiBhbmQgcmV0dXJucyB0aGUgZnVsbCBgSHR0cFJlc3BvbnNlYC5cbiAgICpcbiAgICogQHBhcmFtIG1ldGhvZCAgVGhlIEhUVFAgbWV0aG9kLlxuICAgKiBAcGFyYW0gdXJsICAgICBUaGUgZW5kcG9pbnQgVVJMLlxuICAgKiBAcGFyYW0gb3B0aW9ucyBUaGUgSFRUUCBvcHRpb25zIHRvIHNlbmQgd2l0aCB0aGUgcmVxdWVzdC5cbiAgICpcbiAgICogQHJldHVybiBBbiBgT2JzZXJ2YWJsZWAgb2YgdGhlIGBIdHRwUmVzcG9uc2VgLCB3aXRoIHRoZSByZXNwb25zZSBib2R5IGFzIGFuIGBBcnJheUJ1ZmZlcmAuXG4gICAqL1xuICByZXF1ZXN0KG1ldGhvZDogc3RyaW5nLCB1cmw6IHN0cmluZywgb3B0aW9uczoge1xuICAgIGJvZHk/OiBhbnksXG4gICAgaGVhZGVycz86IEh0dHBIZWFkZXJzfHtbaGVhZGVyOiBzdHJpbmddOiBzdHJpbmcgfCBzdHJpbmdbXX0sIG9ic2VydmU6ICdyZXNwb25zZScsXG4gICAgY29udGV4dD86IEh0dHBDb250ZXh0LFxuICAgIHBhcmFtcz86IEh0dHBQYXJhbXN8XG4gICAgICAgICAge1twYXJhbTogc3RyaW5nXTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IFJlYWRvbmx5QXJyYXk8c3RyaW5nfG51bWJlcnxib29sZWFuPn0sXG4gICAgcmVwb3J0UHJvZ3Jlc3M/OiBib29sZWFuLCByZXNwb25zZVR5cGU6ICdhcnJheWJ1ZmZlcicsXG4gICAgd2l0aENyZWRlbnRpYWxzPzogYm9vbGVhbixcbiAgfSk6IE9ic2VydmFibGU8SHR0cFJlc3BvbnNlPEFycmF5QnVmZmVyPj47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdHMgYSByZXF1ZXN0IHdoaWNoIGludGVycHJldHMgdGhlIGJvZHkgYXMgYSBgQmxvYmAgYW5kIHJldHVybnMgdGhlIGZ1bGwgYEh0dHBSZXNwb25zZWAuXG4gICAqXG4gICAqIEBwYXJhbSBtZXRob2QgIFRoZSBIVFRQIG1ldGhvZC5cbiAgICogQHBhcmFtIHVybCAgICAgVGhlIGVuZHBvaW50IFVSTC5cbiAgICogQHBhcmFtIG9wdGlvbnMgVGhlIEhUVFAgb3B0aW9ucyB0byBzZW5kIHdpdGggdGhlIHJlcXVlc3QuXG4gICAqXG4gICAqIEByZXR1cm4gQW4gYE9ic2VydmFibGVgIG9mIHRoZSBgSHR0cFJlc3BvbnNlYCwgd2l0aCB0aGUgcmVzcG9uc2UgYm9keSBvZiB0eXBlIGBCbG9iYC5cbiAgICovXG4gIHJlcXVlc3QobWV0aG9kOiBzdHJpbmcsIHVybDogc3RyaW5nLCBvcHRpb25zOiB7XG4gICAgYm9keT86IGFueSxcbiAgICBoZWFkZXJzPzogSHR0cEhlYWRlcnN8e1toZWFkZXI6IHN0cmluZ106IHN0cmluZyB8IHN0cmluZ1tdfSwgb2JzZXJ2ZTogJ3Jlc3BvbnNlJyxcbiAgICBjb250ZXh0PzogSHR0cENvbnRleHQsXG4gICAgcGFyYW1zPzogSHR0cFBhcmFtc3xcbiAgICAgICAgICB7W3BhcmFtOiBzdHJpbmddOiBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuIHwgUmVhZG9ubHlBcnJheTxzdHJpbmd8bnVtYmVyfGJvb2xlYW4+fSxcbiAgICByZXBvcnRQcm9ncmVzcz86IGJvb2xlYW4sIHJlc3BvbnNlVHlwZTogJ2Jsb2InLFxuICAgIHdpdGhDcmVkZW50aWFscz86IGJvb2xlYW4sXG4gIH0pOiBPYnNlcnZhYmxlPEh0dHBSZXNwb25zZTxCbG9iPj47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdHMgYSByZXF1ZXN0IHdoaWNoIGludGVycHJldHMgdGhlIGJvZHkgYXMgYSB0ZXh0IHN0cmVhbSBhbmQgcmV0dXJucyB0aGUgZnVsbFxuICAgKiBgSHR0cFJlc3BvbnNlYC5cbiAgICpcbiAgICogQHBhcmFtIG1ldGhvZCAgVGhlIEhUVFAgbWV0aG9kLlxuICAgKiBAcGFyYW0gdXJsICAgICBUaGUgZW5kcG9pbnQgVVJMLlxuICAgKiBAcGFyYW0gb3B0aW9ucyBUaGUgSFRUUCBvcHRpb25zIHRvIHNlbmQgd2l0aCB0aGUgcmVxdWVzdC5cbiAgICpcbiAgICogQHJldHVybiBBbiBgT2JzZXJ2YWJsZWAgb2YgdGhlIEhUVFAgcmVzcG9uc2UsIHdpdGggdGhlIHJlc3BvbnNlIGJvZHkgb2YgdHlwZSBzdHJpbmcuXG4gICAqL1xuICByZXF1ZXN0KG1ldGhvZDogc3RyaW5nLCB1cmw6IHN0cmluZywgb3B0aW9uczoge1xuICAgIGJvZHk/OiBhbnksXG4gICAgaGVhZGVycz86IEh0dHBIZWFkZXJzfHtbaGVhZGVyOiBzdHJpbmddOiBzdHJpbmcgfCBzdHJpbmdbXX0sIG9ic2VydmU6ICdyZXNwb25zZScsXG4gICAgY29udGV4dD86IEh0dHBDb250ZXh0LFxuICAgIHBhcmFtcz86IEh0dHBQYXJhbXN8XG4gICAgICAgICAge1twYXJhbTogc3RyaW5nXTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IFJlYWRvbmx5QXJyYXk8c3RyaW5nfG51bWJlcnxib29sZWFuPn0sXG4gICAgcmVwb3J0UHJvZ3Jlc3M/OiBib29sZWFuLCByZXNwb25zZVR5cGU6ICd0ZXh0JyxcbiAgICB3aXRoQ3JlZGVudGlhbHM/OiBib29sZWFuLFxuICB9KTogT2JzZXJ2YWJsZTxIdHRwUmVzcG9uc2U8c3RyaW5nPj47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdHMgYSByZXF1ZXN0IHdoaWNoIGludGVycHJldHMgdGhlIGJvZHkgYXMgYSBKYXZhU2NyaXB0IG9iamVjdCBhbmQgcmV0dXJucyB0aGUgZnVsbFxuICAgKiBgSHR0cFJlc3BvbnNlYC5cbiAgICpcbiAgICogQHBhcmFtIG1ldGhvZCAgVGhlIEhUVFAgbWV0aG9kLlxuICAgKiBAcGFyYW0gdXJsICAgICBUaGUgZW5kcG9pbnQgVVJMLlxuICAgKiBAcGFyYW0gb3B0aW9ucyBUaGUgSFRUUCBvcHRpb25zIHRvIHNlbmQgd2l0aCB0aGUgcmVxdWVzdC5cbiAgICpcbiAgICogQHJldHVybiBBbiBgT2JzZXJ2YWJsZWAgb2YgdGhlIGZ1bGwgYEh0dHBSZXNwb25zZWAsXG4gICAqIHdpdGggdGhlIHJlc3BvbnNlIGJvZHkgb2YgdHlwZSBgT2JqZWN0YC5cbiAgICovXG4gIHJlcXVlc3QobWV0aG9kOiBzdHJpbmcsIHVybDogc3RyaW5nLCBvcHRpb25zOiB7XG4gICAgYm9keT86IGFueSxcbiAgICBoZWFkZXJzPzogSHR0cEhlYWRlcnN8e1toZWFkZXI6IHN0cmluZ106IHN0cmluZyB8IHN0cmluZ1tdfSxcbiAgICBjb250ZXh0PzogSHR0cENvbnRleHQsXG4gICAgcmVwb3J0UHJvZ3Jlc3M/OiBib29sZWFuLCBvYnNlcnZlOiAncmVzcG9uc2UnLFxuICAgIHBhcmFtcz86IEh0dHBQYXJhbXN8XG4gICAgICAgICAge1twYXJhbTogc3RyaW5nXTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IFJlYWRvbmx5QXJyYXk8c3RyaW5nfG51bWJlcnxib29sZWFuPn0sXG4gICAgcmVzcG9uc2VUeXBlPzogJ2pzb24nLFxuICAgIHdpdGhDcmVkZW50aWFscz86IGJvb2xlYW4sXG4gIH0pOiBPYnNlcnZhYmxlPEh0dHBSZXNwb25zZTxPYmplY3Q+PjtcblxuICAvKipcbiAgICogQ29uc3RydWN0cyBhIHJlcXVlc3Qgd2hpY2ggaW50ZXJwcmV0cyB0aGUgYm9keSBhcyBhIEphdmFTY3JpcHQgb2JqZWN0IGFuZCByZXR1cm5zXG4gICAqIHRoZSBmdWxsIGBIdHRwUmVzcG9uc2VgIHdpdGggdGhlIHJlc3BvbnNlIGJvZHkgaW4gdGhlIHJlcXVlc3RlZCB0eXBlLlxuICAgKlxuICAgKiBAcGFyYW0gbWV0aG9kICBUaGUgSFRUUCBtZXRob2QuXG4gICAqIEBwYXJhbSB1cmwgICAgIFRoZSBlbmRwb2ludCBVUkwuXG4gICAqIEBwYXJhbSBvcHRpb25zIFRoZSBIVFRQIG9wdGlvbnMgdG8gc2VuZCB3aXRoIHRoZSByZXF1ZXN0LlxuICAgKlxuICAgKiBAcmV0dXJuICBBbiBgT2JzZXJ2YWJsZWAgb2YgdGhlIGZ1bGwgYEh0dHBSZXNwb25zZWAsIHdpdGggdGhlIHJlc3BvbnNlIGJvZHkgb2YgdHlwZSBgUmAuXG4gICAqL1xuICByZXF1ZXN0PFI+KG1ldGhvZDogc3RyaW5nLCB1cmw6IHN0cmluZywgb3B0aW9uczoge1xuICAgIGJvZHk/OiBhbnksXG4gICAgaGVhZGVycz86IEh0dHBIZWFkZXJzfHtbaGVhZGVyOiBzdHJpbmddOiBzdHJpbmcgfCBzdHJpbmdbXX0sXG4gICAgY29udGV4dD86IEh0dHBDb250ZXh0LFxuICAgIHJlcG9ydFByb2dyZXNzPzogYm9vbGVhbiwgb2JzZXJ2ZTogJ3Jlc3BvbnNlJyxcbiAgICBwYXJhbXM/OiBIdHRwUGFyYW1zfFxuICAgICAgICAgIHtbcGFyYW06IHN0cmluZ106IHN0cmluZyB8IG51bWJlciB8IGJvb2xlYW4gfCBSZWFkb25seUFycmF5PHN0cmluZ3xudW1iZXJ8Ym9vbGVhbj59LFxuICAgIHJlc3BvbnNlVHlwZT86ICdqc29uJyxcbiAgICB3aXRoQ3JlZGVudGlhbHM/OiBib29sZWFuLFxuICB9KTogT2JzZXJ2YWJsZTxIdHRwUmVzcG9uc2U8Uj4+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIGEgcmVxdWVzdCB3aGljaCBpbnRlcnByZXRzIHRoZSBib2R5IGFzIGEgSmF2YVNjcmlwdCBvYmplY3QgYW5kIHJldHVybnMgdGhlIGZ1bGxcbiAgICogYEh0dHBSZXNwb25zZWAgYXMgYSBKYXZhU2NyaXB0IG9iamVjdC5cbiAgICpcbiAgICogQHBhcmFtIG1ldGhvZCAgVGhlIEhUVFAgbWV0aG9kLlxuICAgKiBAcGFyYW0gdXJsICAgICBUaGUgZW5kcG9pbnQgVVJMLlxuICAgKiBAcGFyYW0gb3B0aW9ucyBUaGUgSFRUUCBvcHRpb25zIHRvIHNlbmQgd2l0aCB0aGUgcmVxdWVzdC5cbiAgICpcbiAgICogQHJldHVybiBBbiBgT2JzZXJ2YWJsZWAgb2YgdGhlIGBIdHRwUmVzcG9uc2VgLCB3aXRoIHRoZSByZXNwb25zZSBib2R5IG9mIHR5cGUgYE9iamVjdGAuXG4gICAqL1xuICByZXF1ZXN0KG1ldGhvZDogc3RyaW5nLCB1cmw6IHN0cmluZywgb3B0aW9ucz86IHtcbiAgICBib2R5PzogYW55LFxuICAgIGhlYWRlcnM/OiBIdHRwSGVhZGVyc3x7W2hlYWRlcjogc3RyaW5nXTogc3RyaW5nIHwgc3RyaW5nW119LFxuICAgIGNvbnRleHQ/OiBIdHRwQ29udGV4dCxcbiAgICBvYnNlcnZlPzogJ2JvZHknLFxuICAgIHBhcmFtcz86IEh0dHBQYXJhbXN8XG4gICAgICAgICAge1twYXJhbTogc3RyaW5nXTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IFJlYWRvbmx5QXJyYXk8c3RyaW5nfG51bWJlcnxib29sZWFuPn0sXG4gICAgcmVzcG9uc2VUeXBlPzogJ2pzb24nLFxuICAgIHJlcG9ydFByb2dyZXNzPzogYm9vbGVhbixcbiAgICB3aXRoQ3JlZGVudGlhbHM/OiBib29sZWFuLFxuICB9KTogT2JzZXJ2YWJsZTxPYmplY3Q+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIGEgcmVxdWVzdCB3aGljaCBpbnRlcnByZXRzIHRoZSBib2R5IGFzIGEgSmF2YVNjcmlwdCBvYmplY3RcbiAgICogd2l0aCB0aGUgcmVzcG9uc2UgYm9keSBvZiB0aGUgcmVxdWVzdGVkIHR5cGUuXG4gICAqXG4gICAqIEBwYXJhbSBtZXRob2QgIFRoZSBIVFRQIG1ldGhvZC5cbiAgICogQHBhcmFtIHVybCAgICAgVGhlIGVuZHBvaW50IFVSTC5cbiAgICogQHBhcmFtIG9wdGlvbnMgVGhlIEhUVFAgb3B0aW9ucyB0byBzZW5kIHdpdGggdGhlIHJlcXVlc3QuXG4gICAqXG4gICAqIEByZXR1cm4gQW4gYE9ic2VydmFibGVgIG9mIHRoZSBgSHR0cFJlc3BvbnNlYCwgd2l0aCB0aGUgcmVzcG9uc2UgYm9keSBvZiB0eXBlIGBSYC5cbiAgICovXG4gIHJlcXVlc3Q8Uj4obWV0aG9kOiBzdHJpbmcsIHVybDogc3RyaW5nLCBvcHRpb25zPzoge1xuICAgIGJvZHk/OiBhbnksXG4gICAgaGVhZGVycz86IEh0dHBIZWFkZXJzfHtbaGVhZGVyOiBzdHJpbmddOiBzdHJpbmcgfCBzdHJpbmdbXX0sXG4gICAgY29udGV4dD86IEh0dHBDb250ZXh0LFxuICAgIG9ic2VydmU/OiAnYm9keScsXG4gICAgcGFyYW1zPzogSHR0cFBhcmFtc3xcbiAgICAgICAgICB7W3BhcmFtOiBzdHJpbmddOiBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuIHwgUmVhZG9ubHlBcnJheTxzdHJpbmd8bnVtYmVyfGJvb2xlYW4+fSxcbiAgICByZXNwb25zZVR5cGU/OiAnanNvbicsXG4gICAgcmVwb3J0UHJvZ3Jlc3M/OiBib29sZWFuLFxuICAgIHdpdGhDcmVkZW50aWFscz86IGJvb2xlYW4sXG4gIH0pOiBPYnNlcnZhYmxlPFI+O1xuXG4gIC8qKlxuICAgKiBDb25zdHJ1Y3RzIGEgcmVxdWVzdCB3aGVyZSByZXNwb25zZSB0eXBlIGFuZCByZXF1ZXN0ZWQgb2JzZXJ2YWJsZSBhcmUgbm90IGtub3duIHN0YXRpY2FsbHkuXG4gICAqXG4gICAqIEBwYXJhbSBtZXRob2QgIFRoZSBIVFRQIG1ldGhvZC5cbiAgICogQHBhcmFtIHVybCAgICAgVGhlIGVuZHBvaW50IFVSTC5cbiAgICogQHBhcmFtIG9wdGlvbnMgVGhlIEhUVFAgb3B0aW9ucyB0byBzZW5kIHdpdGggdGhlIHJlcXVlc3QuXG4gICAqXG4gICAqIEByZXR1cm4gQW4gYE9ic2VydmFibGVgIG9mIHRoZSByZXF1ZXN0ZWQgcmVzcG9uc2UsIHdpdGggYm9keSBvZiB0eXBlIGBhbnlgLlxuICAgKi9cbiAgcmVxdWVzdChtZXRob2Q6IHN0cmluZywgdXJsOiBzdHJpbmcsIG9wdGlvbnM/OiB7XG4gICAgYm9keT86IGFueSxcbiAgICBoZWFkZXJzPzogSHR0cEhlYWRlcnN8e1toZWFkZXI6IHN0cmluZ106IHN0cmluZyB8IHN0cmluZ1tdfSxcbiAgICBjb250ZXh0PzogSHR0cENvbnRleHQsXG4gICAgcGFyYW1zPzogSHR0cFBhcmFtc3xcbiAgICAgICAgICB7W3BhcmFtOiBzdHJpbmddOiBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuIHwgUmVhZG9ubHlBcnJheTxzdHJpbmd8bnVtYmVyfGJvb2xlYW4+fSxcbiAgICBvYnNlcnZlPzogJ2JvZHknfCdldmVudHMnfCdyZXNwb25zZScsXG4gICAgcmVwb3J0UHJvZ3Jlc3M/OiBib29sZWFuLFxuICAgIHJlc3BvbnNlVHlwZT86ICdhcnJheWJ1ZmZlcid8J2Jsb2InfCdqc29uJ3wndGV4dCcsXG4gICAgd2l0aENyZWRlbnRpYWxzPzogYm9vbGVhbixcbiAgfSk6IE9ic2VydmFibGU8YW55PjtcblxuICAvKipcbiAgICogQ29uc3RydWN0cyBhbiBvYnNlcnZhYmxlIGZvciBhIGdlbmVyaWMgSFRUUCByZXF1ZXN0IHRoYXQsIHdoZW4gc3Vic2NyaWJlZCxcbiAgICogZmlyZXMgdGhlIHJlcXVlc3QgdGhyb3VnaCB0aGUgY2hhaW4gb2YgcmVnaXN0ZXJlZCBpbnRlcmNlcHRvcnMgYW5kIG9uIHRvIHRoZVxuICAgKiBzZXJ2ZXIuXG4gICAqXG4gICAqIFlvdSBjYW4gcGFzcyBhbiBgSHR0cFJlcXVlc3RgIGRpcmVjdGx5IGFzIHRoZSBvbmx5IHBhcmFtZXRlci4gSW4gdGhpcyBjYXNlLFxuICAgKiB0aGUgY2FsbCByZXR1cm5zIGFuIG9ic2VydmFibGUgb2YgdGhlIHJhdyBgSHR0cEV2ZW50YCBzdHJlYW0uXG4gICAqXG4gICAqIEFsdGVybmF0aXZlbHkgeW91IGNhbiBwYXNzIGFuIEhUVFAgbWV0aG9kIGFzIHRoZSBmaXJzdCBwYXJhbWV0ZXIsXG4gICAqIGEgVVJMIHN0cmluZyBhcyB0aGUgc2Vjb25kLCBhbmQgYW4gb3B0aW9ucyBoYXNoIGNvbnRhaW5pbmcgdGhlIHJlcXVlc3QgYm9keSBhcyB0aGUgdGhpcmQuXG4gICAqIFNlZSBgYWRkQm9keSgpYC4gSW4gdGhpcyBjYXNlLCB0aGUgc3BlY2lmaWVkIGByZXNwb25zZVR5cGVgIGFuZCBgb2JzZXJ2ZWAgb3B0aW9ucyBkZXRlcm1pbmUgdGhlXG4gICAqIHR5cGUgb2YgcmV0dXJuZWQgb2JzZXJ2YWJsZS5cbiAgICogICAqIFRoZSBgcmVzcG9uc2VUeXBlYCB2YWx1ZSBkZXRlcm1pbmVzIGhvdyBhIHN1Y2Nlc3NmdWwgcmVzcG9uc2UgYm9keSBpcyBwYXJzZWQuXG4gICAqICAgKiBJZiBgcmVzcG9uc2VUeXBlYCBpcyB0aGUgZGVmYXVsdCBganNvbmAsIHlvdSBjYW4gcGFzcyBhIHR5cGUgaW50ZXJmYWNlIGZvciB0aGUgcmVzdWx0aW5nXG4gICAqIG9iamVjdCBhcyBhIHR5cGUgcGFyYW1ldGVyIHRvIHRoZSBjYWxsLlxuICAgKlxuICAgKiBUaGUgYG9ic2VydmVgIHZhbHVlIGRldGVybWluZXMgdGhlIHJldHVybiB0eXBlLCBhY2NvcmRpbmcgdG8gd2hhdCB5b3UgYXJlIGludGVyZXN0ZWQgaW5cbiAgICogb2JzZXJ2aW5nLlxuICAgKiAgICogQW4gYG9ic2VydmVgIHZhbHVlIG9mIGV2ZW50cyByZXR1cm5zIGFuIG9ic2VydmFibGUgb2YgdGhlIHJhdyBgSHR0cEV2ZW50YCBzdHJlYW0sIGluY2x1ZGluZ1xuICAgKiBwcm9ncmVzcyBldmVudHMgYnkgZGVmYXVsdC5cbiAgICogICAqIEFuIGBvYnNlcnZlYCB2YWx1ZSBvZiByZXNwb25zZSByZXR1cm5zIGFuIG9ic2VydmFibGUgb2YgYEh0dHBSZXNwb25zZTxUPmAsXG4gICAqIHdoZXJlIHRoZSBgVGAgcGFyYW1ldGVyIGRlcGVuZHMgb24gdGhlIGByZXNwb25zZVR5cGVgIGFuZCBhbnkgb3B0aW9uYWxseSBwcm92aWRlZCB0eXBlXG4gICAqIHBhcmFtZXRlci5cbiAgICogICAqIEFuIGBvYnNlcnZlYCB2YWx1ZSBvZiBib2R5IHJldHVybnMgYW4gb2JzZXJ2YWJsZSBvZiBgPFQ+YCB3aXRoIHRoZSBzYW1lIGBUYCBib2R5IHR5cGUuXG4gICAqXG4gICAqL1xuICByZXF1ZXN0KGZpcnN0OiBzdHJpbmd8SHR0cFJlcXVlc3Q8YW55PiwgdXJsPzogc3RyaW5nLCBvcHRpb25zOiB7XG4gICAgYm9keT86IGFueSxcbiAgICBoZWFkZXJzPzogSHR0cEhlYWRlcnN8e1toZWFkZXI6IHN0cmluZ106IHN0cmluZyB8IHN0cmluZ1tdfSxcbiAgICBjb250ZXh0PzogSHR0cENvbnRleHQsXG4gICAgb2JzZXJ2ZT86ICdib2R5J3wnZXZlbnRzJ3wncmVzcG9uc2UnLFxuICAgIHBhcmFtcz86IEh0dHBQYXJhbXN8XG4gICAgICAgICAge1twYXJhbTogc3RyaW5nXTogc3RyaW5nIHwgbnVtYmVyIHwgYm9vbGVhbiB8IFJlYWRvbmx5QXJyYXk8c3RyaW5nfG51bWJlcnxib29sZWFuPn0sXG4gICAgcmVwb3J0UHJvZ3Jlc3M/OiBib29sZWFuLFxuICAgIHJlc3BvbnNlVHlwZT86ICdhcnJheWJ1ZmZlcid8J2Jsb2InfCdqc29uJ3wndGV4dCcsXG4gICAgd2l0aENyZWRlbnRpYWxzPzogYm9vbGVhbixcbiAgfSA9IHt9KTogT2JzZXJ2YWJsZTxhbnk+IHtcbiAgICBsZXQgcmVxOiBIdHRwUmVxdWVzdDxhbnk+O1xuICAgIC8vIEZpcnN0LCBjaGVjayB3aGV0aGVyIHRoZSBwcmltYXJ5IGFyZ3VtZW50IGlzIGFuIGluc3RhbmNlIG9mIGBIdHRwUmVxdWVzdGAuXG4gICAgaWYgKGZpcnN0IGluc3RhbmNlb2YgSHR0cFJlcXVlc3QpIHtcbiAgICAgIC8vIEl0IGlzLiBUaGUgb3RoZXIgYXJndW1lbnRzIG11c3QgYmUgdW5kZWZpbmVkIChwZXIgdGhlIHNpZ25hdHVyZXMpIGFuZCBjYW4gYmVcbiAgICAgIC8vIGlnbm9yZWQuXG4gICAgICByZXEgPSBmaXJzdDtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gSXQncyBhIHN0cmluZywgc28gaXQgcmVwcmVzZW50cyBhIFVSTC4gQ29uc3RydWN0IGEgcmVxdWVzdCBiYXNlZCBvbiBpdCxcbiAgICAgIC8vIGFuZCBpbmNvcnBvcmF0ZSB0aGUgcmVtYWluaW5nIGFyZ3VtZW50cyAoYXNzdW1pbmcgYEdFVGAgdW5sZXNzIGEgbWV0aG9kIGlzXG4gICAgICAvLyBwcm92aWRlZC5cblxuICAgICAgLy8gRmlndXJlIG91dCB0aGUgaGVhZGVycy5cbiAgICAgIGxldCBoZWFkZXJzOiBIdHRwSGVhZGVyc3x1bmRlZmluZWQgPSB1bmRlZmluZWQ7XG4gICAgICBpZiAob3B0aW9ucy5oZWFkZXJzIGluc3RhbmNlb2YgSHR0cEhlYWRlcnMpIHtcbiAgICAgICAgaGVhZGVycyA9IG9wdGlvbnMuaGVhZGVycztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGhlYWRlcnMgPSBuZXcgSHR0cEhlYWRlcnMob3B0aW9ucy5oZWFkZXJzKTtcbiAgICAgIH1cblxuICAgICAgLy8gU29ydCBvdXQgcGFyYW1ldGVycy5cbiAgICAgIGxldCBwYXJhbXM6IEh0dHBQYXJhbXN8dW5kZWZpbmVkID0gdW5kZWZpbmVkO1xuICAgICAgaWYgKCEhb3B0aW9ucy5wYXJhbXMpIHtcbiAgICAgICAgaWYgKG9wdGlvbnMucGFyYW1zIGluc3RhbmNlb2YgSHR0cFBhcmFtcykge1xuICAgICAgICAgIHBhcmFtcyA9IG9wdGlvbnMucGFyYW1zO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHBhcmFtcyA9IG5ldyBIdHRwUGFyYW1zKHtmcm9tT2JqZWN0OiBvcHRpb25zLnBhcmFtc30gYXMgSHR0cFBhcmFtc09wdGlvbnMpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIENvbnN0cnVjdCB0aGUgcmVxdWVzdC5cbiAgICAgIHJlcSA9IG5ldyBIdHRwUmVxdWVzdChmaXJzdCwgdXJsISwgKG9wdGlvbnMuYm9keSAhPT0gdW5kZWZpbmVkID8gb3B0aW9ucy5ib2R5IDogbnVsbCksIHtcbiAgICAgICAgaGVhZGVycyxcbiAgICAgICAgY29udGV4dDogb3B0aW9ucy5jb250ZXh0LFxuICAgICAgICBwYXJhbXMsXG4gICAgICAgIHJlcG9ydFByb2dyZXNzOiBvcHRpb25zLnJlcG9ydFByb2dyZXNzLFxuICAgICAgICAvLyBCeSBkZWZhdWx0LCBKU09OIGlzIGFzc3VtZWQgdG8gYmUgcmV0dXJuZWQgZm9yIGFsbCBjYWxscy5cbiAgICAgICAgcmVzcG9uc2VUeXBlOiBvcHRpb25zLnJlc3BvbnNlVHlwZSB8fCAnanNvbicsXG4gICAgICAgIHdpdGhDcmVkZW50aWFsczogb3B0aW9ucy53aXRoQ3JlZGVudGlhbHMsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBTdGFydCB3aXRoIGFuIE9ic2VydmFibGUub2YoKSB0aGUgaW5pdGlhbCByZXF1ZXN0LCBhbmQgcnVuIHRoZSBoYW5kbGVyICh3aGljaFxuICAgIC8vIGluY2x1ZGVzIGFsbCBpbnRlcmNlcHRvcnMpIGluc2lkZSBhIGNvbmNhdE1hcCgpLiBUaGlzIHdheSwgdGhlIGhhbmRsZXIgcnVuc1xuICAgIC8vIGluc2lkZSBhbiBPYnNlcnZhYmxlIGNoYWluLCB3aGljaCBjYXVzZXMgaW50ZXJjZXB0b3JzIHRvIGJlIHJlLXJ1biBvbiBldmVyeVxuICAgIC8vIHN1YnNjcmlwdGlvbiAodGhpcyBhbHNvIG1ha2VzIHJldHJpZXMgcmUtcnVuIHRoZSBoYW5kbGVyLCBpbmNsdWRpbmcgaW50ZXJjZXB0b3JzKS5cbiAgICBjb25zdCBldmVudHMkOiBPYnNlcnZhYmxlPEh0dHBFdmVudDxhbnk+PiA9XG4gICAgICAgIG9mKHJlcSkucGlwZShjb25jYXRNYXAoKHJlcTogSHR0cFJlcXVlc3Q8YW55PikgPT4gdGhpcy5oYW5kbGVyLmhhbmRsZShyZXEpKSk7XG5cbiAgICAvLyBJZiBjb21pbmcgdmlhIHRoZSBBUEkgc2lnbmF0dXJlIHdoaWNoIGFjY2VwdHMgYSBwcmV2aW91c2x5IGNvbnN0cnVjdGVkIEh0dHBSZXF1ZXN0LFxuICAgIC8vIHRoZSBvbmx5IG9wdGlvbiBpcyB0byBnZXQgdGhlIGV2ZW50IHN0cmVhbS4gT3RoZXJ3aXNlLCByZXR1cm4gdGhlIGV2ZW50IHN0cmVhbSBpZlxuICAgIC8vIHRoYXQgaXMgd2hhdCB3YXMgcmVxdWVzdGVkLlxuICAgIGlmIChmaXJzdCBpbnN0YW5jZW9mIEh0dHBSZXF1ZXN0IHx8IG9wdGlvbnMub2JzZXJ2ZSA9PT0gJ2V2ZW50cycpIHtcbiAgICAgIHJldHVybiBldmVudHMkO1xuICAgIH1cblxuICAgIC8vIFR