UNPKG

@microsoft/windows-admin-center-sdk

Version:

Microsoft - Windows Admin Center Shell

387 lines 54.9 kB
import { Injectable, Optional, SkipSelf } from '@angular/core'; import { Net } from '@microsoft/windows-admin-center-sdk/core/data/net'; import { Dom } from '@microsoft/windows-admin-center-sdk/core/dom/dom'; import { EnvironmentModuleEntryPointType } from '@microsoft/windows-admin-center-sdk/core/manifest/environment-modules'; import { EMPTY, of, ReplaySubject } from 'rxjs'; import { catchError, map, mergeMap, takeLast } from 'rxjs/operators'; import { AppContextService } from '../../service/app-context.service'; import { DialogCloseReason } from './dialog.component'; import * as i0 from "@angular/core"; import * as i1 from "../../service/app-context.service"; export var DialogChangeEvent; (function (DialogChangeEvent) { DialogChangeEvent[DialogChangeEvent["Show"] = 0] = "Show"; DialogChangeEvent[DialogChangeEvent["Hide"] = 1] = "Hide"; })(DialogChangeEvent || (DialogChangeEvent = {})); export class DialogService { constructor(appContext, parentDialogService) { this.appContext = appContext; this.parentDialogService = parentDialogService; this.commonIds = { choice: 'sme-common-choice-dialog', confirmation: 'sme-common-confirmation-dialog', confirmationList: 'sme-common-confirmation-list-dialog', message: 'sme-common-message-dialog', notificationsPane: 'sme-common-notifications-pane', settings: 'sme-common-settings-pane', help: 'sme-common-help-pane', userPane: 'sme-common-user-pane', manageAs: 'sme-common-manage-as-dialog', powerShellShowScript: 'sme-common-powershell-show-script', credSSPConfirmation: 'sme-credssp-confirmation-dialog', userAlive: 'sme-user-alive-dialog', postInstall: 'sme-post-install-dialog' }; this.activeDialogsStack = []; this.strings = MsftSme.getStrings().MsftSmeShell.Angular; this.componentMap = {}; this.dialogOrigins = {}; this.iFrameDialogCount = 0; this.changedEventSubject = new ReplaySubject(1); } /** * Gets the subject of notification changed event. */ get changed() { return this.changedEventSubject; } get currentDialogLevel() { return this.activeDialogsStack ? this.activeDialogsStack.length + this.iFrameDialogCount : this.iFrameDialogCount; } /** * Registers the dialog with the service. * * TOptions the type of the dialog options. * TResult the type of the dialog results. * @param id The unique identifier of the dialog. * @param component The dialog component. */ register(id, component) { if (!id) { throw new Error('DialogService.register: ID is required to register a dialog.'); } if (!component) { throw new Error('DialogService.register: A dialog is required to register a dialog.'); } /** * removing until we understand cases where angular can call ngOnInit twice. * see: http://stackoverflow.com/questions/42700116/angular2-routing-issue-and-ngoninit-called-twice * and @msft-sme/local-users-groups for examples */ // if (this.componentMap[id]) { // console.warn(`DialogService.register: A dialog with the ID \'${id}\' has already been registered`); // } this.componentMap[id] = component; } /** * Unregisters the dialog with the service. * * @param id The unique identifier of the dialog. */ unregister(id) { if (this.componentMap[id]) { delete this.componentMap[id]; } if (this.activeDialogsStack && this.activeDialogsStack.length > 0 && MsftSme.last(this.activeDialogsStack).id === id) { this.activeDialogsStack.pop(); } } addIFrameDialog() { this.iFrameDialogCount++; } removeIFrameDialog() { this.iFrameDialogCount = Math.max(this.iFrameDialogCount - 1, 0); } /** * Shows the dialog. * * TOptions The type of the dialog options. * TResult The result of the dialog. * @param id The unique identifier of the dialog. * @param options The dialog options. */ show(id, options) { if (!id) { throw new Error('DialogService.show: ID is required to show a dialog.'); } if (!this.componentMap[id]) { if (this.parentDialogService) { return this.parentDialogService.show(id, options); } else { throw new Error(`DialogService.show: No dialog associated with provided ID \'${id}\'.`); } } const newDialog = this.componentMap[id]; const oldDialog = MsftSme.last(this.activeDialogsStack); // accessibility if (options && !options.isFromRpc) { // if from Rpc then don't resume focus since it will focus back on iframe const origin = document.activeElement; if (origin) { this.dialogOrigins[id] = origin; } } // dont do anything unless we have a subscriber return of(oldDialog) .pipe(mergeMap(it => { // create a placeholder for the new dialog result let resultObservable; // remember if there was an active dialog when we started const existingActiveDialog = !!oldDialog; if (existingActiveDialog) { if (oldDialog.keepOpen) { // If the currently active dialog wants to stay open, then keep it open and show the new dialog on top this.activeDialogsStack.push(newDialog); this.overlayOpen(true, newDialog.id); // we set the dialog level as the length of the active dialogs stack newDialog.setLevel(this.currentDialogLevel); this.activeDialogResult = newDialog.show(options) .pipe(map(result => { this.overlayOpen(false, newDialog.id); this.activeDialogsStack.pop(); if (oldDialog) { oldDialog.autoFocus(); } return result; })); resultObservable = this.activeDialogResult; } else { // if there is an active dialog, wait for it to complete, then show a the new one resultObservable = this.activeDialogResult .pipe(takeLast(1), mergeMap(() => { return this.show(id, options); })); } } else { // if there is no active dialog, then just show the new one this.activeDialogsStack.push(newDialog); this.overlayOpen(true, newDialog.id); newDialog.setLevel(this.currentDialogLevel); this.activeDialogResult = newDialog.show(options) .pipe(map(result => { this.overlayOpen(false, newDialog.id); if (oldDialog) { oldDialog.autoFocus(); } this.activeDialogsStack.pop(); return result; })); resultObservable = this.activeDialogResult; } // if we had an active dialog, request the previous dialog to close unless it wants to stay open if (existingActiveDialog && !oldDialog.keepOpen) { oldDialog.closeRequested(DialogCloseReason.CompetingDialog); } this.emitDialogChangeEvent(id, DialogChangeEvent.Show); return resultObservable; })); } /** * Shows a message dialog with the given options * * @param options The dialog options. * @returns A subject that will be published one time with the dialog result * @deprecated Please use 'AppContextService.frame.showDialogMessage' on extensions. */ showMessage(options) { // if running from shell, manually launch dialog if (this.appContext.rpc.isShell) { return this.show(this.commonIds.message, options); } else { // otherwise ask the shell to do it for us. return this.appContext.frame.showDialogMessage({ buttonText: options.buttonText, checkboxText: options.checkboxText, externalLink: options.externalLink, message: options.message, title: options.title }); } } /** * Hide a message dialog. */ hideMessage() { this.hide(this.commonIds.message); } /** * Shows a choice dialog with the given options. * * @param options The dialog options. * @returns A subject that will be published one time with the dialog result. */ showChoice(options) { if (this.appContext.rpc.isShell) { return this.show(this.commonIds.choice, options); } else { return this.appContext.frame.showDialogChoice({ cancelButtonText: options.cancelButtonText, choices: options.choices, confirmButtonText: options.confirmButtonText, footnote: options.footnote, message: options.message, title: options.title }); } } /** * Hide a choice dialog. */ hideChoice() { this.hide(this.commonIds.choice); } /** * Shows a confirmation dialog with the given options * * @param options The dialog options. * @returns A subject that will be published one time with the dialog result * @deprecated since 02/20/18. Please use 'AppContextService.frame.showDialogConfirmation' instead */ showConfirmation(options) { let confirmationObservable; // if running from shell, manually launch dialog if (this.appContext.rpc.isShell) { confirmationObservable = this.show(this.commonIds.confirmation, options); } else { // otherwise ask the shell to do it for us. confirmationObservable = this.appContext.frame.showDialogConfirmation({ cancelButtonText: options.cancelButtonText, checkboxText: options.checkboxText, confirmButtonText: options.confirmButtonText, doubleCheckText: options.doubleCheckText, message: options.message, title: options.title, externalLink: options.externalLink }); } return confirmationObservable.pipe(map((response) => { return response || { confirmed: false, checkboxResult: false }; })); } /** * Hide a confirmation dialog. */ hideConfirmation() { this.hide(this.commonIds.confirmation); } /** * Shows a confirmation list dialog with the given options * * @param options The dialog options. * @returns A subject that will be published one time with the dialog result */ showConfirmationList(options) { return this.show(this.commonIds.confirmationList, options); } /** * Hide a confirmation list dialog. */ hideConfirmationList() { this.hide(this.commonIds.confirmationList); } /** * Hides the dialog. * * TResult The type of the dialog result. * @param id The unique identifier of the dialog. * @param result The result of the dialog. */ hide(id, result) { if (!id) { throw new Error('DialogService.hide: ID is required to hide a dialog.'); } if (!this.componentMap[id]) { if (this.parentDialogService) { this.parentDialogService.hide(id, result); return; } else { throw new Error(`DialogService.hide: No dialog associated with provided ID \'${id}\'.`); } } this.componentMap[id].hide(result); this.emitDialogChangeEvent(id, DialogChangeEvent.Hide); } /** * Send Rpc request to shell to add/remove overlay * @param overlay true: add, false: remove * @param id id of the dialog */ overlayOpen(overlay, id) { const startOverlay = MsftSme.isExtension() && (MsftSme.entryPointType() === EnvironmentModuleEntryPointType.Tool || MsftSme.entryPointType() === EnvironmentModuleEntryPointType.SettingsForm); if (startOverlay) { // there could be multiple dialog service instances for some reason this.appContext.registerDialogService(this, id); this.appContext.frame.overlayOpen(overlay, id) .pipe(catchError(error => { const notification = this.appContext.notification.create(null); notification.showError(this.strings.Overlay.openErrorTitle, Net.getErrorMessage(error)); return EMPTY; })); } } /** * Handle clicking on dialog background in shell * @param dialogId id of dialog whose background was clicked */ overlayClicked(dialogId) { const lastDialog = MsftSme.last(this.activeDialogsStack); if (lastDialog && lastDialog.id === dialogId) { lastDialog.onBackgroundClicked(); return true; } return false; } /** * Resume focus back to the original element that shows the dialog. * @param id The id of dialog * @param delay If provided, delays resuming focus for a period of time in ms */ resumeFocus(id, delay = 0) { // check to see if there is a dialog stack currently. const wasInDialogStack = this.activeDialogsStack && this.activeDialogsStack.length > 0; if (this.dialogOrigins[id]) { setTimeout(() => { const isInDialogStack = this.activeDialogsStack && this.activeDialogsStack.length > 0; if (!wasInDialogStack && isInDialogStack) { // a dialog was opened during the setTimeout. // This means that the new dialog will resume focus to the wrong element and the new dialog will open unfocused. this.dialogOrigins[this.activeDialogsStack[0].id] = this.dialogOrigins[id]; delete this.dialogOrigins[id]; } else if (this.appContext.frame.activeRpcDialogsOrigins.size > 0) { // an rpc dialog was opened during the setTimeout. So just wait a little longer and then refocus this.resumeFocus(id, 100); } else { const element = this.dialogOrigins[id]; const focusOn = Dom.getFocusOrigin(element); if (focusOn) { focusOn.focus(); } delete this.dialogOrigins[id]; } }, delay); } } emitDialogChangeEvent(dialogId, changeEvent) { this.changedEventSubject.next({ dialogId: dialogId, changeEvent: changeEvent }); } } /** @nocollapse */ DialogService.ɵfac = function DialogService_Factory(t) { return new (t || DialogService)(i0.ɵɵinject(i1.AppContextService), i0.ɵɵinject(DialogService, 12)); }; /** @nocollapse */ DialogService.ɵprov = /** @pureOrBreakMyCode */ i0.ɵɵdefineInjectable({ token: DialogService, factory: DialogService.ɵfac }); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DialogService, [{ type: Injectable }], function () { return [{ type: i1.AppContextService }, { type: DialogService, decorators: [{ type: SkipSelf }, { type: Optional }] }]; }, null); })(); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGlhbG9nLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9hbmd1bGFyL3NyYy9jb250cm9scy9kaWFsb2cvZGlhbG9nLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQy9ELE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxtREFBbUQsQ0FBQztBQUN4RSxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sa0RBQWtELENBQUM7QUFDdkUsT0FBTyxFQUFFLCtCQUErQixFQUFFLE1BQU0sdUVBQXVFLENBQUM7QUFDeEgsT0FBTyxFQUFFLEtBQUssRUFBYyxFQUFFLEVBQUUsYUFBYSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQzVELE9BQU8sRUFBRSxVQUFVLEVBQUUsR0FBRyxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUVyRSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxtQ0FBbUMsQ0FBQztBQUt0RSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQzs7O0FBR3ZELE1BQU0sQ0FBTixJQUFZLGlCQUdYO0FBSEQsV0FBWSxpQkFBaUI7SUFDekIseURBQUksQ0FBQTtJQUNKLHlEQUFJLENBQUE7QUFDUixDQUFDLEVBSFcsaUJBQWlCLEtBQWpCLGlCQUFpQixRQUc1QjtBQVFELE1BQU0sT0FBTyxhQUFhO0lBeUJ0QixZQUFvQixVQUE2QixFQUFrQyxtQkFBbUM7UUFBbEcsZUFBVSxHQUFWLFVBQVUsQ0FBbUI7UUFBa0Msd0JBQW1CLEdBQW5CLG1CQUFtQixDQUFnQjtRQXhCL0csY0FBUyxHQUFHO1lBQ2YsTUFBTSxFQUFFLDBCQUEwQjtZQUNsQyxZQUFZLEVBQUUsZ0NBQWdDO1lBQzlDLGdCQUFnQixFQUFFLHFDQUFxQztZQUN2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RTtvQkFDL0QsZ0dBQWdHO29CQUNoRyxJQUFJLENBQUMsV0FBVyxDQUFDLEVBQUUsRUFBRSxHQUFHLENBQUMsQ0FBQztpQkFDN0I7cUJBQU07b0JBQ0gsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBQyxFQUFFLENBQUMsQ0FBQztvQkFDdkMsTUFBTSxPQUFPLEdBQWdCLEdBQUcsQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDLENBQUM7b0JBQ3pELElBQUksT0FBTyxFQUFFO3dCQUNULE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBQztxQkFDbkI7b0JBQ0QsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFDLEVBQUUsQ0FBQyxDQUFDO2lCQUNqQztZQUVMLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztTQUNqQjtJQUNMLENBQUM7SUFFTSxxQkFBcUIsQ0FBQyxRQUFnQixFQUFFLFdBQThCO1FBQ3pFLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxJQUFJLENBQWMsRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLFdBQVcsRUFBRSxXQUFXLEVBQUUsQ0FBQyxDQUFDO0lBQ2pHLENBQUM7OzZGQWpaUSxhQUFhO2tHQUFiLGFBQWEsV0FBYixhQUFhO3VGQUFiLGFBQWE7Y0FEekIsVUFBVTs7c0JBMEI2QyxRQUFROztzQkFBSSxRQUFRIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgT3B0aW9uYWwsIFNraXBTZWxmIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IE5ldCB9IGZyb20gJ0BtaWNyb3NvZnQvd2luZG93cy1hZG1pbi1jZW50ZXItc2RrL2NvcmUvZGF0YS9uZXQnO1xyXG5pbXBvcnQgeyBEb20gfSBmcm9tICdAbWljcm9zb2Z0L3dpbmRvd3MtYWRtaW4tY2VudGVyLXNkay9jb3JlL2RvbS9kb20nO1xyXG5pbXBvcnQgeyBFbnZpcm9ubWVudE1vZHVsZUVudHJ5UG9pbnRUeXBlIH0gZnJvbSAnQG1pY3Jvc29mdC93aW5kb3dzLWFkbWluLWNlbnRlci1zZGsvY29yZS9tYW5pZmVzdC9lbnZpcm9ubWVudC1tb2R1bGVzJztcclxuaW1wb3J0IHsgRU1QVFksIE9ic2VydmFibGUsIG9mLCBSZXBsYXlTdWJqZWN0IH0gZnJvbSAncnhqcyc7XHJcbmltcG9ydCB7IGNhdGNoRXJyb3IsIG1hcCwgbWVyZ2VNYXAsIHRha2VMYXN0IH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xyXG5pbXBvcnQgeyBTdHJpbmdzIH0gZnJvbSAnLi4vLi4vZ2VuZXJhdGVkL3N0cmluZ3MnO1xyXG5pbXBvcnQgeyBBcHBDb250ZXh0U2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2UvYXBwLWNvbnRleHQuc2VydmljZSc7XHJcbmltcG9ydCB7IEJhc2VEaWFsb2dDb21wb25lbnQsIERpYWxvZ09wdGlvbnMsIERpYWxvZ1Jlc3VsdCB9IGZyb20gJy4vYmFzZS1kaWFsb2cuY29tcG9uZW50JztcclxuaW1wb3J0IHsgQ2hvaWNlRGlhbG9nT3B0aW9ucywgQ2hvaWNlRGlhbG9nUmVzdWx0IH0gZnJvbSAnLi9jaG9pY2UtZGlhbG9nL2Nob2ljZS1kaWFsb2cuY29tcG9uZW50JztcclxuaW1wb3J0IHsgQ29uZmlybWF0aW9uRGlhbG9nT3B0aW9ucywgQ29uZmlybWF0aW9uRGlhbG9nUmVzdWx0IH0gZnJvbSAnLi9jb25maXJtYXRpb24tZGlhbG9nL2NvbmZpcm1hdGlvbi1kaWFsb2cuY29tcG9uZW50JztcclxuaW1wb3J0IHsgQ29uZmlybWF0aW9uTGlzdERpYWxvZ09wdGlvbnMsIENvbmZpcm1hdGlvbkxpc3REaWFsb2dSZXN1bHQgfSBmcm9tICcuL2NvbmZpcm1hdGlvbi1saXN0LWRpYWxvZy9jb25maXJtYXRpb24tbGlzdC1kaWFsb2cuY29tcG9uZW50JztcclxuaW1wb3J0IHsgRGlhbG9nQ2xvc2VSZWFzb24gfSBmcm9tICcuL2RpYWxvZy5jb21wb25lbnQnO1xyXG5pbXBvcnQgeyBNZXNzYWdlRGlhbG9nT3B0aW9ucyB9IGZyb20gJy4vbWVzc2FnZS1kaWFsb2cvbWVzc2FnZS1kaWFsb2cuY29tcG9uZW50JztcclxuXHJcbmV4cG9ydCBlbnVtIERpYWxvZ0NoYW5nZUV2ZW50IHtcclxuICAgIFNob3csXHJcbiAgICBIaWRlXHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgRGlhbG9nRXZlbnQge1xyXG4gICAgZGlhbG9nSWQ6IHN0cmluZztcclxuICAgIGNoYW5nZUV2ZW50OiBEaWFsb2dDaGFuZ2VFdmVudDtcclxufVxyXG5cclxuQEluamVjdGFibGUoKVxyXG5leHBvcnQgY2xhc3MgRGlhbG9nU2VydmljZSB7XHJcbiAgICBwdWJsaWMgY29tbW9uSWRzID0ge1xyXG4gICAgICAgIGNob2ljZTogJ3NtZS1jb21tb24tY2hvaWNlLWRpYWxvZycsXHJcbiAgICAgICAgY29uZmlybWF0aW9uOiAnc21lLWNvbW1vbi1jb25maXJtYXRpb24tZGlhbG9nJyxcclxuICAgICAgICBjb25maXJtYXRpb25MaXN0OiAnc21lLWNvbW1vbi1jb25maXJtYXRpb24tbGlzdC1kaWFsb2cnLFxyXG4gICAgICAgIG1lc3NhZ2U6ICdzbWUtY29tbW9uLW1lc3NhZ2UtZGlhbG9nJyxcclxuICAgICAgICBub3RpZmljYXRpb25zUGFuZTogJ3NtZS1jb21tb24tbm90aWZpY2F0aW9ucy1wYW5lJyxcclxuICAgICAgICBzZXR0aW5nczogJ3NtZS1jb21tb24tc2V0dGluZ3MtcGFuZScsXHJcbiAgICAgICAgaGVscDogJ3NtZS1jb21tb24taGVscC1wYW5lJyxcclxuICAgICAgICB1c2VyUGFuZTogJ3NtZS1jb21tb24tdXNlci1wYW5lJyxcclxuICAgICAgICBtYW5hZ2VBczogJ3NtZS1jb21tb24tbWFuYWdlLWFzLWRpYWxvZycsXHJcbiAgICAgICAgcG93ZXJTaGVsbFNob3dTY3JpcHQ6ICdzbWUtY29tbW9uLXBvd2Vyc2hlbGwtc2hvdy1zY3JpcHQnLFxyXG4gICAgICAgIGNyZWRTU1BDb25maXJtYXRpb246ICdzbWUtY3JlZHNzcC1jb25maXJtYXRpb24tZGlhbG9nJyxcclxuICAgICAgICB1c2VyQWxpdmU6ICdzbWUtdXNlci1hbGl2ZS1kaWFsb2cnLFxyXG4gICAgICAgIHBvc3RJbnN0YWxsOiAnc21lLXBvc3QtaW5zdGFsbC1kaWFsb2cnXHJcbiAgICB9O1xyXG5cclxuICAgIHB1YmxpYyBhY3RpdmVEaWFsb2dzU3RhY2s6IEJhc2VEaWFsb2dDb21wb25lbnQ8RGlhbG9nT3B0aW9ucywgRGlhbG9nUmVzdWx0PltdID0gW107XHJcblxyXG4gICAgcHJpdmF0ZSBzdHJpbmdzID0gTXNmdFNtZS5nZXRTdHJpbmdzPFN0cmluZ3M+KCkuTXNmdFNtZVNoZWxsLkFuZ3VsYXI7XHJcbiAgICBwcml2YXRlIGNvbXBvbmVudE1hcDogeyBbaW5kZXg6IHN0cmluZ106IEJhc2VEaWFsb2dDb21wb25lbnQ8RGlhbG9nT3B0aW9ucywgRGlhbG9nUmVzdWx0PiB9ID0ge307XHJcbiAgICBwcml2YXRlIGFjdGl2ZURpYWxvZ1Jlc3VsdDogT2JzZXJ2YWJsZTxEaWFsb2dSZXN1bHQ+O1xyXG4gICAgcHJpdmF0ZSBkaWFsb2dPcmlnaW5zOiB7IFtpbmRleDogc3RyaW5nXTogSFRNTEVsZW1lbnQgfSA9IHt9O1xyXG4gICAgcHJpdmF0ZSBjaGFuZ2VkRXZlbnRTdWJqZWN0OiBSZXBsYXlTdWJqZWN0PERpYWxvZ0V2ZW50PjtcclxuXHJcbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIGFwcENvbnRleHQ6IEFwcENvbnRleHRTZXJ2aWNlLCBAU2tpcFNlbGYoKSBAT3B0aW9uYWwoKSBwcml2YXRlIHBhcmVudERpYWxvZ1NlcnZpY2U/OiBEaWFsb2dTZXJ2aWNlKSB7XHJcbiAgICAgICAgdGhpcy5jaGFuZ2VkRXZlbnRTdWJqZWN0ID0gbmV3IFJlcGxheVN1YmplY3Q8RGlhbG9nRXZlbnQ+KDEpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2V0cyB0aGUgc3ViamVjdCBvZiBub3RpZmljYXRpb24gY2hhbmdlZCBldmVudC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGdldCBjaGFuZ2VkKCk6IFJlcGxheVN1YmplY3Q8RGlhbG9nRXZlbnQ+IHtcclxuICAgICAgICByZXR1cm4gdGhpcy5jaGFuZ2VkRXZlbnRTdWJqZWN0O1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBnZXQgY3VycmVudERpYWxvZ0xldmVsKCk6IG51bWJlciB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuYWN0aXZlRGlhbG9nc1N0YWNrID8gdGhpcy5hY3RpdmVEaWFsb2dzU3RhY2subGVuZ3RoICsgdGhpcy5pRnJhbWVEaWFsb2dDb3VudCA6IHRoaXMuaUZyYW1lRGlhbG9nQ291bnQ7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBpRnJhbWVEaWFsb2dDb3VudCA9IDA7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZWdpc3RlcnMgdGhlIGRpYWxvZyB3aXRoIHRoZSBzZXJ2aWNlLlxyXG4gICAgICpcclxuICAgICAqIFRPcHRpb25zIHRoZSB0eXBlIG9mIHRoZSBkaWFsb2cgb3B0aW9ucy5cclxuICAgICAqIFRSZXN1bHQgdGhlIHR5cGUgb2YgdGhlIGRpYWxvZyByZXN1bHRzLlxyXG4gICAgICogQHBhcmFtIGlkIFRoZSB1bmlxdWUgaWRlbnRpZmllciBvZiB0aGUgZGlhbG9nLlxyXG4gICAgICogQHBhcmFtIGNvbXBvbmVudCBUaGUgZGlhbG9nIGNvbXBvbmVudC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIHJlZ2lzdGVyPFRPcHRpb25zIGV4dGVuZHMgRGlhbG9nT3B0aW9ucywgVFJlc3VsdCBleHRlbmRzIERpYWxvZ1Jlc3VsdD4oXHJcbiAgICAgICAgaWQ6IHN0cmluZyxcclxuICAgICAgICBjb21wb25lbnQ6IEJhc2VEaWFsb2dDb21wb25lbnQ8VE9wdGlvbnMsIFRSZXN1bHQ+XHJcbiAgICApOiB2b2lkIHtcclxuICAgICAgICBpZiAoIWlkKSB7XHJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignRGlhbG9nU2VydmljZS5yZWdpc3RlcjogSUQgaXMgcmVxdWlyZWQgdG8gcmVnaXN0ZXIgYSBkaWFsb2cuJyk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoIWNvbXBvbmVudCkge1xyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0RpYWxvZ1NlcnZpY2UucmVnaXN0ZXI6IEEgZGlhbG9nIGlzIHJlcXVpcmVkIHRvIHJlZ2lzdGVyIGEgZGlhbG9nLicpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLyoqXHJcbiAgICAgICAgICogcmVtb3ZpbmcgdW50aWwgd2UgdW5kZXJzdGFuZCBjYXNlcyB3aGVyZSBhbmd1bGFyIGNhbiBjYWxsIG5nT25Jbml0IHR3aWNlLlxyXG4gICAgICAgICAqIHNlZTogaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy80MjcwMDExNi9hbmd1bGFyMi1yb3V0aW5nLWlzc3VlLWFuZC1uZ29uaW5pdC1jYWxsZWQtdHdpY2VcclxuICAgICAgICAgKiBhbmQgQG1zZnQtc21lL2xvY2FsLXVzZXJzLWdyb3VwcyBmb3IgZXhhbXBsZXNcclxuICAgICAgICAgKi9cclxuICAgICAgICAvLyBpZiAodGhpcy5jb21wb25lbnRNYXBbaWRdKSB7XHJcbiAgICAgICAgLy8gICAgIGNvbnNvbGUud2FybihgRGlhbG9nU2VydmljZS5yZWdpc3RlcjogQSBkaWFsb2cgd2l0aCB0aGUgSUQgXFwnJHtpZH1cXCcgaGFzIGFscmVhZHkgYmVlbiByZWdpc3RlcmVkYCk7XHJcbiAgICAgICAgLy8gfVxyXG5cclxuICAgICAgICB0aGlzLmNvbXBvbmVudE1hcFtpZF0gPSBjb21wb25lbnQ7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBVbnJlZ2lzdGVycyB0aGUgZGlhbG9nIHdpdGggdGhlIHNlcnZpY2UuXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIGlkIFRoZSB1bmlxdWUgaWRlbnRpZmllciBvZiB0aGUgZGlhbG9nLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgdW5yZWdpc3RlcihpZDogc3RyaW5nKTogdm9pZCB7XHJcbiAgICAgICAgaWYgKHRoaXMuY29tcG9uZW50TWFwW2lkXSkge1xyXG4gICAgICAgICAgICBkZWxldGUgdGhpcy5jb21wb25lbnRNYXBbaWRdO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHRoaXMuYWN0aXZlRGlhbG9nc1N0YWNrICYmIHRoaXMuYWN0aXZlRGlhbG9nc1N0YWNrLmxlbmd0aCA+IDAgJiYgTXNmdFNtZS5sYXN0KHRoaXMuYWN0aXZlRGlhbG9nc1N0YWNrKS5pZCA9PT0gaWQpIHtcclxuICAgICAgICAgICAgdGhpcy5hY3RpdmVEaWFsb2dzU3RhY2sucG9wKCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBhZGRJRnJhbWVEaWFsb2coKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5pRnJhbWVEaWFsb2dDb3VudCsrO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyByZW1vdmVJRnJhbWVEaWFsb2coKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5pRnJhbWVEaWFsb2dDb3VudCA9IE1hdGgubWF4KHRoaXMuaUZyYW1lRGlhbG9nQ291bnQgLSAxLCAwKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFNob3dzIHRoZSBkaWFsb2cuXHJcbiAgICAgKlxyXG4gICAgICogVE9wdGlvbnMgVGhlIHR5cGUgb2YgdGhlIGRpYWxvZyBvcHRpb25zLlxyXG4gICAgICogVFJlc3VsdCBUaGUgcmVzdWx0IG9mIHRoZSBkaWFsb2cuXHJcbiAgICAgKiBAcGFyYW0gaWQgVGhlIHVuaXF1ZSBpZGVudGlmaWVyIG9mIHRoZSBkaWFsb2cuXHJcbiAgICAgKiBAcGFyYW0gb3B0aW9ucyBUaGUgZGlhbG9nIG9wdGlvbnMuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzaG93PFRPcHRpb25zIGV4dGVuZHMgRGlhbG9nT3B0aW9ucywgVFJlc3VsdCBleHRlbmRzIERpYWxvZ1Jlc3VsdD4oaWQ6IHN0cmluZywgb3B0aW9uczogVE9wdGlvbnMpOiBPYnNlcnZhYmxlPFRSZXN1bHQ+IHtcclxuICAgICAgICBpZiAoIWlkKSB7XHJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignRGlhbG9nU2VydmljZS5zaG93OiBJRCBpcyByZXF1aXJlZCB0byBzaG93IGEgZGlhbG9nLicpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKCF0aGlzLmNvbXBvbmVudE1hcFtpZF0pIHtcclxuICAgICAgICAgICAgaWYgKHRoaXMucGFyZW50RGlhbG9nU2VydmljZSkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucGFyZW50RGlhbG9nU2VydmljZS5zaG93KGlkLCBvcHRpb25zKTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgRGlhbG9nU2VydmljZS5zaG93OiBObyBkaWFsb2cgYXNzb2NpYXRlZCB3aXRoIHByb3ZpZGVkIElEIFxcJyR7aWR9XFwnLmApO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBuZXdEaWFsb2cgPSB0aGlzLmNvbXBvbmVudE1hcFtpZF07XHJcbiAgICAgICAgY29uc3Qgb2xkRGlhbG9nID0gTXNmdFNtZS5sYXN0KHRoaXMuYWN0aXZlRGlhbG9nc1N0YWNrKTtcclxuXHJcbiAgICAgICAgLy8gYWNjZXNzaWJpbGl0eVxyXG4gICAgICAgIGlmIChvcHRpb25zICYmICEoPGFueT5vcHRpb25zKS5pc0Zyb21ScGMpIHsgLy8gaWYgZnJvbSBScGMgdGhlbiBkb24ndCByZXN1bWUgZm9jdXMgc2luY2UgaXQgd2lsbCBmb2N1cyBiYWNrIG9uIGlmcmFtZVxyXG4gICAgICAgICAgICBjb25zdCBvcmlnaW4gPSBkb2N1bWVudC5hY3RpdmVFbGVtZW50IGFzIEhUTUxFbGVtZW50O1xyXG4gICAgICAgICAgICBpZiAob3JpZ2luKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmRpYWxvZ09yaWdpbnNbaWRdID0gb3JpZ2luO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBkb250IGRvIGFueXRoaW5nIHVubGVzcyB3ZSBoYXZlIGEgc3Vic2NyaWJlclxyXG4gICAgICAgIHJldHVybiBvZihvbGREaWFsb2cpXHJcbiAgICAgICAgICAgIC5waXBlKFxyXG4gICAgICAgICAgICAgICAgbWVyZ2VNYXAoaXQgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIGNyZWF0ZSBhIHBsYWNlaG9sZGVyIGZvciB0aGUgbmV3IGRpYWxvZyByZXN1bHRcclxuICAgICAgICAgICAgICAgICAgICBsZXQgcmVzdWx0T2JzZXJ2YWJsZTogT2JzZXJ2YWJsZTxUUmVzdWx0PjtcclxuICAgICAgICAgICAgICAgICAgICAvLyByZW1lbWJlciBpZiB0aGVyZSB3YXMgYW4gYWN0aXZlIGRpYWxvZyB3aGVuIHdlIHN0YXJ0ZWRcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBleGlzdGluZ0FjdGl2ZURpYWxvZyA9ICEhb2xkRGlhbG9nO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChleGlzdGluZ0FjdGl2ZURpYWxvZykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAob2xkRGlhbG9nLmtlZXBPcGVuKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgY3VycmVudGx5IGFjdGl2ZSBkaWFsb2cgd2FudHMgdG8gc3RheSBvcGVuLCB0aGVuIGtlZXAgaXQgb3BlbiBhbmQgc2hvdyB0aGUgbmV3IGRpYWxvZyBvbiB0b3BcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYWN0aXZlRGlhbG9nc1N0YWNrLnB1c2gobmV3RGlhbG9nKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMub3ZlcmxheU9wZW4odHJ1ZSwgbmV3RGlhbG9nLmlkKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdlIHNldCB0aGUgZGlhbG9nIGxldmVsIGFzIHRoZSBsZW5ndGggb2YgdGhlIGFjdGl2ZSBkaWFsb2dzIHN0YWNrXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdEaWFsb2cuc2V0TGV2ZWwodGhpcy5jdXJyZW50RGlhbG9nTGV2ZWwpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5hY3RpdmVEaWFsb2dSZXN1bHQgPSBuZXdEaWFsb2cuc2hvdyhvcHRpb25zKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5waXBlKG1hcChyZXN1bHQgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm92ZXJsYXlPcGVuKGZhbHNlLCBuZXdEaWFsb2cuaWQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmFjdGl2ZURpYWxvZ3NTdGFjay5wb3AoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9sZERpYWxvZykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb2xkRGlhbG9nLmF1dG9Gb2N1cygpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdE9ic2VydmFibGUgPSA8T2JzZXJ2YWJsZTxUUmVzdWx0Pj50aGlzLmFjdGl2ZURpYWxvZ1Jlc3VsdDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGlmIHRoZXJlIGlzIGFuIGFjdGl2ZSBkaWFsb2csIHdhaXQgZm9yIGl0IHRvIGNvbXBsZXRlLCB0aGVuIHNob3cgYSB0aGUgbmV3IG9uZVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0T2JzZXJ2YWJsZSA9IDxPYnNlcnZhYmxlPFRSZXN1bHQ+PnRoaXMuYWN0aXZlRGlhbG9nUmVzdWx0XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLnBpcGUoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRha2VMYXN0KDEpLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXJnZU1hcCgoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5zaG93KGlkLCBvcHRpb25zKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSkpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gaWYgdGhlcmUgaXMgbm8gYWN0aXZlIGRpYWxvZywgdGhlbiBqdXN0IHNob3cgdGhlIG5ldyBvbmVcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5hY3RpdmVEaWFsb2dzU3RhY2sucHVzaChuZXdEaWFsb2cpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm92ZXJsYXlPcGVuKHRydWUsIG5ld0RpYWxvZy5pZCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld0RpYWxvZy5zZXRMZXZlbCh0aGlzLmN1cnJlbnREaWFsb2dMZXZlbCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYWN0aXZlRGlhbG9nUmVzdWx0ID0gbmV3RGlhbG9nLnNob3cob3B0aW9ucylcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5waXBlKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcChyZXN1bHQgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm92ZXJsYXlPcGVuKGZhbHNlLCBuZXdEaWFsb2cuaWQpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob2xkRGlhbG9nKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbGREaWFsb2cuYXV0b0ZvY3VzKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYWN0aXZlRGlhbG9nc1N0YWNrLnBvcCgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0T2JzZXJ2YWJsZSA9IDxPYnNlcnZhYmxlPFRSZXN1bHQ+PnRoaXMuYWN0aXZlRGlhbG9nUmVzdWx0O1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgLy8gaWYgd2UgaGFkIGFuIGFjdGl2ZSBkaWFsb2csIHJlcXVlc3QgdGhlIHByZXZpb3VzIGRpYWxvZyB0byBjbG9zZSB1bmxlc3MgaXQgd2FudHMgdG8gc3RheSBvcGVuXHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGV4aXN0aW5nQWN0aXZlRGlhbG9nICYmICFvbGREaWFsb2cua2VlcE9wZW4pIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgb2xkRGlhbG9nLmNsb3NlUmVxdWVzdGVkKERpYWxvZ0Nsb3NlUmVhc29uLkNvbXBldGluZ0RpYWxvZyk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmVtaXREaWFsb2dDaGFuZ2VFdmVudChpZCwgRGlhbG9nQ2hhbmdlRXZlbnQuU2hvdyk7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdE9ic2VydmFibGU7XHJcbiAgICAgICAgICAgICAgICB9KSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBTaG93cyBhIG1lc3NhZ2UgZGlhbG9nIHdpdGggdGhlIGdpdmVuIG9wdGlvbnNcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0gb3B0aW9ucyBUaGUgZGlhbG9nIG9wdGlvbnMuXHJcbiAgICAgKiBAcmV0dXJucyBBIHN1YmplY3QgdGhhdCB3aWxsIGJlIHB1Ymxpc2hlZCBvbmUgdGltZSB3aXRoIHRoZSBkaWFsb2cgcmVzdWx0XHJcbiAgICAgKiBAZGVwcmVjYXRlZCBQbGVhc2UgdXNlICdBcHBDb250ZXh0U2VydmljZS5mcmFtZS5zaG93RGlhbG9nTWVzc2FnZScgb24gZXh0ZW5zaW9ucy5cclxuICAgICAqL1xyXG4gICAgcHVibGljIHNob3dNZXNzYWdlKG9wdGlvbnM6IE1lc3NhZ2VEaWFsb2dPcHRpb25zKTogT2JzZXJ2YWJsZTxEaWFsb2dSZXN1bHQ+IHtcclxuICAgICAgICAvLyBpZiBydW5uaW5nIGZyb20gc2hlbGwsIG1hbnVhbGx5IGxhdW5jaCBkaWFsb2dcclxuICAgICAgICBpZiAodGhpcy5hcHBDb250ZXh0LnJwYy5pc1NoZWxsKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnNob3codGhpcy5jb21tb25JZHMubWVzc2FnZSwgb3B0aW9ucyk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgLy8gb3RoZXJ3aXNlIGFzayB0aGUgc2hlbGwgdG8gZG8gaXQgZm9yIHVzLlxyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5hcHBDb250ZXh0LmZyYW1lLnNob3dEaWFsb2dNZXNzYWdlKHtcclxuICAgICAgICAgICAgICAgIGJ1dHRvblRleHQ6IG9wdGlvbnMuYnV0dG9uVGV4dCxcclxuICAgICAgICAgICAgICAgIGNoZWNrYm94VGV4dDogb3B0aW9ucy5jaGVja2JveFRleHQsXHJcbiAgICAgICAgICAgICAgICBleHRlcm5hbExpbms6IG9wdGlvbnMuZXh0ZXJuYWxMaW5rLFxyXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogb3B0aW9ucy5tZXNzYWdlLFxyXG4gICAgICAgICAgICAgICAgdGl0bGU6IG9wdGlvbnMudGl0bGVcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogSGlkZSBhIG1lc3NhZ2UgZGlhbG9nLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgaGlkZU1lc3NhZ2UoKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5oaWRlKHRoaXMuY29tbW9uSWRzLm1lc3NhZ2UpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogU2hvd3MgYSBjaG9pY2UgZGlhbG9nIHdpdGggdGhlIGdpdmVuIG9wdGlvbnMuXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIG9wdGlvbnMgVGhlIGRpYWxvZyBvcHRpb25zLlxyXG4gICAgICogQHJldHVybnMgQSBzdWJqZWN0IHRoYXQgd2lsbCBiZSBwdWJsaXNoZWQgb25lIHRpbWUgd2l0aCB0aGUgZGlhbG9nIHJlc3VsdC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIHNob3dDaG9pY2Uob3B0aW9uczogQ2hvaWNlRGlhbG9nT3B0aW9ucyk6IE9ic2VydmFibGU8Q2hvaWNlRGlhbG9nUmVzdWx0PiB7XHJcbiAgICAgICAgaWYgKHRoaXMuYXBwQ29udGV4dC5ycGMuaXNTaGVsbCkge1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zaG93KHRoaXMuY29tbW9uSWRzLmNob2ljZSwgb3B0aW9ucyk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYXBwQ29udGV4dC5mcmFtZS5zaG93RGlhbG9nQ2hvaWNlKHtcclxuICAgICAgICAgICAgICAgIGNhbmNlbEJ1dHRvblRleHQ6IG9wdGlvbnMuY2FuY2VsQnV0dG9uVGV4dCxcclxuICAgICAgICAgICAgICAgIGNob2ljZXM6IG9wdGlvbnMuY2hvaWNlcyxcclxuICAgICAgICAgICAgICAgIGNvbmZpcm1CdXR0b25UZXh0OiBvcHRpb25zLmNvbmZpcm1CdXR0b25UZXh0LFxyXG4gICAgICAgICAgICAgICAgZm9vdG5vdGU6IG9wdGlvbnMuZm9vdG5vdGUsXHJcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBvcHRpb25zLm1lc3NhZ2UsXHJcbiAgICAgICAgICAgICAgICB0aXRsZTogb3B0aW9ucy50aXRsZVxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBIaWRlIGEgY2hvaWNlIGRpYWxvZy5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGhpZGVDaG9pY2UoKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5oaWRlPENob2ljZURpYWxvZ1Jlc3VsdD4odGhpcy5jb21tb25JZHMuY2hvaWNlKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFNob3dzIGEgY29uZmlybWF0aW9uIGRpYWxvZyB3aXRoIHRoZSBnaXZlbiBvcHRpb25zXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIG9wdGlvbnMgVGhlIGRpYWxvZyBvcHRpb25zLlxyXG4gICAgICogQHJldHVybnMgQSBzdWJqZWN0IHRoYXQgd2lsbCBiZSBwdWJsaXNoZWQgb25lIHRpbWUgd2l0aCB0aGUgZGlhbG9nIHJlc3VsdFxyXG4gICAgICogQGRlcHJlY2F0ZWQgc2luY2UgMDIvMjAvMTguIFBsZWFzZSB1c2UgJ0FwcENvbnRleHRTZXJ2aWNlLmZyYW1lLnNob3dEaWFsb2dDb25maXJtYXRpb24nIGluc3RlYWRcclxuICAgICAqL1xyXG4gICAgcHVibGljIHNob3dDb25maXJtYXRpb24ob3B0aW9uczogQ29uZmlybWF0aW9uRGlhbG9nT3B0aW9ucyk6IE9ic2VydmFibGU8Q29uZmlybWF0aW9uRGlhbG9nUmVzdWx0PiB7XHJcbiAgICAgICAgbGV0IGNvbmZpcm1hdGlvbk9ic2VydmFibGU7XHJcblxyXG4gICAgICAgIC8vIGlmIHJ1bm5pbmcgZnJvbSBzaGVsbCwgbWFudWFsbHkgbGF1bmNoIGRpYWxvZ1xyXG4gICAgICAgIGlmICh0aGlzLmFwcENvbnRleHQucnBjLmlzU2hlbGwpIHtcclxuICAgICAgICAgICAgY29uZmlybWF0aW9uT2JzZXJ2YWJsZSA9IHRoaXMuc2hvdyh0aGlzLmNvbW1vbklkcy5jb25maXJtYXRpb24sIG9wdGlvbnMpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIC8vIG90aGVyd2lzZSBhc2sgdGhlIHNoZWxsIHRvIGRvIGl0IGZvciB1cy5cclxuICAgICAgICAgICAgY29uZmlybWF0aW9uT2JzZXJ2YWJsZSA9IHRoaXMuYXBwQ29udGV4dC5mcmFtZS5zaG93RGlhbG9nQ29uZmlybWF0aW9uKHtcclxuICAgICAgICAgICAgICAgIGNhbmNlbEJ1dHRvblRleHQ6IG9wdGlvbnMuY2FuY2VsQnV0dG9uVGV4dCxcclxuICAgICAgICAgICAgICAgIGNoZWNrYm94VGV4dDogb3B0aW9ucy5jaGVja2JveFRleHQsXHJcbiAgICAgICAgICAgICAgICBjb25maXJtQnV0dG9uVGV4dDogb3B0aW9ucy5jb25maXJtQnV0dG9uVGV4dCxcclxuICAgICAgICAgICAgICAgIGRvdWJsZUNoZWNrVGV4dDogb3B0aW9ucy5kb3VibGVDaGVja1RleHQsXHJcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBvcHRpb25zLm1lc3NhZ2UsXHJcbiAgICAgICAgICAgICAgICB0aXRsZTogb3B0aW9ucy50aXRsZSxcclxuICAgICAgICAgICAgICAgIGV4dGVybmFsTGluazogb3B0aW9ucy5leHRlcm5hbExpbmtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gY29uZmlybWF0aW9uT2JzZXJ2YWJsZS5waXBlKG1hcCgocmVzcG9uc2U6IENvbmZpcm1hdGlvbkRpYWxvZ1Jlc3VsdCkgPT4ge1xyXG4gICAgICAgICAgICByZXR1cm4gcmVzcG9uc2UgfHwgeyBjb25maXJtZWQ6IGZhbHNlLCBjaGVja2JveFJlc3VsdDogZmFsc2UgfTtcclxuICAgICAgICB9KSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBIaWRlIGEgY29uZmlybWF0aW9uIGRpYWxvZy5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGhpZGVDb25maXJtYXRpb24oKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5oaWRlKHRoaXMuY29tbW9uSWRzLmNvbmZpcm1hdGlvbik7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBTaG93cyBhIGNvbmZpcm1hdGlvbiBsaXN0IGRpYWxvZyB3aXRoIHRoZSBnaXZlbiBvcHRpb25zXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIG9wdGlvbnMgVGhlIGRpYWxvZyBvcHRpb25zLlxyXG4gICAgICogQHJldHVybnMgQSBzdWJqZWN0IHRoYXQgd2lsbCBiZSBwdWJsaXNoZWQgb25lIHRpbWUgd2l0aCB0aGUgZGlhbG9nIHJlc3VsdFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc2hvd0NvbmZpcm1hdGlvbkxpc3Qob3B0aW9uczogQ29uZmlybWF0aW9uTGlzdERpYWxvZ09wdGlvbnMpOiBPYnNlcnZhYmxlPENvbmZpcm1hdGlvbkxpc3REaWFsb2dSZXN1bHQ+IHtcclxuICAgICAgICByZXR1cm4gdGhpcy5zaG93KHRoaXMuY29tbW9uSWRzLmNvbmZpcm1hdGlvbkxpc3QsIG9wdGlvbnMpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogSGlkZSBhIGNvbmZpcm1hdGlvbiBsaXN0ICBkaWFsb2cuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBoaWRlQ29uZmlybWF0aW9uTGlzdCgpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLmhpZGUodGhpcy5jb21tb25JZHMuY29uZmlybWF0aW9uTGlzdCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBIaWRlcyB0aGUgZGlhbG9nLlxyXG4gICAgICpcclxuICAgICAqIFRSZXN1bHQgVGhlIHR5cGUgb2YgdGhlIGRpYWxvZyByZXN1bHQuXHJcbiAgICAgKiBAcGFyYW0gaWQgVGhlIHVuaXF1ZSBpZGVudGlmaWVyIG9mIHRoZSBkaWFsb2cuXHJcbiAgICAgKiBAcGFyYW0gcmVzdWx0IFRoZSByZXN1bHQgb2YgdGhlIGRpYWxvZy5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGhpZGU8VFJlc3VsdCBleHRlbmRzIERpYWxvZ1Jlc3VsdD4oaWQ6IHN0cmluZywgcmVzdWx0PzogVFJlc3VsdCk6IHZvaWQge1xyXG4gICAgICAgIGlmICghaWQpIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdEaWFsb2dTZXJ2aWNlLmhpZGU6IElEIGlzIHJlcXVpcmVkIHRvIGhpZGUgYSBkaWFsb2cuJyk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoIXRoaXMuY29tcG9uZW50TWFwW2lkXSkge1xyXG4gICAgICAgICAgICBpZiAodGhpcy5wYXJlbnREaWFsb2dTZXJ2aWNlKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnBhcmVudERpYWxvZ1NlcnZpY2UuaGlkZShpZCwgcmVzdWx0KTtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgRGlhbG9nU2VydmljZS5oaWRlOiBObyBkaWFsb2cgYXNzb2NpYXRlZCB3aXRoIHByb3ZpZGVkIElEIFxcJyR7aWR9XFwnLmApO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG