atom-languageclient
Version:
Integrate Language Servers with Atom
551 lines • 73.8 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.LanguageClientConnection = void 0;
const lsp = require("vscode-languageserver-protocol");
const events_1 = require("events");
const logger_1 = require("./logger");
__exportStar(require("vscode-languageserver-protocol"), exports);
/**
* TypeScript wrapper around JSONRPC to implement Microsoft Language Server Protocol v3
* https://github.com/Microsoft/language-server-protocol/blob/master/protocol.md
*/
class LanguageClientConnection extends events_1.EventEmitter {
constructor(rpc, logger) {
super();
this._rpc = rpc;
this._log = logger || new logger_1.NullLogger();
this.setupLogging();
rpc.listen();
this.isConnected = true;
this._rpc.onClose(() => {
this.isConnected = false;
this._log.warn("rpc.onClose", "The RPC connection closed unexpectedly");
this.emit("close");
});
}
setupLogging() {
this._rpc.onError((error) => this._log.error(["rpc.onError", error]));
this._rpc.onUnhandledNotification((notification) => {
if (notification.method != null && notification.params != null) {
this._log.warn(`rpc.onUnhandledNotification ${notification.method}`, notification.params);
}
else {
this._log.warn("rpc.onUnhandledNotification", notification);
}
});
this._rpc.onNotification((...args) => this._log.debug("rpc.onNotification", args));
}
dispose() {
this._rpc.dispose();
}
/**
* Public: Initialize the language server with necessary {InitializeParams}.
*
* @param params The {InitializeParams} containing processId, rootPath, options and server capabilities.
* @returns A {Promise} containing the {InitializeResult} with details of the server's capabilities.
*/
initialize(params) {
return this._sendRequest(lsp.InitializeRequest.type, params);
}
/** Public: Send an `initialized` notification to the language server. */
initialized() {
this._sendNotification(lsp.InitializedNotification.type, {});
}
/** Public: Send a `shutdown` request to the language server. */
shutdown() {
return this._sendRequest(lsp.ShutdownRequest.type);
}
/** Public: Send an `exit` notification to the language server. */
exit() {
this._sendNotification(lsp.ExitNotification.type);
}
/**
* Public: Register a callback for a custom notification
*
* @param method A string containing the name of the message to listen for.
* @param callback The function to be called when the message is received. The payload from the message is passed to
* the function.
*/
onCustomNotification(method, callback) {
this._onNotification({ method }, callback);
}
/** @deprecated Use `onCustomNotification` method instead */
onCustom(method, callback) {
this.onCustomNotification(method, callback);
}
/**
* Public: Register a callback for a custom request
*
* @param method A string containing the name of the message to listen for.
* @param callback The function to be called when the message is received. The payload from the message is passed to
* the function.
*/
onCustomRequest(method, callback) {
this._onRequest({ method }, callback);
}
/**
* Public: Send a custom request
*
* @param method A string containing the name of the request message.
* @param params The method's parameters
*/
sendCustomRequest(method, params) {
return this._sendRequest(new lsp.ProtocolRequestType(method), params);
}
/**
* Public: Send a custom notification
*
* @param method A string containing the name of the notification message.
* @param params The method's parameters
*/
sendCustomNotification(method, params) {
this._sendNotification(new lsp.ProtocolNotificationType(method), params);
}
/**
* Public: Register a callback for the `window/showMessage` message.
*
* @param callback The function to be called when the `window/showMessage` message is received with
* {ShowMessageParams} being passed.
*/
onShowMessage(callback) {
this._onNotification({ method: "window/showMessage" }, callback);
}
/**
* Public: Register a callback for the `window/showMessageRequest` message.
*
* @param callback The function to be called when the `window/showMessageRequest` message is received with
* {ShowMessageRequestParam}' being passed.
* @returns A {Promise} containing the {MessageActionItem}.
*/
onShowMessageRequest(callback) {
this._onRequest({ method: "window/showMessageRequest" }, callback);
}
/**
* Public: Register a callback for the `window/showDocument` message.
*
* @param callback The function to be called when the `window/showDocument` message is received with
* {ShowDocumentParams} being passed.
*/
onShowDocument(callback) {
this._onRequest({ method: "window/showDocument" }, callback);
}
/**
* Public: Register a callback for the `window/logMessage` message.
*
* @param callback The function to be called when the `window/logMessage` message is received with {LogMessageParams}
* being passed.
*/
onLogMessage(callback) {
this._onNotification({ method: "window/logMessage" }, callback);
}
/**
* Public: Register a callback for the `telemetry/event` message.
*
* @param callback The function to be called when the `telemetry/event` message is received with any parameters
* received being passed on.
*/
onTelemetryEvent(callback) {
this._onNotification({ method: "telemetry/event" }, callback);
}
/**
* Public: Register a callback for the `workspace/applyEdit` message.
*
* @param callback The function to be called when the `workspace/applyEdit` message is received with
* {ApplyWorkspaceEditParams} being passed.
* @returns A {Promise} containing the {ApplyWorkspaceEditResponse}.
*/
onApplyEdit(callback) {
this._onRequest({ method: "workspace/applyEdit" }, callback);
}
/**
* Public: Send a `workspace/didChangeConfiguration` notification.
*
* @param params The {DidChangeConfigurationParams} containing the new configuration.
*/
didChangeConfiguration(params) {
this._sendNotification(lsp.DidChangeConfigurationNotification.type, params);
}
/**
* Public: Send a `textDocument/didOpen` notification.
*
* @param params The {DidOpenTextDocumentParams} containing the opened text document details.
*/
didOpenTextDocument(params) {
this._sendNotification(lsp.DidOpenTextDocumentNotification.type, params);
}
/**
* Public: Send a `textDocument/didChange` notification.
*
* @param params The {DidChangeTextDocumentParams} containing the changed text document details including the version
* number and actual text changes.
*/
didChangeTextDocument(params) {
this._sendNotification(lsp.DidChangeTextDocumentNotification.type, params);
}
/**
* Public: Send a `textDocument/didClose` notification.
*
* @param params The {DidCloseTextDocumentParams} containing the opened text document details.
*/
didCloseTextDocument(params) {
this._sendNotification(lsp.DidCloseTextDocumentNotification.type, params);
}
/**
* Public: Send a `textDocument/willSave` notification.
*
* @param params The {WillSaveTextDocumentParams} containing the to-be-saved text document details and the reason for the save.
*/
willSaveTextDocument(params) {
this._sendNotification(lsp.WillSaveTextDocumentNotification.type, params);
}
/**
* Public: Send a `textDocument/willSaveWaitUntil` notification.
*
* @param params The {WillSaveTextDocumentParams} containing the to-be-saved text document details and the reason for the save.
* @returns A {Promise} containing an {Array} of {TextEdit}s to be applied to the text document before it is saved.
*/
willSaveWaitUntilTextDocument(params) {
return this._sendRequest(lsp.WillSaveTextDocumentWaitUntilRequest.type, params);
}
/**
* Public: Send a `textDocument/didSave` notification.
*
* @param params The {DidSaveTextDocumentParams} containing the saved text document details.
*/
didSaveTextDocument(params) {
this._sendNotification(lsp.DidSaveTextDocumentNotification.type, params);
}
/**
* Public: Send a `workspace/didChangeWatchedFiles` notification.
*
* @param params The {DidChangeWatchedFilesParams} containing the array of {FileEvent}s that have been observed upon
* the watched files.
*/
didChangeWatchedFiles(params) {
this._sendNotification(lsp.DidChangeWatchedFilesNotification.type, params);
}
/**
* Public: Register a callback for the `workspace.workspaceFolders` request. This request is sent from the server to
* Atom to fetch the current open list of workspace folders
*
* @param A Callback which returns a {Promise} containing an {Array} of {lsp.WorkspaceFolder[]} or {null} if only a
* single file is open in the tool.
*/
onWorkspaceFolders(callback) {
return this._onRequest(lsp.WorkspaceFoldersRequest.type, callback);
}
/**
* Public: Send a `workspace/didChangeWorkspaceFolders` notification.
*
* @param {DidChangeWorkspaceFoldersParams} params An object that contains the actual workspace folder change event
* ({WorkspaceFoldersChangeEvent}) in its {event} property
*/
didChangeWorkspaceFolders(params) {
this._sendNotification(lsp.DidChangeWorkspaceFoldersNotification.type, params);
}
/**
* Public: Register a callback for the `textDocument/publishDiagnostics` message.
*
* @param callback The function to be called when the `textDocument/publishDiagnostics` message is received a
* {PublishDiagnosticsParams} containing new {Diagnostic} messages for a given uri.
*/
onPublishDiagnostics(callback) {
this._onNotification({ method: "textDocument/publishDiagnostics" }, callback);
}
/**
* Public: Send a `textDocument/completion` request.
*
* @param params The {TextDocumentPositionParams} or {CompletionParams} for which {CompletionItem}s are desired.
* @param cancellationToken The {CancellationToken} that is used to cancel this request if necessary.
* @returns A {Promise} containing either a {CompletionList} or an {Array} of {CompletionItem}s.
*/
completion(params, cancellationToken) {
// Cancel prior request if necessary
return this._sendRequest(lsp.CompletionRequest.type, params, cancellationToken);
}
/**
* Public: Send a `completionItem/resolve` request.
*
* @param params The {CompletionItem} for which a fully resolved {CompletionItem} is desired.
* @returns A {Promise} containing a fully resolved {CompletionItem}.
*/
completionItemResolve(params) {
return this._sendRequest(lsp.CompletionResolveRequest.type, params);
}
/**
* Public: Send a `textDocument/hover` request.
*
* @param params The {TextDocumentPositionParams} for which a {Hover} is desired.
* @returns A {Promise} containing a {Hover}.
*/
hover(params) {
return this._sendRequest(lsp.HoverRequest.type, params);
}
/**
* Public: Send a `textDocument/signatureHelp` request.
*
* @param params The {TextDocumentPositionParams} for which a {SignatureHelp} is desired.
* @returns A {Promise} containing a {SignatureHelp}.
*/
signatureHelp(params) {
return this._sendRequest(lsp.SignatureHelpRequest.type, params);
}
/**
* Public: Send a `textDocument/definition` request.
*
* @param params The {TextDocumentPositionParams} of a symbol for which one or more {Location}s that define that
* symbol are required.
* @returns A {Promise} containing either a single {Location} or an {Array} of many {Location}s.
*/
gotoDefinition(params) {
return this._sendRequest(lsp.DefinitionRequest.type, params);
}
/**
* Public: Send a `textDocument/references` request.
*
* @param params The {TextDocumentPositionParams} of a symbol for which all referring {Location}s are desired.
* @returns A {Promise} containing an {Array} of {Location}s that reference this symbol.
*/
findReferences(params) {
return this._sendRequest(lsp.ReferencesRequest.type, params);
}
/**
* Public: Send a `textDocument/documentHighlight` request.
*
* @param params The {TextDocumentPositionParams} of a symbol for which all highlights are desired.
* @returns A {Promise} containing an {Array} of {DocumentHighlight}s that can be used to highlight this symbol.
*/
documentHighlight(params) {
return this._sendRequest(lsp.DocumentHighlightRequest.type, params);
}
/**
* Public: Send a `textDocument/documentSymbol` request.
*
* @param params The {DocumentSymbolParams} that identifies the document for which symbols are desired.
* @param cancellationToken The {CancellationToken} that is used to cancel this request if necessary.
* @returns A {Promise} containing an {Array} of {SymbolInformation}s that can be used to navigate this document.
*/
documentSymbol(params, _cancellationToken) {
return this._sendRequest(lsp.DocumentSymbolRequest.type, params);
}
/**
* Public: Send a `workspace/symbol` request.
*
* @param params The {WorkspaceSymbolParams} containing the query string to search the workspace for.
* @returns A {Promise} containing an {Array} of {SymbolInformation}s that identify where the query string occurs
* within the workspace.
*/
workspaceSymbol(params) {
return this._sendRequest(lsp.WorkspaceSymbolRequest.type, params);
}
/**
* Public: Send a `textDocument/codeAction` request.
*
* @param params The {CodeActionParams} identifying the document, range and context for the code action.
* @returns A {Promise} containing an {Array} of {Command}s or {CodeAction}s that can be performed against the given
* documents range.
*/
codeAction(params) {
return this._sendRequest(lsp.CodeActionRequest.type, params);
}
/**
* Public: Send a `codeAction/resolve` request.
*
* @param params The {CodeAction} whose properties (e.g. `edit`) are to be resolved.
* @returns A resolved {CodeAction} that can be applied immediately.
*/
codeActionResolve(params) {
return this._sendRequest(lsp.CodeActionResolveRequest.type, params);
}
/**
* Public: Send a `textDocument/codeLens` request.
*
* @param params The {CodeLensParams} identifying the document for which code lens commands are desired.
* @returns A {Promise} containing an {Array} of {CodeLens}s that associate commands and data with specified ranges
* within the document.
*/
codeLens(params) {
return this._sendRequest(lsp.CodeLensRequest.type, params);
}
/**
* Public: Send a `codeLens/resolve` request.
*
* @param params The {CodeLens} identifying the code lens to be resolved with full detail.
* @returns A {Promise} containing the {CodeLens} fully resolved.
*/
codeLensResolve(params) {
return this._sendRequest(lsp.CodeLensResolveRequest.type, params);
}
/**
* Public: Send a `textDocument/documentLink` request.
*
* @param params The {DocumentLinkParams} identifying the document for which links should be identified.
* @returns A {Promise} containing an {Array} of {DocumentLink}s relating uri's to specific ranges within the document.
*/
documentLink(params) {
return this._sendRequest(lsp.DocumentLinkRequest.type, params);
}
/**
* Public: Send a `documentLink/resolve` request.
*
* @param params The {DocumentLink} identifying the document link to be resolved with full detail.
* @returns A {Promise} containing the {DocumentLink} fully resolved.
*/
documentLinkResolve(params) {
return this._sendRequest(lsp.DocumentLinkResolveRequest.type, params);
}
/**
* Public: Send a `textDocument/formatting` request.
*
* @param params The {DocumentFormattingParams} identifying the document to be formatted as well as additional
* formatting preferences.
* @returns A {Promise} containing an {Array} of {TextEdit}s to be applied to the document to correctly reformat it.
*/
documentFormatting(params) {
return this._sendRequest(lsp.DocumentFormattingRequest.type, params);
}
/**
* Public: Send a `textDocument/rangeFormatting` request.
*
* @param params The {DocumentRangeFormattingParams} identifying the document and range to be formatted as well as
* additional formatting preferences.
* @returns A {Promise} containing an {Array} of {TextEdit}s to be applied to the document to correctly reformat it.
*/
documentRangeFormatting(params) {
return this._sendRequest(lsp.DocumentRangeFormattingRequest.type, params);
}
/**
* Public: Send a `textDocument/onTypeFormatting` request.
*
* @param params The {DocumentOnTypeFormattingParams} identifying the document to be formatted, the character that was
* typed and at what position as well as additional formatting preferences.
* @returns A {Promise} containing an {Array} of {TextEdit}s to be applied to the document to correctly reformat it.
*/
documentOnTypeFormatting(params) {
return this._sendRequest(lsp.DocumentOnTypeFormattingRequest.type, params);
}
/**
* Public: Send a `textDocument/rename` request.
*
* @param params The {RenameParams} identifying the document containing the symbol to be renamed, as well as the
* position and new name.
* @returns A {Promise} containing an {WorkspaceEdit} that contains a list of {TextEdit}s either on the changes
* property (keyed by uri) or the documentChanges property containing an {Array} of {TextDocumentEdit}s (preferred).
*/
rename(params) {
return this._sendRequest(lsp.RenameRequest.type, params);
}
/**
* Public: Send a `workspace/executeCommand` request.
*
* @param params The {ExecuteCommandParams} specifying the command and arguments the language server should execute
* (these commands are usually from {CodeLens} or {CodeAction} responses).
* @returns A {Promise} containing anything.
*/
executeCommand(params) {
return this._sendRequest(lsp.ExecuteCommandRequest.type, params);
}
/**
* Public: Send a `textDocument/prepareCallHierarchy` request.
*
* @param params The {CallHierarchyIncomingCallsParams} that containing {textDocument} and {position} associated with
* the calling.
* @param cancellationToken The {CancellationToken} that is used to cancel this request if necessary.
* @returns A {Promise} containing an {Array} of {CallHierarchyItem}s that corresponding to the request.
*/
prepareCallHierarchy(params, _cancellationToken) {
return this._sendRequest(lsp.CallHierarchyPrepareRequest.type, params);
}
/**
* Public: Send a `callHierarchy/incomingCalls` request.
*
* @param params The {CallHierarchyIncomingCallsParams} that identifies {CallHierarchyItem} to get incoming calls.
* @param cancellationToken The {CancellationToken} that is used to cancel this request if necessary.
* @returns A {Promise} containing an {Array} of {CallHierarchyIncomingCall}s for the function that called by the
* function given to the parameter.
*/
callHierarchyIncomingCalls(params, _cancellationToken) {
return this._sendRequest(lsp.CallHierarchyIncomingCallsRequest.type, params);
}
/**
* Public: Send a `callHierarchy/outgoingCalls` request.
*
* @param params The {CallHierarchyOutgoingCallsParams} that identifies {CallHierarchyItem} to get outgoing calls.
* @param cancellationToken The {CancellationToken} that is used to cancel this request if necessary.
* @returns A {Promise} containing an {Array} of {CallHierarchyIncomingCall}s for the function that calls the function
* given to the parameter.
*/
callHierarchyOutgoingCalls(params, _cancellationToken) {
return this._sendRequest(lsp.CallHierarchyOutgoingCallsRequest.type, params);
}
_onRequest(type, callback) {
this._rpc.onRequest(type.method, (value) => {
this._log.debug(`rpc.onRequest ${type.method}`, value);
return callback(value);
});
}
_onNotification(type, callback) {
this._rpc.onNotification(type.method, (value) => {
this._log.debug(`rpc.onNotification ${type.method}`, value);
callback(value);
});
}
_sendNotification(protocol, args) {
const { method } = protocol;
this._log.debug(`rpc.sendNotification ${method}`, args);
this._rpc.sendNotification(method, args);
}
_sendRequest(protocol, args, cancellationToken) {
return __awaiter(this, void 0, void 0, function* () {
const { method } = protocol;
this._log.debug(`rpc.sendRequest ${method} sending`, args);
try {
const start = performance.now();
let result;
if (cancellationToken) {
result = yield this._rpc.sendRequest(method, args, cancellationToken);
}
else {
// If cancellationToken is null or undefined, don't add the third
// argument otherwise vscode-jsonrpc will send an additional, null
// message parameter to the request
result = yield this._rpc.sendRequest(method, args);
}
const took = performance.now() - start;
this._log.debug(`rpc.sendRequest ${method} received (${Math.floor(took)}ms)`, result);
return result;
}
catch (e) {
const responseError = e;
if (cancellationToken && responseError.code === lsp.LSPErrorCodes.RequestCancelled) {
this._log.debug(`rpc.sendRequest ${method} was cancelled`);
}
else {
this._log.error(`rpc.sendRequest ${method} threw`, e);
}
throw e;
}
});
}
}
exports.LanguageClientConnection = LanguageClientConnection;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGFuZ3VhZ2VjbGllbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9saWIvbGFuZ3VhZ2VjbGllbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUNBLHNEQUFxRDtBQUNyRCxtQ0FBcUM7QUFDckMscUNBQTZDO0FBRTdDLGlFQUE4QztBQXNCOUM7OztHQUdHO0FBQ0gsTUFBYSx3QkFBeUIsU0FBUSxxQkFBWTtJQUt4RCxZQUFZLEdBQThCLEVBQUUsTUFBZTtRQUN6RCxLQUFLLEVBQUUsQ0FBQTtRQUNQLElBQUksQ0FBQyxJQUFJLEdBQUcsR0FBRyxDQUFBO1FBQ2YsSUFBSSxDQUFDLElBQUksR0FBRyxNQUFNLElBQUksSUFBSSxtQkFBVSxFQUFFLENBQUE7UUFDdEMsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFBO1FBQ25CLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQTtRQUVaLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFBO1FBQ3ZCLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRTtZQUNyQixJQUFJLENBQUMsV0FBVyxHQUFHLEtBQUssQ0FBQTtZQUN4QixJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsd0NBQXdDLENBQUMsQ0FBQTtZQUN2RSxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFBO1FBQ3BCLENBQUMsQ0FBQyxDQUFBO0lBQ0osQ0FBQztJQUVPLFlBQVk7UUFDbEIsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsYUFBYSxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQTtRQUNyRSxJQUFJLENBQUMsSUFBSSxDQUFDLHVCQUF1QixDQUFDLENBQUMsWUFBWSxFQUFFLEVBQUU7WUFDakQsSUFBSSxZ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QUFhLENBQUMsZ0JBQWdCLEVBQUU7b0JBQ2xGLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLG1CQUFtQixNQUFNLGdCQUFnQixDQUFDLENBQUE7aUJBQzNEO3FCQUFNO29CQUNMLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLG1CQUFtQixNQUFNLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQTtpQkFDdEQ7Z0JBRUQsTUFBTSxDQUFDLENBQUE7YUFDUjtRQUNILENBQUM7S0FBQTtDQUNGO0FBbm1CRCw0REFtbUJDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMganNvbnJwYyBmcm9tIFwidnNjb2RlLWpzb25ycGNcIlxuaW1wb3J0ICogYXMgbHNwIGZyb20gXCJ2c2NvZGUtbGFuZ3VhZ2VzZXJ2ZXItcHJvdG9jb2xcIlxuaW1wb3J0IHsgRXZlbnRFbWl0dGVyIH0gZnJvbSBcImV2ZW50c1wiXG5pbXBvcnQgeyBOdWxsTG9nZ2VyLCBMb2dnZXIgfSBmcm9tIFwiLi9sb2dnZXJcIlxuXG5leHBvcnQgKiBmcm9tIFwidnNjb2RlLWxhbmd1YWdlc2VydmVyLXByb3RvY29sXCJcblxuZXhwb3J0IGludGVyZmFjZSBLbm93bk5vdGlmaWNhdGlvbnMge1xuICBcInRleHREb2N1bWVudC9wdWJsaXNoRGlhZ25vc3RpY3NcIjogbHNwLlB1Ymxpc2hEaWFnbm9zdGljc1BhcmFtc1xuICBcInRlbGVtZXRyeS9ldmVudFwiOiBhbnlcbiAgXCJ3aW5kb3cvbG9nTWVzc2FnZVwiOiBsc3AuTG9nTWVzc2FnZVBhcmFtc1xuICBcIndpbmRvdy9zaG93TWVzc2FnZVJlcXVlc3RcIjogbHNwLlNob3dNZXNzYWdlUmVxdWVzdFBhcmFtc1xuICBcIndpbmRvdy9zaG93TWVzc2FnZVwiOiBsc3AuU2hvd01lc3NhZ2VQYXJhbXNcbiAgW2N1c3RvbTogc3RyaW5nXTogb2JqZWN0XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgS25vd25SZXF1ZXN0cyB7XG4gIFwid2luZG93L3Nob3dEb2N1bWVudFwiOiBbbHNwLlNob3dEb2N1bWVudFBhcmFtcywgbHNwLlNob3dEb2N1bWVudFJlc3VsdF1cbiAgXCJ3aW5kb3cvc2hvd01lc3NhZ2VSZXF1ZXN0XCI6IFtsc3AuU2hvd01lc3NhZ2VSZXF1ZXN0UGFyYW1zLCBsc3AuTWVzc2FnZUFjdGlvbkl0ZW0gfCBudWxsXVxuICBcIndvcmtzcGFjZS9hcHBseUVkaXRcIjogW2xzcC5BcHBseVdvcmtzcGFjZUVkaXRQYXJhbXMsIGxzcC5BcHBseVdvcmtzcGFjZUVkaXRSZXNwb25zZV1cbiAgW2N1c3RvbTogc3RyaW5nXTogW1JlY29yZDxzdHJpbmcsIGFueT4sIFJlY29yZDxzdHJpbmcsIGFueT4gfCBudWxsXVxufVxuXG5leHBvcnQgdHlwZSBSZXF1ZXN0Q2FsbGJhY2s8VCBleHRlbmRzIGtleW9mIEtub3duUmVxdWVzdHM+ID0gS25vd25SZXF1ZXN0c1tUXSBleHRlbmRzIFtpbmZlciBVLCBpbmZlciBWXVxuICA/IChwYXJhbTogVSkgPT4gUHJvbWlzZTxWPlxuICA6IG5ldmVyXG5cbi8qKlxuICogVHlwZVNjcmlwdCB3cmFwcGVyIGFyb3VuZCBKU09OUlBDIHRvIGltcGxlbWVudCBNaWNyb3NvZnQgTGFuZ3VhZ2UgU2VydmVyIFByb3RvY29sIHYzXG4gKiBodHRwczovL2dpdGh1Yi5jb20vTWljcm9zb2Z0L2xhbmd1YWdlLXNlcnZlci1wcm90b2NvbC9ibG9iL21hc3Rlci9wcm90b2NvbC5tZFxuICovXG5leHBvcnQgY2xhc3MgTGFuZ3VhZ2VDbGllbnRDb25uZWN0aW9uIGV4dGVuZHMgRXZlbnRFbWl0dGVyIHtcbiAgcHJpdmF0ZSBfcnBjOiBqc29ucnBjLk1lc3NhZ2VDb25uZWN0aW9uXG4gIHByaXZhdGUgX2xvZzogTG9nZ2VyXG4gIHB1YmxpYyBpc0Nvbm5lY3RlZDogYm9vbGVhblxuXG4gIGNvbnN0cnVjdG9yKHJwYzoganNvbnJwYy5NZXNzYWdlQ29ubmVjdGlvbiwgbG9nZ2VyPzogTG9nZ2VyKSB7XG4gICAgc3VwZXIoKVxuICAgIHRoaXMuX3JwYyA9IHJwY1xuICAgIHRoaXMuX2xvZyA9IGxvZ2dlciB8fCBuZXcgTnVsbExvZ2dlcigpXG4gICAgdGhpcy5zZXR1cExvZ2dpbmcoKVxuICAgIHJwYy5saXN0ZW4oKVxuXG4gICAgdGhpcy5pc0Nvbm5lY3RlZCA9IHRydWVcbiAgICB0aGlzLl9ycGMub25DbG9zZSgoKSA9PiB7XG4gICAgICB0aGlzLmlzQ29ubmVjdGVkID0gZmFsc2VcbiAgICAgIHRoaXMuX2xvZy53YXJuKFwicnBjLm9uQ2xvc2VcIiwgXCJUaGUgUlBDIGNvbm5lY3Rpb24gY2xvc2VkIHVuZXhwZWN0ZWRseVwiKVxuICAgICAgdGhpcy5lbWl0KFwiY2xvc2VcIilcbiAgICB9KVxuICB9XG5cbiAgcHJpdmF0ZSBzZXR1cExvZ2dpbmcoKTogdm9pZCB7XG4gICAgdGhpcy5fcnBjLm9uRXJyb3IoKGVycm9yKSA9PiB0aGlzLl9sb2cuZXJyb3IoW1wicnBjLm9uRXJyb3JcIiwgZXJyb3JdKSlcbiAgICB0aGlzLl9ycGMub25VbmhhbmRsZWROb3RpZmljYXRpb24oKG5vdGlmaWNhdGlvbikgPT4ge1xuICAgICAgaWYgKG5vdGlmaWNhdGlvbi5tZXRob2QgIT0gbnVsbCAmJiBub3RpZmljYXRpb24ucGFyYW1zICE9IG51bGwpIHtcbiAgICAgICAgdGhpcy5fbG9nLndhcm4oYHJwYy5vblVuaGFuZGxlZE5vdGlmaWNhdGlvbiAke25vdGlmaWNhdGlvbi5tZXRob2R9YCwgbm90aWZpY2F0aW9uLnBhcmFtcylcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuX2xvZy53YXJuKFwicnBjLm9uVW5oYW5kbGVkTm90aWZpY2F0aW9uXCIsIG5vdGlmaWNhdGlvbilcbiAgICAgIH1cbiAgICB9KVxuICAgIHRoaXMuX3JwYy5vbk5vdGlmaWNhdGlvbigoLi4uYXJnczogYW55W10pID0+IHRoaXMuX2xvZy5kZWJ1ZyhcInJwYy5vbk5vdGlmaWNhdGlvblwiLCBhcmdzKSlcbiAgfVxuXG4gIHB1YmxpYyBkaXNwb3NlKCk6IHZvaWQge1xuICAgIHRoaXMuX3JwYy5kaXNwb3NlKClcbiAgfVxuXG4gIC8qKlxuICAgKiBQdWJsaWM6IEluaXRpYWxpemUgdGhlIGxhbmd1YWdlIHNlcnZlciB3aXRoIG5lY2Vzc2FyeSB7SW5pdGlhbGl6ZVBhcmFtc30uXG4gICAqXG4gICAqIEBwYXJhbSBwYXJhbXMgVGhlIHtJbml0aWFsaXplUGFyYW1zfSBjb250YWluaW5nIHByb2Nlc3NJZCwgcm9vdFBhdGgsIG9wdGlvbnMgYW5kIHNlcnZlciBjYXBhYmlsaXRpZXMuXG4gICAqIEByZXR1cm5zIEEge1Byb21pc2V9IGNvbnRhaW5pbmcgdGhlIHtJbml0aWFsaXplUmVzdWx0fSB3aXRoIGRldGFpbHMgb2YgdGhlIHNlcnZlcidzIGNhcGFiaWxpdGllcy5cbiAgICovXG4gIHB1YmxpYyBpbml0aWFsaXplKHBhcmFtczogbHNwLkluaXRpYWxpemVQYXJhbXMpOiBQcm9taXNlPGxzcC5Jbml0aWFsaXplUmVzdWx0PiB7XG4gICAgcmV0dXJuIHRoaXMuX3NlbmRSZXF1ZXN0KGxzcC5Jbml0aWFsaXplUmVxdWVzdC50eXBlLCBwYXJhbXMpXG4gIH1cblxuICAvKiogUHVibGljOiBTZW5kIGFuIGBpbml0aWFsaXplZGAgbm90aWZpY2F0aW9uIHRvIHRoZSBsYW5ndWFnZSBzZXJ2ZXIuICovXG4gIHB1YmxpYyBpbml0aWFsaXplZCgpOiB2b2lkIHtcbiAgICB0aGlzLl9zZW5kTm90aWZpY2F0aW9uKGxzcC5Jbml0aWFsaXplZE5vdGlmaWNhdGlvbi50eXBlLCB7fSlcbiAgfVxuXG4gIC8qKiBQdWJsaWM6IFNlbmQgYSBgc2h1dGRvd25gIHJlcXVlc3QgdG8gdGhlIGxhbmd1YWdlIHNlcnZlci4gKi9cbiAgcHVibGljIHNodXRkb3duKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiB0aGlzLl9zZW5kUmVxdWVzdChsc3AuU2h1dGRvd25SZXF1ZXN0LnR5cGUpXG4gIH1cblxuICAvKiogUHVibGljOiBTZW5kIGFuIGBleGl0YCBub3RpZmljYXRpb24gdG8gdGhlIGxhbmd1YWdlIHNlcnZlci4gKi9cbiAgcHVibGljIGV4aXQoKTogdm9pZCB7XG4gICAgdGhpcy5fc2VuZE5vdGlmaWNhdGlvbihsc3AuRXhpdE5vdGlmaWNhdGlvbi50eXBlKVxuICB9XG5cbiAgLyoqXG4gICAqIFB1YmxpYzogUmVnaXN0ZXIgYSBjYWxsYmFjayBmb3IgYSBjdXN0b20gbm90aWZpY2F0aW9uXG4gICAqXG4gICAqIEBwYXJhbSBtZXRob2QgQSBzdHJpbmcgY29udGFpbmluZyB0aGUgbmFtZSBvZiB0aGUgbWVzc2FnZSB0byBsaXN0ZW4gZm9yLlxuICAgKiBAcGFyYW0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBtZXNzYWdlIGlzIHJlY2VpdmVkLiBUaGUgcGF5bG9hZCBmcm9tIHRoZSBtZXNzYWdlIGlzIHBhc3NlZCB0b1xuICAgKiAgIHRoZSBmdW5jdGlvbi5cbiAgICovXG4gIHB1YmxpYyBvbkN1c3RvbU5vdGlmaWNhdGlvbihtZXRob2Q6IHN0cmluZywgY2FsbGJhY2s6IChvYmo6IG9iamVjdCkgPT4gdm9pZCk6IHZvaWQge1xuICAgIHRoaXMuX29uTm90aWZpY2F0aW9uKHsgbWV0aG9kIH0sIGNhbGxiYWNrKVxuICB9XG5cbiAgLyoqIEBkZXByZWNhdGVkIFVzZSBgb25DdXN0b21Ob3RpZmljYXRpb25gIG1ldGhvZCBpbnN0ZWFkICovXG4gIHB1YmxpYyBvbkN1c3RvbShtZXRob2Q6IHN0cmluZywgY2FsbGJhY2s6IChvYmo6IG9iamVjdCkgPT4gdm9pZCk6IHZvaWQge1xuICAgIHRoaXMub25DdXN0b21Ob3RpZmljYXRpb24obWV0aG9kLCBjYWxsYmFjaylcbiAgfVxuXG4gIC8qKlxuICAgKiBQdWJsaWM6IFJlZ2lzdGVyIGEgY2FsbGJhY2sgZm9yIGEgY3VzdG9tIHJlcXVlc3RcbiAgICpcbiAgICogQHBhcmFtIG1ldGhvZCBBIHN0cmluZyBjb250YWluaW5nIHRoZSBuYW1lIG9mIHRoZSBtZXNzYWdlIHRvIGxpc3RlbiBmb3IuXG4gICAqIEBwYXJhbSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gdG8gYmUgY2FsbGVkIHdoZW4gdGhlIG1lc3NhZ2UgaXMgcmVjZWl2ZWQuIFRoZSBwYXlsb2FkIGZyb20gdGhlIG1lc3NhZ2UgaXMgcGFzc2VkIHRvXG4gICAqICAgdGhlIGZ1bmN0aW9uLlxuICAgKi9cbiAgcHVibGljIG9uQ3VzdG9tUmVxdWVzdChcbiAgICBtZXRob2Q6IHN0cmluZyxcbiAgICBjYWxsYmFjazogKG9iajogUmVjb3JkPHN0cmluZywgYW55PikgPT4gUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+IHwgbnVsbD5cbiAgKTogdm9pZCB7XG4gICAgdGhpcy5fb25SZXF1ZXN0KHsgbWV0aG9kIH0sIGNhbGxiYWNrKVxuICB9XG5cbiAgLyoqXG4gICAqIFB1YmxpYzogU2VuZCBhIGN1c3RvbSByZXF1ZXN0XG4gICAqXG4gICAqIEBwYXJhbSBtZXRob2QgQSBzdHJpbmcgY29udGFpbmluZyB0aGUgbmFtZSBvZiB0aGUgcmVxdWVzdCBtZXNzYWdlLlxuICAgKiBAcGFyYW0gcGFyYW1zIFRoZSBtZXRob2QncyBwYXJhbWV0ZXJzXG4gICAqL1xuICBwdWJsaWMgc2VuZEN1c3RvbVJlcXVlc3QobWV0aG9kOiBzdHJpbmcsIHBhcmFtcz86IGFueVtdIHwgb2JqZWN0KTogUHJvbWlzZTxhbnk+IHtcbiAgICByZXR1cm4gdGhpcy5fc2VuZFJlcXVlc3QobmV3IGxzcC5Qcm90b2NvbFJlcXVlc3RUeXBlPHR5cGVvZiBwYXJhbXMsIGFueSwgYW55LCB2b2lkLCBhbnk+KG1ldGhvZCksIHBhcmFtcylcbiAgfVxuXG4gIC8qKlxuICAgKiBQdWJsaWM6IFNlbmQgYSBjdXN0b20gbm90aWZpY2F0aW9uXG4gICAqXG4gICAqIEBwYXJhbSBtZXRob2QgQSBzdHJpbmcgY29udGFpbmluZyB0aGUgbmFtZSBvZiB0aGUgbm90aWZpY2F0aW9uIG1lc3NhZ2UuXG4gICAqIEBwYXJhbSBwYXJhbXMgVGhlIG1ldGhvZCdzIHBhcmFtZXRlcnNcbiAgICovXG4gIHB1YmxpYyBzZW5kQ3VzdG9tTm90aWZpY2F0aW9uKG1ldGhvZDogc3RyaW5nLCBwYXJhbXM/OiBhbnlbXSB8IG9iamVjdCk6IHZvaWQge1xuICAgIHRoaXMuX3NlbmROb3RpZmljYXRpb24obmV3IGxzcC5Qcm90b2NvbE5vdGlmaWNhdGlvblR5cGU8dHlwZW9mIHBhcmFtcywgYW55PihtZXRob2QpLCBwYXJhbXMpXG4gIH1cblxuICAvKipcbiAgICogUHVibGljOiBSZWdpc3RlciBhIGNhbGxiYWNrIGZvciB0aGUgYHdpbmRvdy9zaG93TWVzc2FnZWAgbWVzc2FnZS5cbiAgICpcbiAgICogQHBhcmFtIGNhbGxiYWNrIFRoZSBmdW5jdGlvbiB0byBiZSBjYWxsZWQgd2hlbiB0aGUgYHdpbmRvdy9zaG93TWVzc2FnZWAgbWVzc2FnZSBpcyByZWNlaXZlZCB3aXRoXG4gICAqICAge1Nob3dNZXNzYWdlUGFyYW1zfSBiZWluZyBwYXNzZWQuXG4gICAqL1xuICBwdWJsaWMgb25TaG93TWVzc2FnZShjYWxsYmFjazogKHBhcmFtczogbHNwLlNob3dNZXNzYWdlUGFyYW1zKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgdGhpcy5fb25Ob3RpZmljYXRpb24oeyBtZXRob2Q6IFwid2luZG93L3Nob3dNZXNzYWdlXCIgfSwgY2FsbGJhY2spXG4gIH1cblxuICAvKipcbiAgICogUHVibGljOiBSZWdpc3RlciBhIGNhbGxiYWNrIGZvciB0aGUgYHdpbmRvdy9zaG93TWVzc2FnZVJlcXVlc3RgIG1lc3NhZ2UuXG4gICAqXG4gICAqIEBwYXJhbSBjYWxsYmFjayBUaGUgZnVuY3Rpb24gdG8gYmUgY2FsbGVkIHdoZW4gdGhlIGB3aW5kb3cvc2hvd01lc3NhZ2VSZXF1ZXN0YCBtZXNzYWdlIGlzIHJlY2VpdmVkIHdpdGhcbiAgICogICB7U2hvd01lc3NhZ2VSZXF1ZXN0UGFyYW19JyBiZWluZyBwYXNzZWQuXG4gICAqIEByZXR1cm5zIEEge1Byb21pc2V9IGNvbnRhaW5pbmcgdGhlIHtNZXNzYWdlQWN0aW9uSXRlbX0uXG4gICAqL1xuICBwdWJsaWMgb25TaG93TWVzc2FnZVJlcXVlc3QoXG4gICAgY2FsbGJhY2s6IChwYXJhbXM6IGxzcC5TaG93TWVzc2FnZVJlcXVlc3RQYXJhbXMpID0+IFByb21pc2U8bHNwLk1lc3NhZ2VBY3Rpb25JdGVtIHwgbnVsbD5cbiAgKTogdm9pZCB7XG4gICAgdGhpcy5fb25SZXF1ZXN0KHsgbWV0aG9kOiBcIndpbmRvdy9zaG93TWVzc2FnZVJlcXVlc3RcIiB9LCBjYWxsYmFjaylcbiAgfVxuXG4gIC8qKlxuICAgKiBQdWJsaWM6IFJlZ2lzdGVyIGEgY2FsbGJhY2sgZm9yIHRoZSBgd2luZG93L3Nob3dEb2N1bWVudGAgbWVzc2FnZS5cbiAgICpcbiAgICogQHBhcmFtIGNhbGxiYWNrIFRoZSBmdW5jdGlvbiB0byBiZSBjYWxsZWQgd2hlbiB0aGUgYHdpbmRvdy9zaG93RG9jdW1lbnRgIG1lc3NhZ2UgaXMgcmVjZWl2ZWQgd2l0aFxuICAgKiAgIHtTaG93RG9jdW1lbnRQYXJhbXN9IGJlaW5nIHBhc3NlZC5cbiAgICovXG4gIHB1YmxpYyBvblNob3dEb2N1bWVudChjYWxsYmFjazogKHBhcmFtczogbHNwLlNob3dEb2N1bWVudFBhcmFtcykgPT4gUHJvbWlzZTxsc3AuU2hvd0RvY3VtZW50UmVzdWx0Pik6IHZvaWQge1xuICAgIHRoaXMuX29uUmVxdWVzdCh7IG1ldGhvZDogXCJ3aW5kb3cvc2hvd0RvY3VtZW50XCIgfSwgY2FsbGJhY2spXG4gIH1cblxuICAvKipcbiAgICogUHVibGljOiBSZWdpc3RlciBhIGNhbGxiYWNrIGZvciB0aGUgYHdpbmRvdy9sb2dNZXNzYWdlYCBtZXNzYWdlLlxuICAgKlxuICAgKiBAcGFyYW0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBgd2luZG93L2xvZ01lc3NhZ2VgIG1lc3NhZ2UgaXMgcmVjZWl2ZWQgd2l0aCB7TG9nTWVzc2FnZVBhcmFtc31cbiAgICogICBiZWluZyBwYXNzZWQuXG4gICAqL1xuICBwdWJsaWMgb25Mb2dNZXNzYWdlKGNhbGxiYWNrOiAocGFyYW1zOiBsc3AuTG9nTWVzc2FnZVBhcmFtcykgPT4gdm9pZCk6IHZvaWQge1xuICAgIHRoaXMuX29uTm90aWZpY2F0aW9uKHsgbWV0aG9kOiBcIndpbmRvdy9sb2dNZXNzYWdlXCIgfSwgY2FsbGJhY2spXG4gIH1cblxuICAvKipcbiAgICogUHVibGljOiBSZWdpc3RlciBhIGNhbGxiYWNrIGZvciB0aGUgYHRlbGVtZXRyeS9ldmVudGAgbWVzc2FnZS5cbiAgICpcbiAgICogQHBhcmFtIGNhbGxiYWNrIFRoZSBmdW5jdGlvbiB0byBiZSBjYWxsZWQgd2hlbiB0aGUgYHRlbGVtZXRyeS9ldmVudGAgbWVzc2FnZSBpcyByZWNlaXZlZCB3aXRoIGFueSBwYXJhbWV0ZXJzXG4gICAqICAgcmVjZWl2ZWQgYmVpbmcgcGFzc2VkIG9uLlxuICAgKi9cbiAgcHVibGljIG9uVGVsZW1ldHJ5RXZlbnQoY2FsbGJhY2s6ICguLi5hcmdzOiBhbnlbXSkgPT4gdm9pZCk6IHZvaWQge1xuICAgIHRoaXMuX29uTm90aWZpY2F0aW9uKHsgbWV0aG9kOiBcInRlbGVtZXRyeS9ldmVudFwiIH0sIGNhbGxiYWNrKVxuICB9XG5cbiAgLyoqXG4gICAqIFB1YmxpYzogUmVnaXN0ZXIgYSBjYWxsYmFjayBmb3IgdGhlIGB3b3Jrc3BhY2UvYXBwbHlFZGl0YCBtZXNzYWdlLlxuICAgKlxuICAgKiBAcGFyYW0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBgd29ya3NwYWNlL2FwcGx5RWRpdGAgbWVzc2FnZSBpcyByZWNlaXZlZCB3aXRoXG4gICAqICAge0FwcGx5V29ya3NwYWNlRWRpdFBhcmFtc30gYmVpbmcgcGFzc2VkLlxuICAgKiBAcmV0dXJucyBBIHtQcm9taXNlfSBjb250YWluaW5nIHRoZSB7QXBwbHlXb3Jrc3BhY2VFZGl0UmVzcG9uc2V9LlxuICAgKi9cbiAgcHVibGljIG9uQXBwbHlFZGl0KFxuICAgIGNhbGxiYWNrOiAocGFyYW1zOiBsc3AuQXBwbHlXb3Jrc3BhY2VFZGl0UGFyYW1zKSA9PiBQcm9taXNlPGxzcC5BcHBseVdvcmtzcGFjZUVkaXRSZXNwb25zZT5cbiAgKTogdm9pZCB7XG4gICAgdGhpcy5fb25SZXF1ZXN0KHsgbWV0aG9kOiBcIndvcmtzcGFjZS9hcHBseUVkaXRcIiB9LCBjYWxsYmFjaylcbiAgfVxuXG4gIC8qKlxuICAgKiBQdWJsaWM6IFNlbmQgYSBgd29ya3NwYWNlL2RpZENoYW5nZUNvbmZpZ3VyYXRpb25gIG5vdGlmaWNhdGlvbi5cbiAgICpcbiAgICogQHBhcmFtIHBhcmFtcyBUaGUge0RpZENoYW5nZUNvbmZpZ3VyYXRpb25QYXJhbXN9IGNvbnRhaW5pbmcgdGhlIG5ldyBjb25maWd1cmF0aW9uLlxuICAgKi9cbiAgcHVibGljIGRpZENoYW5nZUNvbmZpZ3VyYXRpb24ocGFyYW1zOiBsc3AuRGlkQ2hhbmdlQ29uZmlndXJhdGlvblBhcmFtcyk6IHZvaWQge1xuICAgIHRoaXMuX3NlbmROb3RpZmljYXRpb24obHNwLkRpZENoYW5nZUNvbmZpZ3VyYXRpb25Ob3RpZmljYXRpb24udHlwZSwgcGFyYW1zKVxuICB9XG5cbiAgLyoqXG4gICAqIFB1YmxpYzogU2VuZCBhIGB0ZXh0RG9jdW1lbnQvZGlkT3BlbmAgbm90aWZpY2F0aW9uLlxuICAgKlxuICAgKiBAcGFyYW0gcGFyYW1zIFRoZSB7RGlkT3BlblRleHREb2N1bWVudFBhcmFtc30gY29udGFpbmluZyB0aGUgb3BlbmVkIHRleHQgZG9jdW1lbnQgZGV0YWlscy5cbiAgICovXG4gIHB1YmxpYyBkaWRPcGVuVGV4dERvY3VtZW50KHBhcmFtczogbHNwLkRpZE9wZW5UZXh0RG9jdW1lbnRQYXJhbXMpOiB2b2lkIHtcbiAgICB0aGlzLl9zZW5kTm90aWZpY2F0aW9uKGxzcC5EaWRPcGVuVGV4dERvY3VtZW50Tm90aWZpY2F0aW9uLnR5cGUsIHBhcmFtcylcbiAgfVxuXG4gIC8qKlxuICAgKiBQdWJsaWM6IFNlbmQgYSBgdGV4dERvY3VtZW50L2RpZENoYW5nZWAgbm90aWZpY2F0aW9uLlxuICAgKlxuICAgKiBAcGFyYW0gcGFyYW1zIFRoZSB7RGlkQ2hhbmdlVGV4dERvY3VtZW50UGFyYW1zfSBjb250YWluaW5nIHRoZSBjaGFuZ2VkIHRleHQgZG9jdW1lbnQgZGV0YWlscyBpbmNsdWRpbmcgdGhlIHZlcnNpb25cbiAgICogICBudW1iZXIgYW5kIGFjdHVhbCB0ZXh0IGNoYW5nZXMuXG4gICAqL1xuICBwdWJsaWMgZGlkQ2hhbmdlVGV4dERvY3VtZW50KHBhcmFtczogbHNwLkRpZENoYW5nZVRleHREb2N1bWVudFBhcmFtcyk6IHZvaWQge1xuICAgIHRoaXMuX3NlbmROb3RpZmljYXRpb24obHNwLkRpZENoYW5nZVRleHREb2N1bWVudE5vdGlmaWNhdGlvbi50eXBlLCBwYXJhbXMpXG4gIH1cblxuICAvKipcbiAgICogUHVibGljOiBTZW5kIGEgYHRleHREb2N1bWVudC9kaWRDbG9zZWAgbm90aWZpY2F0aW9uLlxuICAgKlxuICAgKiBAcGFyYW0gcGFyYW1zIFRoZSB7RGlkQ2xvc2VUZXh0RG9jdW1lbnRQYXJhbXN9IGNvbnRhaW5pbmcgdGhlIG9wZW5lZCB0ZXh0IGRvY3VtZW50IGRldGFpbHMuXG4gICAqL1xuICBwdWJsaWMgZGlkQ2xvc2VUZXh0RG9jdW1lbnQocGFyYW1zOiBsc3AuRGlkQ2xvc2VUZXh0RG9jdW1lbnRQYXJhbXMpOiB2b2lkIHtcbiAgICB0aGlzLl9zZW5kTm90aWZpY2F0aW9uKGxzcC5EaWRDbG9zZVRleHREb2N1bWVudE5vdGlmaWNhdGlvbi50eXBlLCBwYXJhbXMpXG4gIH1cblxuICAvKipcbiAgICogUHVibGljOiBTZW5kIGEgYHRleHREb2N1bWVudC93aWxsU2F2ZWAgbm90aWZpY2F0aW9uLlxuICAgKlxuICAgKiBAcGFyYW0gcGFyYW1zIFRoZSB7V2lsbFNhdmVUZXh0RG9jdW1lbnRQYXJhbXN9IGNvbnRhaW5pbmcgdGhlIHRvLWJlLXNhdmVkIHRleHQgZG9jdW1lbnQgZGV0YWlscyBhbmQgdGhlIHJlYXNvbiBmb3IgdGhlIHNhdmUuXG4gICAqL1xuICBwdWJsaWMgd2lsbFNhdmVUZXh0RG9jdW1lbnQocGFyYW1zOiBsc3AuV2lsbFNhdmVUZXh0RG9jdW1lbnRQYXJhbXMpOiB2b2lkIHtcbiAgICB0aGlzLl9zZW5kTm90aWZpY2F0aW9uKGxzcC5XaWxsU2F2ZVRleHREb2N1bWVudE5vdGlmaWNhdGlvbi50eXBlLCBwYXJhbXMpXG4gIH1cblxuICAvKipcbiAgICogUHVibGljOiBTZW5kIGEgYHRleHREb2N1bWVudC93aWxsU2F2ZVdhaXRVbnRpbGAgbm90aWZpY2F0aW9uLlxuICAgKlxuICAgKiBAcGFyYW0gcGFyYW1zIFRoZSB7V2lsbFNhdmVUZXh0RG9jdW1lbnRQYXJh