UNPKG

@harbor/ui

Version:

Harbor shared UI components based on Clarity and Angular6

442 lines (441 loc) 45.2 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ import { Component, Input, Output, EventEmitter, ViewChild } from '@angular/core'; import { NgForm } from '@angular/forms'; import { Configuration } from '../config'; import { ScanningResultService, SystemInfoService, ConfigurationService } from '../../service/index'; import { ErrorHandler } from '../../error-handler/index'; import { toPromise, isEmptyObject, clone } from '../../utils'; import { TranslateService } from '@ngx-translate/core'; /** @type {?} */ const ONE_HOUR_SECONDS = 3600; /** @type {?} */ const ONE_DAY_SECONDS = 24 * ONE_HOUR_SECONDS; /** @type {?} */ const SCHEDULE_TYPE = { NONE: "none", DAILY: "daily" }; export class VulnerabilityConfigComponent { /** * @param {?} scanningService * @param {?} errorHandler * @param {?} translate * @param {?} systemInfoService * @param {?} configService */ constructor(scanningService, errorHandler, translate, systemInfoService, configService) { this.scanningService = scanningService; this.errorHandler = errorHandler; this.translate = translate; this.systemInfoService = systemInfoService; this.configService = configService; this._localTime = new Date(); this.isEditMode = false; this.SCHEDULE_TYPE = SCHEDULE_TYPE; this.onSubmitting = false; this.openState = false; this.configChange = new EventEmitter(); this.showSubTitle = false; this.showScanningNamespaces = false; } /** * @return {?} */ get vulnerabilityConfig() { return this.config; } /** * @param {?} cfg * @return {?} */ set vulnerabilityConfig(cfg) { this.config = cfg; if (this.config.scan_all_policy && this.config.scan_all_policy.value) { if (this.config.scan_all_policy.value.type === "daily") { if (!this.config.scan_all_policy.value.parameter) { this.config.scan_all_policy.value.parameter = { daily_time: 0 }; } } } this.configChange.emit(this.config); } /** * @return {?} */ get scanAvailable() { return !this.onSubmitting; } /** * @return {?} */ get updatedTimestamp() { if (this.systemInfo && this.systemInfo.clair_vulnerability_status && this.systemInfo.clair_vulnerability_status.overall_last_update > 0) { return this.convertToLocalTime(this.systemInfo.clair_vulnerability_status.overall_last_update); } return null; } /** * @return {?} */ get namespaceTimestamps() { if (this.systemInfo && this.systemInfo.clair_vulnerability_status && this.systemInfo.clair_vulnerability_status.details && this.systemInfo.clair_vulnerability_status.details.length > 0) { return this.systemInfo.clair_vulnerability_status.details; } return []; } /** * @return {?} */ get dailyTime() { if (!(this.config && this.config.scan_all_policy && this.config.scan_all_policy.value && this.config.scan_all_policy.value.type === "daily")) { return "00:00"; } /** @type {?} */ let timeOffset = 0; // seconds if (this.config.scan_all_policy.value.parameter) { /** @type {?} */ let daily_time = this.config.scan_all_policy.value.parameter.daily_time; if (daily_time && typeof daily_time === "number") { timeOffset = +daily_time; } } /** @type {?} */ let timezoneOffset = this._localTime.getTimezoneOffset(); // Local time timeOffset = timeOffset - timezoneOffset * 60; if (timeOffset < 0) { timeOffset = timeOffset + ONE_DAY_SECONDS; } if (timeOffset >= ONE_DAY_SECONDS) { timeOffset -= ONE_DAY_SECONDS; } /** @type {?} */ let hours = Math.floor(timeOffset / ONE_HOUR_SECONDS); /** @type {?} */ let minutes = Math.floor((timeOffset - hours * ONE_HOUR_SECONDS) / 60); /** @type {?} */ let timeStr = "" + hours; if (hours < 10) { timeStr = "0" + timeStr; } if (minutes < 10) { timeStr += ":0"; } else { timeStr += ":"; } timeStr += minutes; return timeStr; } /** * @param {?} v * @return {?} */ set dailyTime(v) { if (!v || v === "") { return; } if (!(this.config && this.config.scan_all_policy && this.config.scan_all_policy.value && this.config.scan_all_policy.value.type === "daily")) { return; } // Double confirm inner parameter existing. if (!this.config.scan_all_policy.value.parameter) { this.config.scan_all_policy.value.parameter = { daily_time: 0 }; } /** @type {?} */ let values = v.split(":"); if (!values || values.length !== 2) { return; } /** @type {?} */ let hours = +values[0]; /** @type {?} */ let minutes = +values[1]; /** @type {?} */ let timezoneOffset = this._localTime.getTimezoneOffset(); /** @type {?} */ let utcTimes = hours * ONE_HOUR_SECONDS + minutes * 60; utcTimes += timezoneOffset * 60; if (utcTimes < 0) { utcTimes += ONE_DAY_SECONDS; } if (utcTimes >= ONE_DAY_SECONDS) { utcTimes -= ONE_DAY_SECONDS; } this.config.scan_all_policy.value.parameter.daily_time = utcTimes; } /** * @return {?} */ get scanningType() { if (this.config && this.config.scan_all_policy && this.config.scan_all_policy.value) { return this.config.scan_all_policy.value.type; } else { // default return "none"; } } /** * @param {?} v * @return {?} */ set scanningType(v) { if (this.config && this.config.scan_all_policy && this.config.scan_all_policy.value) { /** @type {?} */ let type = (v && v.trim() !== "") ? v : "none"; this.config.scan_all_policy.value.type = type; if (type !== "daily") { // No parameter if (this.config.scan_all_policy.value.parameter) { delete (this.config.scan_all_policy.value.parameter); } } else { // Has parameter if (!this.config.scan_all_policy.value.parameter) { this.config.scan_all_policy.value.parameter = { daily_time: 0 }; } } } } /** * @return {?} */ get editable() { return this.vulnerabilityConfig && this.vulnerabilityConfig.scan_all_policy && this.vulnerabilityConfig.scan_all_policy.editable; } /** * @return {?} */ get isValid() { return this.systemSettingsForm && this.systemSettingsForm.valid; } /** * @return {?} */ get showTimePicker() { return this.vulnerabilityConfig && this.vulnerabilityConfig.scan_all_policy && this.vulnerabilityConfig.scan_all_policy.value && this.vulnerabilityConfig.scan_all_policy.value.type === "daily"; } /** * @return {?} */ get isClairDBFullyReady() { return this.systemInfo && this.systemInfo.clair_vulnerability_status && this.systemInfo.clair_vulnerability_status.overall_last_update > 0; } /** * @return {?} */ ngOnInit() { this.getSystemInfo(); this.getConfigurations(); } /** * @return {?} */ getConfigurations() { toPromise(this.configService.getConfigurations()) .then((config) => { this.configCopy = clone(config); this.config = config; }) .catch(error => { this.errorHandler.error(error); }); } /** * @return {?} */ editSchedule() { this.isEditMode = true; } /** * @param {?} utcTime * @return {?} */ convertToLocalTime(utcTime) { /** @type {?} */ let dt = new Date(); dt.setTime(utcTime * 1000); return dt; } /** * @return {?} */ scanNow() { if (this.onSubmitting) { return; // Aoid duplicated submitting } if (!this.scanAvailable) { return; // Aoid page hacking } this.onSubmitting = true; toPromise(this.scanningService.startScanningAll()) .then(() => { this.translate.get("CONFIG.SCANNING.TRIGGER_SCAN_ALL_SUCCESS").subscribe((res) => { this.errorHandler.info(res); }); // Update system info this.getSystemInfo().then(() => { this.onSubmitting = false; }).catch(() => { this.onSubmitting = false; }); }) .catch(error => { if (error && error.status && error.status === 412) { this.translate.get("CONFIG.SCANNING.TRIGGER_SCAN_ALL_FAIL", { error: '' + error }).subscribe((res) => { this.errorHandler.error(res); }); } else { this.errorHandler.error(error); } this.onSubmitting = false; }); } /** * @return {?} */ getSystemInfo() { return toPromise(this.systemInfoService.getSystemInfo()) .then((info) => this.systemInfo = info) .catch(error => this.errorHandler.error(error)); } /** * @return {?} */ save() { /** @type {?} */ let getchanges = this.config.scan_all_policy.value; /** @type {?} */ let changes = { "scan_all_policy": getchanges }; if (isEmptyObject(changes)) { return; } toPromise(this.configService.saveConfigurations(changes)) .then(() => { this.translate.get("CONFIG.SAVE_SUCCESS").subscribe((res) => { this.errorHandler.info(res); }); this.getConfigurations(); this.isEditMode = false; }, () => { this.reset(); }) .catch(error => { this.errorHandler.error(error); this.reset(); }); } /** * @return {?} */ cancel() { this.reset(); this.isEditMode = false; } /** * @return {?} */ reset() { /** @type {?} */ let getchanges = this.config.scan_all_policy.value; /** @type {?} */ let changes = { "scan_all_policy": getchanges }; for (let prop of Object.keys(changes)) { this.config[prop] = clone(this.configCopy[prop]); } } } VulnerabilityConfigComponent.decorators = [ { type: Component, args: [{ selector: 'vulnerability-config', template: "<form #systemConfigFrom=\"ngForm\" class=\"compact\">\n <section class=\"form-block\" style=\"margin-top:0px;margin-bottom:0px;\">\n <label class=\"section-title\" *ngIf=\"showSubTitle\">{{ 'CONFIG.SCANNING.TITLE' | translate }}</label>\n <div class=\"form-group\">\n <label>{{ 'CONFIG.SCANNING.DB_REFRESH_TIME' | translate }}</label>\n <clr-tooltip *ngIf=\"!isClairDBFullyReady\">\n <clr-icon shape=\"warning\" class=\"is-warning\" size=\"22\"></clr-icon>\n <clr-tooltip-content [clrPosition]=\"'top-right'\" [clrSize]=\"'md'\" *clrIfOpen>\n <span>{{'CONFIG.SCANNING.DB_NOT_READY' | translate }}</span>\n </clr-tooltip-content>\n </clr-tooltip>\n <clr-dropdown *ngIf=\"isClairDBFullyReady && showScanningNamespaces\" style=\"margin-top:-8px;\" class=\"clr-dropdown-override\">\n <button class=\"btn btn-link btn-font\" clrDropdownToggle>\n {{ updatedTimestamp | date:'MM/dd/y HH:mm:ss' }} AM\n <clr-icon shape=\"caret down\"></clr-icon>\n </button>\n <clr-dropdown-menu [clrPosition]=\"'bottom-right'\" style=\"min-width:300px;\">\n <div *ngFor=\"let nt of namespaceTimestamps\" class=\"namespace\">\n <span class=\"label label-info\">{{nt.namespace}}</span>\n <span>{{ convertToLocalTime(nt.last_update) | date:'MM/dd/y HH:mm:ss'}} AM</span>\n </div>\n </clr-dropdown-menu>\n </clr-dropdown>\n <span *ngIf=\"isClairDBFullyReady && !showScanningNamespaces\">{{ updatedTimestamp | date:'MM/dd/y HH:mm:ss' }} AM</span>\n </div>\n <div class=\"form-group vertical-center normal-wrapper\" *ngIf=\"!isEditMode\">\n <span>{{ 'CONFIG.SCANNING.SCAN_ALL' | translate }}</span>\n <span>{{ (scanningType ? 'SCHEDULE.'+ scanningType.toUpperCase(): \"\") | translate }}</span>\n <span [hidden]=\"scanningType===SCHEDULE_TYPE.NONE\">{{'SCHEDULE.AT' | translate}}</span>\n <span [hidden]=\"scanningType===SCHEDULE_TYPE.NONE\">{{ dailyTime | translate }} AM</span>\n <button class=\"btn btn-outline btn-sm\" (click)=\"editSchedule()\" id=\"editSchedule\">{{'BUTTON.EDIT' | translate}}</button>\n </div>\n <div class=\"form-group vertical-center\" *ngIf=\"isEditMode\">\n <label for=\"scanAllPolicy\">{{ 'CONFIG.SCANNING.SCAN_ALL' | translate }}</label>\n <div class=\"select\">\n <select id=\"scanAllPolicy\" name=\"scanAllPolicy\" [disabled]=\"!editable\" [(ngModel)]=\"scanningType\">\n <option value=\"none\">{{ 'SCHEDULE.NONE' | translate }}</option>\n <option value=\"daily\">{{ 'SCHEDULE.DAILY' | translate }}</option>\n </select>\n </div>\n <span [hidden]=\"!showTimePicker\">{{'SCHEDULE.AT' | translate}}</span>\n <input type=\"time\" name=\"dailyTimePicker\" required [disabled]=\"!editable\" [hidden]=\"!showTimePicker\" [(ngModel)]=\"dailyTime\" />\n <a href=\"javascript:void(0)\" role=\"tooltip\" aria-haspopup=\"true\" class=\"tooltip tooltip-top-right\">\n <clr-icon shape=\"info-circle\" class=\"info-tips-icon\" size=\"24\"></clr-icon>\n <span class=\"tooltip-content\">{{'CONFIG.TOOLTIP.SCANNING_POLICY' | translate}}</span>\n </a>\n <button id=\"config_vulnerbility_save\" class=\"btn btn-primary btn-sm\" (click)=\"save()\">{{'BUTTON.SAVE' | translate}}</button>\n <button class=\"btn btn-primary btn-sm\" (click)=\"cancel()\" >{{'BUTTON.CANCEL' | translate}}</button>\n </div>\n <div class=\"btn-scan-right btn-scan\">\n <button class=\"btn btn-primary btn-sm btn-scan\" (click)=\"scanNow()\" [disabled]=\"!scanAvailable\">{{ 'CONFIG.SCANNING.SCAN_NOW' | translate }}</button><br>\n </div>\n </section>\n</form>", styles: [".form-group-override{padding-left:0!important}.vertical-center{display:flex;align-items:center}.normal-wrapper>span:not(:first-child){margin-right:18px}.section-title{font-size:14px!important;font-weight:600!important}.btn-font{font-size:12px!important}.namespace{margin-left:24px}.clr-dropdown-override{margin-top:-8px}.btn-scan-right button{width:160px;margin-bottom:0;margin-top:5px}.btn-scan-right span{margin-top:4px}", ".info-tips-icon{color:grey}.info-tips-icon:hover{color:#007cbb}"] }] } ]; /** @nocollapse */ VulnerabilityConfigComponent.ctorParameters = () => [ { type: ScanningResultService }, { type: ErrorHandler }, { type: TranslateService }, { type: SystemInfoService }, { type: ConfigurationService } ]; VulnerabilityConfigComponent.propDecorators = { configChange: [{ type: Output }], vulnerabilityConfig: [{ type: Input }], showSubTitle: [{ type: Input }], showScanningNamespaces: [{ type: Input }], systemSettingsForm: [{ type: ViewChild, args: ["systemConfigFrom",] }] }; if (false) { /** @type {?} */ VulnerabilityConfigComponent.prototype._localTime; /** @type {?} */ VulnerabilityConfigComponent.prototype.isEditMode; /** @type {?} */ VulnerabilityConfigComponent.prototype.SCHEDULE_TYPE; /** @type {?} */ VulnerabilityConfigComponent.prototype.configCopy; /** @type {?} */ VulnerabilityConfigComponent.prototype.onSubmitting; /** @type {?} */ VulnerabilityConfigComponent.prototype.config; /** @type {?} */ VulnerabilityConfigComponent.prototype.openState; /** @type {?} */ VulnerabilityConfigComponent.prototype.configChange; /** @type {?} */ VulnerabilityConfigComponent.prototype.showSubTitle; /** @type {?} */ VulnerabilityConfigComponent.prototype.showScanningNamespaces; /** @type {?} */ VulnerabilityConfigComponent.prototype.systemInfo; /** @type {?} */ VulnerabilityConfigComponent.prototype.systemSettingsForm; /** @type {?} */ VulnerabilityConfigComponent.prototype.scanningService; /** @type {?} */ VulnerabilityConfigComponent.prototype.errorHandler; /** @type {?} */ VulnerabilityConfigComponent.prototype.translate; /** @type {?} */ VulnerabilityConfigComponent.prototype.systemInfoService; /** @type {?} */ VulnerabilityConfigComponent.prototype.configService; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidnVsbmVyYWJpbGl0eS1jb25maWcuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vQGhhcmJvci91aS8iLCJzb3VyY2VzIjpbInNyYy9jb25maWcvdnVsbmVyYWJpbGl0eS92dWxuZXJhYmlsaXR5LWNvbmZpZy5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxZQUFZLEVBQUUsU0FBUyxFQUFVLE1BQU0sZUFBZSxDQUFDO0FBQzFGLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUV4QyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQzFDLE9BQU8sRUFDSCxxQkFBcUIsRUFFckIsaUJBQWlCLEVBQ2pCLG9CQUFvQixFQUN2QixNQUFNLHFCQUFxQixDQUFDO0FBQzdCLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsU0FBUyxFQUFFLGFBQWEsRUFBRSxLQUFLLEVBQUMsTUFBTSxhQUFhLENBQUM7QUFDN0QsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0scUJBQXFCLENBQUM7O0FBRXZELE1BQU0sZ0JBQWdCLEdBQVcsSUFBSSxDQUFDOztBQUN0QyxNQUFNLGVBQWUsR0FBVyxFQUFFLEdBQUcsZ0JBQWdCLENBQUM7O0FBQ3RELE1BQU0sYUFBYSxHQUFHO0lBQ2xCLElBQUksRUFBRSxNQUFNO0lBQ1osS0FBSyxFQUFFLE9BQU87Q0FDakIsQ0FBQztBQU1GLE1BQU07Ozs7Ozs7O0lBaUNGLFlBQ1ksaUJBQ0EsY0FDQSxXQUNBLG1CQUNBO1FBSkEsb0JBQWUsR0FBZixlQUFlO1FBQ2YsaUJBQVksR0FBWixZQUFZO1FBQ1osY0FBUyxHQUFULFNBQVM7UUFDVCxzQkFBaUIsR0FBakIsaUJBQWlCO1FBQ2pCLGtCQUFhLEdBQWIsYUFBYTswQkFyQ04sSUFBSSxJQUFJ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QUM7YUFDRCxLQUFLLENBQUMsS0FBSyxDQUFDLEVBQUU7WUFDWCxJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUMvQixJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7U0FDaEIsQ0FBQyxDQUFDO0tBQ1Y7Ozs7SUFFRCxNQUFNO1FBQ0YsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ2IsSUFBSSxDQUFDLFVBQVUsR0FBRyxLQUFLLENBQUM7S0FDM0I7Ozs7SUFFRCxLQUFLOztRQUVELElBQUksVUFBVSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsZUFBZSxDQUFDLEtBQUssQ0FBQzs7UUFDbkQsSUFBSSxPQUFPLEdBQUcsRUFBQyxpQkFBaUIsRUFBRSxVQUFVLEVBQUMsQ0FBQztRQUM5QyxLQUFLLElBQUksSUFBSSxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUU7WUFDbkMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1NBQ3BEO0tBQ0o7OztZQWpVSixTQUFTLFNBQUM7Z0JBQ1AsUUFBUSxFQUFFLHNCQUFzQjtnQkFDaEMsdTlIQUFvRDs7YUFFdkQ7Ozs7WUFuQkcscUJBQXFCO1lBS2hCLFlBQVk7WUFFWixnQkFBZ0I7WUFMckIsaUJBQWlCO1lBQ2pCLG9CQUFvQjs7OzJCQXlCbkIsTUFBTTtrQ0FFTixLQUFLOzJCQW1CTCxLQUFLO3FDQUNMLEtBQUs7aUNBNkpMLFNBQVMsU0FBQyxrQkFBa0IiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIElucHV0LCBPdXRwdXQsIEV2ZW50RW1pdHRlciwgVmlld0NoaWxkLCBPbkluaXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE5nRm9ybSB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcblxuaW1wb3J0IHsgQ29uZmlndXJhdGlvbiB9IGZyb20gJy4uL2NvbmZpZyc7XG5pbXBvcnQge1xuICAgIFNjYW5uaW5nUmVzdWx0U2VydmljZSxcbiAgICBTeXN0ZW1JbmZvLFxuICAgIFN5c3RlbUluZm9TZXJ2aWNlLFxuICAgIENvbmZpZ3VyYXRpb25TZXJ2aWNlXG59IGZyb20gJy4uLy4uL3NlcnZpY2UvaW5kZXgnO1xuaW1wb3J0IHsgRXJyb3JIYW5kbGVyIH0gZnJvbSAnLi4vLi4vZXJyb3ItaGFuZGxlci9pbmRleCc7XG5pbXBvcnQgeyB0b1Byb21pc2UsIGlzRW1wdHlPYmplY3QsIGNsb25lfSBmcm9tICcuLi8uLi91dGlscyc7XG5pbXBvcnQgeyBUcmFuc2xhdGVTZXJ2aWNlIH0gZnJvbSAnQG5neC10cmFuc2xhdGUvY29yZSc7XG5pbXBvcnQgeyBDbGFpckRldGFpbCB9IGZyb20gJy4uLy4uL3NlcnZpY2UvaW50ZXJmYWNlJztcbmNvbnN0IE9ORV9IT1VSX1NFQ09ORFM6IG51bWJlciA9IDM2MDA7XG5jb25zdCBPTkVfREFZX1NFQ09ORFM6IG51bWJlciA9IDI0ICogT05FX0hPVVJfU0VDT05EUztcbmNvbnN0IFNDSEVEVUxFX1RZUEUgPSB7XG4gICAgTk9ORTogXCJub25lXCIsXG4gICAgREFJTFk6IFwiZGFpbHlcIlxufTtcbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiAndnVsbmVyYWJpbGl0eS1jb25maWcnLFxuICAgIHRlbXBsYXRlVXJsOiAnLi92dWxuZXJhYmlsaXR5LWNvbmZpZy5jb21wb25lbnQuaHRtbCcsXG4gICAgc3R5bGVVcmxzOiBbJy4vdnVsbmVyYWJpbGl0eS1jb25maWcuY29tcG9uZW50LnNjc3MnLCAnLi4vcmVnaXN0cnktY29uZmlnLmNvbXBvbmVudC5zY3NzJ11cbn0pXG5leHBvcnQgY2xhc3MgVnVsbmVyYWJpbGl0eUNvbmZpZ0NvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG4gICAgX2xvY2FsVGltZTogRGF0ZSA9IG5ldyBEYXRlKCk7XG4gICAgaXNFZGl0TW9kZTogYm9vbGVhbiA9IGZhbHNlO1xuICAgIFNDSEVEVUxFX1RZUEUgPSBTQ0hFRFVMRV9UWVBFO1xuICAgIGNvbmZpZ0NvcHk6IENvbmZpZ3VyYXRpb247XG4gICAgb25TdWJtaXR0aW5nOiBib29sZWFuID0gZmFsc2U7XG4gICAgY29uZmlnOiBDb25maWd1cmF0aW9uO1xuICAgIG9wZW5TdGF0ZTogYm9vbGVhbiA9IGZhbHNlO1xuICAgIEBPdXRwdXQoKSBjb25maWdDaGFuZ2U6IEV2ZW50RW1pdHRlcjxDb25maWd1cmF0aW9uPiA9IG5ldyBFdmVudEVtaXR0ZXI8Q29uZmlndXJhdGlvbj4oKTtcblxuICAgIEBJbnB1dCgpXG4gICAgZ2V0IHZ1bG5lcmFiaWxpdHlDb25maWcoKTogQ29uZmlndXJhdGlvbiB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbmZpZztcbiAgICB9XG4gICAgc2V0IHZ1bG5lcmFiaWxpdHlDb25maWcoY2ZnOiBDb25maWd1cmF0aW9uKSB7XG4gICAgICAgIHRoaXMuY29uZmlnID0gY2ZnO1xuICAgICAgICBpZiAodGhpcy5jb25maWcuc2Nhbl9hbGxfcG9saWN5ICYmXG4gICAgICAgICAgICB0aGlzLmNvbmZpZy5zY2FuX2FsbF9wb2xpY3kudmFsdWUpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZy5zY2FuX2FsbF9wb2xpY3kudmFsdWUudHlwZSA9PT0gXCJkYWlseVwiKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmNvbmZpZy5zY2FuX2FsbF9wb2xpY3kudmFsdWUucGFyYW1ldGVyKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLnNjYW5fYWxsX3BvbGljeS52YWx1ZS5wYXJhbWV0ZXIgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkYWlseV90aW1lOiAwXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHRoaXMuY29uZmlnQ2hhbmdlLmVtaXQodGhpcy5jb25maWcpO1xuICAgIH1cblxuICAgIEBJbnB1dCgpIHNob3dTdWJUaXRsZTogYm9vbGVhbiA9IGZhbHNlO1xuICAgIEBJbnB1dCgpIHNob3dTY2FubmluZ05hbWVzcGFjZXM6IGJvb2xlYW4gPSBmYWxzZTtcbiAgICBzeXN0ZW1JbmZvOiBTeXN0ZW1JbmZvO1xuXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIHByaXZhdGUgc2Nhbm5pbmdTZXJ2aWNlOiBTY2FubmluZ1Jlc3VsdFNlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgZXJyb3JIYW5kbGVyOiBFcnJvckhhbmRsZXIsXG4gICAgICAgIHByaXZhdGUgdHJhbnNsYXRlOiBUcmFuc2xhdGVTZXJ2aWNlLFxuICAgICAgICBwcml2YXRlIHN5c3RlbUluZm9TZXJ2aWNlOiBTeXN0ZW1JbmZvU2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSBjb25maWdTZXJ2aWNlOiBDb25maWd1cmF0aW9uU2VydmljZVxuICAgICkgeyB9XG5cbiAgICBnZXQgc2NhbkF2YWlsYWJsZSgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuICF0aGlzLm9uU3VibWl0dGluZztcbiAgICB9XG5cbiAgICBnZXQgdXBkYXRlZFRpbWVzdGFtcCgpOiBEYXRlIHtcbiAgICAgICAgaWYgKHRoaXMuc3lzdGVtSW5mbyAmJlxuICAgICAgICAgICAgdGhpcy5zeXN0ZW1JbmZvLmNsYWlyX3Z1bG5lcmFiaWxpdHlfc3RhdHVzICYmXG4gICAgICAgICAgICB0aGlzLnN5c3RlbUluZm8uY2xhaXJfdnVsbmVyYWJpbGl0eV9zdGF0dXMub3ZlcmFsbF9sYXN0X3VwZGF0ZSA+IDApIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbnZlcnRUb0xvY2FsVGltZSh0aGlzLnN5c3RlbUluZm8uY2xhaXJfdnVsbmVyYWJpbGl0eV9zdGF0dXMub3ZlcmFsbF9sYXN0X3VwZGF0ZSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBnZXQgbmFtZXNwYWNlVGltZXN0YW1wcygpOiBDbGFpckRldGFpbFtdIHtcbiAgICAgICAgaWYgKHRoaXMuc3lzdGVtSW5mbyAmJlxuICAgICAgICAgICAgdGhpcy5zeXN0ZW1JbmZvLmNsYWlyX3Z1bG5lcmFiaWxpdHlfc3RhdHVzICYmXG4gICAgICAgICAgICB0aGlzLnN5c3RlbUluZm8uY2xhaXJfdnVsbmVyYWJpbGl0eV9zdGF0dXMuZGV0YWlscyAmJlxuICAgICAgICAgICAgdGhpcy5zeXN0ZW1JbmZvLmNsYWlyX3Z1bG5lcmFiaWxpdHlfc3RhdHVzLmRldGFpbHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc3lzdGVtSW5mby5jbGFpcl92dWxuZXJhYmlsaXR5X3N0YXR1cy5kZXRhaWxzO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIC8vIFVUQyB0aW1lXG4gICAgZ2V0IGRhaWx5VGltZSgpOiBzdHJpbmcge1xuICAgICAgICBpZiAoISh0aGlzLmNvbmZpZyAmJlxuICAgICAgICAgICAgdGhpcy5jb25maWcuc2Nhbl9hbGxfcG9saWN5ICYmXG4gICAgICAgICAgICB0aGlzLmNvbmZpZy5zY2FuX2FsbF9wb2xpY3kudmFsdWUgJiZcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLnNjYW5fYWxsX3BvbGljeS52YWx1ZS50eXBlID09PSBcImRhaWx5XCIpKSB7XG4gICAgICAgICAgICByZXR1cm4gXCIwMDowMFwiO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHRpbWVPZmZzZXQ6IG51bWJlciA9IDA7IC8vIHNlY29uZHNcbiAgICAgICAgaWYgKHRoaXMuY29uZmlnLnNjYW5fYWxsX3BvbGljeS52YWx1ZS5wYXJhbWV0ZXIpIHtcbiAgICAgICAgICAgIGxldCBkYWlseV90aW1lID0gdGhpcy5jb25maWcuc2Nhbl9hbGxfcG9saWN5LnZhbHVlLnBhcmFtZXRlci5kYWlseV90aW1lO1xuICAgICAgICAgICAgaWYgKGRhaWx5X3RpbWUgJiYgdHlwZW9mIGRhaWx5X3RpbWUgPT09IFwibnVtYmVyXCIpIHtcbiAgICAgICAgICAgICAgICB0aW1lT2Zmc2V0ID0gK2RhaWx5X3RpbWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gQ29udmVydCB0byBjdXJyZW50IHRpbWVcbiAgICAgICAgbGV0IHRpbWV6b25lT2Zmc2V0OiBudW1iZXIgPSB0aGlzLl9sb2NhbFRpbWUuZ2V0VGltZXpvbmVPZmZzZXQoKTtcbiAgICAgICAgLy8gTG9jYWwgdGltZVxuICAgICAgICB0aW1lT2Zmc2V0ID0gdGltZU9mZnNldCAtIHRpbWV6b25lT2Zmc2V0ICogNjA7XG4gICAgICAgIGlmICh0aW1lT2Zmc2V0IDwgMCkge1xuICAgICAgICAgICAgdGltZU9mZnNldCA9IHRpbWVPZmZzZXQgKyBPTkVfREFZX1NFQ09ORFM7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGltZU9mZnNldCA+PSBPTkVfREFZX1NFQ09ORFMpIHtcbiAgICAgICAgICAgIHRpbWVPZmZzZXQgLT0gT05FX0RBWV9TRUNPTkRTO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVG8gdGltZSBzdHJpbmdcbiAgICAgICAgbGV0IGhvdXJzOiBudW1iZXIgPSBNYXRoLmZsb29yKHRpbWVPZmZzZXQgLyBPTkVfSE9VUl9TRUNPTkRTKTtcbiAgICAgICAgbGV0IG1pbnV0ZXM6IG51bWJlciA9IE1hdGguZmxvb3IoKHRpbWVPZmZzZXQgLSBob3VycyAqIE9ORV9IT1VSX1NFQ09ORFMpIC8gNjApO1xuXG4gICAgICAgIGxldCB0aW1lU3RyOiBzdHJpbmcgPSBcIlwiICsgaG91cnM7XG4gICAgICAgIGlmIChob3VycyA8IDEwKSB7XG4gICAgICAgICAgICB0aW1lU3RyID0gXCIwXCIgKyB0aW1lU3RyO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtaW51dGVzIDwgMTApIHtcbiAgICAgICAgICAgIHRpbWVTdHIgKz0gXCI6MFwiO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGltZVN0ciArPSBcIjpcIjtcbiAgICAgICAgfVxuICAgICAgICB0aW1lU3RyICs9IG1pbnV0ZXM7XG5cbiAgICAgICAgcmV0dXJuIHRpbWVTdHI7XG4gICAgfVxuICAgIHNldCBkYWlseVRpbWUodjogc3RyaW5nKSB7XG4gICAgICAgIGlmICghdiB8fCB2ID09PSBcIlwiKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoISh0aGlzLmNvbmZpZyAmJlxuICAgICAgICAgICAgdGhpcy5jb25maWcuc2Nhbl9hbGxfcG9saWN5ICYmXG4gICAgICAgICAgICB0aGlzLmNvbmZpZy5zY2FuX2FsbF9wb2xpY3kudmFsdWUgJiZcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLnNjYW5fYWxsX3BvbGljeS52YWx1ZS50eXBlID09PSBcImRhaWx5XCIpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBEb3VibGUgY29uZmlybSBpbm5lciBwYXJhbWV0ZXIgZXhpc3RpbmcuXG4gICAgICAgIGlmICghdGhpcy5jb25maWcuc2Nhbl9hbGxfcG9saWN5LnZhbHVlLnBhcmFtZXRlcikge1xuICAgICAgICAgICAgdGhpcy5jb25maWcuc2Nhbl9hbGxfcG9saWN5LnZhbHVlLnBhcmFtZXRlciA9IHtcbiAgICAgICAgICAgICAgICBkYWlseV90aW1lOiAwXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHZhbHVlczogc3RyaW5nW10gPSB2LnNwbGl0KFwiOlwiKTtcbiAgICAgICAgaWYgKCF2YWx1ZXMgfHwgdmFsdWVzLmxlbmd0aCAhPT0gMikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGhvdXJzOiBudW1iZXIgPSArdmFsdWVzWzBdO1xuICAgICAgICBsZXQgbWludXRlczogbnVtYmVyID0gK3ZhbHVlc1sxXTtcbiAgICAgICAgLy8gQ29udmVydCB0byBVVEMgdGltZVxuICAgICAgICBsZXQgdGltZXpvbmVPZmZzZXQ6IG51bWJlciA9IHRoaXMuX2xvY2FsVGltZS5nZXRUaW1lem9uZU9mZnNldCgpO1xuICAgICAgICBsZXQgdXRjVGltZXM6IG51bWJlciA9IGhvdXJzICogT05FX0hPVVJfU0VDT05EUyArIG1pbnV0ZXMgKiA2MDtcbiAgICAgICAgdXRjVGltZXMgKz0gdGltZXpvbmVPZmZzZXQgKiA2MDtcbiAgICAgICAgaWYgKHV0Y1RpbWVzIDwgMCkge1xuICAgICAgICAgICAgdXRjVGltZXMgKz0gT05FX0RBWV9TRUNPTkRTO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHV0Y1RpbWVzID49IE9ORV9EQVlfU0VDT05EUykge1xuICAgICAgICAgICAgdXRjVGltZXMgLT0gT05FX0RBWV9TRUNPTkRTO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5jb25maWcuc2Nhbl9hbGxfcG9saWN5LnZhbHVlLnBhcmFtZXRlci5kYWlseV90aW1lID0gdXRjVGltZXM7XG4gICAgfVxuXG4gICAgLy8gU2Nhbm5pbmcgdHlwZVxuICAgIGdldCBzY2FubmluZ1R5cGUoKTogc3RyaW5nIHtcbiAgICAgICAgaWYgKHRoaXMuY29uZmlnICYmXG4gICAgICAgICAgICB0aGlzLmNvbmZpZy5zY2FuX2FsbF9wb2xpY3kgJiZcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLnNjYW5fYWxsX3BvbGljeS52YWx1ZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY29uZmlnLnNjYW5fYWxsX3BvbGljeS52YWx1ZS50eXBlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gZGVmYXVsdFxuICAgICAgICAgICAgcmV0dXJuIFwibm9uZVwiO1xuICAgICAgICB9XG4gICAgfVxuXG5cbiAgICBzZXQgc2Nhbm5pbmdUeXBlKHY6IHN0cmluZykge1xuICAgICAgICBpZiAodGhpcy5jb25maWcgJiZcbiAgICAgICAgICAgIHRoaXMuY29uZmlnLnNjYW5fYWxsX3BvbGljeSAmJlxuICAgICAgICAgICAgdGhpcy5jb25maWcuc2Nhbl9hbGxfcG9saWN5LnZhbHVlKSB7XG4gICAgICAgICAgICBsZXQgdHlwZTogc3RyaW5nID0gKHYgJiYgdi50cmltKCkgIT09IFwiXCIpID8gdiA6IFwibm9uZVwiO1xuICAgICAgICAgICAgdGhpcy5jb25maWcuc2Nhbl9hbGxfcG9saWN5LnZhbHVlLnR5cGUgPSB0eXBlO1xuICAgICAgICAgICAgaWYgKHR5cGUgIT09IFwiZGFpbHlcIikge1xuICAgICAgICAgICAgICAgIC8vIE5vIHBhcmFtZXRlclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLmNvbmZpZy5zY2FuX2FsbF9wb2xpY3kudmFsdWUucGFyYW1ldGVyKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSAodGhpcy5jb25maWcuc2Nhbl9hbGxfcG9saWN5LnZhbHVlLnBhcmFtZXRlcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBIYXMgcGFyYW1ldGVyXG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmNvbmZpZy5zY2FuX2FsbF9wb2xpY3kudmFsdWUucGFyYW1ldGVyKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnLnNjYW5fYWxsX3BvbGljeS52YWx1ZS5wYXJhbWV0ZXIgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkYWlseV90aW1lOiAwXG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgQFZpZXdDaGlsZChcInN5c3RlbUNvbmZpZ0Zyb21cIikgc3lzdGVtU2V0dGluZ3NGb3JtOiBOZ0Zvcm07XG5cbiAgICBnZXQgZWRpdGFibGUoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLnZ1bG5lcmFiaWxpdHlDb25maWcgJiZcbiAgICAgICAgICAgIHRoaXMudnVsbmVyYWJpbGl0eUNvbmZpZy5zY2FuX2FsbF9wb2xpY3kgJiZcbiAgICAgICAgICAgIHRoaXMudnVsbmVyYWJpbGl0eUNvbmZpZy5zY2FuX2FsbF9wb2xpY3kuZWRpdGFibGU7XG4gICAgfVxuXG4gICAgZ2V0IGlzVmFsaWQoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLnN5c3RlbVNldHRpbmdzRm9ybSAmJiB0aGlzLnN5c3RlbVNldHRpbmdzRm9ybS52YWxpZDtcbiAgICB9XG5cbiAgICBnZXQgc2hvd1RpbWVQaWNrZXIoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLnZ1bG5lcmFiaWxpdHlDb25maWcgJiZcbiAgICAgICAgICAgIHRoaXMudnVsbmVyYWJpbGl0eUNvbmZpZy5zY2FuX2FsbF9wb2xpY3kgJiZcbiAgICAgICAgICAgIHRoaXMudnVsbmVyYWJpbGl0eUNvbmZpZy5zY2FuX2FsbF9wb2xpY3kudmFsdWUgJiZcbiAgICAgICAgICAgIHRoaXMudnVsbmVyYWJpbGl0eUNvbmZpZy5zY2FuX2FsbF9wb2xpY3kudmFsdWUudHlwZSA9PT0gXCJkYWlseVwiO1xuICAgIH1cblxuICAgIGdldCBpc0NsYWlyREJGdWxseVJlYWR5KCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5zeXN0ZW1JbmZvICYmXG4gICAgICAgICAgICB0aGlzLnN5c3RlbUluZm8uY2xhaXJfdnVsbmVyYWJpbGl0eV9zdGF0dXMgJiZcbiAgICAgICAgICAgIHRoaXMuc3lzdGVtSW5mby5jbGFpcl92dWxuZXJhYmlsaXR5X3N0YXR1cy5vdmVyYWxsX2xhc3RfdXBkYXRlID4gMDtcbiAgICB9XG5cbiAgICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5nZXRTeXN0ZW1JbmZvKCk7XG4gICAgICAgIHRoaXMuZ2V0Q29uZmlndXJhdGlvbnMoKTtcbiAgICB9XG5cbiAgICBnZXRDb25maWd1cmF0aW9ucygpOiB2b2lkIHtcbiAgICAgICAgdG9Qcm9taXNlPENvbmZpZ3VyYXRpb24+KHRoaXMuY29uZmlnU2VydmljZS5nZXRDb25maWd1cmF0aW9ucygpKVxuICAgICAgICAgICAgLnRoZW4oKGNvbmZpZzogQ29uZmlndXJhdGlvbikgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuY29uZmlnQ29weSA9IGNsb25lKGNvbmZpZyk7XG4gICAgICAgICAgICAgICAgdGhpcy5jb25maWcgPSBjb25maWc7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmVycm9ySGFuZGxlci5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBlZGl0U2NoZWR1bGUoKSB7XG4gICAgICAgIHRoaXMuaXNFZGl0TW9kZSA9IHRydWU7XG4gICAgIH1cblxuICAgIGNvbnZlcnRUb0xvY2FsVGltZSh1dGNUaW1lOiBudW1iZXIpOiBEYXRlIHtcbiAgICAgICAgbGV0IGR0OiBEYXRlID0gbmV3IERhdGUoKTtcbiAgICAgICAgZHQuc2V0VGltZSh1dGNUaW1lICogMTAwMCk7XG5cbiAgICAgICAgcmV0dXJuIGR0O1xuICAgIH1cblxuICAgIHNjYW5Ob3coKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLm9uU3VibWl0dGluZykge1xuICAgICAgICAgICAgcmV0dXJuOyAvLyBBb2lkIGR1cGxpY2F0ZWQgc3VibWl0dGluZ1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCF0aGlzLnNjYW5BdmFpbGFibGUpIHtcbiAgICAgICAgICAgIHJldHVybjsgLy8gQW9pZCBwYWdlIGhhY2tpbmdcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMub25TdWJtaXR0aW5nID0gdHJ1ZTtcbiAgICAgICAgdG9Qcm9taXNlPGFueT4odGhpcy5zY2FubmluZ1NlcnZpY2Uuc3RhcnRTY2FubmluZ0FsbCgpKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudHJhbnNsYXRlLmdldChcIkNPTkZJRy5TQ0FOTklORy5UUklHR0VSX1NDQU5fQUxMX1NVQ0NFU1NcIikuc3Vic2NyaWJlKChyZXM6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVycm9ySGFuZGxlci5pbmZvKHJlcyk7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAvLyBVcGRhdGUgc3lzdGVtIGluZm9cbiAgICAgICAgICAgICAgICB0aGlzLmdldFN5c3RlbUluZm8oKS50aGVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5vblN1Ym1pdHRpbmcgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB9KS5jYXRjaCgoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub25TdWJtaXR0aW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoZXJyb3IgJiYgZXJyb3Iuc3RhdHVzICYmIGVycm9yLnN0YXR1cyA9PT0gNDEyKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudHJhbnNsYXRlLmdldChcIkNPTkZJRy5TQ0FOTklORy5UUklHR0VSX1NDQU5fQUxMX0ZBSUxcIiwgeyBlcnJvcjogJycgKyBlcnJvciB9KS5zdWJzY3JpYmUoKHJlczogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmVycm9ySGFuZGxlci5lcnJvcihyZXMpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVycm9ySGFuZGxlci5lcnJvcihlcnJvcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMub25TdWJtaXR0aW5nID0gZmFsc2U7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBnZXRTeXN0ZW1JbmZvKCk6IFByb21pc2U8dm9pZCB8IFN5c3RlbUluZm8+IHtcbiAgICAgICAgcmV0dXJuIHRvUHJvbWlzZTxTeXN0ZW1JbmZvPih0aGlzLnN5c3RlbUluZm9TZXJ2aWNlLmdldFN5c3RlbUluZm8oKSlcbiAgICAgICAgICAgIC50aGVuKChpbmZvOiBTeXN0ZW1JbmZvKSA9PiB0aGlzLnN5c3RlbUluZm8gPSBpbmZvKVxuICAgICAgICAgICAgLmNhdGNoKGVycm9yID0+IHRoaXMuZXJyb3JIYW5kbGVyLmVycm9yKGVycm9yKSk7XG4gICAgfVxuXG4gICAgc2F2ZSgpOiB2b2lkIHtcbiAgICAgICAgbGV0IGdldGNoYW5nZXMgPSB0aGlzLmNvbmZpZy5zY2FuX2FsbF9wb2xpY3kudmFsdWU7XG4gICAgICAgIGxldCBjaGFuZ2VzID0ge1wic2Nhbl9hbGxfcG9saWN5XCI6IGdldGNoYW5nZXN9O1xuXG4gICAgICAgIGlmIChpc0VtcHR5T2JqZWN0KGNoYW5nZXMpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0b1Byb21pc2U8YW55Pih0aGlzLmNvbmZpZ1NlcnZpY2Uuc2F2ZUNvbmZpZ3VyYXRpb25zKGNoYW5nZXMpKVxuICAgICAgICAgICAgLnRoZW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudHJhbnNsYXRlLmdldChcIkNPTkZJRy5TQVZFX1NVQ0NFU1NcIikuc3Vic2NyaWJlKChyZXM6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmVycm9ySGFuZGxlci5pbmZvKHJlcyk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgdGhpcy5nZXRDb25maWd1cmF0aW9ucygpO1xuICAgICAgICAgICAgICAgIHRoaXMuaXNFZGl0TW9kZSA9IGZhbHNlO1xuICAgICAgICAgICAgfSwgKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMucmVzZXQoKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2goZXJyb3IgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuZXJyb3JIYW5kbGVyLmVycm9yKGVycm9yKTtcbiAgICAgICAgICAgICAgICB0aGlzLnJlc2V0KCk7XG4gICAgICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBjYW5jZWwoKTogdm9pZCB7XG4gICAgICAgIHRoaXMucmVzZXQoKTtcbiAgICAgICAgdGhpcy5pc0VkaXRNb2RlID0gZmFsc2U7XG4gICAgfVxuXG4gICAgcmVzZXQoKTogdm9pZCB7XG4gICAgICAgIC8vIFJlc2V0IHRvIHRoZSB2YWx1ZXMgb2YgY29weVxuICAgICAgICBsZXQgZ2V0Y2hhbmdlcyA9IHRoaXMuY29uZmlnLnNjYW5fYWxsX3BvbGljeS52YWx1ZTtcbiAgICAgICAgbGV0IGNoYW5nZXMgPSB7XCJzY2FuX2FsbF9wb2xpY3lcIjogZ2V0Y2hhbmdlc307XG4gICAgICAgIGZvciAobGV0IHByb3Agb2YgT2JqZWN0LmtleXMoY2hhbmdlcykpIHtcbiAgICAgICAgICAgIHRoaXMuY29uZmlnW3Byb3BdID0gY2xvbmUodGhpcy5jb25maWdDb3B5W3Byb3BdKTtcbiAgICAgICAgfVxuICAgIH1cbn1cbiJdfQ==