@financialforcedev/orizuru-auth
Version:
Salesforce authentication for Heroku Node applications.
294 lines • 52.1 kB
JavaScript
"use strict";
/*
* Copyright (c) 2019, FinancialForce.com, inc
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the FinancialForce.com, inc nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
/**
* @module client/oauth2
*/
const axios_1 = __importDefault(require("axios"));
const form_urlencoded_1 = __importDefault(require("form-urlencoded"));
/**
* The return formats when requesting a grant.
*/
var ResponseFormat;
(function (ResponseFormat) {
ResponseFormat["JSON"] = "application/json";
ResponseFormat["URL_ENCODED"] = "application/x-www-form-urlencoded";
ResponseFormat["XML"] = "application/xml";
})(ResponseFormat = exports.ResponseFormat || (exports.ResponseFormat = {}));
const DEFAULT_GRANT_OPTIONS = Object.freeze({
decodeIdToken: true,
parseUserInfo: true,
responseFormat: 'application/json',
verifyIdToken: true,
verifySignature: true
});
/**
* An OAuth 2.0 client that implements the [OAuth 2.0 Authorization Framework](https://tools.ietf.org/html/rfc6749) specification.
*/
class OAuth2Client {
/**
* Creates a new OAuth2 client with the given environment.
*
* @param env The OAuth2 environment parameters.
*/
constructor(env) {
this.clientType = 'OAuth2';
this.env = Object.freeze(Object.assign({}, env));
}
/**
* @inheritdoc
*/
async init() {
if (!this.env.authorizationEndpoint) {
throw new Error('Missing required string parameter: env[authorizationEndpoint]');
}
if (!this.env.revocationEndpoint) {
throw new Error('Missing required string parameter: env[revocationEndpoint]');
}
if (!this.env.tokenEndpoint) {
throw new Error('Missing required string parameter: env[tokenEndpoint]');
}
this.authorizationEndpoint = this.env.authorizationEndpoint;
this.introspectionEndpoint = this.env.introspectionEndpoint || null;
this.revocationEndpoint = this.env.revocationEndpoint;
this.tokenEndpoint = this.env.tokenEndpoint;
}
/**
* @inheritdoc
*/
createAuthorizationUrl(params, opts) {
if (!this.authorizationEndpoint) {
throw new Error(`${this.clientType} client has not been initialized`);
}
// To avoid any inadvertent parameter leaks, create a new object from which to generate the request.
const internalOpts = {
display: opts && opts.display,
immediate: opts && opts.immediate,
prompt: opts && opts.prompt,
state: opts && opts.state
};
const internalParams = {
client_id: params.clientId,
redirect_uri: params.redirectUri,
response_type: 'code',
scope: params.scope
};
const data = Object.assign({}, internalParams, internalOpts);
if (!data.client_id) {
throw new Error('Missing required string parameter: clientId');
}
if (!data.redirect_uri) {
throw new Error('Missing required string parameter: redirectUri');
}
// Encode the parameters and then replace any encoded spaces (+)
// with the url version (%20)
const query = form_urlencoded_1.default(data, { sorted: true }).replace('+', '%20');
return `${this.authorizationEndpoint}?${query}`;
}
/**
* @inheritdoc
*/
async grant(params, opts) {
this.validateGrantParameters(params);
// To avoid any inadvertent parameter leaks, create a new object to generate the request from.
const internalOpts = Object.assign({}, DEFAULT_GRANT_OPTIONS, opts);
const internalParams = await this.createGrantInternalParameters(params, internalOpts);
const body = form_urlencoded_1.default(internalParams, { sorted: true });
const config = Object.assign({}, OAuth2Client.DEFAULT_REQUEST_CONFIG, {
headers: {
'Accept': internalOpts.responseFormat,
'Content-Type': 'application/x-www-form-urlencoded'
}
});
const response = await axios_1.default.post(this.tokenEndpoint, body, config);
if (response.status !== 200) {
const error = response.data;
throw new Error(`Failed to obtain grant: ${error.error} (${error.error_description}).`);
}
const accessTokenResponse = response.data;
return this.handleAccessTokenResponse(accessTokenResponse, internalOpts);
}
/**
* @inheritdoc
*/
async introspect(token, params, opts) {
if (this.introspectionEndpoint === undefined) {
throw new Error(`${this.clientType} client has not been initialized`);
}
if (this.introspectionEndpoint === null) {
throw new Error(`${this.clientType} client does not support token introspection`);
}
if (!params.clientId) {
throw new Error('Missing required string parameter: clientId');
}
if (!params.clientSecret) {
throw new Error('Missing required string parameter: clientSecret');
}
const config = Object.assign({}, OAuth2Client.DEFAULT_REQUEST_CONFIG, {
headers: {
'Accept': (opts && opts.responseFormat) || ResponseFormat.JSON,
'Content-Type': 'application/x-www-form-urlencoded'
}
});
const internalOpts = Object.assign({}, {
parseUserInfo: true
}, opts);
const body = form_urlencoded_1.default({
client_id: params.clientId,
client_secret: params.clientSecret,
token
});
const response = await axios_1.default.post(this.introspectionEndpoint, body, config);
if (response.status !== 200) {
const error = response.data;
throw new Error(`Failed to introspect token: ${error.error} (${error.error_description}).`);
}
const introspectionResponse = response.data;
return this.handleIntrospectionResponse(introspectionResponse, internalOpts);
}
/**
* @inheritdoc
*/
async revoke(token, opts) {
if (!this.revocationEndpoint) {
throw new Error(`${this.clientType} client has not been initialized`);
}
const internalOpts = Object.assign({
useGet: false
}, opts);
let response;
let revocationUri = this.revocationEndpoint;
if (internalOpts.useGet) {
revocationUri += `?token=${token}`;
response = await axios_1.default.get(revocationUri, OAuth2Client.DEFAULT_REQUEST_CONFIG);
}
else {
const config = Object.assign({}, OAuth2Client.DEFAULT_REQUEST_CONFIG, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
const body = form_urlencoded_1.default({ token });
response = await axios_1.default.post(revocationUri, body, config);
}
return response.status === 200;
}
/**
* @inheritdoc
*/
getType() {
return this.clientType;
}
/**
* Handle the access token response, performing validation and parsing as defined in the grant options.
*
* @param accessTokenResponse The access token response.
* @param internalOpts: The internal options.
*/
handleAccessTokenResponse(accessTokenResponse, internalOpts) {
return accessTokenResponse;
}
/**
* Handle the introspection response, performing validation and parsing as defined in the grant options.
*
* @param introspectionResponse The access token response.
* @param internalOpts: The internal options.
*/
handleIntrospectionResponse(introspectionResponse, internalOpts) {
return introspectionResponse;
}
/**
* Update the internal grant parameters is accordance with the selected [client authentication](https://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication)
* mechanism.
*
* @param params The grant parameters.
* @param internalParams The internal grant parameters.
* @param internalOpts: The internal options.
*/
async handleClientAuthentication(params, internalParams, internalOpts) {
if (!params.clientId) {
throw new Error('Missing required string parameter: clientId');
}
if (!internalOpts.clientSecret) {
throw new Error('Missing required string parameter: clientSecret');
}
internalParams.client_id = params.clientId;
internalParams.client_secret = internalOpts.clientSecret;
}
/**
* Validate the grant parameters.
*
* @param params The grant parameters.
*/
validateGrantParameters(params) {
if (!this.tokenEndpoint) {
throw new Error(`${this.clientType} client has not been initialized`);
}
if (params.grantType === 'authorization_code') {
if (!params.code) {
throw new Error('Missing required string parameter: code');
}
}
else if (params.grantType === 'refresh_token') {
if (!params.refreshToken) {
throw new Error('Missing required string parameter: refreshToken');
}
}
}
/**
* To avoid any inadvertent parameter leaks, create a new object from which to generate the grant request.
*
* @param params The grant parameters.
* @param internalOpts: The internal options.
* @returns The internal grant parameters.
*/
async createGrantInternalParameters(params, internalOpts) {
const internalParams = {};
if (params.grantType === 'authorization_code') {
internalParams.code = params.code;
internalParams.grant_type = 'authorization_code';
internalParams.redirect_uri = internalOpts.redirectUri;
}
if (params.grantType === 'refresh_token') {
internalParams.grant_type = 'refresh_token';
internalParams.refresh_token = params.refreshToken;
}
await this.handleClientAuthentication(params, internalParams, internalOpts);
return internalParams;
}
}
/**
* The default configuration for an Axios request.
*/
OAuth2Client.DEFAULT_REQUEST_CONFIG = Object.freeze({
validateStatus: () => true
});
exports.OAuth2Client = OAuth2Client;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib2F1dGgyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2luZGV4L2NsaWVudC9vYXV0aDIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F3Qkc7Ozs7O0FBRUg7O0dBRUc7QUFFSCxrREFBaUU7QUFDakUsc0VBQTZDO0FBTTdDOztHQUVHO0FBQ0gsSUFBWSxjQUlYO0FBSkQsV0FBWSxjQUFjO0lBQ3pCLDJDQUF5QixDQUFBO0lBQ3pCLG1FQUFpRCxDQUFBO0lBQ2pELHlDQUF1QixDQUFBO0FBQ3hCLENBQUMsRUFKVyxjQUFjLEdBQWQsc0JBQWMsS0FBZCxzQkFBYyxRQUl6QjtBQXdhRCxNQUFNLHFCQUFxQixHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUM7SUFDM0MsYUFBYSxFQUFFLElBQUk7SUFDbkIsYUFBYSxFQUFFLElBQUk7SUFDbkIsY0FBYyxFQUFFLGtCQUFrQjtJQUNsQyxhQUFhLEVBQUUsSUFBSTtJQUNuQixlQUFlLEVBQUUsSUFBSTtDQUNyQixDQUFDLENBQUM7QUFFSDs7R0FFRztBQUNILE1BQWEsWUFBWTtJQXVDeEI7Ozs7T0FJRztJQUNILFlBQVksR0FBZ0I7UUFDM0IsSUFBSSxDQUFDLFVBQVUsR0FBRyxRQUFRLENBQUM7UUFDM0IsSUFBSSxDQUFDLEdBQUcsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDbEQsQ0FBQztJQUVEOztPQUVHO0lBQ0ksS0FBSyxDQUFDLElBQUk7UUFFaEIsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMscUJBQXFCLEVBQUU7WUFDcEMsTUFBTSxJQUFJLEtBQUssQ0FBQywrREFBK0QsQ0FBQyxDQUFDO1NBQ2pGO1FBRUQsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsa0JBQWtCLEVBQUU7WUFDakMsTUFBTSxJQUFJ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QUFHLE1BQU0sQ0FBQyxJQUFJLENBQUM7WUFDbEMsY0FBYyxDQUFDLFVBQVUsR0FBRyxvQkFBb0IsQ0FBQztZQUNqRCxjQUFjLENBQUMsWUFBWSxHQUFHLFlBQVksQ0FBQyxXQUFXLENBQUM7U0FDdkQ7UUFFRCxJQUFJLE1BQU0sQ0FBQyxTQUFTLEtBQUssZUFBZSxFQUFFO1lBQ3pDLGNBQWMsQ0FBQyxVQUFVLEdBQUcsZUFBZSxDQUFDO1lBQzVDLGNBQWMsQ0FBQyxhQUFhLEdBQUcsTUFBTSxDQUFDLFlBQVksQ0FBQztTQUNuRDtRQUVELE1BQU0sSUFBSSxDQUFDLDBCQUEwQixDQUFDLE1BQU0sRUFBRSxjQUFjLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFFNUUsT0FBTyxjQUFjLENBQUM7SUFFdkIsQ0FBQzs7QUE1VUQ7O0dBRUc7QUFDb0IsbUNBQXNCLEdBQXVCLE1BQU0sQ0FBQyxNQUFNLENBQUM7SUFDakYsY0FBYyxFQUFFLEdBQUcsRUFBRSxDQUFDLElBQUk7Q0FDMUIsQ0FBQyxDQUFDO0FBUEosb0NBZ1ZDIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoYykgMjAxOSwgRmluYW5jaWFsRm9yY2UuY29tLCBpbmNcbiAqIEFsbCByaWdodHMgcmVzZXJ2ZWQuXG4gKlxuICogUmVkaXN0cmlidXRpb24gYW5kIHVzZSBpbiBzb3VyY2UgYW5kIGJpbmFyeSBmb3Jtcywgd2l0aCBvciB3aXRob3V0IG1vZGlmaWNhdGlvbixcbiAqICAgYXJlIHBlcm1pdHRlZCBwcm92aWRlZCB0aGF0IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucyBhcmUgbWV0OlxuICpcbiAqIC0gUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLFxuICogICAgICB0aGlzIGxpc3Qgb2YgY29uZGl0aW9ucyBhbmQgdGhlIGZvbGxvd2luZyBkaXNjbGFpbWVyLlxuICogLSBSZWRpc3RyaWJ1dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsXG4gKiAgICAgIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlIGRvY3VtZW50YXRpb25cbiAqICAgICAgYW5kL29yIG90aGVyIG1hdGVyaWFscyBwcm92aWRlZCB3aXRoIHRoZSBkaXN0cmlidXRpb24uXG4gKiAtIE5laXRoZXIgdGhlIG5hbWUgb2YgdGhlIEZpbmFuY2lhbEZvcmNlLmNvbSwgaW5jIG5vciB0aGUgbmFtZXMgb2YgaXRzIGNvbnRyaWJ1dG9yc1xuICogICAgICBtYXkgYmUgdXNlZCB0byBlbmRvcnNlIG9yIHByb21vdGUgcHJvZHVjdHMgZGVyaXZlZCBmcm9tIHRoaXMgc29mdHdhcmUgd2l0aG91dFxuICogICAgICBzcGVjaWZpYyBwcmlvciB3cml0dGVuIHBlcm1pc3Npb24uXG4gKlxuICogVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIENPTlRSSUJVVE9SUyBcIkFTIElTXCIgQU5EXG4gKiAgQU5ZIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFIElNUExJRUQgV0FSUkFOVElFU1xuICogIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFIERJU0NMQUlNRUQuIElOIE5PIEVWRU5UIFNIQUxMXG4gKiAgVEhFIENPUFlSSUdIVCBIT0xERVIgT1IgQ09OVFJJQlVUT1JTIEJFIExJQUJMRSBGT1IgQU5ZIERJUkVDVCwgSU5ESVJFQ1QsIElOQ0lERU5UQUwsIFNQRUNJQUwsXG4gKiAgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgKElOQ0xVRElORywgQlVUIE5PVCBMSU1JVEVEIFRPLCBQUk9DVVJFTUVOVCBPRiBTVUJTVElUVVRFIEdPT0RTXG4gKiAgT1IgU0VSVklDRVM7IExPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVIgQ0FVU0VEIEFORCBPTiBBTlkgVEhFT1JZXG4gKiAgT0YgTElBQklMSVRZLCBXSEVUSEVSIElOIENPTlRSQUNULCBTVFJJQ1QgTElBQklMSVRZLCBPUiBUT1JUIChJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpXG4gKiAgQVJJU0lORyBJTiBBTlkgV0FZIE9VVCBPRiBUSEUgVVNFIE9GIFRISVMgU09GVFdBUkUsIEVWRU4gSUYgQURWSVNFRCBPRiBUSEUgUE9TU0lCSUxJVFkgT0YgU1VDSCBEQU1BR0UuXG4gKi9cblxuLyoqXG4gKiBAbW9kdWxlIGNsaWVudC9vYXV0aDJcbiAqL1xuXG5pbXBvcnQgYXhpb3MsIHsgQXhpb3NSZXF1ZXN0Q29uZmlnLCBBeGlvc1Jlc3BvbnNlIH0gZnJvbSAnYXhpb3MnO1xuaW1wb3J0IGZvcm1VcmxlbmNvZGVkIGZyb20gJ2Zvcm0tdXJsZW5jb2RlZCc7XG5cbmltcG9ydCB7IEVudmlyb25tZW50IH0gZnJvbSAnLi9jYWNoZSc7XG5pbXBvcnQgeyBKd3RHcmFudFBhcmFtcyB9IGZyb20gJy4vb2F1dGgySnd0JztcbmltcG9ydCB7IFVzZXJJbmZvUmVzcG9uc2UgfSBmcm9tICcuL3NhbGVzZm9yY2UvaWRlbnRpdHknO1xuXG4vKipcbiAqIFRoZSByZXR1cm4gZm9ybWF0cyB3aGVuIHJlcXVlc3RpbmcgYSBncmFudC5cbiAqL1xuZXhwb3J0IGVudW0gUmVzcG9uc2VGb3JtYXQge1xuXHRKU09OID0gJ2FwcGxpY2F0aW9uL2pzb24nLFxuXHRVUkxfRU5DT0RFRCA9ICdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQnLFxuXHRYTUwgPSAnYXBwbGljYXRpb24veG1sJ1xufVxuXG4vKipcbiAqIFRoZSBbQWNjZXNzIFRva2VuIFJlc3BvbnNlXShodHRwczovL3Rvb2xzLmlldGYub3JnL2h0bWwvcmZjNjc0OSNzZWN0aW9uLTUuMSkuXG4gKlxuICogQGV4YW1wbGVcbiAqXG4gKiBgYGBqc29uXG4gKlxuICoge1xuICogXHRcImFjY2Vzc190b2tlblwiOlwiMllvdG5GWkZFanIxekNzaWNNV3BBQVwiLFxuICogXHRcInRva2VuX3R5cGVcIjpcImV4YW1wbGVcIixcbiAqIFx0XCJleHBpcmVzX2luXCI6MzYwMCxcbiAqIFx0XCJyZWZyZXNoX3Rva2VuXCI6XCJ0R3p2M0pPa0YwWEc1UXgyVGxLV0lBXCJcbiAqIH1cbiAqXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBY2Nlc3NUb2tlblJlc3BvbnNlIHtcblxuXHQvKipcblx0ICogVGhlIGFjY2VzcyB0b2tlbiBpc3N1ZWQgYnkgdGhlIGF1dGhvcml6YXRpb24gc2VydmVyLlxuXHQgKi9cblx0YWNjZXNzX3Rva2VuOiBzdHJpbmc7XG5cblx0LyoqXG5cdCAqIFRoZSBsaWZldGltZSBpbiBzZWNvbmRzIG9mIHRoZSBhY2Nlc3MgdG9rZW4uXG5cdCAqL1xuXHRleHBpcmVzX2luPzogbnVtYmVyO1xuXG5cdC8qKlxuXHQgKiBUb2tlbiB0aGF0IGNhbiBiZSB1c2VkIGluIHRoZSBmdXR1cmUgdG8gb2J0YWluIG5ldyBhY2Nlc3MgdG9rZW5zIChzZXNzaW9ucykuXG5cdCAqIFRoaXMgdmFsdWUgaXMgYSBzZWNyZXQuIFRyZWF0IGl0IGxpa2UgdGhlIHVzZXLigJlzIHBhc3N3b3JkLCBhbmQgdXNlIGFwcHJvcHJpYXRlIG1lYXN1cmVzIHRvIHByb3RlY3QgaXQuXG5cdCAqL1xuXHRyZWZyZXNoX3Rva2VuPzogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBUaGlzIHBhcmFtZXRlciBpcyByZXR1cm5lZCBpZiB0aGUgc2NvcGUgcGFyYW1ldGVyIGluY2x1ZGVzIG9wZW5pZC5cblx0ICovXG5cdHNjb3BlPzogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBUaGUgW2FjY2VzcyB0b2tlbiB0eXBlXShodHRwczovL3Rvb2xzLmlldGYub3JnL2h0bWwvcmZjNjc0OSNzZWN0aW9uLTcuMSkuXG5cdCAqL1xuXHR0b2tlbl90eXBlOiBzdHJpbmc7XG5cbn1cblxuLyoqXG4gKiBQYXJhbWV0ZXJzIHJlcXVpcmVkIGZvciB0aGUgYXV0aCBncmFudCB0eXBlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEF1dGhDb2RlR3JhbnRQYXJhbXMgZXh0ZW5kcyBUb2tlbkdyYW50b3JQYXJhbXMge1xuXG5cdC8qKlxuXHQgKiBBdXRob3JpemF0aW9uIGNvZGUgdGhhdCB0aGUgY29uc3VtZXIgbXVzdCB1c2UgdG8gb2J0YWluIHRoZSBhY2Nlc3MgYW5kIHJlZnJlc2ggdG9rZW5zLlxuXHQgKi9cblx0Y29kZTogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBEZWZpbmVzIHRoaXMgZ3JhbnQgdHlwZS5cblx0ICovXG5cdGdyYW50VHlwZTogJ2F1dGhvcml6YXRpb25fY29kZSc7XG5cbn1cblxuLyoqXG4gKiBPcHRpb25hbCBwYXJhbWV0ZXJzIHVzZWQgd2hlbiBnZW5lcmF0aW5nIGF1dGhvcml6YXRpb24gVVJMcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBdXRoT3B0aW9ucyB7XG5cblx0LyoqXG5cdCAqIENoYW5nZXMgdGhlIGRpc3BsYXkgdHlwZSBvZiB0aGUgbG9naW4gYW5kIGF1dGhvcml6YXRpb24gcGFnZXMuXG5cdCAqL1xuXHRkaXNwbGF5PzogJ3BhZ2UnIHwgJ3BvcHVwJyB8ICd0b3VjaCcgfCAnbW9iaWxlJztcblxuXHQvKipcblx0ICogSWYgdHJ1ZSBhbmQgdGhlIHVzZXIgaXMgbG9nZ2VkIGluIGFuZCBoYXMgcHJldmlvdXNseSBhcHByb3ZlZCB0aGUgY2xpZW50SWQsXG5cdCAqIFNhbGVzZm9yY2Ugc2tpcHMgdGhlIGFwcHJvdmFsIHN0ZXAuXG5cdCAqXG5cdCAqIElmIHRydWUgYW5kIHRoZSB1c2VyIGlzbuKAmXQgbG9nZ2VkIGluIG9yIGhhcyBub3QgcHJldmlvdXNseSBhcHByb3ZlZCB0aGUgY2xpZW50LFxuXHQgKiBTYWxlc2ZvcmNlIGltbWVkaWF0ZWx5IHRlcm1pbmF0ZXMgd2l0aCB0aGUgaW1tZWRpYXRlX3Vuc3VjY2Vzc2Z1bCBlcnJvciBjb2RlLlxuXHQgKi9cblx0aW1tZWRpYXRlPzogYm9vbGVhbjtcblxuXHQvKipcblx0ICogU3BlY2lmaWVzIGhvdyB0aGUgYXV0aG9yaXphdGlvbiBzZXJ2ZXIgcHJvbXB0cyB0aGUgdXNlciBmb3IgcmVhdXRoZW50aWNhdGlvbiBhbmRcblx0ICogcmVhcHByb3ZhbC5cblx0ICpcblx0ICogRGVmaW5lZCBpbiB0aGUgW09wZW5JRCBzcGVjaWZpY2F0aW9uXShodHRwczovL29wZW5pZC5uZXQvc3BlY3Mvb3BlbmlkLWNvbm5lY3QtY29yZS0xXzAuaHRtbCNBdXRoUmVxdWVzdCkuXG5cdCAqL1xuXHRwcm9tcHQ/OiAnbm9uZScgfCAnbG9naW4nIHwgJ2NvbnNlbnQnIHwgJ3NlbGVjdF9hY2NvdW50JztcblxuXHQvKipcblx0ICogT3BhcXVlIHZhbHVlIHVzZWQgdG8gbWFpbnRhaW4gc3RhdGUgYmV0d2VlbiB0aGUgcmVxdWVzdCBhbmQgdGhlIGNhbGxiYWNrLlxuXHQgKi9cblx0c3RhdGU/OiBzdHJpbmc7XG5cbn1cblxuLyoqXG4gKiBUaGUgcmVxdWlyZWQgcGFyYW1ldGVycyByZXF1aXJlZCBmb3IgYW4gW2F1dGhvcml6YXRpb24gcmVxdWVzdF0oaHR0cHM6Ly90b29scy5pZXRmLm9yZy9odG1sL3JmYzY3NDkjc2VjdGlvbi00LjEuMSkuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQXV0aFVybFBhcmFtcyBleHRlbmRzIEhhc0NsaWVudElkIHtcblxuXHQvKipcblx0ICogQSBzcGFjZS1kZWxpbWl0ZWQgbGlzdCBvZiBzY29wZXMgdGhhdCBpZGVudGlmeSB0aGUgcmVzb3VyY2VzIHRoYXQgeW91ciBhcHBsaWNhdGlvblxuXHQgKiBjb3VsZCBhY2Nlc3Mgb24gdGhlIHVzZXIncyBiZWhhbGYuXG5cdCAqXG5cdCAqIFRoZSBzY29wZXMgY2FuIGJlIG9taXR0ZWQgaW4gYWNjb3JkYW5jZSB3aXRoIHRoZSBbc3BlY2lmaWNhdGlvbl0oaHR0cHM6Ly90b29scy5pZXRmLm9yZy9odG1sL3JmYzY3NDkjc2VjdGlvbi0zLjMpLlxuXHQgKi9cblx0c2NvcGU/OiBzdHJpbmc7XG5cblx0LyoqXG5cdCAqIERldGVybWluZXMgd2hlcmUgdGhlIEFQSSBzZXJ2ZXIgcmVkaXJlY3RzIHRoZSB1c2VyIGFmdGVyIHRoZSB1c2VyIGNvbXBsZXRlcyB0aGVcblx0ICogYXV0aG9yaXphdGlvbiBmbG93LlxuXHQgKi9cblx0cmVkaXJlY3RVcmk6IHN0cmluZztcblxufVxuXG4vKipcbiAqIFRoZSBbRXJyb3IgUmVzcG9uc2VdKGh0dHBzOi8vdG9vbHMuaWV0Zi5vcmcvaHRtbC9yZmM2NzQ5I3NlY3Rpb24tNC4xLjIuMSkgcGFyYW1ldGVycy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBFcnJvclJlc3BvbnNlIHtcblxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgZXJyb3IgY29kZS5cblx0ICovXG5cdGVycm9yOiBzdHJpbmc7XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIGRlc2NyaXB0aW9uIG9mIHRoZSBlcnJvciB3aXRoIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24uXG5cdCAqL1xuXHRlcnJvcl9kZXNjcmlwdGlvbj86IHN0cmluZztcblxufVxuXG4vKipcbiAqIFNpbXBsZSBpbnRlcmZhY2UgdG8gaW5jbHVkZSB0aGUgY2xpZW50IElELlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEhhc0NsaWVudElkIHtcblxuXHQvKipcblx0ICogVGhlIGNsaWVudCBJRCBmb3IgeW91ciBhcHBsaWNhdGlvbi5cblx0ICovXG5cdGNsaWVudElkOiBzdHJpbmc7XG5cbn1cblxuLyoqXG4gKiBUaGUgYmFzZSBpbnRlcmZhY2UgZm9yIGFsbCBhdXRoZW50aWNhdGlvbiBjbGllbnRzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEF1dGhDbGllbnQge1xuXG5cdC8qKlxuXHQgKiBDcmVhdGVzIHRoZSBhdXRob3JpemF0aW9uIFVSTC5cblx0ICpcblx0ICogQHBhcmFtIHBhcmFtcyBUaGUgYXV0aGVudGljYXRpb24gVVJMIHBhcmFtZXRlcnMuXG5cdCAqIEBwYXJhbSBbb3B0c10gVGhlIGF1dGhlbnRpY2F0aW9uIG9wdGlvbnMgdG8gYmUgdXNlZCB3aGVuIGdlbmVyYXRpbmcgdGhlIFVSTC5cblx0ICogQHJldHVybnMgVGhlIGF1dGhvcml6YXRpb24gVVJMLlxuXHQgKi9cblx0Y3JlYXRlQXV0aG9yaXphdGlvblVybChwYXJhbXM6IEF1dGhVcmxQYXJhbXMsIG9wdHM/OiBBdXRoT3B0aW9ucyk6IHN0cmluZztcblxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgY2xpZW50IHR5cGUuXG5cdCAqL1xuXHRnZXRUeXBlKCk6IHN0cmluZztcblxuXHQvKipcblx0ICogT2J0YWluIGEgZ3JhbnQgd2l0aCB0aGUgc3BlY2lmaWVkIHBhcmFtZXRlcnMuXG5cdCAqXG5cdCAqIFRoaXMgbWFrZXMgdGhlIFtBY2Nlc3MgVG9rZW4gUmVxdWVzdF0oaHR0cHM6Ly90b29scy5pZXRmLm9yZy9odG1sL3JmYzY3NDkjc2VjdGlvbi00LjEuMykgYXMgcGVyIHRoZSBPQXV0aCAyLjAgc3BlY2lmaWNhdGlvbi5cblx0ICpcblx0ICogQHBhcmFtIHBhcmFtcyBUaGUgZ3JhbnQgcGFyYW1ldGVycy5cblx0ICogQHBhcmFtIFtvcHRzXSBUaGUgZ3JhbnQgb3B0aW9ucyB0byBiZSB1c2VkLlxuXHQgKiBAcmV0dXJucyBUaGUgW0FjY2VzcyBUb2tlbiBSZXNwb25zZV0oaHR0cHM6Ly90b29scy5pZXRmLm9yZy9odG1sL3JmYzY3NDkjc2VjdGlvbi00LjEuNCkuXG5cdCAqL1xuXHRncmFudChwYXJhbXM6IEdyYW50UGFyYW1zLCBvcHRzPzogT0F1dGgyR3JhbnRPcHRpb25zKTogUHJvbWlzZTxBY2Nlc3NUb2tlblJlc3BvbnNlPjtcblxuXHQvKipcblx0ICogSW5pdGFsaXplIHRoZSBjbGllbnQgYnkgZGVmaW5pbmcgdGhlIGVuZHBvaW50cy5cblx0ICovXG5cdGluaXQoKTogUHJvbWlzZTx2b2lkPjtcblxuXHQvKipcblx0ICogSW50cm9zcGVjdCBhIHRva2VuLlxuXHQgKi9cblx0aW50cm9zcGVjdCh0b2tlbjogc3RyaW5nLCBwYXJhbXM6IEludHJvc3BlY3Rpb25QYXJhbXMsIG9wdHM/OiBJbnRyb3NwZWN0aW9uT3B0aW9ucyk6IFByb21pc2U8SW50cm9zcGVjdGlvblJlc3BvbnNlPjtcblxuXHQvKipcblx0ICogUmV2b2tlIGEgdG9rZW4uXG5cdCAqXG5cdCAqIFRoaXMgbWFrZXMgYSBbUmV2b2NhdGlvbiBSZXF1ZXN0XShodHRwczovL3Rvb2xzLmlldGYub3JnL2h0bWwvcmZjNzAwOSNzZWN0aW9uLTIuMSkgYXMgcGVyIHRoZSBPQXV0aCAyLjAgc3BlY2lmaWNhdGlvbi5cblx0ICpcblx0ICogQHBhcmFtIHRva2VuIFRoZSB0b2tlbiB0byBiZSByZXZva2VkLlxuXHQgKiBAcGFyYW0gW29wdHNdIFRoZSByZXZvY2F0aW9uIG9wdGlvbnMgdG8gYmUgdXNlZC5cblx0ICogQHJldHVybnMgSWYgdHJ1ZSB0aGUgdG9rZW4gaGFzIGJlZW4gcmV2b2tlZCBzdWNjZXNzZnVsbHkuXG5cdCAqL1xuXHRyZXZva2UodG9rZW46IHN0cmluZywgb3B0cz86IFJldm9jYXRpb25PcHRpb25zKTogUHJvbWlzZTxib29sZWFuPjtcblxufVxuXG5leHBvcnQgaW50ZXJmYWNlIEF1dGhDbGllbnRHcmFudFBhcmFtcyB7XG5cblx0LyoqXG5cdCAqIFRoZSBhc3NlcnRpb24gZm9yIHRoZSBKV1QgQmVhcmVyIGZsb3cuXG5cdCAqL1xuXHRhc3NlcnRpb24/OiBzdHJpbmc7XG5cblx0LyoqXG5cdCAqIFRoZSB0eXBlIG9mIHRoZSBjbGllbnQgYXNzZXJ0aW9uLlxuXHQgKlxuXHQgKiBUaGlzIGlzIGFsd2F5cyAqdXJuOmlldGY6cGFyYW1zOm9hdXRoOmNsaWVudC1hc3NlcnRpb24tdHlwZTpqd3QtYmVhcmVyKi5cblx0ICovXG5cdGNsaWVudF9hc3NlcnRpb25fdHlwZT86IHN0cmluZztcblxuXHQvKipcblx0ICogVGhlIGNsaWVudCBhc3NlcnRpb24uXG5cdCAqL1xuXHRjbGllbnRfYXNzZXJ0aW9uPzogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBUaGUgY2xpZW50IElEIGZvciB5b3VyIGFwcGxpY2F0aW9uLlxuXHQgKi9cblx0Y2xpZW50X2lkPzogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBUaGUgY2xpZW50IHNlY3JldCBmb3IgeW91ciBhcHBsaWNhdGlvbi5cblx0ICovXG5cdGNsaWVudF9zZWNyZXQ/OiBzdHJpbmc7XG5cblx0LyoqXG5cdCAqIEF1dGhvcml6YXRpb24gY29kZSB0aGF0IHRoZSBjb25zdW1lciBtdXN0IHVzZSB0byBvYnRhaW4gdGhlIGFjY2VzcyBhbmQgcmVmcmVzaCB0b2tlbnMuXG5cdCAqL1xuXHRjb2RlPzogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBUaGUgZ3JhbnQgdHlwZS5cblx0ICovXG5cdGdyYW50X3R5cGU/OiBzdHJpbmc7XG5cblx0LyoqXG5cdCAqIERldGVybWluZXMgd2hlcmUgdGhlIEFQSSBzZXJ2ZXIgcmVkaXJlY3RzIHRoZSB1c2VyIGFmdGVyIHRoZSB1c2VyIGNvbXBsZXRlcyB0aGVcblx0ICogYXV0aG9yaXphdGlvbiBmbG93LlxuXHQgKi9cblx0cmVkaXJlY3RfdXJpPzogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBUaGUgcmVmcmVzaCB0b2tlbi5cblx0ICovXG5cdHJlZnJlc2hfdG9rZW4/OiBzdHJpbmc7XG5cbn1cblxuLyoqXG4gKiBPcHRpb25hbCBwYXJhbWV0ZXJzIHVzZWQgd2hlbiByZXF1ZXN0aW5nIGdyYW50cy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBPQXV0aDJHcmFudE9wdGlvbnMge1xuXG5cdC8qKlxuXHQgKiBUaGUgY2xpZW50IHNlY3JldCBmb3IgeW91ciBhcHBsaWNhdGlvbi5cblx0ICpcblx0ICogRWl0aGVyIHRoaXMgdmFsdWUgb3IgdGhlIHNpZ25pbmdTZWNyZXQgc2hvdWxkIGJlIHNldCBmb3IgdGhlIGF1dGhvcml6YXRpb24gY29kZSBvciByZWZyZXNoIGZsb3dzLlxuXHQgKi9cblx0Y2xpZW50U2VjcmV0Pzogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBEZXRlcm1pbmVzIHdoZXJlIHRoZSBBUEkgc2VydmVyIHJlZGlyZWN0cyB0aGUgdXNlciBhZnRlciB0aGUgdXNlciBjb21wbGV0ZXMgdGhlXG5cdCAqIGF1dGhvcml6YXRpb24gZmxvdy5cblx0ICpcblx0ICogSXQgbXVzdCBiZSB0aGUgc2FtZSB2YWx1ZSBzZW50IGJ5IHRoZSBpbml0aWFsIHJlZGlyZWN0LlxuXHQgKi9cblx0cmVkaXJlY3RVcmk/OiBzdHJpbmc7XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIHJlc3BvbnNlIGZvcm1hdCwgZWl0aGVyIEpTT04sIFhNTCBvciBVUkxfRU5DT0RFRC5cblx0ICovXG5cdHJlc3BvbnNlRm9ybWF0PzogUmVzcG9uc2VGb3JtYXQ7XG5cbn1cblxuLyoqXG4gKiBSZXF1aXJlZCBwYXJhbWV0ZXJzIHdocm4gaW50cm9zcGVjdGluZyB0b2tlbnMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSW50cm9zcGVjdGlvblBhcmFtcyBleHRlbmRzIEhhc0NsaWVudElkIHtcblxuXHQvKipcblx0ICogVGhlIGNsaWVudCBzZWNyZXQgZm9yIHlvdXIgYXBwbGljYXRpb24uXG5cdCAqL1xuXHRjbGllbnRTZWNyZXQ/OiBzdHJpbmc7XG5cbn1cblxuLyoqXG4gKiBPcHRpb25hbCBwYXJhbWV0ZXJzIHVzZWQgd2hlbiBpbnRyb3NwZWN0aW5nIHRva2Vucy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJbnRyb3NwZWN0aW9uT3B0aW9ucyB7XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIHJlc3BvbnNlIGZvcm1hdCwgZWl0aGVyIEpTT04sIFhNTCBvciBVUkxfRU5DT0RFRC5cblx0ICovXG5cdHJlc3BvbnNlRm9ybWF0PzogUmVzcG9uc2VGb3JtYXQ7XG5cbn1cblxuLyoqXG4gKiBbSW50cm9zcGVjdGlvbiBSZXNwb25zZV0oaHR0cHM6Ly90b29scy5pZXRmLm9yZy9odG1sL3JmYzc2NjIjc2VjdGlvbi0yLjIpXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSW50cm9zcGVjdGlvblJlc3BvbnNlIGV4dGVuZHMgVXNlckluZm9SZXNwb25zZSB7XG5cblx0LyoqXG5cdCAqIEJvb2xlYW4gaW5kaWNhdG9yIG9mIHdoZXRoZXIgb3Igbm90IHRoZSBwcmVzZW50ZWQgdG9rZW4gaXMgY3VycmVudGx5IGFjdGl2ZS4gIFRoZVxuXHQgKiBzcGVjaWZpY3Mgb2YgYSB0b2tlbidzIFwiYWN0aXZlXCIgc3RhdGUgd2lsbCB2YXJ5IGRlcGVuZGluZyBvbiB0aGUgaW1wbGVtZW50YXRpb24gb2YgdGhlXG5cdCAqIGF1dGhvcml6YXRpb24gc2VydmVyIGFuZCB0aGUgaW5mb3JtYXRpb24gaXQga2VlcHMgYWJvdXQgaXRzIHRva2VucywgYnV0IGEgXCJ0cnVlXCIgdmFsdWVcblx0ICogcmV0dXJuIGZvciB0aGUgXCJhY3RpdmVcIiBwcm9wZXJ0eSB3aWxsIGdlbmVyYWxseSBpbmRpY2F0ZSB0aGF0IGEgZ2l2ZW4gdG9rZW4gaGFzIGJlZW5cblx0ICogaXNzdWVkIGJ5IHRoaXMgYXV0aG9yaXphdGlvbiBzZXJ2ZXIsIGhhcyBub3QgYmVlbiByZXZva2VkIGJ5IHRoZSByZXNvdXJjZSBvd25lciwgYW5kXG5cdCAqIGlzIHdpdGhpbiBpdHMgZ2l2ZW4gdGltZSB3aW5kb3cgb2YgdmFsaWRpdHkgKGUuZy4sIGFmdGVyIGl0cyBpc3N1YW5jZSB0aW1lIGFuZCBiZWZvcmUgaXRzXG5cdCAqIGV4cGlyYXRpb24gdGltZSkuXG5cdCAqL1xuXHRhY3RpdmU6IGJvb2xlYW47XG5cblx0LyoqXG5cdCAqIFNlcnZpY2Utc3BlY2lmaWMgc3RyaW5nIGlkZW50aWZpZXIgb3IgbGlzdCBvZiBzdHJpbmcgaWRlbnRpZmllcnMgcmVwcmVzZW50aW5nIHRoZSBpbnRlbmRlZFxuXHQgKiBhdWRpZW5jZSBmb3IgdGhpcyB0b2tlbiwgYXMgZGVmaW5lZCBpbiBKV1QuXG5cdCAqL1xuXHRhdWQ/OiBzdHJpbmc7XG5cblx0LyoqXG5cdCAqIENsaWVudCBpZGVudGlmaWVyIGZvciB0aGUgT0F1dGggMi4wIGNsaWVudCB0aGF0IHJlcXVlc3RlZCB0aGlzIHRva2VuLlxuXHQgKi9cblx0Y2xpZW50X2lkPzogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBJbnRlZ2VyIHRpbWVzdGFtcCwgbWVhc3VyZWQgaW4gdGhlIG51bWJlciBvZiBzZWNvbmRzIHNpbmNlIEphbnVhcnkgMSAxOTcwIFVUQyxcblx0ICogaW5kaWNhdGluZyB3aGVuIHRoaXMgdG9rZW4gd2lsbCBleHBpcmUsIGFzIGRlZmluZWQgaW4gSldULlxuXHQgKi9cblx0ZXhwPzogbnVtYmVyO1xuXG5cdC8qKlxuXHQgKiBJbnRlZ2VyIHRpbWVzdGFtcCwgbWVhc3VyZWQgaW4gdGhlIG51bWJlciBvZiBzZWNvbmRzIHNpbmNlIEphbnVhcnkgMSAxOTcwIFVUQyxcblx0ICogaW5kaWNhdGluZyB3aGVuIHRoaXMgdG9rZW4gd2FzIG9yaWdpbmFsbHkgaXNzdWVkLCBhcyBkZWZpbmVkIGluIEpXVC5cblx0ICovXG5cdGlhdD86IG51bWJlcjtcblxuXHQvKipcblx0ICogU3RyaW5nIHJlcHJlc2VudGluZyB0aGUgaXNzdWVyIG9mIHRoaXMgdG9rZW4sIGFzIGRlZmluZWQgaW4gSldULlxuXHQgKi9cblx0aXNzPzogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBTdHJpbmcgaWRlbnRpZmllciBmb3IgdGhlIHRva2VuLCBhcyBkZWZpbmVkIGluIEpXVC5cblx0ICovXG5cdGp0aT86IHN0cmluZztcblxuXHQvKipcblx0ICogSW50ZWdlciB0aW1lc3RhbXAsIG1lYXN1cmVkIGluIHRoZSBudW1iZXIgb2Ygc2Vjb25kcyBzaW5jZSBKYW51YXJ5IDEgMTk3MCBVVEMsXG5cdCAqIGluZGljYXRpbmcgd2hlbiB0aGlzIHRva2VuIGlzIG5vdCB0byBiZSB1c2VkIGJlZm9yZSwgYXMgZGVmaW5lZCBpbiBKV1QuXG5cdCAqL1xuXHRuYmY/OiBudW1iZXI7XG5cblx0LyoqXG5cdCAqIEEgSlNPTiBzdHJpbmcgY29udGFpbmluZyBhIHNwYWNlLXNlcGFyYXRlZCBsaXN0IG9mIHNjb3BlcyBhc3NvY2lhdGVkIHdpdGggdGhpcyB0b2tlbi5cblx0ICovXG5cdHNjb3BlPzogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBTdWJqZWN0IG9mIHRoZSB0b2tlbiwgYXMgZGVmaW5lZCBpbiBKV1QuIFVzdWFsbHkgYSBtYWNoaW5lLXJlYWRhYmxlIGlkZW50aWZpZXIgb2YgdGhlXG5cdCAqIHJlc291cmNlIG93bmVyIHdobyBhdXRob3JpemVkIHRoaXMgdG9rZW4uXG5cdCAqL1xuXHRzdWI/OiBzdHJpbmc7XG5cblx0LyoqXG5cdCAqIFR5cGUgb2YgdGhlIHRva2VuLlxuXHQgKi9cblx0dG9rZW5fdHlwZT86IHN0cmluZztcblxuXHQvKipcblx0ICogSHVtYW4tcmVhZGFibGUgaWRlbnRpZmllciBmb3IgdGhlIHJlc291cmNlIG93bmVyIHdobyBhdXRob3JpemVkIHRoaXMgdG9rZW4uXG5cdCAqL1xuXHR1c2VybmFtZT86IHN0cmluZztcblxufVxuXG4vKipcbiAqIFBhcmFtZXRlcnMgcmVxdWlyZWQgZm9yIHRoZSBbUmVmcmVzaCByZXF1ZXN0XShodHRwczovL29wZW5pZC5uZXQvc3BlY3Mvb3BlbmlkLWNvbm5lY3QtY29yZS0xXzAuaHRtbCNSZWZyZXNoaW5nQWNjZXNzVG9rZW4pLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJlZnJlc2hHcmFudFBhcmFtcyBleHRlbmRzIFJlZnJlc2hUb2tlbkdyYW50b3JQYXJhbXMge1xuXG5cdC8qKlxuXHQgKiBEZWZpbmVzIHRoaXMgZ3JhbnQgdHlwZS5cblx0ICovXG5cdGdyYW50VHlwZTogJ3JlZnJlc2hfdG9rZW4nO1xuXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVmcmVzaFRva2VuR3JhbnRvclBhcmFtcyBleHRlbmRzIFRva2VuR3JhbnRvclBhcmFtcyB7XG5cblx0LyoqXG5cdCAqIFRoZSByZWZyZXNoIHRva2VuLlxuXHQgKi9cblx0cmVmcmVzaFRva2VuOiBzdHJpbmc7XG5cbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXZvY2F0aW9uT3B0aW9ucyB7XG5cblx0LyoqXG5cdCAqIElmIHRydWUsIHVzZXMgYSBHRVQgcmF0aGVyIHRoYW4gUE9TVCByZXF1ZXN0IHRvIHJldm9rZSBhbiBhY2Nlc3MgdG9rZW4uXG5cdCAqL1xuXHR1c2VHZXQ/OiBib29sZWFuO1xuXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgVG9rZW5HcmFudG9yUGFyYW1zIGV4dGVuZHMgSGFzQ2xpZW50SWQge1xuXG5cdC8qKlxuXHQgKiBUaGUgY2xpZW50IHNlY3JldCBmb3IgeW91ciBhcHBsaWNhdGlvbi5cblx0ICovXG5cdGNsaWVudFNlY3JldD86IHN0cmluZztcblxufVxuXG5leHBvcnQgdHlwZSBHcmFudFBhcmFtcyA9IEF1dGhDb2RlR3JhbnRQYXJhbXMgfCBKd3RHcmFudFBhcmFtcyB8IFJlZnJlc2hHcmFudFBhcmFtcztcblxuY29uc3QgREVGQVVMVF9HUkFOVF9PUFRJT05TID0gT2JqZWN0LmZyZWV6ZSh7XG5cdGRlY29kZUlkVG9rZW46IHRydWUsXG5cdHBhcnNlVXNlckluZm86IHRydWUsXG5cdHJlc3BvbnNlRm9ybWF0OiAnYXBwbGljYXRpb24vanNvbicsXG5cdHZlcmlmeUlkVG9rZW46IHRydWUsXG5cdHZlcmlmeVNpZ25hdHVyZTogdHJ1ZVxufSk7XG5cbi8qKlxuICogIEFuIE9BdXRoIDIuMCBjbGllbnQgdGhhdCBpbXBsZW1lbnRzIHRoZSBbT0F1dGggMi4wIEF1dGhvcml6YXRpb24gRnJhbWV3b3JrXShodHRwczovL3Rvb2xzLmlldGYub3JnL2h0bWwvcmZjNjc0OSkgc3BlY2lmaWNhdGlvbi5cbiAqL1xuZXhwb3J0IGNsYXNzIE9BdXRoMkNsaWVudCBpbXBsZW1lbnRzIEF1dGhDbGllbnQge1xuXG5cdC8qKlxuXHQgKiBUaGUgZGVmYXVsdCBjb25maWd1cmF0aW9uIGZvciBhbiBBeGlvcyByZXF1ZXN0LlxuXHQgKi9cblx0cHVibGljIHN0YXRpYyByZWFkb25seSBERUZBVUxUX1JFUVVFU1RfQ09ORklHOiBBeGlvc1JlcXVlc3RDb25maWcgPSBPYmplY3QuZnJlZXplKHtcblx0XHR2YWxpZGF0ZVN0YXR1czogKCkgPT4gdHJ1ZVxuXHR9KTtcblxuXHQvKipcblx0ICogVGhlIGNsaWVudCBuYW1lLlxuXHQgKi9cblx0cHJvdGVjdGVkIGNsaWVudFR5cGU6IHN0cmluZztcblxuXHQvKipcblx0ICogW0F1dGhvcml6YXRpb24gRW5kcG9pbnRdKGh0dHBzOi8vdG9vbHMuaWV0Zi5vcmcvaHRtbC9yZmM2NzQ5I3NlY3Rpb24tMy4xKVxuXHQgKi9cblx0cHJvdGVjdGVkIGF1dGhvcml6YXRpb25FbmRwb2ludD86IHN0cmluZztcblxuXHQvKipcblx0ICogW0ludHJvc3BlY3Rpb24gRW5kcG9pbnRdKGh0dHBzOi8vdG9vbHMuaWV0Zi5vcmcvaHRtbC9yZmM3NjYyI3NlY3Rpb24tMilcblx0ICovXG5cdHByb3RlY3RlZCBpbnRyb3NwZWN0aW9uRW5kcG9pbnQ/OiBzdHJpbmcgfCBudWxsO1xuXG5cdC8qKlxuXHQgKiBbUmV2b2NhdGlvbiBFbmRwb2ludF0oaHR0cHM6Ly90b29scy5pZXRmLm9yZy9odG1sL3JmYzcwMDkjc2VjdGlvbi0yKVxuXHQgKi9cblx0cHJvdGVjdGVkIHRva2VuRW5kcG9pbnQ/OiBzdHJpbmc7XG5cblx0LyoqXG5cdCAqIFtSZXZvY2F0aW9uIEVuZHBvaW50XShodHRwczovL3Rvb2xzLmlldGYub3JnL2h0bWwvcmZjNzAwOSNzZWN0aW9uLTIpXG5cdCAqL1xuXHRwcm90ZWN0ZWQgcmV2b2NhdGlvbkVuZHBvaW50Pzogc3RyaW5nO1xuXG5cdC8qKlxuXHQgKiBUaGUgZW52aXJvbm1lbnQgcGFyYW1ldGVycyB1c2VkIGZvciB0aGlzIGNsaWVudC5cblx0ICovXG5cdHByb3RlY3RlZCByZWFkb25seSBlbnY6IFJlYWRvbmx5PEVudmlyb25tZW50PjtcblxuXHQvKipcblx0ICogQ3JlYXRlcyBhIG5ldyBPQXV0aDIgY2xpZW50IHdpdGggdGhlIGdpdmVuIGVudmlyb25tZW50LlxuXHQgKlxuXHQgKiBAcGFyYW0gZW52IFRoZSBPQXV0aDIgZW52aXJvbm1lbnQgcGFyYW1ldGVycy5cblx0ICovXG5cdGNvbnN0cnVjdG9yKGVudjogRW52aXJvbm1lbnQpIHtcblx0XHR0aGlzLmNsaWVudFR5cGUgPSAnT0F1dGgyJztcblx0XHR0aGlzLmVudiA9IE9iamVjdC5mcmVlemUoT2JqZWN0LmFzc2lnbih7fSwgZW52KSk7XG5cdH1cblxuXHQvKipcblx0ICogQGluaGVyaXRkb2Ncblx0ICovXG5cdHB1YmxpYyBhc3luYyBpbml0KCkge1xuXG5cdFx0aWYgKCF0aGlzLmVudi5hdXRob3JpemF0aW9uRW5kcG9pbnQpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcignTWlzc2luZyByZXF1aXJlZCBzdHJpbmcgcGFyYW1ldGVyOiBlbnZbYXV0aG9yaXphdGlvbkVuZHBvaW50XScpO1xuXHRcdH1cblxuXHRcdGlmICghdGhpcy5lbnYucmV2b2NhdGlvbkVuZHBvaW50KSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ01pc3NpbmcgcmVxdWlyZWQgc3RyaW5nIHBhcmFtZXRlcjogZW52W3Jldm9jYXRpb25FbmRwb2ludF0nKTtcblx0XHR9XG5cblx0XHRpZiAoIXRoaXMuZW52LnRva2VuRW5kcG9pbnQpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcignTWlzc2luZyByZXF1aXJlZCBzdHJpbmcgcGFyYW1ldGVyOiBlbnZbdG9rZW5FbmRwb2ludF0nKTtcblx0XHR9XG5cblx0XHR0aGlzLmF1dGhvcml6YXRpb25FbmRwb2ludCA9IHRoaXMuZW52LmF1dGhvcml6YXRpb25FbmRwb2ludDtcblx0XHR0aGlzLmludHJvc3BlY3Rpb25FbmRwb2ludCA9IHRoaXMuZW52LmludHJvc3BlY3Rpb25FbmRwb2ludCB8fCBudWxsO1xuXHRcdHRoaXMucmV2b2NhdGlvbkVuZHBvaW50ID0gdGhpcy5lbnYucmV2b2NhdGlvbkVuZHBvaW50O1xuXHRcdHRoaXMudG9rZW5FbmRwb2ludCA9IHRoaXMuZW52LnRva2VuRW5kcG9pbnQ7XG5cblx0fVxuXG5cdC8qKlxuXHQgKiBAaW5oZXJpdGRvY1xuXHQgKi9cblx0cHVibGljIGNyZWF0ZUF1dGhvcml6YXRpb25VcmwocGFyYW1zOiBBdXRoVXJsUGFyYW1zLCBvcHRzPzogQXV0aE9wdGlvbnMpIHtcblxuXHRcdGlmICghdGhpcy5hdXRob3JpemF0aW9uRW5kcG9pbnQpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcihgJHt0aGlzLmNsaWVudFR5cGV9IGNsaWVudCBoYXMgbm90IGJlZW4gaW5pdGlhbGl6ZWRgKTtcblx0XHR9XG5cblx0XHQvLyBUbyBhdm9pZCBhbnkgaW5hZHZlcnRlbnQgcGFyYW1ldGVyIGxlYWtzLCBjcmVhdGUgYSBuZXcgb2JqZWN0IGZyb20gd2hpY2ggdG8gZ2VuZXJhdGUgdGhlIHJlcXVlc3QuXG5cdFx0Y29uc3QgaW50ZXJuYWxPcHRzOiBBdXRoT3B0aW9ucyA9IHtcblx0XHRcdGRpc3BsYXk6IG9wdHMgJiYgb3B0cy5kaXNwbGF5LFxuXHRcdFx0aW1tZWRpYXRlOiBvcHRzICYmIG9wdHMuaW1tZWRpYXRlLFxuXHRcdFx0cHJvbXB0OiBvcHRzICYmIG9wdHMucHJvbXB0LFxuXHRcdFx0c3RhdGU6IG9wdHMgJiYgb3B0cy5zdGF0ZVxuXHRcdH07XG5cblx0XHRjb25zdCBpbnRlcm5hbFBhcmFtcyA9IHtcblx0XHRcdGNsaWVudF9pZDogcGFyYW1zLmNsaWVudElkLFxuXHRcdFx0cmVkaXJlY3RfdXJpOiBwYXJhbXMucmVkaXJlY3RVcmksXG5cdFx0XHRyZXNwb25zZV90eXBlOiAnY29kZScsXG5cdFx0XHRzY29wZTogcGFyYW1zLnNjb3BlXG5cdFx0fTtcblxuXHRcdGNvbnN0IGRhdGEgPSBPYmplY3QuYXNzaWduKHt9LCBpbnRlcm5hbFBhcmFtcywgaW50ZXJuYWxPcHRzKTtcblxuXHRcdGlmICghZGF0YS5jbGllbnRfaWQpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcignTWlzc2luZyByZXF1aXJlZCBzdHJpbmcgcGFyYW1ldGVyOiBjbGllbnRJZCcpO1xuXHRcdH1cblxuXHRcdGlmICghZGF0YS5yZWRpcmVjdF91cmkpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcignTWlzc2luZyByZXF1aXJlZCBzdHJpbmcgcGFyYW1ldGVyOiByZWRpcmVjdFVyaScpO1xuXHRcdH1cblxuXHRcdC8vIEVuY29kZSB0aGUgcGFyYW1ldGVycyBhbmQgdGhlbiByZXBsYWNlIGFueSBlbmNvZGVkIHNwYWNlcyAoKylcblx0XHQvLyB3aXRoIHRoZSB1cmwgdmVyc2lvbiAoJTIwKVxuXHRcdGNvbnN0IHF1ZXJ5ID0gZm9ybVVybGVuY29kZWQoZGF0YSwgeyBzb3J0ZWQ6IHRydWUgfSkucmVwbGFjZSgnKycsICclMjAnKTtcblx0XHRyZXR1cm4gYCR7dGhpcy5hdXRob3JpemF0aW9uRW5kcG9pbnR9PyR7cXVlcnl9YDtcblxuXHR9XG5cblx0LyoqXG5cdCAqIEBpbmhlcml0ZG9jXG5cdCAqL1xuXHRwdWJsaWMgYXN5bmMgZ3JhbnQocGFyYW1zOiBHcmFudFBhcmFtcywgb3B0cz86IE9BdXRoMkdyYW50T3B0aW9ucyk6IFByb21pc2U8QWNjZXNzVG9rZW5SZXNwb25zZT4ge1xuXG5cdFx0dGhpcy52YWxpZGF0ZUdyYW50UGFyYW1ldGVycyhwYXJhbXMpO1xuXG5cdFx0Ly8gVG8gYXZvaWQgYW55IGluYWR2ZXJ0ZW50IHBhcmFtZXRlciBsZWFrcywgY3JlYXRlICBhIG5ldyBvYmplY3QgdG8gZ2VuZXJhdGUgdGhlIHJlcXVlc3QgZnJvbS5cblx0XHRjb25zdCBpbnRlcm5hbE9wdHMgPSBPYmplY3QuYXNzaWduKHt9LCBERUZBVUxUX0dSQU5UX09QVElPTlMsIG9wdHMpO1xuXHRcdGNvbnN0IGludGVybmFsUGFyYW1zID0gYXdhaXQgdGhpcy5jcmVhdGVHcmFudEludGVybmFsUGFyYW1ldGVycyhwYXJhbXMsIGludGVybmFsT3B0cyk7XG5cblx0XHRjb25zdCBib2R5ID0gZm9ybVVybGVuY29kZWQoaW50ZXJuYWxQYXJhbXMsIHsgc29ydGVkOiB0cnVlIH0pO1xuXG5cdFx0Y29uc3QgY29uZmlnID0gT2JqZWN0LmFzc2lnbih7fSwgT0F1dGgyQ2xpZW50LkRFRkFVTFRfUkVRVUVTVF9DT05GSUcsIHtcblx0XHRcdGhlYWRlcnM6IHtcblx0XHRcdFx0J0FjY2VwdCc6IGludGVybmFsT3B0cy5yZXNwb25zZUZvcm1hdCxcblx0XHRcdFx0J0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQnXG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0XHRjb25zdCByZXNwb25zZSA9IGF3YWl0IGF4aW9zLnBvc3Q8QWNjZXNzVG9rZW5SZXNwb25zZSB8IEVycm9yUmVzcG9uc2U+KHRoaXMudG9rZW5FbmRwb2ludCEsIGJvZHksIGNvbmZpZyk7XG5cblx0XHRpZiAocmVzcG9uc2Uuc3RhdHVzICE9PSAyMDApIHtcblx0XHRcdGNvbnN0IGVycm9yID0gcmVzcG9uc2UuZGF0YSBhcyBFcnJvclJlc3BvbnNlO1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gb2J0YWluIGdyYW50OiAke2Vycm9yLmVycm9yfSAoJHtlcnJvci5lcnJvcl9kZXNjcmlwdGlvbn0pLmApO1xuXHRcdH1cblxuXHRcdGNvbnN0IGFjY2Vzc1Rva2VuUmVzcG9uc2UgPSByZXNwb25zZS5kYXRhIGFzIEFjY2Vzc1Rva2VuUmVzcG9uc2U7XG5cdFx0cmV0dXJuIHRoaXMuaGFuZGxlQWNjZXNzVG9rZW5SZXNwb25zZShhY2Nlc3NUb2tlblJlc3BvbnNlLCBpbnRlcm5hbE9wdHMpO1xuXG5cdH1cblxuXHQvKipcblx0ICogQGluaGVyaXRkb2Ncblx0ICovXG5cdHB1YmxpYyBhc3luYyBpbnRyb3NwZWN0KHRva2VuOiBzdHJpbmcsIHBhcmFtczogSW50cm9zcGVjdGlvblBhcmFtcywgb3B0cz86IEludHJvc3BlY3Rpb25PcHRpb25zKSB7XG5cblx0XHRpZiAodGhpcy5pbnRyb3NwZWN0aW9uRW5kcG9pbnQgPT09IHVuZGVmaW5lZCkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKGAke3RoaXMuY2xpZW50VHlwZX0gY2xpZW50IGhhcyBub3QgYmVlbiBpbml0aWFsaXplZGApO1xuXHRcdH1cblxuXHRcdGlmICh0aGlzLmludHJvc3BlY3Rpb25FbmRwb2ludCA9PT0gbnVsbCkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKGAke3RoaXMuY2xpZW50VHlwZX0gY2xpZW50IGRvZXMgbm90IHN1cHBvcnQgdG9rZW4gaW50cm9zcGVjdGlvbmApO1xuXHRcdH1cblxuXHRcdGlmICghcGFyYW1zLmNsaWVudElkKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoJ01pc3NpbmcgcmVxdWlyZWQgc3RyaW5nIHBhcmFtZXRlcjogY2xpZW50SWQnKTtcblx0XHR9XG5cblx0XHRpZiAoIXBhcmFtcy5jbGllbnRTZWNyZXQpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcignTWlzc2luZyByZXF1aXJlZCBzdHJpbmcgcGFyYW1ldGVyOiBjbGllbnRTZWNyZXQnKTtcblx0XHR9XG5cblx0XHRjb25zdCBjb25maWcgPSBPYmplY3QuYXNzaWduKHt9LCBPQXV0aDJDbGllbnQuREVGQVVMVF9SRVFVRVNUX0NPTkZJRywge1xuXHRcdFx0aGVhZGVyczoge1xuXHRcdFx0XHQnQWNjZXB0JzogKG9wdHMgJiYgb3B0cy5yZXNwb25zZUZvcm1hdCkgfHwgUmVzcG9uc2VGb3JtYXQuSlNPTixcblx0XHRcdFx0J0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQnXG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0XHRjb25zdCBpbnRlcm5hbE9wdHMgPSBPYmplY3QuYXNzaWduKHt9LCB7XG5cdFx0XHRwYXJzZVVzZXJJbmZvOiB0cnVlXG5cdFx0fSwgb3B0cyk7XG5cblx0XHRjb25zdCBib2R5ID0gZm9ybVVybGVuY29kZWQoe1xuXHRcdFx0Y2xpZW50X2lkOiBwYXJhbXMuY2xpZW50SWQsXG5cdFx0XHRjbGllbnRfc2VjcmV0OiBwYXJhbXMuY2xpZW50U2VjcmV0LFxuXHRcdFx0dG9rZW5cblx0XHR9KTtcblxuXHRcdGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgYXhpb3MucG9zdDxJbnRyb3NwZWN0aW9uUmVzcG9uc2UgfCBFcnJvclJlc3BvbnNlPih0aGlzLmludHJvc3BlY3Rpb25FbmRwb2ludCwgYm9keSwgY29uZmlnKTtcblx0XHRpZiAocmVzcG9uc2Uuc3RhdHVzICE9PSAyMDApIHtcblx0XHRcdGNvbnN0IGVycm9yID0gcmVzcG9uc2UuZGF0YSBhcyBFcnJvclJlc3BvbnNlO1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKGBGYWlsZWQgdG8gaW50cm9zcGVjdCB0b2tlbjogJHtlcnJvci5lcnJvcn0gKCR7ZXJyb3IuZXJyb3JfZGVzY3JpcHRpb259KS5gKTtcblx0XHR9XG5cblx0XHRjb25zdCBpbnRyb3NwZWN0aW9uUmVzcG9uc2UgPSByZXNwb25zZS5kYXRhIGFzIEludHJvc3BlY3Rpb25SZXNwb25zZTtcblx0XHRyZXR1cm4gdGhpcy5oYW5kbGVJbnRyb3NwZWN0aW9uUmVzcG9uc2UoaW50cm9zcGVjdGlvblJlc3BvbnNlLCBpbnRlcm5hbE9wdHMpO1xuXG5cdH1cblxuXHQvKipcblx0ICogQGluaGVyaXRkb2Ncblx0ICovXG5cdHB1YmxpYyBhc3luYyByZXZva2UodG9rZW46IHN0cmluZywgb3B0cz86IFJldm9jYXRpb25PcHRpb25zKSB7XG5cblx0XHRpZiAoIXRoaXMucmV2b2NhdGlvbkVuZHBvaW50KSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoYCR7dGhpcy5jbGllbnRUeXBlfSBjbGllbnQgaGFzIG5vdCBiZWVuIGluaXRpYWxpemVkYCk7XG5cdFx0fVxuXG5cdFx0Y29uc3QgaW50ZXJuYWxPcHRzID0gT2JqZWN0LmFzc2lnbih7XG5cdFx0XHR1c2VHZXQ6IGZhbHNlXG5cdFx0fSwgb3B0cyk7XG5cblx0XHRsZXQgcmVzcG9uc2U6IEF4aW9zUmVzcG9uc2U7XG5cdFx0bGV0IHJldm9jYXRpb25VcmkgPSB0aGlzLnJldm9jYXRpb25FbmRwb2ludDtcblxuXHRcdGlmIChpbnRlcm5hbE9wdHMudXNlR2V0KSB7XG5cdFx0XHRyZXZvY2F0aW9uVXJpICs9IGA/dG9rZW49JHt0b2tlbn1gO1xuXHRcdFx0cmVzcG9uc2UgPSBhd2FpdCBheGlvcy5nZXQocmV2b2NhdGlvblVyaSwgT0F1dGgyQ2xpZW50LkRFRkFVTFRfUkVRVUVTVF9DT05GSUcpO1xuXHRcdH0gZWxzZSB7XG5cblx0XHRcdGNvbnN0IGNvbmZpZyA9IE9iamVjdC5hc3NpZ24oe30sIE9BdXRoMkNsaWVudC5ERUZBVUxUX1JFUVVFU1RfQ09ORklHLCB7XG5cdFx0XHRcdGhlYWRlcnM6IHtcblx0XHRcdFx0XHQnQ29udGVudC1UeXBlJzogJ2FwcGxpY2F0aW9uL3gtd3d3LWZvcm0tdXJsZW5jb2RlZCdcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cblx0XHRcdGNvbnN0IGJvZHkgPSBmb3JtVXJsZW5jb2RlZCh7IHRva2VuIH0pO1xuXHRcdFx0cmVzcG9uc2UgPSBhd2FpdCBheGlvcy5wb3N0KHJldm9jYXRpb25VcmksIGJvZHksIGNvbmZpZyk7XG5cblx0XHR9XG5cblx0XHRyZXR1cm4gcmVzcG9uc2Uuc3RhdHVzID09PSAyMDA7XG5cblx0fVxuXG5cdC8qKlxuXHQgKiBAaW5oZXJpdGRvY1xuXHQgKi9cblx0cHVibGljIGdldFR5cGUoKSB7XG5cdFx0cmV0dXJuIHRoaXMuY2xpZW50VHlwZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBIYW5kbGUgdGhlIGFjY2VzcyB0b2tlbiByZXNwb25zZSwgcGVyZm9ybWluZyB2YWxpZGF0aW9uIGFuZCBwYXJzaW5nIGFzIGRlZmluZWQgaW4gdGhlIGdyYW50IG9wdGlvbnMuXG5cdCAqXG5cdCAqIEBwYXJhbSBhY2Nlc3NUb2tlblJlc3BvbnNlIFRoZSBhY2Nlc3MgdG9rZW4gcmVzcG9uc2UuXG5cdCAqIEBwYXJhbSBpbnRlcm5hbE9wdHM6IFRoZSBpbnRlcm5hbCBvcHRpb25zLlxuXHQgKi9cblx0cHJvdGVjdGVkIGhhbmRsZUFjY2Vzc1Rva2VuUmVzcG9uc2UoYWNjZXNzVG9rZW5SZXNwb25zZTogQWNjZXNzVG9rZW5SZXNwb25zZSwgaW50ZXJuYWxPcHRzOiBPQXV0aDJHcmFudE9wdGlvbnMpIHtcblx0XHRyZXR1cm4gYWNjZXNzVG9rZW5SZXNwb25zZTtcblx0fVxuXG5cdC8qKlxuXHQgKiBIYW5kbGUgdGhlIGludHJvc3BlY3Rpb24gcmVzcG9uc2UsIHBlcmZvcm1pbmcgdmFsaWRhdGlvbiBhbmQgcGFyc2luZyBhcyBkZWZpbmVkIGluIHRoZSBncmFudCBvcHRpb25zLlxuXHQgKlxuXHQgKiBAcGFyYW0gaW50cm9zcGVjdGlvblJlc3BvbnNlIFRoZSBhY2Nlc3MgdG9rZW4gcmVzcG9uc2UuXG5cdCAqIEBwYXJhbSBpbnRlcm5hbE9wdHM6IFRoZSBpbnRlcm5hbCBvcHRpb25zLlxuXHQgKi9cblx0cHJvdGVjdGVkIGhhbmRsZUludHJvc3BlY3Rpb25SZXNwb25zZShpbnRyb3NwZWN0aW9uUmVzcG9uc2U6IEludHJvc3BlY3Rpb25SZXNwb25zZSwgaW50ZXJuYWxPcHRzOiBJbnRyb3NwZWN0aW9uT3B0aW9ucykge1xuXHRcdHJldHVybiBpbnRyb3NwZWN0aW9uUmVzcG9uc2U7XG5cdH1cblxuXHQvKipcblx0ICogVXBkYXRlIHRoZSBpbnRlcm5hbCBncmFudCBwYXJhbWV0ZXJzIGlzIGFjY29yZGFuY2Ugd2l0aCB0aGUgc2VsZWN0ZWQgW2NsaWVudCBhdXRoZW50aWNhdGlvbl0oaHR0cHM6Ly9vcGVuaWQubmV0L3NwZWNzL29wZW5pZC1jb25uZWN0LWNvcmUtMV8wLmh0bWwjQ2xpZW50QXV0aGVudGljYXRpb24pXG5cdCAqIG1lY2hhbmlzbS5cblx0ICpcblx0ICogQHBhcmFtIHBhcmFtcyBUaGUgZ3JhbnQgcGFyYW1ldGVycy5cblx0ICogQHBhcmFtIGludGVybmFsUGFyYW1zIFRoZSBpbnRlcm5hbCBncmFudCBwYXJhbWV0ZXJzLlxuXHQgKiBAcGFyYW0gaW50ZXJuYWxPcHRzOiBUaGUgaW50ZXJuYWwgb3B0aW9ucy5cblx0ICovXG5cdHByb3RlY3RlZCBhc3luYyBoYW5kbGVDbGllbnRBdXRoZW50aWNhdGlvbihwYXJhbXM6IEdyYW50UGFyYW1zLCBpbnRlcm5hbFBhcmFtczogQXV0aENsaWVudEdyYW50UGFyYW1zLCBpbnRlcm5hbE9wdHM6IE9BdXRoMkdyYW50T3B0aW9ucykge1xuXG5cdFx0aWYgKCFwYXJhbXMuY2xpZW50SWQpIHtcblx0XHRcdHRocm93IG5ldyBFcnJvcignTWlzc2luZyByZXF1aXJlZCBzdHJpbmcgcGFyYW1ldGVyOiBjbGllbnRJZCcpO1xuXHRcdH1cblxuXHRcdGlmICghaW50ZXJuYWxPcHRzLmNsaWVudFNlY3JldCkge1xuXHRcdFx0dGhyb3cgbmV3IEVycm9yKCdNaXNzaW5nIHJlcXVpcmVkIHN0cmluZyBwYXJhbWV0ZXI6IGNsaWVudFNlY3JldCcpO1xuXHRcdH1cblxuXHRcdGludGVybmFsUGFyYW1zLmNsaWVudF9pZCA9IHBhcmFtcy5jbGllbnRJZDtcblx0XHRpbnRlcm5hbFBhcmFtcy5jbGllbnRfc2VjcmV0ID0gaW50ZXJuYWxPcHRzLmNsaWVudFNlY3JldDtcblxuXHR9XG5cblx0LyoqXG5cdCAqIFZhbG