ionic-logging-service
Version:
Logging functionalities for apps built with Ionic framework
167 lines • 22.3 kB
JavaScript
import { EventEmitter, Injectable } from "@angular/core";
import * as log4javascript from "log4javascript";
import { AjaxAppender } from "./ajax-appender.model";
import { LocalStorageAppender } from "./local-storage-appender.model";
import { LogLevelConverter } from "./log-level.converter";
import { Logger } from "./logger.model";
import { MemoryAppender } from "./memory-appender.model";
import * as i0 from "@angular/core";
/**
* Service for logging functionality.
*
* By default, the following settings are used:
* - logger: root with level WARN
* - appender: BrowserConsoleAppender with threshold DEBUG and MemoryAppender with threshold ALL
*
* Via [configure](#configure), it is possible to amend these settings.
*/
export class LoggingService {
/**
* Creates a new instance of the service.
*/
constructor() {
// prevent log4javascript to show alerts on case of errors
log4javascript.logLog.setQuietMode(true);
// create event emitter
this.logMessagesChanged = new EventEmitter();
this.ajaxAppenderFailed = new EventEmitter();
// configure appender
const logger = log4javascript.getRootLogger();
logger.setLevel(log4javascript.Level.WARN);
// browser console appender for debugger
this.browserConsoleAppender = new log4javascript.BrowserConsoleAppender();
this.browserConsoleAppender.setLayout(new log4javascript.PatternLayout("%d{HH:mm:ss,SSS} %c %m"));
this.browserConsoleAppender.setThreshold(log4javascript.Level.ALL);
logger.addAppender(this.browserConsoleAppender);
// in-memory appender for display on log messages page
this.memoryAppender = new MemoryAppender();
this.memoryAppender.setLayout(new log4javascript.PatternLayout("%d{HH:mm:ss,SSS} %c %m"));
this.memoryAppender.setOnLogMessagesChangedCallback((message) => {
this.logMessagesChanged.emit();
});
logger.addAppender(this.memoryAppender);
this.configure();
}
/**
* Configures the logging depending on the given configuration.
*
* @param configuration configuration data.
*/
configure(configuration) {
if (typeof configuration === "undefined") {
configuration = {};
}
// set log levels
if (typeof configuration.logLevels !== "undefined") {
for (const level of configuration.logLevels) {
let logger;
if (level.loggerName === "root") {
logger = log4javascript.getRootLogger();
}
else {
logger = log4javascript.getLogger(level.loggerName);
}
try {
logger.setLevel(LogLevelConverter.levelToLog4Javascript(LogLevelConverter.levelFromString(level.logLevel)));
}
catch (e) {
throw new Error(`invalid log level ${level.logLevel}`);
}
}
}
// configure AjaxAppender
if (typeof configuration.ajaxAppender !== "undefined") {
const ajaxAppender = new AjaxAppender(configuration.ajaxAppender);
ajaxAppender.appenderFailed.subscribe((message) => {
this.ajaxAppenderFailed.emit(message);
});
log4javascript.getRootLogger().addAppender(ajaxAppender);
}
// configure LocalStorageAppender
if (typeof configuration.localStorageAppender !== "undefined") {
const localStorageAppender = new LocalStorageAppender(configuration.localStorageAppender);
log4javascript.getRootLogger().addAppender(localStorageAppender);
// ensure that an eventual memoryAppender is behind the localStorageAppender
const appenders = new Logger().getInternalLogger().getEffectiveAppenders();
const memoryAppender = appenders.find((a) => a.toString() === "Ionic.Logging.MemoryAppender");
if (memoryAppender) {
log4javascript.getRootLogger().removeAppender(memoryAppender);
log4javascript.getRootLogger().addAppender(memoryAppender);
}
}
// configure MemoryAppender
if (configuration.memoryAppender) {
this.memoryAppender.configure(configuration.memoryAppender);
}
// configure BrowserConsoleAppender
if (configuration.browserConsoleAppender) {
if (configuration.browserConsoleAppender.threshold) {
const convertedThreshold = LogLevelConverter.levelToLog4Javascript(LogLevelConverter.levelFromString(configuration.browserConsoleAppender.threshold));
this.browserConsoleAppender.setThreshold(convertedThreshold);
}
}
}
/**
* Gets the root logger from which all other loggers derive.
*
* @return root logger
*/
getRootLogger() {
return new Logger();
}
/**
* Gets a logger with the specified name, creating it if a logger with that name does not already exist.
*
* @param loggerName name of the logger
* @return logger
*/
getLogger(loggerName) {
return new Logger(loggerName);
}
/**
* Gets the last log messages.
*
* The log messages are retrieved from the internal [MemoryAppender](../memoryappender.html).
* That means you will get only the most current messages. The number of the messages is limited
* by its maxMessages value.
*
* @return log messages
*/
getLogMessages() {
return this.memoryAppender.getLogMessages();
}
/**
* Loads the log messages written by the LocalStorageAppender with the given key.
*
* @param localStorageKey key for the local storage
* @returns log messages
*/
getLogMessagesFromLocalStorage(localStorageKey) {
return LocalStorageAppender.loadLogMessages(localStorageKey);
}
/**
* Remove all log messages.
*/
removeLogMessages() {
this.memoryAppender.removeLogMessages();
this.logMessagesChanged.emit();
}
/**
* Removes the log messages written by the LocalStorageAppender with the given key.
*
* @param localStorageKey key for the local storage
*/
removeLogMessagesFromLocalStorage(localStorageKey) {
LocalStorageAppender.removeLogMessages(localStorageKey);
this.logMessagesChanged.emit();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.2.2", ngImport: i0, type: LoggingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "17.2.2", ngImport: i0, type: LoggingService, providedIn: "root" }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.2.2", ngImport: i0, type: LoggingService, decorators: [{
type: Injectable,
args: [{
providedIn: "root"
}]
}], ctorParameters: () => [] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9nZ2luZy5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcHJvamVjdHMvaW9uaWMtbG9nZ2luZy1zZXJ2aWNlL3NyYy9saWIvbG9nZ2luZy5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsVUFBVSxFQUFZLE1BQU0sZUFBZSxDQUFDO0FBRW5FLE9BQU8sS0FBSyxjQUFjLE1BQU0sZ0JBQWdCLENBQUM7QUFFakQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ3JELE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ3RFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBRTFELE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUV4QyxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0seUJBQXlCLENBQUM7O0FBRXpEOzs7Ozs7OztHQVFHO0FBSUgsTUFBTSxPQUFPLGNBQWM7SUFxQjFCOztPQUVHO0lBQ0g7UUFFQywwREFBMEQ7UUFDMUQsY0FBYyxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFekMsdUJBQXVCO1FBQ3ZCLElBQUksQ0FBQyxrQkFBa0IsR0FBRyxJQUFJLFlBQVksRUFBUSxDQUFDO1FBQ25ELElBQUksQ0FBQyxrQkFBa0IsR0FBRyxJQUFJLFlBQVksRUFBVSxDQUFDO1FBRXJELHFCQUFxQjtRQUNyQixNQUFNLE1BQU0sR0FBRyxjQUFjLENBQUMsYUFBYSxFQUFFLENBQUM7UUFDOUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBRTNDLHdDQUF3QztRQUN4QyxJQUFJLENBQUMsc0JBQXNCLEdBQUcsSUFBSSxjQUFjLENBQUMsc0JBQXNCLEVBQUUsQ0FBQztRQUMxRSxJ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O09BUUc7SUFDSSxjQUFjO1FBQ3BCLE9BQU8sSUFBSSxDQUFDLGNBQWMsQ0FBQyxjQUFjLEVBQUUsQ0FBQztJQUM3QyxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSSw4QkFBOEIsQ0FBQyxlQUF1QjtRQUM1RCxPQUFPLG9CQUFvQixDQUFDLGVBQWUsQ0FBQyxlQUFlLENBQUMsQ0FBQztJQUM5RCxDQUFDO0lBRUQ7O09BRUc7SUFDSSxpQkFBaUI7UUFDdkIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBQ3hDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUNoQyxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNJLGlDQUFpQyxDQUFDLGVBQXVCO1FBQy9ELG9CQUFvQixDQUFDLGlCQUFpQixDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBQ3hELElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUNoQyxDQUFDOzhHQW5MVyxjQUFjO2tIQUFkLGNBQWMsY0FGZCxNQUFNOzsyRkFFTixjQUFjO2tCQUgxQixVQUFVO21CQUFDO29CQUNYLFVBQVUsRUFBRSxNQUFNO2lCQUNsQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEV2ZW50RW1pdHRlciwgSW5qZWN0YWJsZSwgT3B0aW9uYWwgfSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuXG5pbXBvcnQgKiBhcyBsb2c0amF2YXNjcmlwdCBmcm9tIFwibG9nNGphdmFzY3JpcHRcIjtcblxuaW1wb3J0IHsgQWpheEFwcGVuZGVyIH0gZnJvbSBcIi4vYWpheC1hcHBlbmRlci5tb2RlbFwiO1xuaW1wb3J0IHsgTG9jYWxTdG9yYWdlQXBwZW5kZXIgfSBmcm9tIFwiLi9sb2NhbC1zdG9yYWdlLWFwcGVuZGVyLm1vZGVsXCI7XG5pbXBvcnQgeyBMb2dMZXZlbENvbnZlcnRlciB9IGZyb20gXCIuL2xvZy1sZXZlbC5jb252ZXJ0ZXJcIjtcbmltcG9ydCB7IExvZ01lc3NhZ2UgfSBmcm9tIFwiLi9sb2ctbWVzc2FnZS5tb2RlbFwiO1xuaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSBcIi4vbG9nZ2VyLm1vZGVsXCI7XG5pbXBvcnQgeyBMb2dnaW5nU2VydmljZUNvbmZpZ3VyYXRpb24gfSBmcm9tIFwiLi9sb2dnaW5nLXNlcnZpY2UuY29uZmlndXJhdGlvblwiO1xuaW1wb3J0IHsgTWVtb3J5QXBwZW5kZXIgfSBmcm9tIFwiLi9tZW1vcnktYXBwZW5kZXIubW9kZWxcIjtcblxuLyoqXG4gKiBTZXJ2aWNlIGZvciBsb2dnaW5nIGZ1bmN0aW9uYWxpdHkuXG4gKlxuICogQnkgZGVmYXVsdCwgdGhlIGZvbGxvd2luZyBzZXR0aW5ncyBhcmUgdXNlZDpcbiAqICAtIGxvZ2dlcjogcm9vdCB3aXRoIGxldmVsIFdBUk5cbiAqICAtIGFwcGVuZGVyOiBCcm93c2VyQ29uc29sZUFwcGVuZGVyIHdpdGggdGhyZXNob2xkIERFQlVHIGFuZCBNZW1vcnlBcHBlbmRlciB3aXRoIHRocmVzaG9sZCBBTExcbiAqXG4gKiBWaWEgW2NvbmZpZ3VyZV0oI2NvbmZpZ3VyZSksIGl0IGlzIHBvc3NpYmxlIHRvIGFtZW5kIHRoZXNlIHNldHRpbmdzLlxuICovXG5ASW5qZWN0YWJsZSh7XG5cdHByb3ZpZGVkSW46IFwicm9vdFwiXG59KVxuZXhwb3J0IGNsYXNzIExvZ2dpbmdTZXJ2aWNlIHtcblxuXHQvKipcblx0ICogRXZlbnQgdHJpZ2dlcmVkIHdoZW4gdGhlIGxvZyBtZXNzYWdlcyBnb3QgKHBvdGVudGlhbGx5KSBjaGFuZ2UuXG5cdCAqIFRoaXMgY2FuIGhhcHBlbiB3aGVuOlxuXHQgKiAtIG5ldyBtZXNzYWdlIHdhcyBhZGRlZFxuXHQgKiAtIGFsbCBtZXNzYWdlIHdoZXJlIHJlbW92ZWQgZnJvbSBtZW1vcnlcblx0ICogLSBhbGwgbWFzc2FnZXMgd2hlcmUgcmVtb3ZlZCBmb3Igb25lIHNwY2lmaWMgTG9jYWxTdG9yYWdlQXBwZW5kZXJcblx0ICovXG5cdHB1YmxpYyBsb2dNZXNzYWdlc0NoYW5nZWQ6IEV2ZW50RW1pdHRlcjx2b2lkPjtcblxuXHQvKipcblx0ICogRXZlbnQgdHJpZ2dlcmVkIHdoZW4gYWpheCBhcHBlbmRlciBjb3VsZCBub3Qgc2VuZCBsb2cgbWVzc2FnZXMgdG8gdGhlIHNlcnZlci5cblx0ICpcblx0ICogQHBhcmFtIG1lc3NhZ2UgZXJyb3IgbWVzc2FnZVxuXHQgKi9cblx0cHVibGljIGFqYXhBcHBlbmRlckZhaWxlZDogRXZlbnRFbWl0dGVyPHN0cmluZz47XG5cblx0cHJpdmF0ZSBtZW1vcnlBcHBlbmRlcjogTWVtb3J5QXBwZW5kZXI7XG5cdHByaXZhdGUgYnJvd3NlckNvbnNvbGVBcHBlbmRlcjogbG9nNGphdmFzY3JpcHQuQnJvd3NlckNvbnNvbGVBcHBlbmRlcjtcblxuXHQvKipcblx0ICogQ3JlYXRlcyBhIG5ldyBpbnN0YW5jZSBvZiB0aGUgc2VydmljZS5cblx0ICovXG5cdGNvbnN0cnVjdG9yKCkge1xuXG5cdFx0Ly8gcHJldmVudCBsb2c0amF2YXNjcmlwdCB0byBzaG93IGFsZXJ0cyBvbiBjYXNlIG9mIGVycm9yc1xuXHRcdGxvZzRqYXZhc2NyaXB0LmxvZ0xvZy5zZXRRdWlldE1vZGUodHJ1ZSk7XG5cblx0XHQvLyBjcmVhdGUgZXZlbnQgZW1pdHRlclxuXHRcdHRoaXMubG9nTWVzc2FnZXNDaGFuZ2VkID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xuXHRcdHRoaXMuYWpheEFwcGVuZGVyRmFpbGVkID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmc+KCk7XG5cblx0XHQvLyBjb25maWd1cmUgYXBwZW5kZXJcblx0XHRjb25zdCBsb2dnZXIgPSBsb2c0amF2YXNjcmlwdC5nZXRSb290TG9nZ2VyKCk7XG5cdFx0bG9nZ2VyLnNldExldmVsKGxvZzRqYXZhc2NyaXB0LkxldmVsLldBUk4pO1xuXG5cdFx0Ly8gYnJvd3NlciBjb25zb2xlIGFwcGVuZGVyIGZvciBkZWJ1Z2dlclxuXHRcdHRoaXMuYnJvd3NlckNvbnNvbGVBcHBlbmRlciA9IG5ldyBsb2c0amF2YXNjcmlwdC5Ccm93c2VyQ29uc29sZUFwcGVuZGVyKCk7XG5cdFx0dGhpcy5icm93c2VyQ29uc29sZUFwcGVuZGVyLnNldExheW91dChuZXcgbG9nNGphdmFzY3JpcHQuUGF0dGVybkxheW91dChcIiVke0hIOm1tOnNzLFNTU30gJWMgJW1cIikpO1xuXHRcdHRoaXMuYnJvd3NlckNvbnNvbGVBcHBlbmRlci5zZXRUaHJlc2hvbGQobG9nNGphdmFzY3JpcHQuTGV2ZWwuQUxMKTtcblx0XHRsb2dnZXIuYWRkQXBwZW5kZXIodGhpcy5icm93c2VyQ29uc29sZUFwcGVuZGVyKTtcblxuXHRcdC8vIGluLW1lbW9yeSBhcHBlbmRlciBmb3IgZGlzcGxheSBvbiBsb2cgbWVzc2FnZXMgcGFnZVxuXHRcdHRoaXMubWVtb3J5QXBwZW5kZXIgPSBuZXcgTWVtb3J5QXBwZW5kZXIoKTtcblx0XHR0aGlzLm1lbW9yeUFwcGVuZGVyLnNldExheW91dChuZXcgbG9nNGphdmFzY3JpcHQuUGF0dGVybkxheW91dChcIiVke0hIOm1tOnNzLFNTU30gJWMgJW1cIikpO1xuXHRcdHRoaXMubWVtb3J5QXBwZW5kZXIuc2V0T25Mb2dNZXNzYWdlc0NoYW5nZWRDYWxsYmFjaygobWVzc2FnZSkgPT4ge1xuXHRcdFx0dGhpcy5sb2dNZXNzYWdlc0NoYW5nZWQuZW1pdCgpO1xuXHRcdH0pO1xuXHRcdGxvZ2dlci5hZGRBcHBlbmRlcih0aGlzLm1lbW9yeUFwcGVuZGVyKTtcblxuXHRcdHRoaXMuY29uZmlndXJlKCk7XG5cdH1cblxuXHQvKipcblx0ICogQ29uZmlndXJlcyB0aGUgbG9nZ2luZyBkZXBlbmRpbmcgb24gdGhlIGdpdmVuIGNvbmZpZ3VyYXRpb24uXG5cdCAqXG5cdCAqIEBwYXJhbSBjb25maWd1cmF0aW9uIGNvbmZpZ3VyYXRpb24gZGF0YS5cblx0ICovXG5cdHB1YmxpYyBjb25maWd1cmUoY29uZmlndXJhdGlvbj86IExvZ2dpbmdTZXJ2aWNlQ29uZmlndXJhdGlvbik6IHZvaWQge1xuXG5cdFx0aWYgKHR5cGVvZiBjb25maWd1cmF0aW9uID09PSBcInVuZGVmaW5lZFwiKSB7XG5cdFx0XHRjb25maWd1cmF0aW9uID0ge307XG5cdFx0fVxuXG5cdFx0Ly8gc2V0IGxvZyBsZXZlbHNcblx0XHRpZiAodHlwZW9mIGNvbmZpZ3VyYXRpb24ubG9nTGV2ZWxzICE9PSBcInVuZGVmaW5lZFwiKSB7XG5cdFx0XHRmb3IgKGNvbnN0IGxldmVsIG9mIGNvbmZpZ3VyYXRpb24ubG9nTGV2ZWxzKSB7XG5cdFx0XHRcdGxldCBsb2dnZXI6IGxvZzRqYXZhc2NyaXB0LkxvZ2dlcjtcblx0XHRcdFx0aWYgKGxldmVsLmxvZ2dlck5hbWUgPT09IFwicm9vdFwiKSB7XG5cdFx0XHRcdFx0bG9nZ2VyID0gbG9nNGphdmFzY3JpcHQuZ2V0Um9vdExvZ2dlcigpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGxvZ2dlciA9IGxvZzRqYXZhc2NyaXB0LmdldExvZ2dlcihsZXZlbC5sb2dnZXJOYW1lKTtcblx0XHRcdFx0fVxuXHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdGxvZ2dlci5zZXRMZXZlbChMb2dMZXZlbENvbnZlcnRlci5sZXZlbFRvTG9nNEphdmFzY3JpcHQoTG9nTGV2ZWxDb252ZXJ0ZXIubGV2ZWxGcm9tU3RyaW5nKGxldmVsLmxvZ0xldmVsKSkpO1xuXHRcdFx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKGBpbnZhbGlkIGxvZyBsZXZlbCAke2xldmVsLmxvZ0xldmVsfWApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gY29uZmlndXJlIEFqYXhBcHBlbmRlclxuXHRcdGlmICh0eXBlb2YgY29uZmlndXJhdGlvbi5hamF4QXBwZW5kZXIgIT09IFwidW5kZWZpbmVkXCIpIHtcblx0XHRcdGNvbnN0IGFqYXhBcHBlbmRlciA9IG5ldyBBamF4QXBwZW5kZXIoY29uZmlndXJhdGlvbi5hamF4QXBwZW5kZXIpO1xuXHRcdFx0YWpheEFwcGVuZGVyLmFwcGVuZGVyRmFpbGVkLnN1YnNjcmliZSgobWVzc2FnZTogc3RyaW5nKSA9PiB7XG5cdFx0XHRcdHRoaXMuYWpheEFwcGVuZGVyRmFpbGVkLmVtaXQobWVzc2FnZSk7XG5cdFx0XHR9KTtcblx0XHRcdGxvZzRqYXZhc2NyaXB0LmdldFJvb3RMb2dnZXIoKS5hZGRBcHBlbmRlcihhamF4QXBwZW5kZXIpO1xuXHRcdH1cblxuXHRcdC8vIGNvbmZpZ3VyZSBMb2NhbFN0b3JhZ2VBcHBlbmRlclxuXHRcdGlmICh0eXBlb2YgY29uZmlndXJhdGlvbi5sb2NhbFN0b3JhZ2VBcHBlbmRlciAhPT0gXCJ1bmRlZmluZWRcIikge1xuXHRcdFx0Y29uc3QgbG9jYWxTdG9yYWdlQXBwZW5kZXIgPSBuZXcgTG9jYWxTdG9yYWdlQXBwZW5kZXIoY29uZmlndXJhdGlvbi5sb2NhbFN0b3JhZ2VBcHBlbmRlcik7XG5cdFx0XHRsb2c0amF2YXNjcmlwdC5nZXRSb290TG9nZ2VyKCkuYWRkQXBwZW5kZXIobG9jYWxTdG9yYWdlQXBwZW5kZXIpO1xuXG5cdFx0XHQvLyBlbnN1cmUgdGhhdCBhbiBldmVudHVhbCBtZW1vcnlBcHBlbmRlciBpcyBiZWhpbmQgdGhlIGxvY2FsU3RvcmFnZUFwcGVuZGVyXG5cdFx0XHRjb25zdCBhcHBlbmRlcnMgPSBuZXcgTG9nZ2VyKCkuZ2V0SW50ZXJuYWxMb2dnZXIoKS5nZXRFZmZlY3RpdmVBcHBlbmRlcnMoKTtcblx0XHRcdGNvbnN0IG1lbW9yeUFwcGVuZGVyID0gYXBwZW5kZXJzLmZpbmQoKGEpID0+IGEudG9TdHJpbmcoKSA9PT0gXCJJb25pYy5Mb2dnaW5nLk1lbW9yeUFwcGVuZGVyXCIpIGFzIE1lbW9yeUFwcGVuZGVyO1xuXHRcdFx0aWYgKG1lbW9yeUFwcGVuZGVyKSB7XG5cdFx0XHRcdGxvZzRqYXZhc2NyaXB0LmdldFJvb3RMb2dnZXIoKS5yZW1vdmVBcHBlbmRlcihtZW1vcnlBcHBlbmRlcik7XG5cdFx0XHRcdGxvZzRqYXZhc2NyaXB0LmdldFJvb3RMb2dnZXIoKS5hZGRBcHBlbmRlcihtZW1vcnlBcHBlbmRlcik7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gY29uZmlndXJlIE1lbW9yeUFwcGVuZGVyXG5cdFx0aWYgKGNvbmZpZ3VyYXRpb24ubWVtb3J5QXBwZW5kZXIpIHtcblx0XHRcdHRoaXMubWVtb3J5QXBwZW5kZXIuY29uZmlndXJlKGNvbmZpZ3VyYXRpb24ubWVtb3J5QXBwZW5kZXIpO1xuXHRcdH1cblxuXHRcdC8vIGNvbmZpZ3VyZSBCcm93c2VyQ29uc29sZUFwcGVuZGVyXG5cdFx0aWYgKGNvbmZpZ3VyYXRpb24uYnJvd3NlckNvbnNvbGVBcHBlbmRlcikge1xuXHRcdFx0aWYgKGNvbmZpZ3VyYXRpb24uYnJvd3NlckNvbnNvbGVBcHBlbmRlci50aHJlc2hvbGQpIHtcblx0XHRcdFx0Y29uc3QgY29udmVydGVkVGhyZXNob2xkID0gTG9nTGV2ZWxDb252ZXJ0ZXIubGV2ZWxUb0xvZzRKYXZhc2NyaXB0KFxuXHRcdFx0XHRcdExvZ0xldmVsQ29udmVydGVyLmxldmVsRnJvbVN0cmluZyhjb25maWd1cmF0aW9uLmJyb3dzZXJDb25zb2xlQXBwZW5kZXIudGhyZXNob2xkKSk7XG5cdFx0XHRcdHRoaXMuYnJvd3NlckNvbnNvbGVBcHBlbmRlci5zZXRUaHJlc2hvbGQoY29udmVydGVkVGhyZXNob2xkKTtcblx0XHRcdH1cblx0XHR9XG5cblx0fVxuXG5cdC8qKlxuXHQgKiBHZXRzIHRoZSByb290IGxvZ2dlciBmcm9tIHdoaWNoIGFsbCBvdGhlciBsb2dnZXJzIGRlcml2ZS5cblx0ICpcblx0ICogQHJldHVybiByb290IGxvZ2dlclxuXHQgKi9cblx0cHVibGljIGdldFJvb3RMb2dnZXIoKTogTG9nZ2VyIHtcblx0XHRyZXR1cm4gbmV3IExvZ2dlcigpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgYSBsb2dnZXIgd2l0aCB0aGUgc3BlY2lmaWVkIG5hbWUsIGNyZWF0aW5nIGl0IGlmIGEgbG9nZ2VyIHdpdGggdGhhdCBuYW1lIGRvZXMgbm90IGFscmVhZHkgZXhpc3QuXG5cdCAqXG5cdCAqIEBwYXJhbSBsb2dnZXJOYW1lIG5hbWUgb2YgdGhlIGxvZ2dlclxuXHQgKiBAcmV0dXJuIGxvZ2dlclxuXHQgKi9cblx0cHVibGljIGdldExvZ2dlcihsb2dnZXJOYW1lOiBzdHJpbmcpOiBMb2dnZXIge1xuXHRcdHJldHVybiBuZXcgTG9nZ2VyKGxvZ2dlck5hbWUpO1xuXHR9XG5cblx0LyoqXG5cdCAqIEdldHMgdGhlIGxhc3QgbG9nIG1lc3NhZ2VzLlxuXHQgKlxuXHQgKiBUaGUgbG9nIG1lc3NhZ2VzIGFyZSByZXRyaWV2ZWQgZnJvbSB0aGUgaW50ZXJuYWwgW01lbW9yeUFwcGVuZGVyXSguLi9tZW1vcnlhcHBlbmRlci5odG1sKS5cblx0ICogVGhhdCBtZWFucyB5b3Ugd2lsbCBnZXQgb25seSB0aGUgbW9zdCBjdXJyZW50IG1lc3NhZ2VzLiBUaGUgbnVtYmVyIG9mIHRoZSBtZXNzYWdlcyBpcyBsaW1pdGVkXG5cdCAqIGJ5IGl0cyBtYXhNZXNzYWdlcyB2YWx1ZS5cblx0ICpcblx0ICogQHJldHVybiBsb2cgbWVzc2FnZXNcblx0ICovXG5cdHB1YmxpYyBnZXRMb2dNZXNzYWdlcygpOiBMb2dNZXNzYWdlW10ge1xuXHRcdHJldHVybiB0aGlzLm1lbW9yeUFwcGVuZGVyLmdldExvZ01lc3NhZ2VzKCk7XG5cdH1cblxuXHQvKipcblx0ICogTG9hZHMgdGhlIGxvZyBtZXNzYWdlcyB3cml0dGVuIGJ5IHRoZSBMb2NhbFN0b3JhZ2VBcHBlbmRlciB3aXRoIHRoZSBnaXZlbiBrZXkuXG5cdCAqXG5cdCAqIEBwYXJhbSBsb2NhbFN0b3JhZ2VLZXkga2V5IGZvciB0aGUgbG9jYWwgc3RvcmFnZVxuXHQgKiBAcmV0dXJucyBsb2cgbWVzc2FnZXNcblx0ICovXG5cdHB1YmxpYyBnZXRMb2dNZXNzYWdlc0Zyb21Mb2NhbFN0b3JhZ2UobG9jYWxTdG9yYWdlS2V5OiBzdHJpbmcpOiBMb2dNZXNzYWdlW10ge1xuXHRcdHJldHVybiBMb2NhbFN0b3JhZ2VBcHBlbmRlci5sb2FkTG9nTWVzc2FnZXMobG9jYWxTdG9yYWdlS2V5KTtcblx0fVxuXG5cdC8qKlxuXHQgKiBSZW1vdmUgYWxsIGxvZyBtZXNzYWdlcy5cblx0ICovXG5cdHB1YmxpYyByZW1vdmVMb2dNZXNzYWdlcygpOiB2b2lkIHtcblx0XHR0aGlzLm1lbW9yeUFwcGVuZGVyLnJlbW92ZUxvZ01lc3NhZ2VzKCk7XG5cdFx0dGhpcy5sb2dNZXNzYWdlc0NoYW5nZWQuZW1pdCgpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJlbW92ZXMgdGhlIGxvZyBtZXNzYWdlcyB3cml0dGVuIGJ5IHRoZSBMb2NhbFN0b3JhZ2VBcHBlbmRlciB3aXRoIHRoZSBnaXZlbiBrZXkuXG5cdCAqXG5cdCAqIEBwYXJhbSBsb2NhbFN0b3JhZ2VLZXkga2V5IGZvciB0aGUgbG9jYWwgc3RvcmFnZVxuXHQgKi9cblx0cHVibGljIHJlbW92ZUxvZ01lc3NhZ2VzRnJvbUxvY2FsU3RvcmFnZShsb2NhbFN0b3JhZ2VLZXk6IHN0cmluZyk6IHZvaWQge1xuXHRcdExvY2FsU3RvcmFnZUFwcGVuZGVyLnJlbW92ZUxvZ01lc3NhZ2VzKGxvY2FsU3RvcmFnZUtleSk7XG5cdFx0dGhpcy5sb2dNZXNzYWdlc0NoYW5nZWQuZW1pdCgpO1xuXHR9XG59XG4iXX0=