UNPKG

ngx-matomo

Version:

Matomo (aka. Piwik) web analytics for Angular applications.

1,718 lines 162 kB
import { Inject, Injectable } from '@angular/core';
import { MATOMO_CONFIGURATION } from './matomo-configuration';
import * as i0 from "@angular/core";
/**
 * Wrapper for functions available in the Matomo Javascript tracker.
 *
 * @export
 */
export class MatomoTracker {
    /**
     * Creates an instance of MatomoTracker.
     *
     * @param configuration Matomo configuration provided by DI.
     */
    constructor(configuration) {
        this.configuration = configuration;
        try {
            if (typeof window['_paq'] === 'undefined') {
                console.warn('Matomo has not yet been initialized!');
            }
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Logs a visit to this page.
     *
     * @param [customTitle] Optional title of the visited page.
     */
    trackPageView(customTitle) {
        try {
            const args = [];
            if (!!customTitle) {
                args.push(customTitle);
            }
            window['_paq'].push(['trackPageView', ...args]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Logs an event with an event category (Videos, Music, Games…), an event action (Play, Pause, Duration,
     * Add Playlist, Downloaded, Clicked…), and an optional event name and optional numeric value.
     *
     * @param category Category of the event.
     * @param action Action of the event.
     * @param [name] Optional name of the event.
     * @param [value] Optional value for the event.
     */
    trackEvent(category, action, name, value) {
        try {
            const args = [category, action];
            if (!!name) {
                args.push(name);
                if (typeof value === 'number') {
                    args.push(value);
                }
            }
            window['_paq'].push(['trackEvent', ...args]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Logs an internal site search for a specific keyword, in an optional category,
     * specifying the optional count of search results in the page.
     *
     * @param keyword Keywords of the search query.
     * @param [category] Optional category of the search query.
     * @param [resultsCount] Optional number of results returned by the search query.
     */
    trackSiteSearch(keyword, category, resultsCount) {
        try {
            const args = [keyword];
            if (!!category) {
                args.push(category);
                if (typeof resultsCount === 'number') {
                    args.push(resultsCount);
                }
            }
            window['_paq'].push(['trackSiteSearch', ...args]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Manually logs a conversion for the numeric goal ID, with an optional numeric custom revenue customRevenue.
     *
     * @param idGoal numeric ID of the goal to log a conversion for.
     * @param [customRevenue] Optional custom revenue to log for the goal.
     */
    trackGoal(idGoal, customRevenue) {
        try {
            const args = [idGoal];
            if (typeof customRevenue === 'number') {
                args.push(customRevenue);
            }
            window['_paq'].push(['trackGoal', ...args]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Manually logs a click from your own code.
     *
     * @param url Full URL which is to be tracked as a click.
     * @param linkType Either 'link' for an outlink or 'download' for a download.
     */
    trackLink(url, linkType) {
        try {
            window['_paq'].push(['trackLink', url, linkType]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Scans the entire DOM for all content blocks and tracks all impressions once the DOM ready event has been triggered.
     *
     * @see {@link https://developer.matomo.org/guides/content-tracking|Content Tracking}
     */
    trackAllContentImpressions() {
        try {
            window['_paq'].push(['trackAllContentImpressions']);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Scans the entire DOM for all content blocks as soon as the page is loaded.<br />
     * It tracks an impression only if a content block is actually visible.
     *
     * @param checkOnScroll If true, checks for new content blocks while scrolling the page.
     * @param timeInterval Duration, in milliseconds, between two checks upon scroll.
     * @see {@link https://developer.matomo.org/guides/content-tracking|Content Tracking}
     */
    trackVisibleContentImpressions(checkOnScroll, timeInterval) {
        try {
            window['_paq'].push(['trackVisibleContentImpressions', checkOnScroll, timeInterval]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Scans the given DOM node and its children for content blocks and tracks an impression for them
     * if no impression was already tracked for it.
     *
     * @param node DOM node in which to look for content blocks which have not been previously tracked.
     * @see {@link https://developer.matomo.org/guides/content-tracking|Content Tracking}
     */
    trackContentImpressionsWithinNode(node) {
        try {
            window['_paq'].push(['trackContentImpressionsWithinNode', node]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Tracks an interaction with the given DOM node/content block.
     *
     * @param node DOM node for which to track a content interaction.
     * @param contentInteraction Name of the content interaction.
     * @see {@link https://developer.matomo.org/guides/content-tracking|Content Tracking}
     */
    trackContentInteractionNode(node, contentInteraction) {
        try {
            window['_paq'].push(['trackContentInteractionNode', node, contentInteraction]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Tracks a content impression using the specified values.
     *
     * @param contentName Content name.
     * @param contentPiece Content piece.
     * @param contentTarget Content target.
     * @see {@link https://developer.matomo.org/guides/content-tracking|Content Tracking}
     */
    trackContentImpression(contentName, contentPiece, contentTarget) {
        try {
            window['_paq'].push(['trackContentImpression', contentName, contentPiece, contentTarget]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Tracks a content interaction using the specified values.
     *
     * @param contentInteraction Content interaction.
     * @param contentName Content name.
     * @param contentPiece Content piece.
     * @param contentTarget Content target.
     * @see {@link https://developer.matomo.org/guides/content-tracking|Content Tracking}
     */
    trackContentInteraction(contentInteraction, contentName, contentPiece, contentTarget) {
        try {
            window['_paq'].push([
                'trackContentInteraction',
                contentInteraction,
                contentName,
                contentPiece,
                contentTarget,
            ]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Logs all found content blocks within a page to the console.<br />
     * This is useful to debug / test content tracking.
     */
    logAllContentBlocksOnPage() {
        try {
            window['_paq'].push(['logAllContentBlocksOnPage']);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Sends a ping request.<br />
     * Ping requests do not track new actions.
     * If they are sent within the standard visit length, they will extend the existing visit and the current last action for the visit.
     * If sent after the standard visit length, ping requests will create a new visit using the last action in the last known visit.<br />
     * See also enableHeartBeatTimer.
     */
    ping() {
        try {
            window['_paq'].push(['ping']);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Installs a Heart beat timer that will regularly send requests to Matomo in order to better measure the time spent on the page.<br />
     * These requests will be sent only when the user is actively viewing the page (when the tab is active and in focus).<br />
     * These requests will not track additional actions or page views.<br />
     * By default, the delay is set to 15 seconds.
     *
     * @param delay Delay, in seconds, between two heart beats to the server.
     */
    enableHeartBeatTimer(delay) {
        try {
            window['_paq'].push(['enableHeartBeatTimer', delay]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Installs link tracking on all applicable link elements.
     *
     * @param [enable=false] Set to true to use pseudo click-handler (treat middle click and open contextmenu as
     * left click).<br />
     * A right click (or any click that opens the context menu) on a link will be tracked as clicked even if "Open in new tab"
     * is not selected.<br />
     * If false (default), nothing will be tracked on open context menu or middle click.
     */
    enableLinkTracking(enable = false) {
        try {
            window['_paq'].push(['enableLinkTracking', enable]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Enables cross domain linking. By default, the visitor ID that identifies a unique visitor is stored in the browser's
     * first party cookies.<br />
     * This means the cookie can only be accessed by pages on the same domain.<br />
     * If you own multiple domains and would like to track all the actions and pageviews of a specific visitor into the same visit,
     * you may enable cross domain linking.<br />
     * Whenever a user clicks on a link it will append a URL parameter pk_vid to the clicked URL which forwards the current
     * visitor ID value to the page of the different domain.
     *
     * @see {@link https://matomo.org/faq/how-to/faq_23654/|Cross Domain Linking}
     */
    enableCrossDomainLinking() {
        try {
            window['_paq'].push(['enableCrossDomainLinking']);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Sets the cross domain linking timeout.<br />
     * By default, the two visits across domains will be linked together when the link is clicked and the page is loaded within
     * a 180 seconds timeout window.
     *
     * @param timeout Timeout, in seconds, between two actions across two domains before creating a new visit.
     * @see {@link https://matomo.org/faq/how-to/faq_23654/|Cross Domain Linking}
     */
    setCrossDomainLinkingTimeout(timeout) {
        try {
            window['_paq'].push(['setCrossDomainLinkingTimeout', timeout]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Returns the query parameter to append to links to handle cross domain linking.<br />
     * Use this to add cross domain support for links that are added to the DOM dynamically.
     *
     * @returns Promise for the `pk_vid` query parameter.
     * @see {@link https://matomo.org/faq/how-to/faq_23654/|Cross Domain Linking}
     */
    getCrossDomainLinkingUrlParameter() {
        return new Promise((resolve, reject) => {
            try {
                window['_paq'].push([
                    function () {
                        resolve(this.getCrossDomainLinkingUrlParameter());
                    },
                ]);
            }
            catch (e) {
                if (!(e instanceof ReferenceError)) {
                    reject(e);
                }
            }
        });
    }
    /**
     * Overrides document.title
     *
     * @param title Title of the document.
     */
    setDocumentTitle(title) {
        try {
            window['_paq'].push(['setDocumentTitle', title]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Sets array of hostnames or domains to be treated as local.<br />
     * For wildcard subdomains, you can use: `setDomains('.example.com')`; or `setDomains('*.example.com');`.<br />
     * You can also specify a path along a domain: `setDomains('*.example.com/subsite1');`.
     *
     * @param domains List of hostnames or domains, with or without path, to be treated as local.
     * @see {@link https://matomo.org/faq/how-to/faq_23654/|Cross Domain Linking}
     */
    setDomains(domains) {
        try {
            window['_paq'].push(['setDomains', domains]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Override the page's reported URL.
     *
     * @param url URL to be reported for the page.
     */
    setCustomUrl(url) {
        try {
            window['_paq'].push(['setCustomUrl', url]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Overrides the detected Http-Referer.
     *
     * @param url URL to be reported for the referer.
     */
    setReferrerUrl(url) {
        try {
            window['_paq'].push(['setReferrerUrl', url]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Specifies the website ID.<br />
     * Redundant: can be specified in getTracker() constructor.
     *
     * // TODO Investigate if setSiteId needs to be removed from MatomoTracker.
     * @param siteId Site ID for the tracker.
     */
    setSiteId(siteId) {
        try {
            window['_paq'].push(['setSiteId', siteId]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Specifies the Matomo HTTP API URL endpoint.<br />
     * Points to the root directory of Matomo, e.g. http://matomo.example.org/ or https://example.org/matomo/.<br />
     * This function is only useful when the 'Overlay' report is not working.<br />
     * By default, you do not need to use this function.
     *
     * @param url URL for Matomo HTTP API endpoint.
     */
    setApiUrl(url) {
        try {
            window['_paq'].push(['setApiUrl', url]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Specifies the Matomo server URL.<br />
     * Redundant: can be specified in getTracker() constructor.
     *
     * // TODO Investigate if setTrackerUrl needs to be removed from MatomoTracker.
     * @param url URL for the Matomo server.
     */
    setTrackerUrl(url) {
        try {
            window['_paq'].push(['setTrackerUrl', url]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Returns the Matomo server URL.
     *
     * @returns Promise for the Matomo server URL.
     */
    getMatomoUrl() {
        return new Promise((resolve, reject) => {
            try {
                window['_paq'].push([
                    function () {
                        resolve(this.getPiwikUrl());
                    },
                ]);
            }
            catch (e) {
                if (!(e instanceof ReferenceError)) {
                    reject(e);
                }
            }
        });
    }
    /**
     * Returns the current url of the page that is currently being visited.<br />
     * If a custom URL was set before calling this method, the custom URL will be returned.
     *
     * @returns Promise for the URL of the current page.
     */
    getCurrentUrl() {
        return new Promise((resolve, reject) => {
            try {
                window['_paq'].push([
                    function () {
                        resolve(this.getCurrentUrl());
                    },
                ]);
            }
            catch (e) {
                if (!(e instanceof ReferenceError)) {
                    reject(e);
                }
            }
        });
    }
    /**
     * Sets classes to be treated as downloads (in addition to piwik_download).
     *
     * @param classes Class, or list of classes to be treated as downloads.
     */
    setDownloadClasses(classes) {
        try {
            window['_paq'].push(['setDownloadClasses', classes]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Sets file extensions to be recognized as downloads.<br />
     * Example: `'docx'` or `['docx', 'xlsx']`.
     *
     * @param extensions Extension, or list of extensions to be recognized as downloads.
     */
    setDownloadExtensions(extensions) {
        try {
            window['_paq'].push(['setDownloadClasses', extensions]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Sets additional file extensions to be recognized as downloads.<br />
     * Example: `'docx'` or `['docx', 'xlsx']`.
     *
     * @param extensions Extension, or list of extensions to be recognized as downloads.
     */
    addDownloadExtensions(extensions) {
        try {
            window['_paq'].push(['setDownloadClasses', extensions]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Specifies file extensions to be removed from the list of download file extensions.<br />
     * Example: `'docx'` or `['docx', 'xlsx']`.
     *
     * @param extensions Extension, or list of extensions not to be recognized as downloads.
     */
    removeDownloadExtensions(extensions) {
        try {
            window['_paq'].push(['setDownloadClasses', extensions]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Sets classes to be ignored if present in link (in addition to piwik_ignore).
     *
     * @param classes Class, or list of classes to be ignored if present in link.
     */
    setIgnoreClasses(classes) {
        try {
            window['_paq'].push(['setDownloadClasses', classes]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Sets classes to be treated as outlinks (in addition to piwik_link).
     *
     * @param classes Class, or list of classes to be treated as outlinks.
     */
    setLinkClasses(classes) {
        try {
            window['_paq'].push(['setDownloadClasses', classes]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Sets delay for link tracking (in milliseconds).
     *
     * @param delay Delay, in milliseconds, for link tracking.
     */
    setLinkTrackingTimer(delay) {
        try {
            window['_paq'].push(['setLinkTrackingTimer', delay]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Returns delay for link tracking.
     *
     * @returns Promise for the delay in milliseconds.
     */
    getLinkTrackingTimer() {
        return new Promise((resolve, reject) => {
            try {
                window['_paq'].push([
                    function () {
                        resolve(this.getLinkTrackingTimer());
                    },
                ]);
            }
            catch (e) {
                if (!(e instanceof ReferenceError)) {
                    reject(e);
                }
            }
        });
    }
    /**
     * Sets if or not to record the hash tag (anchor) portion of URLs.
     *
     * @param value If true, the hash tag portion of the URLs won't be recorded.
     */
    discardHashTag(value) {
        try {
            window['_paq'].push(['discardHashTag', value]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * By default Matomo uses the browser DOM Timing API to accurately determine the time it takes to generate and download
     * the page. You may overwrite this value with this function.
     * This function is deprecated in Matomo 4.x.
     *
     * @param generationTime Time, in milliseconds, of the page generation.
     */
    setGenerationTimeMs(generationTime) {
        if (this.configuration.scriptVersion < 4) {
            try {
                window['_paq'].push(['setGenerationTimeMs', generationTime]);
            }
            catch (e) {
                if (!(e instanceof ReferenceError)) {
                    throw e;
                }
            }
        }
    }
    /**
     * Appends a custom string to the end of the HTTP request to piwik.php.
     *
     * @param appendToUrl String to append to the end of the HTTP request to piwik.php/matomo.php.
     */
    appendToTrackingUrl(appendToUrl) {
        try {
            window['_paq'].push(['appendToTrackingUrl', appendToUrl]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Enables a frame-buster to prevent the tracked web page from being framed/iframed.
     */
    killFrame() {
        try {
            window['_paq'].push(['killFrame']);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Forces the browser to load the live URL if the tracked web page is loaded from a local file
     * (e.g., saved to someone's desktop).
     *
     * @param url URL to track instead of file:// URLs.
     */
    redirectFile(url) {
        try {
            window['_paq'].push(['redirectFile', url]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Records how long the page has been viewed if the minimumVisitLength is attained;
     * the heartBeatDelay determines how frequently to update the server.
     *
     * @param minimumVisitLength Duration before notifying the server for the duration of the visit to a page.
     * @param heartBeatDelay Delay, in seconds, between two updates to the server.
     * @see {@link https://developer.matomo.org/guides/tracking-javascript-guide#accurately-measure-the-time-spent-on-each-page}
     */
    setHeartBeatTimer(minimumVisitLength, heartBeatDelay) {
        try {
            window['_paq'].push(['setHeartBeatTimer', minimumVisitLength, heartBeatDelay]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Returns the 16 characters ID for the visitor.
     *
     * @returns Promise for the the 16 characters ID for the visitor.
     */
    getVisitorId() {
        return new Promise((resolve, reject) => {
            try {
                window['_paq'].push([
                    function () {
                        resolve(this.getVisitorId());
                    },
                ]);
            }
            catch (e) {
                if (!(e instanceof ReferenceError)) {
                    reject(e);
                }
            }
        });
    }
    /**
     * Returns the visitor cookie contents in an array.
     *
     * @returns Promise for the cookie contents in an array.
     */
    getVisitorInfo() {
        return new Promise((resolve, reject) => {
            try {
                window['_paq'].push([
                    function () {
                        resolve(this.getVisitorInfo());
                    },
                ]);
            }
            catch (e) {
                if (!(e instanceof ReferenceError)) {
                    reject(e);
                }
            }
        });
    }
    /**
     * Returns the visitor attribution array (Referer information and/or Campaign name & keyword).<br />
     * Attribution information is used by Matomo to credit the correct referrer (first or last referrer)
     * used when a user triggers a goal conversion.
     *
     * @returns Promise for the visitor attribution array (Referer information and/or Campaign name & keyword).
     */
    getAttributionInfo() {
        return new Promise((resolve, reject) => {
            try {
                window['_paq'].push([
                    function () {
                        resolve(this.getAttributionInfo());
                    },
                ]);
            }
            catch (e) {
                if (!(e instanceof ReferenceError)) {
                    reject(e);
                }
            }
        });
    }
    /**
     * Returns the attribution campaign name.
     *
     * @returns Promise for the the attribution campaign name.
     */
    getAttributionCampaignName() {
        return new Promise((resolve, reject) => {
            try {
                window['_paq'].push([
                    function () {
                        resolve(this.getAttributionCampaignName());
                    },
                ]);
            }
            catch (e) {
                if (!(e instanceof ReferenceError)) {
                    reject(e);
                }
            }
        });
    }
    /**
     * Returns the attribution campaign keyword.
     *
     * @returns Promise for the attribution campaign keyword.
     */
    getAttributionCampaignKeyword() {
        return new Promise((resolve, reject) => {
            try {
                window['_paq'].push([
                    function () {
                        resolve(this.getAttributionCampaignKeyword());
                    },
                ]);
            }
            catch (e) {
                if (!(e instanceof ReferenceError)) {
                    reject(e);
                }
            }
        });
    }
    /**
     * Returns the attribution referrer timestamp.
     *
     * @returns Promise for the attribution referrer timestamp (as string).
     */
    getAttributionReferrerTimestamp() {
        return new Promise((resolve, reject) => {
            try {
                window['_paq'].push([
                    function () {
                        resolve(this.getAttributionReferrerTimestamp());
                    },
                ]);
            }
            catch (e) {
                if (!(e instanceof ReferenceError)) {
                    reject(e);
                }
            }
        });
    }
    /**
     * Returns the attribution referrer URL.
     *
     * @returns Promise for the attribution referrer URL
     */
    getAttributionReferrerUrl() {
        return new Promise((resolve, reject) => {
            try {
                window['_paq'].push([
                    function () {
                        resolve(this.getAttributionReferrerUrl());
                    },
                ]);
            }
            catch (e) {
                if (!(e instanceof ReferenceError)) {
                    reject(e);
                }
            }
        });
    }
    /**
     * Returns the User ID string if it was set.
     *
     * @returns Promise for the User ID for the visitor.
     * @see {@link https://matomo.org/docs/user-id/|Matomo User ID}
     */
    getUserId() {
        return new Promise((resolve, reject) => {
            try {
                window['_paq'].push([
                    function () {
                        resolve(this.getUserId());
                    },
                ]);
            }
            catch (e) {
                if (!(e instanceof ReferenceError)) {
                    reject(e);
                }
            }
        });
    }
    /**
     * Sets a User ID to this user (such as an email address or a username).
     *
     * @param userId User ID to set for the current visitor.
     * @see {@link https://matomo.org/docs/user-id/|Matomo User ID}
     */
    setUserId(userId) {
        try {
            window['_paq'].push(['setUserId', userId]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Resets the User ID which also generates a new Visitor ID.
     *
     * @see {@link https://matomo.org/docs/user-id/|Matomo User ID}
     */
    resetUserId() {
        try {
            window['_paq'].push(['resetUserId']);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Sets a custom variable.
     *
     * @param index Index, the number from 1 to 5 where this custom variable name is stored for the current page view.
     * @param name Name, the name of the variable, for example: Category, Sub-category, UserType.
     * @param value Value, for example: "Sports", "News", "World", "Business"…
     * @param scope Scope of the custom variable:<br />
     * - 'page' means the custom variable applies to the current page view.
     * - 'visit' means the custom variable applies to the current visitor.
     * - 'event' means the custom variable applies to the current event.
     * @see {@link https://matomo.org/docs/custom-variables/|Custom Variables}
     */
    setCustomVariable(index, name, value, scope) {
        try {
            window['_paq'].push(['setCustomVariable', index, name, value, scope]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Deletes a custom variable.
     *
     * @param index Index of the custom variable to delete.
     * @param scope Scope of the custom variable to delete.
     * @see {@link https://matomo.org/docs/custom-variables/|Custom Variables}
     */
    deleteCustomVariable(index, scope) {
        try {
            window['_paq'].push(['deleteCustomVariable', index, scope]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Deletes all custom variables.
     *
     * @param scope Scope of the custom variables to delete.
     * @see {@link https://matomo.org/docs/custom-variables/|Custom Variables}
     */
    deleteCustomVariables(scope) {
        try {
            window['_paq'].push(['deleteCustomVariables', scope]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Retrieves a custom variable.
     *
     * @param index Index of the custom variable to retrieve.
     * @param scope Scope of the custom variable to retrieve.
     * @returns Promise for the value of custom variable.
     * @see {@link https://matomo.org/docs/custom-variables/|Custom Variables}
     */
    getCustomVariable(index, scope) {
        return new Promise((resolve, reject) => {
            try {
                window['_paq'].push([
                    function () {
                        resolve(this.getCustomVariable(index, scope));
                    },
                ]);
            }
            catch (e) {
                if (!(e instanceof ReferenceError)) {
                    reject(e);
                }
            }
        });
    }
    /**
     * When called then the Custom Variables of scope 'visit' will be stored (persisted) in a first party cookie
     * for the duration of the visit.<br />
     * This is useful if you want to call getCustomVariable later in the visit.<br />
     * (by default custom variables are not stored on the visitor's computer.)
     *
     * @see {@link https://matomo.org/docs/custom-variables/|Custom Variables}
     */
    storeCustomVariablesInCookie() {
        try {
            window['_paq'].push(['storeCustomVariablesInCookie']);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Sets a custom dimension.<br />
     * (requires Matomo 2.15.1 + Custom Dimensions plugin)
     *
     * @param customDimensionId ID of the custom dimension to set.
     * @param customDimensionValue Value to be set.
     * @see {@link https://plugins.piwik.org/CustomDimensions|Custom Dimensions}
     */
    setCustomDimension(customDimensionId, customDimensionValue) {
        try {
            window['_paq'].push(['setCustomDimension', customDimensionId, customDimensionValue]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Deletes a custom dimension.<br />
     * (requires Matomo 2.15.1 + Custom Dimensions plugin)
     *
     * @param customDimensionId ID of the custom dimension to delete.
     * @see {@link https://plugins.piwik.org/CustomDimensions|Custom Dimensions}
     */
    deleteCustomDimension(customDimensionId) {
        try {
            window['_paq'].push(['deleteCustomDimension', customDimensionId]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Retrieve a custom dimension.<br />
     * (requires Matomo 2.15.1 + Custom Dimensions plugin)
     *
     * @param customDimensionId ID of the custom dimension to retrieve.
     * @returns Promise for the value for the requested custom dimension.
     * @see {@link https://plugins.piwik.org/CustomDimensions|Custom Dimensions}
     */
    getCustomDimension(customDimensionId) {
        return new Promise((resolve, reject) => {
            try {
                window['_paq'].push([
                    function () {
                        resolve(this.getCustomDimension(customDimensionId));
                    },
                ]);
            }
            catch (e) {
                if (!(e instanceof ReferenceError)) {
                    reject(e);
                }
            }
        });
    }
    /**
     * Sets campaign name parameter(s).
     *
     * @param name Name of the campaign
     * @see {@link https://matomo.org/docs/tracking-campaigns/|Campaigns}
     */
    setCampaignNameKey(name) {
        try {
            window['_paq'].push(['setCampaignNameKey', name]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Sets campaign keyword parameter(s).
     *
     * @param keyword Keyword parameter(s) of the campaign.
     * @see {@link https://matomo.org/docs/tracking-campaigns/|Campaigns}
     */
    setCampaignKeywordKey(keyword) {
        try {
            window['_paq'].push(['setCampaignKeywordKey', keyword]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Sets if or not to attribute a conversion to the first referrer.<br />
     * By default, conversion is attributed to the most recent referrer.
     *
     * @param conversionToFirstReferrer If true, Matomo will attribute the Goal conversion to the first referrer used
     * instead of the last one.
     * @see {@link https://matomo.org/docs/tracking-campaigns/|Campaigns}
     * @see {@link https://matomo.org/faq/general/faq_106/#faq_106|Conversions to the first referrer}
     */
    setConversionAttributionFirstReferrer(conversionToFirstReferrer) {
        try {
            window['_paq'].push(['setConversionAttributionFirstReferrer', conversionToFirstReferrer]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Sets the current page view as a product or category page view.<br />
     * When you call setEcommerceView, it must be followed by a call to trackPageView to record the product or category page view.
     *
     * @param productSKU SKU of the viewed product.
     * @param productName Name of the viewed product.
     * @param productCategory Category of the viewed product.
     * @param price Price of the viewed product.
     */
    setEcommerceView(productSKU, productName, productCategory, price) {
        try {
            window['_paq'].push(['setEcommerceView', productSKU, productName, productCategory, price]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Adds a product into the eCommerce order.<br />
     * Must be called for each product in the order.
     *
     * @param productSKU SKU of the product to add.
     * @param [productName] Optional name of the product to add.
     * @param [productCategory] Optional category of the product to add.
     * @param [price] Optional price of the product to add.
     * @param [quantity] Optional quantity of the product to add.
     */
    addEcommerceItem(productSKU, productName, productCategory, price, quantity) {
        try {
            const args = [productSKU];
            if (!!productName) {
                args.push(productName);
                if (!!productCategory) {
                    args.push(productCategory);
                    if (typeof price === 'number') {
                        args.push(price);
                        if (typeof quantity === 'number') {
                            args.push(quantity);
                        }
                    }
                }
            }
            window['_paq'].push(['addEcommerceItem', ...args]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Removes the specified product from the untracked ecommerce order.
     *
     * @param productSKU SKU of the product to remove.
     */
    removeEcommerceItem(productSKU) {
        try {
            const args = [productSKU];
            window['_paq'].push(['removeEcommerceItem', ...args]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Removes all products in the untracked ecommerce order.<br />
     * Note: this is done automatically after trackEcommerceOrder() is called.
     */
    clearEcommerceCart() {
        try {
            window['_paq'].push(['clearEcommerceCart']);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Returns all ecommerce items currently in the untracked ecommerce order.
     * The returned array will be a copy, so changing it won't affect the ecommerce order.<br />
     * To affect what gets tracked, use the addEcommerceItem()/removeEcommerceItem()/clearEcommerceCart() methods.<br />
     * Use this method to see what will be tracked before you track an order or cart update.
     */
    getEcommerceItems() {
        return new Promise((resolve, reject) => {
            try {
                window['_paq'].push([
                    function () {
                        resolve(this.getEcommerceItems());
                    },
                ]);
            }
            catch (e) {
                if (!(e instanceof ReferenceError)) {
                    reject(e);
                }
            }
        });
    }
    /**
     * Tracks a shopping cart.<br />
     * Call this function every time a user is adding, updating or deleting a product from the cart.
     *
     * @param grandTotal Grand total of the shopping cart.
     */
    trackEcommerceCartUpdate(grandTotal) {
        try {
            window['_paq'].push(['trackEcommerceCartUpdate', grandTotal]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Tracks an Ecommerce order, including any eCommerce item previously added to the order.<br />
     * orderId and grandTotal (ie.revenue) are required parameters.
     *
     * @param orderId ID of the tracked order.
     * @param grandTotal Grand total of the tracked order.
     * @param [subTotal] Sub total of the tracked order.
     * @param [tax] Taxes for the tracked order.
     * @param [shipping] Shipping fees for the tracked order.
     * @param [discount] Discount granted for the tracked order.
     */
    trackEcommerceOrder(orderId, grandTotal, subTotal, tax, shipping, discount) {
        try {
            const args = [orderId, grandTotal];
            if (typeof subTotal === 'number') {
                args.push(subTotal);
                if (typeof tax === 'number') {
                    args.push(tax);
                    if (typeof shipping === 'number') {
                        args.push(shipping);
                        if (typeof discount === 'number' || typeof discount === 'boolean') {
                            args.push(discount);
                        }
                    }
                }
            }
            window['_paq'].push(['trackEcommerceOrder', ...args]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * By default the Matomo tracker assumes consent to tracking.
     * To change this behavior so nothing is tracked until a user consents, you must call requireConsent.
     */
    requireConsent() {
        try {
            window['_paq'].push(['requireConsent']);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Require user cookie consent before storing and using any cookies.
     */
    requireCookieConsent() {
        try {
            window['_paq'].push(['requireCookieConsent']);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Marks that the current user has consented.<br />
     * The consent is one-time only, so in a subsequent browser session, the user will have to consent again.<br />
     * To remember consent, see the method below: rememberConsentGiven.
     */
    setConsentGiven() {
        try {
            window['_paq'].push(['setConsentGiven']);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Marks that the current user has consented to store and use cookies.<br />
     * The consent is one-time only, so in a subsequent browser session, the user will have to consent again.<br />
     * To remember consent, see the method below: rememberCookieConsentGiven.
     */
    setCookieConsentGiven() {
        try {
            window['_paq'].push(['setCookieConsentGiven']);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Marks that the current user has consented, and remembers this consent through a browser cookie.<br />
     * The next time the user visits the site, Matomo will remember that they consented, and track them.<br />
     * If you call this method, you do not need to call setConsentGiven.
     *
     * @param hoursToExpire Expiry period for your user consent.
     */
    rememberConsentGiven(hoursToExpire) {
        try {
            const args = [];
            if (typeof hoursToExpire === 'number') {
                args.push(hoursToExpire);
            }
            window['_paq'].push(['rememberConsentGiven', ...args]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Marks that the current user has consented, and remembers this consent through a browser cookie.<br />
     * The next time the user visits the site, Matomo will remember that they consented, and track them.<br />
     * If you call this method, you do not need to call setCookieConsentGiven.
     *
     * @param hoursToExpire Expiry period for your user consent.
     */
    rememberCookieConsentGiven(hoursToExpire) {
        try {
            const args = [];
            if (typeof hoursToExpire === 'number') {
                args.push(hoursToExpire);
            }
            window['_paq'].push(['rememberCookieConsentGiven', ...args]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Removes a user's consent, both if the consent was one-time only and if the consent was remembered.<br />
     * This makes sure the cookie that remembered the given consent is deleted.<br />
     * After calling this method, the user will have to consent again in order to be tracked.
     */
    forgetConsentGiven() {
        try {
            window['_paq'].push(['forgetConsentGiven']);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Removes a user's consent, both if the consent was one-time only and if the consent was remembered.<br />
     * This makes sure the cookie that remembered the given consent is deleted.<br />
     * After calling this method, the user will have to consent again in order to be tracked.
     */
    forgetCookieConsentGiven() {
        try {
            window['_paq'].push(['forgetCookieConsentGiven']);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Sets if to not to track users who opt out of tracking using Mozilla's (proposed) Do Not Track setting.
     *
     * @param doNotTrack If true, users who opted for Do Not Track in their settings won't be tracked.
     * @see {@link https://www.w3.org/TR/tracking-dnt/}
     */
    setDoNotTrack(doNotTrack) {
        try {
            window['_paq'].push(['setDoNotTrack', doNotTrack]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Disables all first party cookies.<br />
     * Existing Matomo cookies for this websites will be deleted on the next page view.
     */
    disableCookies() {
        try {
            window['_paq'].push(['disableCookies']);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Deletes the tracking cookies currently set (useful when creating new visits).
     */
    deleteCookies() {
        try {
            window['_paq'].push(['deleteCookies']);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Returns whether cookies are enabled and supported by this browser.
     *
     * @returns Promise for the support and activation of cookies.
     */
    hasCookies() {
        return new Promise((resolve, reject) => {
            try {
                window['_paq'].push([
                    function () {
                        resolve(this.hasCookies());
                    },
                ]);
            }
            catch (e) {
                if (!(e instanceof ReferenceError)) {
                    reject(e);
                }
            }
        });
    }
    /**
     * Sets the tracking cookie name prefix.<br />
     * Default prefix is 'pk'.
     *
     * @param prefix Prefix for the tracking cookie names.
     */
    setCookieNamePrefix(prefix) {
        try {
            window['_paq'].push(['setCookieNamePrefix', prefix]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Sets the domain of the tracking cookies.<br />
     * Default is the document domain.<br />
     * If your website can be visited at both www.example.com and example.com, you would use: `'.example.com'` or `'*.example.com'`.
     *
     * @param domain Domain of the tracking cookies.
     */
    setCookieDomain(domain) {
        try {
            window['_paq'].push(['setCookieDomain', domain]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Sets the path of the tracking cookies.<br />
     * Default is '/'.
     *
     * @param path Path of the tracking cookies.
     */
    setCookiePath(path) {
        try {
            window['_paq'].push(['setCookiePath', path]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Sets if or not to enable the Secure cookie flag on all first party cookies.<br />
     * This should be used when your website is only available under HTTPS so that all tracking cookies are always sent
     * over secure connection.
     *
     * @param secure If true, the secure cookie flag will be set on all first party cookies.
     */
    setSecureCookie(secure) {
        try {
            window['_paq'].push(['setSecureCookie', secure]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Sets the visitor cookie timeout.<br />
     * Default is 13 months.
     *
     * @param timeout Timeout, in seconds, for the visitor cookie timeout.
     */
    setVisitorCookieTimeout(timeout) {
        try {
            window['_paq'].push(['setVisitorCookieTimeout', timeout]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Sets the referral cookie timeout.<br />
     * Default is 6 months.
     *
     * @param timeout Timeout, in seconds, for the referral cookie timeout.
     */
    setReferralCookieTimeout(timeout) {
        try {
            window['_paq'].push(['setReferralCookieTimeout', timeout]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Sets the session cookie timeout.<br />
     * Default is 30 minutes.
     *
     * @param timeout Timeout, in seconds, for the session cookie timeout.
     */
    setSessionCookieTimeout(timeout) {
        try {
            window['_paq'].push(['setSessionCookieTimeout', timeout]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Adds a click listener to a specific link element.<br />
     * When clicked, Matomo will log the click automatically.
     *
     * @param element Element on which to add a click listener.
     */
    addListener(element) {
        try {
            window['_paq'].push(['addListener', element]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Sets the request method to either 'GET' or 'POST'. (The default is 'GET'.)<br />
     * To use the POST request method, either:<br />
     * 1) the Matomo host is the same as the tracked website host (Matomo installed in the same domain as your tracked website), or<br />
     * 2) if Matomo is not installed on the same host as your website, you need to enable CORS (Cross domain requests).
     *
     * @param method HTTP method for sending information to the Matomo server.
     */
    setRequestMethod(method) {
        try {
            window['_paq'].push(['setRequestMethod', method]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Sets a function that will process the request content.<br />
     * The function will be called once the request (query parameters string) has been prepared, and before the request content is sent.
     *
     * @param callback Function that will process the request content.
     */
    setCustomRequestProcessing(callback) {
        try {
            window['_paq'].push(['setCustomRequestProcessing', callback]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Sets request Content-Type header value.<br />
     * Applicable when 'POST' request method is used via setRequestMethod.
     *
     * @param contentType Value for Content-Type HTTP header.
     */
    setRequestContentType(contentType) {
        try {
            window['_paq'].push(['setRequestContentType', contentType]);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    /**
     * Disables the feature which groups together multiple tracking requests and send them as a bulk POST request.<br />
     * Disabling this feature is useful when you want to be able to replay all logs: one must use disableQueueRequest
     * to disable this behavior to later be able to replay logged Matomo logs (otherwise a subset of the requests
     * wouldn't be able to be replayed).
     */
    disableQueueRequest() {
        try {
            window['_paq'].push(['disableQueueRequest']);
        }
        catch (e) {
            if (!(e instanceof ReferenceError)) {
                throw e;
            }
        }
    }
    static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.3", ngImport: i0, type: MatomoTracker, deps: [{ token: MATOMO_CONFIGURATION }], target: i0.ɵɵFactoryTarget.Injectable }); }
    static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.1.3", ngImport: i0, type: MatomoTracker }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.3", ngImport: i0, type: MatomoTracker, decorators: [{
            type: Injectable
        }], ctorParameters: function () { return [{ type: undefined, decorators: [{
                    type: Inject,
                    args: [MATOMO_CONFIGURATION]
                }] }]; } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWF0b21vLXRyYWNrZXIuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1tYXRvbW8vc3JjL2xpYi9tYXRvbW8tdHJhY2tlci5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRW5ELE9BQU8sRUFBRSxvQkFBb0IsRUFBdUIsTUFBTSx3QkFBd0IsQ0FBQzs7QUFtQm5GOzs7O0dBSUc7QUFFSCxNQUFNLE9BQU8sYUFBYTtJQUN4Qjs7OztPQUlHO0lBQ0gsWUFBMkQsYUFBa0M7UUFBbEMsa0JBQWEsR0FBYixhQUFhLENBQXFCO1FBQzNGLElBQUk7WUFDRixJQUFJLE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLFdBQVcsRUFBRTtnQkFDekMsT0FBTyxDQUFDLElBQUksQ0FBQyxzQ0FBc0MsQ0FBQyxDQUFDO2FBQ3REO1NBQ0Y7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLElBQUksQ0FBQyxDQUFDLENBQUMsWUFBWSxjQUFjLENBQUMsRUFBRTtnQkFDbEMsTUFBTSxDQUFDLENBQUM7YUFDVDtTQUNGO0lBQ0gsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxhQUFhLENBQUMsV0FBb0I7UUFDaEMsSUFBSTtZQUNGLE1BQU0sSUFBSSxHQUFVLEVBQUUsQ0FBQztZQUN2QixJQUFJLENBQUMsQ0FBQyxXQUFXLEVBQUU7Z0JBQ2pCLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7YUFDeEI7WUFDRCxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsZUFBZSxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQztTQUNqRDtRQUFDLE9BQU8sQ0FBQyxFQUFFO1lBQ1YsSUFBSSxDQUFDLENBQUMsQ0FBQyxZQUFZLGNBQWMsQ0FBQyxFQUFFO2dCQUNsQyxNQUFNLENB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QUMsQ0FBQyxDQUFDLFlBQVksY0FBYyxDQUFDLEVBQUU7Z0JBQ2xDLE1BQU0sQ0FBQyxDQUFDO2FBQ1Q7U0FDRjtJQUNILENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILHFCQUFxQixDQUFDLFdBQW1CO1FBQ3ZDLElBQUk7WUFDRixNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsdUJBQXVCLEVBQUUsV0FBVyxDQUFDLENBQUMsQ0FBQztTQUM3RDtRQUFDLE9BQU8sQ0FBQyxFQUFFO1lBQ1YsSUFBSSxDQUFDLENBQUMsQ0FBQyxZQUFZLGNBQWMsQ0FBQyxFQUFFO2dCQUNsQyxNQUFNLENBQUMsQ0FBQzthQUNUO1NBQ0Y7SUFDSCxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxtQkFBbUI7UUFDakIsSUFBSTtZQUNGLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLENBQUM7U0FDOUM7UUFBQyxPQUFPLENBQUMsRUFBRTtZQUNWLElBQUksQ0FBQyxDQUFDLENBQUMsWUFBWSxjQUFjLENBQUMsRUFBRTtnQkFDbEMsTUFBTSxDQUFDLENBQUM7YUFDVDtTQUNGO0lBQ0gsQ0FBQzs4R0Foc0RVLGFBQWEsa0JBTUosb0JBQW9CO2tIQU43QixhQUFhOzsyRkFBYixhQUFhO2tCQUR6QixVQUFVOzswQkFPSSxNQUFNOzJCQUFDLG9CQUFvQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdCwgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5pbXBvcnQgeyBNQVRPTU9fQ09ORklHVVJBVElPTiwgTWF0b21vQ29uZmlndXJhdGlvbiB9IGZyb20gJy4vbWF0b21vLWNvbmZpZ3VyYXRpb24nO1xuXG4vKipcbiAqIEFjY2VzcyB0byB0aGUgZ2xvYmFsIHdpbmRvdyB2YXJpYWJsZS5cbiAqL1xuZGVjbGFyZSB2YXIgd2luZG93OiB7XG4gIFtrZXk6IHN0cmluZ106IGFueTtcbiAgcHJvdG90eXBlOiBXaW5kb3c7XG4gIG5ldyAoKTogV2luZG93O1xufTtcbi8vIGRlY2xhcmUgaW50ZXJmYWNlIFdpbmRvdyB7XG4vLyAgIF9wYXE6IGFueTtcbi8vIH1cblxuLyoqXG4gKiBNYXRvbW8gc2NvcGVcbiAqL1xudHlwZSBNYXRvbW9TY29wZSA9ICdwYWdlJyB8ICd2aXNpdCcgfCAnZXZlbnQnO1xuXG4vKipcbiAqIFdyYXBwZXIgZm9yIGZ1bmN0aW9ucyBhdmFpbGFibGUgaW4gdGhlIE1hdG9tbyBKYXZhc2NyaXB0IHRyYWNrZXIuXG4gKlxuICogQGV4cG9ydFxuICovXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgTWF0b21vVHJhY2tlciB7XG4gIC8qKlxuICAgKiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIE1hdG9tb1RyYWNrZXIuXG4gICAqXG4gICAqIEBwYXJhbSBjb25maWd1cmF0aW9uIE1hdG9tbyBjb25maWd1cmF0aW9uIHByb3ZpZGVkIGJ5IERJLlxuICAgKi9cbiAgY29uc3RydWN0b3IoQEluamVjdChNQVRPTU9fQ09ORklHVVJBVElPTikgcHJpdmF0ZSByZWFkb25seSBjb25maWd1cmF0aW9uOiBNYXRvbW9Db25maWd1cmF0aW9uKSB7XG4gICAgdHJ5IHtcbiAgICAgIGlmICh0eXBlb2Ygd2luZG93WydfcGFxJ10gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIGNvbnNvbGUud2FybignTWF0b21vIGhhcyBub3QgeWV0IGJlZW4gaW5pdGlhbGl6ZWQhJyk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBMb2dzIGEgdmlzaXQgdG8gdGhpcyBwYWdlLlxuICAgKlxuICAgKiBAcGFyYW0gW2N1c3RvbVRpdGxlXSBPcHRpb25hbCB0aXRsZSBvZiB0aGUgdmlzaXRlZCBwYWdlLlxuICAgKi9cbiAgdHJhY2tQYWdlVmlldyhjdXN0b21UaXRsZT86IHN0cmluZyk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBhcmdzOiBhbnlbXSA9IFtdO1xuICAgICAgaWYgKCEhY3VzdG9tVGl0bGUpIHtcbiAgICAgICAgYXJncy5wdXNoKGN1c3RvbVRpdGxlKTtcbiAgICAgIH1cbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWyd0cmFja1BhZ2VWaWV3JywgLi4uYXJnc10pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTG9ncyBhbiBldmVudCB3aXRoIGFuIGV2ZW50IGNhdGVnb3J5IChWaWRlb3MsIE11c2ljLCBHYW1lc+KApiksIGFuIGV2ZW50IGFjdGlvbiAoUGxheSwgUGF1c2UsIER1cmF0aW9uLFxuICAgKiBBZGQgUGxheWxpc3QsIERvd25sb2FkZWQsIENsaWNrZWTigKYpLCBhbmQgYW4gb3B0aW9uYWwgZXZlbnQgbmFtZSBhbmQgb3B0aW9uYWwgbnVtZXJpYyB2YWx1ZS5cbiAgICpcbiAgICogQHBhcmFtIGNhdGVnb3J5IENhdGVnb3J5IG9mIHRoZSBldmVudC5cbiAgICogQHBhcmFtIGFjdGlvbiBBY3Rpb24gb2YgdGhlIGV2ZW50LlxuICAgKiBAcGFyYW0gW25hbWVdIE9wdGlvbmFsIG5hbWUgb2YgdGhlIGV2ZW50LlxuICAgKiBAcGFyYW0gW3ZhbHVlXSBPcHRpb25hbCB2YWx1ZSBmb3IgdGhlIGV2ZW50LlxuICAgKi9cbiAgdHJhY2tFdmVudChjYXRlZ29yeTogc3RyaW5nLCBhY3Rpb246IHN0cmluZywgbmFtZT86IHN0cmluZywgdmFsdWU/OiBudW1iZXIpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgYXJnczogYW55W10gPSBbY2F0ZWdvcnksIGFjdGlvbl07XG4gICAgICBpZiAoISFuYW1lKSB7XG4gICAgICAgIGFyZ3MucHVzaChuYW1lKTtcbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICBhcmdzLnB1c2godmFsdWUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsndHJhY2tFdmVudCcsIC4uLmFyZ3NdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIExvZ3MgYW4gaW50ZXJuYWwgc2l0ZSBzZWFyY2ggZm9yIGEgc3BlY2lmaWMga2V5d29yZCwgaW4gYW4gb3B0aW9uYWwgY2F0ZWdvcnksXG4gICAqIHNwZWNpZnlpbmcgdGhlIG9wdGlvbmFsIGNvdW50IG9mIHNlYXJjaCByZXN1bHRzIGluIHRoZSBwYWdlLlxuICAgKlxuICAgKiBAcGFyYW0ga2V5d29yZCBLZXl3b3JkcyBvZiB0aGUgc2VhcmNoIHF1ZXJ5LlxuICAgKiBAcGFyYW0gW2NhdGVnb3J5XSBPcHRpb25hbCBjYXRlZ29yeSBvZiB0aGUgc2VhcmNoIHF1ZXJ5LlxuICAgKiBAcGFyYW0gW3Jlc3VsdHNDb3VudF0gT3B0aW9uYWwgbnVtYmVyIG9mIHJlc3VsdHMgcmV0dXJuZWQgYnkgdGhlIHNlYXJjaCBxdWVyeS5cbiAgICovXG4gIHRyYWNrU2l0ZVNlYXJjaChrZXl3b3JkOiBzdHJpbmcsIGNhdGVnb3J5Pzogc3RyaW5nLCByZXN1bHRzQ291bnQ/OiBudW1iZXIpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgYXJnczogYW55W10gPSBba2V5d29yZF07XG4gICAgICBpZiAoISFjYXRlZ29yeSkge1xuICAgICAgICBhcmdzLnB1c2goY2F0ZWdvcnkpO1xuICAgICAgICBpZiAodHlwZW9mIHJlc3VsdHNDb3VudCA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICBhcmdzLnB1c2gocmVzdWx0c0NvdW50KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3RyYWNrU2l0ZVNlYXJjaCcsIC4uLmFyZ3NdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE1hbnVhbGx5IGxvZ3MgYSBjb252ZXJzaW9uIGZvciB0aGUgbnVtZXJpYyBnb2FsIElELCB3aXRoIGFuIG9wdGlvbmFsIG51bWVyaWMgY3VzdG9tIHJldmVudWUgY3VzdG9tUmV2ZW51ZS5cbiAgICpcbiAgICogQHBhcmFtIGlkR29hbCBudW1lcmljIElEIG9mIHRoZSBnb2FsIHRvIGxvZyBhIGNvbnZlcnNpb24gZm9yLlxuICAgKiBAcGFyYW0gW2N1c3RvbVJldmVudWVdIE9wdGlvbmFsIGN1c3RvbSByZXZlbnVlIHRvIGxvZyBmb3IgdGhlIGdvYWwuXG4gICAqL1xuICB0cmFja0dvYWwoaWRHb2FsOiBudW1iZXIsIGN1c3RvbVJldmVudWU/OiBudW1iZXIpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgYXJnczogYW55W10gPSBbaWRHb2FsXTtcbiAgICAgIGlmICh0eXBlb2YgY3VzdG9tUmV2ZW51ZSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgYXJncy5wdXNoKGN1c3RvbVJldmVudWUpO1xuICAgICAgfVxuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3RyYWNrR29hbCcsIC4uLmFyZ3NdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE1hbnVhbGx5IGxvZ3MgYSBjbGljayBmcm9tIHlvdXIgb3duIGNvZGUuXG4gICAqXG4gICAqIEBwYXJhbSB1cmwgRnVsbCBVUkwgd2hpY2ggaXMgdG8gYmUgdHJhY2tlZCBhcyBhIGNsaWNrLlxuICAgKiBAcGFyYW0gbGlua1R5cGUgRWl0aGVyICdsaW5rJyBmb3IgYW4gb3V0bGluayBvciAnZG93bmxvYWQnIGZvciBhIGRvd25sb2FkLlxuICAgKi9cbiAgdHJhY2tMaW5rKHVybDogc3RyaW5nLCBsaW5rVHlwZTogJ2xpbmsnIHwgJ2Rvd25sb2FkJyk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsndHJhY2tMaW5rJywgdXJsLCBsaW5rVHlwZV0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2NhbnMgdGhlIGVudGlyZSBET00gZm9yIGFsbCBjb250ZW50IGJsb2NrcyBhbmQgdHJhY2tzIGFsbCBpbXByZXNzaW9ucyBvbmNlIHRoZSBET00gcmVhZHkgZXZlbnQgaGFzIGJlZW4gdHJpZ2dlcmVkLlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RldmVsb3Blci5tYXRvbW8ub3JnL2d1aWRlcy9jb250ZW50LXRyYWNraW5nfENvbnRlbnQgVHJhY2tpbmd9XG4gICAqL1xuICB0cmFja0FsbENvbnRlbnRJbXByZXNzaW9ucygpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3RyYWNrQWxsQ29udGVudEltcHJlc3Npb25zJ10pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2NhbnMgdGhlIGVudGlyZSBET00gZm9yIGFsbCBjb250ZW50IGJsb2NrcyBhcyBzb29uIGFzIHRoZSBwYWdlIGlzIGxvYWRlZC48YnIgLz5cbiAgICogSXQgdHJhY2tzIGFuIGltcHJlc3Npb24gb25seSBpZiBhIGNvbnRlbnQgYmxvY2sgaXMgYWN0dWFsbHkgdmlzaWJsZS5cbiAgICpcbiAgICogQHBhcmFtIGNoZWNrT25TY3JvbGwgSWYgdHJ1ZSwgY2hlY2tzIGZvciBuZXcgY29udGVudCBibG9ja3Mgd2hpbGUgc2Nyb2xsaW5nIHRoZSBwYWdlLlxuICAgKiBAcGFyYW0gdGltZUludGVydmFsIER1cmF0aW9uLCBpbiBtaWxsaXNlY29uZHMsIGJldHdlZW4gdHdvIGNoZWNrcyB1cG9uIHNjcm9sbC5cbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kZXZlbG9wZXIubWF0b21vLm9yZy9ndWlkZXMvY29udGVudC10cmFja2luZ3xDb250ZW50IFRyYWNraW5nfVxuICAgKi9cbiAgdHJhY2tWaXNpYmxlQ29udGVudEltcHJlc3Npb25zKGNoZWNrT25TY3JvbGw6IGJvb2xlYW4sIHRpbWVJbnRlcnZhbDogbnVtYmVyKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWyd0cmFja1Zpc2libGVDb250ZW50SW1wcmVzc2lvbnMnLCBjaGVja09uU2Nyb2xsLCB0aW1lSW50ZXJ2YWxdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNjYW5zIHRoZSBnaXZlbiBET00gbm9kZSBhbmQgaXRzIGNoaWxkcmVuIGZvciBjb250ZW50IGJsb2NrcyBhbmQgdHJhY2tzIGFuIGltcHJlc3Npb24gZm9yIHRoZW1cbiAgICogaWYgbm8gaW1wcmVzc2lvbiB3YXMgYWxyZWFkeSB0cmFja2VkIGZvciBpdC5cbiAgICpcbiAgICogQHBhcmFtIG5vZGUgRE9NIG5vZGUgaW4gd2hpY2ggdG8gbG9vayBmb3IgY29udGVudCBibG9ja3Mgd2hpY2ggaGF2ZSBub3QgYmVlbiBwcmV2aW91c2x5IHRyYWNrZWQuXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZGV2ZWxvcGVyLm1hdG9tby5vcmcvZ3VpZGVzL2NvbnRlbnQtdHJhY2tpbmd8Q29udGVudCBUcmFja2luZ31cbiAgICovXG4gIHRyYWNrQ29udGVudEltcHJlc3Npb25zV2l0aGluTm9kZShub2RlOiBOb2RlKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWyd0cmFja0NvbnRlbnRJbXByZXNzaW9uc1dpdGhpbk5vZGUnLCBub2RlXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUcmFja3MgYW4gaW50ZXJhY3Rpb24gd2l0aCB0aGUgZ2l2ZW4gRE9NIG5vZGUvY29udGVudCBibG9jay5cbiAgICpcbiAgICogQHBhcmFtIG5vZGUgRE9NIG5vZGUgZm9yIHdoaWNoIHRvIHRyYWNrIGEgY29udGVudCBpbnRlcmFjdGlvbi5cbiAgICogQHBhcmFtIGNvbnRlbnRJbnRlcmFjdGlvbiBOYW1lIG9mIHRoZSBjb250ZW50IGludGVyYWN0aW9uLlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RldmVsb3Blci5tYXRvbW8ub3JnL2d1aWRlcy9jb250ZW50LXRyYWNraW5nfENvbnRlbnQgVHJhY2tpbmd9XG4gICAqL1xuICB0cmFja0NvbnRlbnRJbnRlcmFjdGlvbk5vZGUobm9kZTogTm9kZSwgY29udGVudEludGVyYWN0aW9uOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3RyYWNrQ29udGVudEludGVyYWN0aW9uTm9kZScsIG5vZGUsIGNvbnRlbnRJbnRlcmFjdGlvbl0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVHJhY2tzIGEgY29udGVudCBpbXByZXNzaW9uIHVzaW5nIHRoZSBzcGVjaWZpZWQgdmFsdWVzLlxuICAgKlxuICAgKiBAcGFyYW0gY29udGVudE5hbWUgQ29udGVudCBuYW1lLlxuICAgKiBAcGFyYW0gY29udGVudFBpZWNlIENvbnRlbnQgcGllY2UuXG4gICAqIEBwYXJhbSBjb250ZW50VGFyZ2V0IENvbnRlbnQgdGFyZ2V0LlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RldmVsb3Blci5tYXRvbW8ub3JnL2d1aWRlcy9jb250ZW50LXRyYWNraW5nfENvbnRlbnQgVHJhY2tpbmd9XG4gICAqL1xuICB0cmFja0NvbnRlbnRJbXByZXNzaW9uKGNvbnRlbnROYW1lOiBzdHJpbmcsIGNvbnRlbnRQaWVjZTogc3RyaW5nLCBjb250ZW50VGFyZ2V0OiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3RyYWNrQ29udGVudEltcHJlc3Npb24nLCBjb250ZW50TmFtZSwgY29udGVudFBpZWNlLCBjb250ZW50VGFyZ2V0XSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUcmFja3MgYSBjb250ZW50IGludGVyYWN0aW9uIHVzaW5nIHRoZSBzcGVjaWZpZWQgdmFsdWVzLlxuICAgKlxuICAgKiBAcGFyYW0gY29udGVudEludGVyYWN0aW9uIENvbnRlbnQgaW50ZXJhY3Rpb24uXG4gICAqIEBwYXJhbSBjb250ZW50TmFtZSBDb250ZW50IG5hbWUuXG4gICAqIEBwYXJhbSBjb250ZW50UGllY2UgQ29udGVudCBwaWVjZS5cbiAgICogQHBhcmFtIGNvbnRlbnRUYXJnZXQgQ29udGVudCB0YXJnZXQuXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZGV2ZWxvcGVyLm1hdG9tby5vcmcvZ3VpZGVzL2NvbnRlbnQtdHJhY2tpbmd8Q29udGVudCBUcmFja2luZ31cbiAgICovXG4gIHRyYWNrQ29udGVudEludGVyYWN0aW9uKFxuICAgIGNvbnRlbnRJbnRlcmFjdGlvbjogc3RyaW5nLFxuICAgIGNvbnRlbnROYW1lOiBzdHJpbmcsXG4gICAgY29udGVudFBpZWNlOiBzdHJpbmcsXG4gICAgY29udGVudFRhcmdldDogc3RyaW5nXG4gICk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFtcbiAgICAgICAgJ3RyYWNrQ29udGVudEludGVyYWN0aW9uJyxcbiAgICAgICAgY29udGVudEludGVyYWN0aW9uLFxuICAgICAgICBjb250ZW50TmFtZSxcbiAgICAgICAgY29udGVudFBpZWNlLFxuICAgICAgICBjb250ZW50VGFyZ2V0LFxuICAgICAgXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBMb2dzIGFsbCBmb3VuZCBjb250ZW50IGJsb2NrcyB3aXRoaW4gYSBwYWdlIHRvIHRoZSBjb25zb2xlLjxiciAvPlxuICAgKiBUaGlzIGlzIHVzZWZ1bCB0byBkZWJ1ZyAvIHRlc3QgY29udGVudCB0cmFja2luZy5cbiAgICovXG4gIGxvZ0FsbENvbnRlbnRCbG9ja3NPblBhZ2UoKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydsb2dBbGxDb250ZW50QmxvY2tzT25QYWdlJ10pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2VuZHMgYSBwaW5nIHJlcXVlc3QuPGJyIC8+XG4gICAqIFBpbmcgcmVxdWVzdHMgZG8gbm90IHRyYWNrIG5ldyBhY3Rpb25zLlxuICAgKiBJZiB0aGV5IGFyZSBzZW50IHdpdGhpbiB0aGUgc3RhbmRhcmQgdmlzaXQgbGVuZ3RoLCB0aGV5IHdpbGwgZXh0ZW5kIHRoZSBleGlzdGluZyB2aXNpdCBhbmQgdGhlIGN1cnJlbnQgbGFzdCBhY3Rpb24gZm9yIHRoZSB2aXNpdC5cbiAgICogSWYgc2VudCBhZnRlciB0aGUgc3RhbmRhcmQgdmlzaXQgbGVuZ3RoLCBwaW5nIHJlcXVlc3RzIHdpbGwgY3JlYXRlIGEgbmV3IHZpc2l0IHVzaW5nIHRoZSBsYXN0IGFjdGlvbiBpbiB0aGUgbGFzdCBrbm93biB2aXNpdC48YnIgLz5cbiAgICogU2VlIGFsc28gZW5hYmxlSGVhcnRCZWF0VGltZXIuXG4gICAqL1xuICBwaW5nKCk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsncGluZyddKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEluc3RhbGxzIGEgSGVhcnQgYmVhdCB0aW1lciB0aGF0IHdpbGwgcmVndWxhcmx5IHNlbmQgcmVxdWVzdHMgdG8gTWF0b21vIGluIG9yZGVyIHRvIGJldHRlciBtZWFzdXJlIHRoZSB0aW1lIHNwZW50IG9uIHRoZSBwYWdlLjxiciAvPlxuICAgKiBUaGVzZSByZXF1ZXN0cyB3aWxsIGJlIHNlbnQgb25seSB3aGVuIHRoZSB1c2VyIGlzIGFjdGl2ZWx5IHZpZXdpbmcgdGhlIHBhZ2UgKHdoZW4gdGhlIHRhYiBpcyBhY3RpdmUgYW5kIGluIGZvY3VzKS48YnIgLz5cbiAgICogVGhlc2UgcmVxdWVzdHMgd2lsbCBub3QgdHJhY2sgYWRkaXRpb25hbCBhY3Rpb25zIG9yIHBhZ2Ugdmlld3MuPGJyIC8+XG4gICAqIEJ5IGRlZmF1bHQsIHRoZSBkZWxheSBpcyBzZXQgdG8gMTUgc2Vjb25kcy5cbiAgICpcbiAgICogQHBhcmFtIGRlbGF5IERlbGF5LCBpbiBzZWNvbmRzLCBiZXR3ZWVuIHR3byBoZWFydCBiZWF0cyB0byB0aGUgc2VydmVyLlxuICAgKi9cbiAgZW5hYmxlSGVhcnRCZWF0VGltZXIoZGVsYXk6IG51bWJlcik6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnZW5hYmxlSGVhcnRCZWF0VGltZXInLCBkZWxheV0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSW5zdGFsbHMgbGluayB0cmFja2luZyBvbiBhbGwgYXBwbGljYWJsZSBsaW5rIGVsZW1lbnRzLlxuICAgKlxuICAgKiBAcGFyYW0gW2VuYWJsZT1mYWxzZV0gU2V0IHRvIHRydWUgdG8gdXNlIHBzZXVkbyBjbGljay1oYW5kbGVyICh0cmVhdCBtaWRkbGUgY2xpY2sgYW5kIG9wZW4gY29udGV4dG1lbnUgYXNcbiAgICogbGVmdCBjbGljaykuPGJyIC8+XG4gICAqIEEgcmlnaHQgY2xpY2sgKG9yIGFueSBjbGljayB0aGF0IG9wZW5zIHRoZSBjb250ZXh0IG1lbnUpIG9uIGEgbGluayB3aWxsIGJlIHRyYWNrZWQgYXMgY2xpY2tlZCBldmVuIGlmIFwiT3BlbiBpbiBuZXcgdGFiXCJcbiAgICogaXMgbm90IHNlbGVjdGVkLjxiciAvPlxuICAgKiBJZiBmYWxzZSAoZGVmYXVsdCksIG5vdGhpbmcgd2lsbCBiZSB0cmFja2VkIG9uIG9wZW4gY29udGV4dCBtZW51IG9yIG1pZGRsZSBjbGljay5cbiAgICovXG4gIGVuYWJsZUxpbmtUcmFja2luZyhlbmFibGU6IGJvb2xlYW4gPSBmYWxzZSk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnZW5hYmxlTGlua1RyYWNraW5nJywgZW5hYmxlXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBFbmFibGVzIGNyb3NzIGRvbWFpbiBsaW5raW5nLiBCeSBkZWZhdWx0LCB0aGUgdmlzaXRvciBJRCB0aGF0IGlkZW50aWZpZXMgYSB1bmlxdWUgdmlzaXRvciBpcyBzdG9yZWQgaW4gdGhlIGJyb3dzZXInc1xuICAgKiBmaXJzdCBwYXJ0eSBjb29raWVzLjxiciAvPlxuICAgKiBUaGlzIG1lYW5zIHRoZSBjb29raWUgY2FuIG9ubHkgYmUgYWNjZXNzZWQgYnkgcGFnZXMgb24gdGhlIHNhbWUgZG9tYWluLjxiciAvPlxuICAgKiBJZiB5b3Ugb3duIG11bHRpcGxlIGRvbWFpbnMgYW5kIHdvdWxkIGxpa2UgdG8gdHJhY2sgYWxsIHRoZSBhY3Rpb25zIGFuZCBwYWdldmlld3Mgb2YgYSBzcGVjaWZpYyB2aXNpdG9yIGludG8gdGhlIHNhbWUgdmlzaXQsXG4gICAqIHlvdSBtYXkgZW5hYmxlIGNyb3NzIGRvbWFpbiBsaW5raW5nLjxiciAvPlxuICAgKiBXaGVuZXZlciBhIHVzZXIgY2xpY2tzIG9uIGEgbGluayBpdCB3aWxsIGFwcGVuZCBhIFVSTCBwYXJhbWV0ZXIgcGtfdmlkIHRvIHRoZSBjbGlja2VkIFVSTCB3aGljaCBmb3J3YXJkcyB0aGUgY3VycmVudFxuICAgKiB2aXNpdG9yIElEIHZhbHVlIHRvIHRoZSBwYWdlIG9mIHRoZSBkaWZmZXJlbnQgZG9tYWluLlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL21hdG9tby5vcmcvZmFxL2hvdy10by9mYXFfMjM2NTQvfENyb3NzIERvbWFpbiBMaW5raW5nfVxuICAgKi9cbiAgZW5hYmxlQ3Jvc3NEb21haW5MaW5raW5nKCk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnZW5hYmxlQ3Jvc3NEb21haW5MaW5raW5nJ10pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGUgY3Jvc3MgZG9tYWluIGxpbmtpbmcgdGltZW91dC48YnIgLz5cbiAgICogQnkgZGVmYXVsdCwgdGhlIHR3byB2aXNpdHMgYWNyb3NzIGRvbWFpbnMgd2lsbCBiZSBsaW5rZWQgdG9nZXRoZXIgd2hlbiB0aGUgbGluayBpcyBjbGlja2VkIGFuZCB0aGUgcGFnZSBpcyBsb2FkZWQgd2l0aGluXG4gICAqIGEgMTgwIHNlY29uZHMgdGltZW91dCB3aW5kb3cuXG4gICAqXG4gICAqIEBwYXJhbSB0aW1lb3V0IFRpbWVvdXQsIGluIHNlY29uZHMsIGJldHdlZW4gdHdvIGFjdGlvbnMgYWNyb3NzIHR3byBkb21haW5zIGJlZm9yZSBjcmVhdGluZyBhIG5ldyB2aXNpdC5cbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9tYXRvbW8ub3JnL2ZhcS9ob3ctdG8vZmFxXzIzNjU0L3xDcm9zcyBEb21haW4gTGlua2luZ31cbiAgICovXG4gIHNldENyb3NzRG9tYWluTGlua2luZ1RpbWVvdXQodGltZW91dDogbnVtYmVyKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydzZXRDcm9zc0RvbWFpbkxpbmtpbmdUaW1lb3V0JywgdGltZW91dF0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgcXVlcnkgcGFyYW1ldGVyIHRvIGFwcGVuZCB0byBsaW5rcyB0byBoYW5kbGUgY3Jvc3MgZG9tYWluIGxpbmtpbmcuPGJyIC8+XG4gICAqIFVzZSB0aGlzIHRvIGFkZCBjcm9zcyBkb21haW4gc3VwcG9ydCBmb3IgbGlua3MgdGhhdCBhcmUgYWRkZWQgdG8gdGhlIERPTSBkeW5hbWljYWxseS5cbiAgICpcbiAgICogQHJldHVybnMgUHJvbWlzZSBmb3IgdGhlIGBwa192aWRgIHF1ZXJ5IHBhcmFtZXRlci5cbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9tYXRvbW8ub3JnL2ZhcS9ob3ctdG8vZmFxXzIzNjU0L3xDcm9zcyBEb21haW4gTGlua2luZ31cbiAgICovXG4gIGdldENyb3NzRG9tYWluTGlua2luZ1VybFBhcmFtZXRlcigpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFtcbiAgICAgICAgICBmdW5jdGlvbiAodGhpczogYW55KTogdm9pZCB7XG4gICAgICAgICAgICByZXNvbHZlKHRoaXMuZ2V0Q3Jvc3NEb21haW5MaW5raW5nVXJsUGFyYW1ldGVyKCkpO1xuICAgICAgICAgIH0sXG4gICAgICAgIF0pO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogT3ZlcnJpZGVzIGRvY3VtZW50LnRpdGxlXG4gICAqXG4gICAqIEBwYXJhbSB0aXRsZSBUaXRsZSBvZiB0aGUgZG9jdW1lbnQuXG4gICAqL1xuICBzZXREb2N1bWVudFRpdGxlKHRpdGxlOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3NldERvY3VtZW50VGl0bGUnLCB0aXRsZV0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2V0cyBhcnJheSBvZiBob3N0bmFtZXMgb3IgZG9tYWlucyB0byBiZSB0cmVhdGVkIGFzIGxvY2FsLjxiciAvPlxuICAgKiBGb3Igd2lsZGNhcmQgc3ViZG9tYWlucywgeW91IGNhbiB1c2U6IGBzZXREb21haW5zKCcuZXhhbXBsZS5jb20nKWA7IG9yIGBzZXREb21haW5zKCcqLmV4YW1wbGUuY29tJyk7YC48YnIgLz5cbiAgICogWW91IGNhbiBhbHNvIHNwZWNpZnkgYSBwYXRoIGFsb25nIGEgZG9tYWluOiBgc2V0RG9tYWlucygnKi5leGFtcGxlLmNvbS9zdWJzaXRlMScpO2AuXG4gICAqXG4gICAqIEBwYXJhbSBkb21haW5zIExpc3Qgb2YgaG9zdG5hbWVzIG9yIGRvbWFpbnMsIHdpdGggb3Igd2l0aG91dCBwYXRoLCB0byBiZSB0cmVhdGVkIGFzIGxvY2FsLlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL21hdG9tby5vcmcvZmFxL2hvdy10by9mYXFfMjM2NTQvfENyb3NzIERvbWFpbiBMaW5raW5nfVxuICAgKi9cbiAgc2V0RG9tYWlucyhkb21haW5zOiBzdHJpbmdbXSk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnc2V0RG9tYWlucycsIGRvbWFpbnNdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE92ZXJyaWRlIHRoZSBwYWdlJ3MgcmVwb3J0ZWQgVVJMLlxuICAgKlxuICAgKiBAcGFyYW0gdXJsIFVSTCB0byBiZSByZXBvcnRlZCBmb3IgdGhlIHBhZ2UuXG4gICAqL1xuICBzZXRDdXN0b21VcmwodXJsOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3NldEN1c3RvbVVybCcsIHVybF0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogT3ZlcnJpZGVzIHRoZSBkZXRlY3RlZCBIdHRwLVJlZmVyZXIuXG4gICAqXG4gICAqIEBwYXJhbSB1cmwgVVJMIHRvIGJlIHJlcG9ydGVkIGZvciB0aGUgcmVmZXJlci5cbiAgICovXG4gIHNldFJlZmVycmVyVXJsKHVybDogc3RyaW5nKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydzZXRSZWZlcnJlclVybCcsIHVybF0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU3BlY2lmaWVzIHRoZSB3ZWJzaXRlIElELjxiciAvPlxuICAgKiBSZWR1bmRhbnQ6IGNhbiBiZSBzcGVjaWZpZWQgaW4gZ2V0VHJhY2tlcigpIGNvbnN0cnVjdG9yLlxuICAgKlxuICAgKiAvLyBUT0RPIEludmVzdGlnYXRlIGlmIHNldFNpdGVJZCBuZWVkcyB0byBiZSByZW1vdmVkIGZyb20gTWF0b21vVHJhY2tlci5cbiAgICogQHBhcmFtIHNpdGVJZCBTaXRlIElEIGZvciB0aGUgdHJhY2tlci5cbiAgICovXG4gIHNldFNpdGVJZChzaXRlSWQ6IG51bWJlcik6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnc2V0U2l0ZUlkJywgc2l0ZUlkXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTcGVjaWZpZXMgdGhlIE1hdG9tbyBIVFRQIEFQSSBVUkwgZW5kcG9pbnQuPGJyIC8+XG4gICAqIFBvaW50cyB0byB0aGUgcm9vdCBkaXJlY3Rvcnkgb2YgTWF0b21vLCBlLmcuIGh0dHA6Ly9tYXRvbW8uZXhhbXBsZS5vcmcvIG9yIGh0dHBzOi8vZXhhbXBsZS5vcmcvbWF0b21vLy48YnIgLz5cbiAgICogVGhpcyBmdW5jdGlvbiBpcyBvbmx5IHVzZWZ1bCB3aGVuIHRoZSAnT3ZlcmxheScgcmVwb3J0IGlzIG5vdCB3b3JraW5nLjxiciAvPlxuICAgKiBCeSBkZWZhdWx0LCB5b3UgZG8gbm90IG5lZWQgdG8gdXNlIHRoaXMgZnVuY3Rpb24uXG4gICAqXG4gICAqIEBwYXJhbSB1cmwgVVJMIGZvciBNYXRvbW8gSFRUUCBBUEkgZW5kcG9pbnQuXG4gICAqL1xuICBzZXRBcGlVcmwodXJsOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3NldEFwaVVybCcsIHVybF0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU3BlY2lmaWVzIHRoZSBNYXRvbW8gc2VydmVyIFVSTC48YnIgLz5cbiAgICogUmVkdW5kYW50OiBjYW4gYmUgc3BlY2lmaWVkIGluIGdldFRyYWNrZXIoKSBjb25zdHJ1Y3Rvci5cbiAgICpcbiAgICogLy8gVE9ETyBJbnZlc3RpZ2F0ZSBpZiBzZXRUcmFja2VyVXJsIG5lZWRzIHRvIGJlIHJlbW92ZWQgZnJvbSBNYXRvbW9UcmFja2VyLlxuICAgKiBAcGFyYW0gdXJsIFVSTCBmb3IgdGhlIE1hdG9tbyBzZXJ2ZXIuXG4gICAqL1xuICBzZXRUcmFja2VyVXJsKHVybDogc3RyaW5nKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydzZXRUcmFja2VyVXJsJywgdXJsXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBNYXRvbW8gc2VydmVyIFVSTC5cbiAgICpcbiAgICogQHJldHVybnMgUHJvbWlzZSBmb3IgdGhlIE1hdG9tbyBzZXJ2ZXIgVVJMLlxuICAgKi9cbiAgZ2V0TWF0b21vVXJsKCk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goW1xuICAgICAgICAgIGZ1bmN0aW9uICh0aGlzOiBhbnkpOiB2b2lkIHtcbiAgICAgICAgICAgIHJlc29sdmUodGhpcy5nZXRQaXdpa1VybCgpKTtcbiAgICAgICAgICB9LFxuICAgICAgICBdKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICAgIHJlamVjdChlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGN1cnJlbnQgdXJsIG9mIHRoZSBwYWdlIHRoYXQgaXMgY3VycmVudGx5IGJlaW5nIHZpc2l0ZWQuPGJyIC8+XG4gICAqIElmIGEgY3VzdG9tIFVSTCB3YXMgc2V0IGJlZm9yZSBjYWxsaW5nIHRoaXMgbWV0aG9kLCB0aGUgY3VzdG9tIFVSTCB3aWxsIGJlIHJldHVybmVkLlxuICAgKlxuICAgKiBAcmV0dXJucyBQcm9taXNlIGZvciB0aGUgVVJMIG9mIHRoZSBjdXJyZW50IHBhZ2UuXG4gICAqL1xuICBnZXRDdXJyZW50VXJsKCk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goW1xuICAgICAgICAgIGZ1bmN0aW9uICh0aGlzOiBhbnkpOiB2b2lkIHtcbiAgICAgICAgICAgIHJlc29sdmUodGhpcy5nZXRDdXJyZW50VXJsKCkpO1xuICAgICAgICAgIH0sXG4gICAgICAgIF0pO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyBjbGFzc2VzIHRvIGJlIHRyZWF0ZWQgYXMgZG93bmxvYWRzIChpbiBhZGRpdGlvbiB0byBwaXdpa19kb3dubG9hZCkuXG4gICAqXG4gICAqIEBwYXJhbSBjbGFzc2VzIENsYXNzLCBvciBsaXN0IG9mIGNsYXNzZXMgdG8gYmUgdHJlYXRlZCBhcyBkb3dubG9hZHMuXG4gICAqL1xuICBzZXREb3dubG9hZENsYXNzZXMoY2xhc3Nlczogc3RyaW5nIHwgc3RyaW5nW10pOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3NldERvd25sb2FkQ2xhc3NlcycsIGNsYXNzZXNdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgZmlsZSBleHRlbnNpb25zIHRvIGJlIHJlY29nbml6ZWQgYXMgZG93bmxvYWRzLjxiciAvPlxuICAgKiBFeGFtcGxlOiBgJ2RvY3gnYCBvciBgWydkb2N4JywgJ3hsc3gnXWAuXG4gICAqXG4gICAqIEBwYXJhbSBleHRlbnNpb25zIEV4dGVuc2lvbiwgb3IgbGlzdCBvZiBleHRlbnNpb25zIHRvIGJlIHJlY29nbml6ZWQgYXMgZG93bmxvYWRzLlxuICAgKi9cbiAgc2V0RG93bmxvYWRFeHRlbnNpb25zKGV4dGVuc2lvbnM6IHN0cmluZyB8IHN0cmluZ1tdKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydzZXREb3dubG9hZENsYXNzZXMnLCBleHRlbnNpb25zXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIGFkZGl0aW9uYWwgZmlsZSBleHRlbnNpb25zIHRvIGJlIHJlY29nbml6ZWQgYXMgZG93bmxvYWRzLjxiciAvPlxuICAgKiBFeGFtcGxlOiBgJ2RvY3gnYCBvciBgWydkb2N4JywgJ3hsc3gnXWAuXG4gICAqXG4gICAqIEBwYXJhbSBleHRlbnNpb25zIEV4dGVuc2lvbiwgb3IgbGlzdCBvZiBleHRlbnNpb25zIHRvIGJlIHJlY29nbml6ZWQgYXMgZG93bmxvYWRzLlxuICAgKi9cbiAgYWRkRG93bmxvYWRFeHRlbnNpb25zKGV4dGVuc2lvbnM6IHN0cmluZyB8IHN0cmluZ1tdKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydzZXREb3dubG9hZENsYXNzZXMnLCBleHRlbnNpb25zXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTcGVjaWZpZXMgZmlsZSBleHRlbnNpb25zIHRvIGJlIHJlbW92ZWQgZnJvbSB0aGUgbGlzdCBvZiBkb3dubG9hZCBmaWxlIGV4dGVuc2lvbnMuPGJyIC8+XG4gICAqIEV4YW1wbGU6IGAnZG9jeCdgIG9yIGBbJ2RvY3gnLCAneGxzeCddYC5cbiAgICpcbiAgICogQHBhcmFtIGV4dGVuc2lvbnMgRXh0ZW5zaW9uLCBvciBsaXN0IG9mIGV4dGVuc2lvbnMgbm90IHRvIGJlIHJlY29nbml6ZWQgYXMgZG93bmxvYWRzLlxuICAgKi9cbiAgcmVtb3ZlRG93bmxvYWRFeHRlbnNpb25zKGV4dGVuc2lvbnM6IHN0cmluZyB8IHN0cmluZ1tdKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydzZXREb3dubG9hZENsYXNzZXMnLCBleHRlbnNpb25zXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIGNsYXNzZXMgdG8gYmUgaWdub3JlZCBpZiBwcmVzZW50IGluIGxpbmsgKGluIGFkZGl0aW9uIHRvIHBpd2lrX2lnbm9yZSkuXG4gICAqXG4gICAqIEBwYXJhbSBjbGFzc2VzIENsYXNzLCBvciBsaXN0IG9mIGNsYXNzZXMgdG8gYmUgaWdub3JlZCBpZiBwcmVzZW50IGluIGxpbmsuXG4gICAqL1xuICBzZXRJZ25vcmVDbGFzc2VzKGNsYXNzZXM6IHN0cmluZyB8IHN0cmluZ1tdKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydzZXREb3dubG9hZENsYXNzZXMnLCBjbGFzc2VzXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIGNsYXNzZXMgdG8gYmUgdHJlYXRlZCBhcyBvdXRsaW5rcyAoaW4gYWRkaXRpb24gdG8gcGl3aWtfbGluaykuXG4gICAqXG4gICAqIEBwYXJhbSBjbGFzc2VzIENsYXNzLCBvciBsaXN0IG9mIGNsYXNzZXMgdG8gYmUgdHJlYXRlZCBhcyBvdXRsaW5rcy5cbiAgICovXG4gIHNldExpbmtDbGFzc2VzKGNsYXNzZXM6IHN0cmluZyB8IHN0cmluZ1tdKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydzZXREb3dubG9hZENsYXNzZXMnLCBjbGFzc2VzXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIGRlbGF5IGZvciBsaW5rIHRyYWNraW5nIChpbiBtaWxsaXNlY29uZHMpLlxuICAgKlxuICAgKiBAcGFyYW0gZGVsYXkgRGVsYXksIGluIG1pbGxpc2Vjb25kcywgZm9yIGxpbmsgdHJhY2tpbmcuXG4gICAqL1xuICBzZXRMaW5rVHJhY2tpbmdUaW1lcihkZWxheTogbnVtYmVyKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydzZXRMaW5rVHJhY2tpbmdUaW1lcicsIGRlbGF5XSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGRlbGF5IGZvciBsaW5rIHRyYWNraW5nLlxuICAgKlxuICAgKiBAcmV0dXJucyBQcm9taXNlIGZvciB0aGUgZGVsYXkgaW4gbWlsbGlzZWNvbmRzLlxuICAgKi9cbiAgZ2V0TGlua1RyYWNraW5nVGltZXIoKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbXG4gICAgICAgICAgZnVuY3Rpb24gKHRoaXM6IGFueSk6IHZvaWQge1xuICAgICAgICAgICAgcmVzb2x2ZSh0aGlzLmdldExpbmtUcmFja2luZ1RpbWVyKCkpO1xuICAgICAgICAgIH0sXG4gICAgICAgIF0pO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyBpZiBvciBub3QgdG8gcmVjb3JkIHRoZSBoYXNoIHRhZyAoYW5jaG9yKSBwb3J0aW9uIG9mIFVSTHMuXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSBJZiB0cnVlLCB0aGUgaGFzaCB0YWcgcG9ydGlvbiBvZiB0aGUgVVJMcyB3b24ndCBiZSByZWNvcmRlZC5cbiAgICovXG4gIGRpc2NhcmRIYXNoVGFnKHZhbHVlOiBib29sZWFuKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydkaXNjYXJkSGFzaFRhZycsIHZhbHVlXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBCeSBkZWZhdWx0IE1hdG9tbyB1c2VzIHRoZSBicm93c2VyIERPTSBUaW1pbmcgQVBJIHRvIGFjY3VyYXRlbHkgZGV0ZXJtaW5lIHRoZSB0aW1lIGl0IHRha2VzIHRvIGdlbmVyYXRlIGFuZCBkb3dubG9hZFxuICAgKiB0aGUgcGFnZS4gWW91IG1heSBvdmVyd3JpdGUgdGhpcyB2YWx1ZSB3aXRoIHRoaXMgZnVuY3Rpb24uXG4gICAqIFRoaXMgZnVuY3Rpb24gaXMgZGVwcmVjYXRlZCBpbiBNYXRvbW8gNC54LlxuICAgKlxuICAgKiBAcGFyYW0gZ2VuZXJhdGlvblRpbWUgVGltZSwgaW4gbWlsbGlzZWNvbmRzLCBvZiB0aGUgcGFnZSBnZW5lcmF0aW9uLlxuICAgKi9cbiAgc2V0R2VuZXJhdGlvblRpbWVNcyhnZW5lcmF0aW9uVGltZTogbnVtYmVyKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuY29uZmlndXJhdGlvbi5zY3JpcHRWZXJzaW9uIDwgNCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3NldEdlbmVyYXRpb25UaW1lTXMnLCBnZW5lcmF0aW9uVGltZV0pO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgICAgdGhyb3cgZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBcHBlbmRzIGEgY3VzdG9tIHN0cmluZyB0byB0aGUgZW5kIG9mIHRoZSBIVFRQIHJlcXVlc3QgdG8gcGl3aWsucGhwLlxuICAgKlxuICAgKiBAcGFyYW0gYXBwZW5kVG9VcmwgU3RyaW5nIHRvIGFwcGVuZCB0byB0aGUgZW5kIG9mIHRoZSBIVFRQIHJlcXVlc3QgdG8gcGl3aWsucGhwL21hdG9tby5waHAuXG4gICAqL1xuICBhcHBlbmRUb1RyYWNraW5nVXJsKGFwcGVuZFRvVXJsOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ2FwcGVuZFRvVHJhY2tpbmdVcmwnLCBhcHBlbmRUb1VybF0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRW5hYmxlcyBhIGZyYW1lLWJ1c3RlciB0byBwcmV2ZW50IHRoZSB0cmFja2VkIHdlYiBwYWdlIGZyb20gYmVpbmcgZnJhbWVkL2lmcmFtZWQuXG4gICAqL1xuICBraWxsRnJhbWUoKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydraWxsRnJhbWUnXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBGb3JjZXMgdGhlIGJyb3dzZXIgdG8gbG9hZCB0aGUgbGl2ZSBVUkwgaWYgdGhlIHRyYWNrZWQgd2ViIHBhZ2UgaXMgbG9hZGVkIGZyb20gYSBsb2NhbCBmaWxlXG4gICAqIChlLmcuLCBzYXZlZCB0byBzb21lb25lJ3MgZGVza3RvcCkuXG4gICAqXG4gICAqIEBwYXJhbSB1cmwgVVJMIHRvIHRyYWNrIGluc3RlYWQgb2YgZmlsZTovLyBVUkxzLlxuICAgKi9cbiAgcmVkaXJlY3RGaWxlKHVybDogc3RyaW5nKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydyZWRpcmVjdEZpbGUnLCB1cmxdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlY29yZHMgaG93IGxvbmcgdGhlIHBhZ2UgaGFzIGJlZW4gdmlld2VkIGlmIHRoZSBtaW5pbXVtVmlzaXRMZW5ndGggaXMgYXR0YWluZWQ7XG4gICAqIHRoZSBoZWFydEJlYXREZWxheSBkZXRlcm1pbmVzIGhvdyBmcmVxdWVudGx5IHRvIHVwZGF0ZSB0aGUgc2VydmVyLlxuICAgKlxuICAgKiBAcGFyYW0gbWluaW11bVZpc2l0TGVuZ3RoIER1cmF0aW9uIGJlZm9yZSBub3RpZnlpbmcgdGhlIHNlcnZlciBmb3IgdGhlIGR1cmF0aW9uIG9mIHRoZSB2aXNpdCB0byBhIHBhZ2UuXG4gICAqIEBwYXJhbSBoZWFydEJlYXREZWxheSBEZWxheSwgaW4gc2Vjb25kcywgYmV0d2VlbiB0d28gdXBkYXRlcyB0byB0aGUgc2VydmVyLlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RldmVsb3Blci5tYXRvbW8ub3JnL2d1aWRlcy90cmFja2luZy1qYXZhc2NyaXB0LWd1aWRlI2FjY3VyYXRlbHktbWVhc3VyZS10aGUtdGltZS1zcGVudC1vbi1lYWNoLXBhZ2V9XG4gICAqL1xuICBzZXRIZWFydEJlYXRUaW1lcihtaW5pbXVtVmlzaXRMZW5ndGg6IG51bWJlciwgaGVhcnRCZWF0RGVsYXk6IG51bWJlcik6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnc2V0SGVhcnRCZWF0VGltZXInLCBtaW5pbXVtVmlzaXRMZW5ndGgsIGhlYXJ0QmVhdERlbGF5XSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSAxNiBjaGFyYWN0ZXJzIElEIGZvciB0aGUgdmlzaXRvci5cbiAgICpcbiAgICogQHJldHVybnMgUHJvbWlzZSBmb3IgdGhlIHRoZSAxNiBjaGFyYWN0ZXJzIElEIGZvciB0aGUgdmlzaXRvci5cbiAgICovXG4gIGdldFZpc2l0b3JJZCgpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFtcbiAgICAgICAgICBmdW5jdGlvbiAodGhpczogYW55KTogdm9pZCB7XG4gICAgICAgICAgICByZXNvbHZlKHRoaXMuZ2V0VmlzaXRvcklkKCkpO1xuICAgICAgICAgIH0sXG4gICAgICAgIF0pO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgdmlzaXRvciBjb29raWUgY29udGVudHMgaW4gYW4gYXJyYXkuXG4gICAqXG4gICAqIEByZXR1cm5zIFByb21pc2UgZm9yIHRoZSBjb29raWUgY29udGVudHMgaW4gYW4gYXJyYXkuXG4gICAqL1xuICBnZXRWaXNpdG9ySW5mbygpOiBQcm9taXNlPGFueVtdPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goW1xuICAgICAgICAgIGZ1bmN0aW9uICh0aGlzOiBhbnkpOiB2b2lkIHtcbiAgICAgICAgICAgIHJlc29sdmUodGhpcy5nZXRWaXNpdG9ySW5mbygpKTtcbiAgICAgICAgICB9LFxuICAgICAgICBdKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICAgIHJlamVjdChlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHZpc2l0b3IgYXR0cmlidXRpb24gYXJyYXkgKFJlZmVyZXIgaW5mb3JtYXRpb24gYW5kL29yIENhbXBhaWduIG5hbWUgJiBrZXl3b3JkKS48YnIgLz5cbiAgICogQXR0cmlidXRpb24gaW5mb3JtYXRpb24gaXMgdXNlZCBieSBNYXRvbW8gdG8gY3JlZGl0IHRoZSBjb3JyZWN0IHJlZmVycmVyIChmaXJzdCBvciBsYXN0IHJlZmVycmVyKVxuICAgKiB1c2VkIHdoZW4gYSB1c2VyIHRyaWdnZXJzIGEgZ29hbCBjb252ZXJzaW9uLlxuICAgKlxuICAgKiBAcmV0dXJucyBQcm9taXNlIGZvciB0aGUgdmlzaXRvciBhdHRyaWJ1dGlvbiBhcnJheSAoUmVmZXJlciBpbmZvcm1hdGlvbiBhbmQvb3IgQ2FtcGFpZ24gbmFtZSAmIGtleXdvcmQpLlxuICAgKi9cbiAgZ2V0QXR0cmlidXRpb25JbmZvKCk6IFByb21pc2U8YW55W10+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbXG4gICAgICAgICAgZnVuY3Rpb24gKHRoaXM6IGFueSk6IHZvaWQge1xuICAgICAgICAgICAgcmVzb2x2ZSh0aGlzLmdldEF0dHJpYnV0aW9uSW5mbygpKTtcbiAgICAgICAgICB9LFxuICAgICAgICBdKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICAgIHJlamVjdChlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGF0dHJpYnV0aW9uIGNhbXBhaWduIG5hbWUuXG4gICAqXG4gICAqIEByZXR1cm5zIFByb21pc2UgZm9yIHRoZSB0aGUgYXR0cmlidXRpb24gY2FtcGFpZ24gbmFtZS5cbiAgICovXG4gIGdldEF0dHJpYnV0aW9uQ2FtcGFpZ25OYW1lKCk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goW1xuICAgICAgICAgIGZ1bmN0aW9uICh0aGlzOiBhbnkpOiB2b2lkIHtcbiAgICAgICAgICAgIHJlc29sdmUodGhpcy5nZXRBdHRyaWJ1dGlvbkNhbXBhaWduTmFtZSgpKTtcbiAgICAgICAgICB9LFxuICAgICAgICBdKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICAgIHJlamVjdChlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGF0dHJpYnV0aW9uIGNhbXBhaWduIGtleXdvcmQuXG4gICAqXG4gICAqIEByZXR1cm5zIFByb21pc2UgZm9yIHRoZSBhdHRyaWJ1dGlvbiBjYW1wYWlnbiBrZXl3b3JkLlxuICAgKi9cbiAgZ2V0QXR0cmlidXRpb25DYW1wYWlnbktleXdvcmQoKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbXG4gICAgICAgICAgZnVuY3Rpb24gKHRoaXM6IGFueSk6IHZvaWQge1xuICAgICAgICAgICAgcmVzb2x2ZSh0aGlzLmdldEF0dHJpYnV0aW9uQ2FtcGFpZ25LZXl3b3JkKCkpO1xuICAgICAgICAgIH0sXG4gICAgICAgIF0pO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgYXR0cmlidXRpb24gcmVmZXJyZXIgdGltZXN0YW1wLlxuICAgKlxuICAgKiBAcmV0dXJucyBQcm9taXNlIGZvciB0aGUgYXR0cmlidXRpb24gcmVmZXJyZXIgdGltZXN0YW1wIChhcyBzdHJpbmcpLlxuICAgKi9cbiAgZ2V0QXR0cmlidXRpb25SZWZlcnJlclRpbWVzdGFtcCgpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFtcbiAgICAgICAgICBmdW5jdGlvbiAodGhpczogYW55KTogdm9pZCB7XG4gICAgICAgICAgICByZXNvbHZlKHRoaXMuZ2V0QXR0cmlidXRpb25SZWZlcnJlclRpbWVzdGFtcCgpKTtcbiAgICAgICAgICB9LFxuICAgICAgICBdKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICAgIHJlamVjdChlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGF0dHJpYnV0aW9uIHJlZmVycmVyIFVSTC5cbiAgICpcbiAgICogQHJldHVybnMgUHJvbWlzZSBmb3IgdGhlIGF0dHJpYnV0aW9uIHJlZmVycmVyIFVSTFxuICAgKi9cbiAgZ2V0QXR0cmlidXRpb25SZWZlcnJlclVybCgpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFtcbiAgICAgICAgICBmdW5jdGlvbiAodGhpczogYW55KTogdm9pZCB7XG4gICAgICAgICAgICByZXNvbHZlKHRoaXMuZ2V0QXR0cmlidXRpb25SZWZlcnJlclVybCgpKTtcbiAgICAgICAgICB9LFxuICAgICAgICBdKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICAgIHJlamVjdChlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIFVzZXIgSUQgc3RyaW5nIGlmIGl0IHdhcyBzZXQuXG4gICAqXG4gICAqIEByZXR1cm5zIFByb21pc2UgZm9yIHRoZSBVc2VyIElEIGZvciB0aGUgdmlzaXRvci5cbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9tYXRvbW8ub3JnL2RvY3MvdXNlci1pZC98TWF0b21vIFVzZXIgSUR9XG4gICAqL1xuICBnZXRVc2VySWQoKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbXG4gICAgICAgICAgZnVuY3Rpb24gKHRoaXM6IGFueSk6IHZvaWQge1xuICAgICAgICAgICAgcmVzb2x2ZSh0aGlzLmdldFVzZXJJZCgpKTtcbiAgICAgICAgICB9LFxuICAgICAgICBdKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICAgIHJlamVjdChlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgYSBVc2VyIElEIHRvIHRoaXMgdXNlciAoc3VjaCBhcyBhbiBlbWFpbCBhZGRyZXNzIG9yIGEgdXNlcm5hbWUpLlxuICAgKlxuICAgKiBAcGFyYW0gdXNlcklkIFVzZXIgSUQgdG8gc2V0IGZvciB0aGUgY3VycmVudCB2aXNpdG9yLlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL21hdG9tby5vcmcvZG9jcy91c2VyLWlkL3xNYXRvbW8gVXNlciBJRH1cbiAgICovXG4gIHNldFVzZXJJZCh1c2VySWQ6IHN0cmluZyk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnc2V0VXNlcklkJywgdXNlcklkXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNldHMgdGhlIFVzZXIgSUQgd2hpY2ggYWxzbyBnZW5lcmF0ZXMgYSBuZXcgVmlzaXRvciBJRC5cbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9tYXRvbW8ub3JnL2RvY3MvdXNlci1pZC98TWF0b21vIFVzZXIgSUR9XG4gICAqL1xuICByZXNldFVzZXJJZCgpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3Jlc2V0VXNlcklkJ10pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2V0cyBhIGN1c3RvbSB2YXJpYWJsZS5cbiAgICpcbiAgICogQHBhcmFtIGluZGV4IEluZGV4LCB0aGUgbnVtYmVyIGZyb20gMSB0byA1IHdoZXJlIHRoaXMgY3VzdG9tIHZhcmlhYmxlIG5hbWUgaXMgc3RvcmVkIGZvciB0aGUgY3VycmVudCBwYWdlIHZpZXcuXG4gICAqIEBwYXJhbSBuYW1lIE5hbWUsIHRoZSBuYW1lIG9mIHRoZSB2YXJpYWJsZSwgZm9yIGV4YW1wbGU6IENhdGVnb3J5LCBTdWItY2F0ZWdvcnksIFVzZXJUeXBlLlxuICAgKiBAcGFyYW0gdmFsdWUgVmFsdWUsIGZvciBleGFtcGxlOiBcIlNwb3J0c1wiLCBcIk5ld3NcIiwgXCJXb3JsZFwiLCBcIkJ1c2luZXNzXCLigKZcbiAgICogQHBhcmFtIHNjb3BlIFNjb3BlIG9mIHRoZSBjdXN0b20gdmFyaWFibGU6PGJyIC8+XG4gICAqIC0gJ3BhZ2UnIG1lYW5zIHRoZSBjdXN0b20gdmFyaWFibGUgYXBwbGllcyB0byB0aGUgY3VycmVudCBwYWdlIHZpZXcuXG4gICAqIC0gJ3Zpc2l0JyBtZWFucyB0aGUgY3VzdG9tIHZhcmlhYmxlIGFwcGxpZXMgdG8gdGhlIGN1cnJlbnQgdmlzaXRvci5cbiAgICogLSAnZXZlbnQnIG1lYW5zIHRoZSBjdXN0b20gdmFyaWFibGUgYXBwbGllcyB0byB0aGUgY3VycmVudCBldmVudC5cbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9tYXRvbW8ub3JnL2RvY3MvY3VzdG9tLXZhcmlhYmxlcy98Q3VzdG9tIFZhcmlhYmxlc31cbiAgICovXG4gIHNldEN1c3RvbVZhcmlhYmxlKGluZGV4OiBudW1iZXIsIG5hbWU6IHN0cmluZywgdmFsdWU6IHN0cmluZywgc2NvcGU6IE1hdG9tb1Njb3BlKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydzZXRDdXN0b21WYXJpYWJsZScsIGluZGV4LCBuYW1lLCB2YWx1ZSwgc2NvcGVdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERlbGV0ZXMgYSBjdXN0b20gdmFyaWFibGUuXG4gICAqXG4gICAqIEBwYXJhbSBpbmRleCBJbmRleCBvZiB0aGUgY3VzdG9tIHZhcmlhYmxlIHRvIGRlbGV0ZS5cbiAgICogQHBhcmFtIHNjb3BlIFNjb3BlIG9mIHRoZSBjdXN0b20gdmFyaWFibGUgdG8gZGVsZXRlLlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL21hdG9tby5vcmcvZG9jcy9jdXN0b20tdmFyaWFibGVzL3xDdXN0b20gVmFyaWFibGVzfVxuICAgKi9cbiAgZGVsZXRlQ3VzdG9tVmFyaWFibGUoaW5kZXg6IG51bWJlciwgc2NvcGU6IE1hdG9tb1Njb3BlKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydkZWxldGVDdXN0b21WYXJpYWJsZScsIGluZGV4LCBzY29wZV0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRGVsZXRlcyBhbGwgY3VzdG9tIHZhcmlhYmxlcy5cbiAgICpcbiAgICogQHBhcmFtIHNjb3BlIFNjb3BlIG9mIHRoZSBjdXN0b20gdmFyaWFibGVzIHRvIGRlbGV0ZS5cbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9tYXRvbW8ub3JnL2RvY3MvY3VzdG9tLXZhcmlhYmxlcy98Q3VzdG9tIFZhcmlhYmxlc31cbiAgICovXG4gIGRlbGV0ZUN1c3RvbVZhcmlhYmxlcyhzY29wZTogTWF0b21vU2NvcGUpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ2RlbGV0ZUN1c3RvbVZhcmlhYmxlcycsIHNjb3BlXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgYSBjdXN0b20gdmFyaWFibGUuXG4gICAqXG4gICAqIEBwYXJhbSBpbmRleCBJbmRleCBvZiB0aGUgY3VzdG9tIHZhcmlhYmxlIHRvIHJldHJpZXZlLlxuICAgKiBAcGFyYW0gc2NvcGUgU2NvcGUgb2YgdGhlIGN1c3RvbSB2YXJpYWJsZSB0byByZXRyaWV2ZS5cbiAgICogQHJldHVybnMgUHJvbWlzZSBmb3IgdGhlIHZhbHVlIG9mIGN1c3RvbSB2YXJpYWJsZS5cbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9tYXRvbW8ub3JnL2RvY3MvY3VzdG9tLXZhcmlhYmxlcy98Q3VzdG9tIFZhcmlhYmxlc31cbiAgICovXG4gIGdldEN1c3RvbVZhcmlhYmxlKGluZGV4OiBudW1iZXIsIHNjb3BlOiBNYXRvbW9TY29wZSk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goW1xuICAgICAgICAgIGZ1bmN0aW9uICh0aGlzOiBhbnkpOiB2b2lkIHtcbiAgICAgICAgICAgIHJlc29sdmUodGhpcy5nZXRDdXN0b21WYXJpYWJsZShpbmRleCwgc2NvcGUpKTtcbiAgICAgICAgICB9LFxuICAgICAgICBdKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICAgIHJlamVjdChlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFdoZW4gY2FsbGVkIHRoZW4gdGhlIEN1c3RvbSBWYXJpYWJsZXMgb2Ygc2NvcGUgJ3Zpc2l0JyB3aWxsIGJlIHN0b3JlZCAocGVyc2lzdGVkKSBpbiBhIGZpcnN0IHBhcnR5IGNvb2tpZVxuICAgKiBmb3IgdGhlIGR1cmF0aW9uIG9mIHRoZSB2aXNpdC48YnIgLz5cbiAgICogVGhpcyBpcyB1c2VmdWwgaWYgeW91IHdhbnQgdG8gY2FsbCBnZXRDdXN0b21WYXJpYWJsZSBsYXRlciBpbiB0aGUgdmlzaXQuPGJyIC8+XG4gICAqIChieSBkZWZhdWx0IGN1c3RvbSB2YXJpYWJsZXMgYXJlIG5vdCBzdG9yZWQgb24gdGhlIHZpc2l0b3IncyBjb21wdXRlci4pXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vbWF0b21vLm9yZy9kb2NzL2N1c3RvbS12YXJpYWJsZXMvfEN1c3RvbSBWYXJpYWJsZXN9XG4gICAqL1xuICBzdG9yZUN1c3RvbVZhcmlhYmxlc0luQ29va2llKCk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnc3RvcmVDdXN0b21WYXJpYWJsZXNJbkNvb2tpZSddKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgYSBjdXN0b20gZGltZW5zaW9uLjxiciAvPlxuICAgKiAocmVxdWlyZXMgTWF0b21vIDIuMTUuMSArIEN1c3RvbSBEaW1lbnNpb25zIHBsdWdpbilcbiAgICpcbiAgICogQHBhcmFtIGN1c3RvbURpbWVuc2lvbklkIElEIG9mIHRoZSBjdXN0b20gZGltZW5zaW9uIHRvIHNldC5cbiAgICogQHBhcmFtIGN1c3RvbURpbWVuc2lvblZhbHVlIFZhbHVlIHRvIGJlIHNldC5cbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9wbHVnaW5zLnBpd2lrLm9yZy9DdXN0b21EaW1lbnNpb25zfEN1c3RvbSBEaW1lbnNpb25zfVxuICAgKi9cbiAgc2V0Q3VzdG9tRGltZW5zaW9uKGN1c3RvbURpbWVuc2lvbklkOiBudW1iZXIsIGN1c3RvbURpbWVuc2lvblZhbHVlOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3NldEN1c3RvbURpbWVuc2lvbicsIGN1c3RvbURpbWVuc2lvbklkLCBjdXN0b21EaW1lbnNpb25WYWx1ZV0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRGVsZXRlcyBhIGN1c3RvbSBkaW1lbnNpb24uPGJyIC8+XG4gICAqIChyZXF1aXJlcyBNYXRvbW8gMi4xNS4xICsgQ3VzdG9tIERpbWVuc2lvbnMgcGx1Z2luKVxuICAgKlxuICAgKiBAcGFyYW0gY3VzdG9tRGltZW5zaW9uSWQgSUQgb2YgdGhlIGN1c3RvbSBkaW1lbnNpb24gdG8gZGVsZXRlLlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL3BsdWdpbnMucGl3aWsub3JnL0N1c3RvbURpbWVuc2lvbnN8Q3VzdG9tIERpbWVuc2lvbnN9XG4gICAqL1xuICBkZWxldGVDdXN0b21EaW1lbnNpb24oY3VzdG9tRGltZW5zaW9uSWQ6IG51bWJlcik6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnZGVsZXRlQ3VzdG9tRGltZW5zaW9uJywgY3VzdG9tRGltZW5zaW9uSWRdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlIGEgY3VzdG9tIGRpbWVuc2lvbi48YnIgLz5cbiAgICogKHJlcXVpcmVzIE1hdG9tbyAyLjE1LjEgKyBDdXN0b20gRGltZW5zaW9ucyBwbHVnaW4pXG4gICAqXG4gICAqIEBwYXJhbSBjdXN0b21EaW1lbnNpb25JZCBJRCBvZiB0aGUgY3VzdG9tIGRpbWVuc2lvbiB0byByZXRyaWV2ZS5cbiAgICogQHJldHVybnMgUHJvbWlzZSBmb3IgdGhlIHZhbHVlIGZvciB0aGUgcmVxdWVzdGVkIGN1c3RvbSBkaW1lbnNpb24uXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vcGx1Z2lucy5waXdpay5vcmcvQ3VzdG9tRGltZW5zaW9uc3xDdXN0b20gRGltZW5zaW9uc31cbiAgICovXG4gIGdldEN1c3RvbURpbWVuc2lvbihjdXN0b21EaW1lbnNpb25JZDogbnVtYmVyKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbXG4gICAgICAgICAgZnVuY3Rpb24gKHRoaXM6IGFueSk6IHZvaWQge1xuICAgICAgICAgICAgcmVzb2x2ZSh0aGlzLmdldEN1c3RvbURpbWVuc2lvbihjdXN0b21EaW1lbnNpb25JZCkpO1xuICAgICAgICAgIH0sXG4gICAgICAgIF0pO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyBjYW1wYWlnbiBuYW1lIHBhcmFtZXRlcihzKS5cbiAgICpcbiAgICogQHBhcmFtIG5hbWUgTmFtZSBvZiB0aGUgY2FtcGFpZ25cbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9tYXRvbW8ub3JnL2RvY3MvdHJhY2tpbmctY2FtcGFpZ25zL3xDYW1wYWlnbnN9XG4gICAqL1xuICBzZXRDYW1wYWlnbk5hbWVLZXkobmFtZTogc3RyaW5nKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydzZXRDYW1wYWlnbk5hbWVLZXknLCBuYW1lXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIGNhbXBhaWduIGtleXdvcmQgcGFyYW1ldGVyKHMpLlxuICAgKlxuICAgKiBAcGFyYW0ga2V5d29yZCBLZXl3b3JkIHBhcmFtZXRlcihzKSBvZiB0aGUgY2FtcGFpZ24uXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vbWF0b21vLm9yZy9kb2NzL3RyYWNraW5nLWNhbXBhaWducy98Q2FtcGFpZ25zfVxuICAgKi9cbiAgc2V0Q2FtcGFpZ25LZXl3b3JkS2V5KGtleXdvcmQ6IHN0cmluZyk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnc2V0Q2FtcGFpZ25LZXl3b3JkS2V5Jywga2V5d29yZF0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2V0cyBpZiBvciBub3QgdG8gYXR0cmlidXRlIGEgY29udmVyc2lvbiB0byB0aGUgZmlyc3QgcmVmZXJyZXIuPGJyIC8+XG4gICAqIEJ5IGRlZmF1bHQsIGNvbnZlcnNpb24gaXMgYXR0cmlidXRlZCB0byB0aGUgbW9zdCByZWNlbnQgcmVmZXJyZXIuXG4gICAqXG4gICAqIEBwYXJhbSBjb252ZXJzaW9uVG9GaXJzdFJlZmVycmVyIElmIHRydWUsIE1hdG9tbyB3aWxsIGF0dHJpYnV0ZSB0aGUgR29hbCBjb252ZXJzaW9uIHRvIHRoZSBmaXJzdCByZWZlcnJlciB1c2VkXG4gICAqIGluc3RlYWQgb2YgdGhlIGxhc3Qgb25lLlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL21hdG9tby5vcmcvZG9jcy90cmFja2luZy1jYW1wYWlnbnMvfENhbXBhaWduc31cbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9tYXRvbW8ub3JnL2ZhcS9nZW5lcmFsL2ZhcV8xMDYvI2ZhcV8xMDZ8Q29udmVyc2lvbnMgdG8gdGhlIGZpcnN0IHJlZmVycmVyfVxuICAgKi9cbiAgc2V0Q29udmVyc2lvbkF0dHJpYnV0aW9uRmlyc3RSZWZlcnJlcihjb252ZXJzaW9uVG9GaXJzdFJlZmVycmVyOiBib29sZWFuKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydzZXRDb252ZXJzaW9uQXR0cmlidXRpb25GaXJzdFJlZmVycmVyJywgY29udmVyc2lvblRvRmlyc3RSZWZlcnJlcl0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGUgY3VycmVudCBwYWdlIHZpZXcgYXMgYSBwcm9kdWN0IG9yIGNhdGVnb3J5IHBhZ2Ugdmlldy48YnIgLz5cbiAgICogV2hlbiB5b3UgY2FsbCBzZXRFY29tbWVyY2VWaWV3LCBpdCBtdXN0IGJlIGZvbGxvd2VkIGJ5IGEgY2FsbCB0byB0cmFja1BhZ2VWaWV3IHRvIHJlY29yZCB0aGUgcHJvZHVjdCBvciBjYXRlZ29yeSBwYWdlIHZpZXcuXG4gICAqXG4gICAqIEBwYXJhbSBwcm9kdWN0U0tVIFNLVSBvZiB0aGUgdmlld2VkIHByb2R1Y3QuXG4gICAqIEBwYXJhbSBwcm9kdWN0TmFtZSBOYW1lIG9mIHRoZSB2aWV3ZWQgcHJvZHVjdC5cbiAgICogQHBhcmFtIHByb2R1Y3RDYXRlZ29yeSBDYXRlZ29yeSBvZiB0aGUgdmlld2VkIHByb2R1Y3QuXG4gICAqIEBwYXJhbSBwcmljZSBQcmljZSBvZiB0aGUgdmlld2VkIHByb2R1Y3QuXG4gICAqL1xuICBzZXRFY29tbWVyY2VWaWV3KFxuICAgIHByb2R1Y3RTS1U6IHN0cmluZyxcbiAgICBwcm9kdWN0TmFtZTogc3RyaW5nLFxuICAgIHByb2R1Y3RDYXRlZ29yeTogc3RyaW5nLFxuICAgIHByaWNlOiBudW1iZXJcbiAgKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydzZXRFY29tbWVyY2VWaWV3JywgcHJvZHVjdFNLVSwgcHJvZHVjdE5hbWUsIHByb2R1Y3RDYXRlZ29yeSwgcHJpY2VdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYSBwcm9kdWN0IGludG8gdGhlIGVDb21tZXJjZSBvcmRlci48YnIgLz5cbiAgICogTXVzdCBiZSBjYWxsZWQgZm9yIGVhY2ggcHJvZHVjdCBpbiB0aGUgb3JkZXIuXG4gICAqXG4gICAqIEBwYXJhbSBwcm9kdWN0U0tVIFNLVSBvZiB0aGUgcHJvZHVjdCB0byBhZGQuXG4gICAqIEBwYXJhbSBbcHJvZHVjdE5hbWVdIE9wdGlvbmFsIG5hbWUgb2YgdGhlIHByb2R1Y3QgdG8gYWRkLlxuICAgKiBAcGFyYW0gW3Byb2R1Y3RDYXRlZ29yeV0gT3B0aW9uYWwgY2F0ZWdvcnkgb2YgdGhlIHByb2R1Y3QgdG8gYWRkLlxuICAgKiBAcGFyYW0gW3ByaWNlXSBPcHRpb25hbCBwcmljZSBvZiB0aGUgcHJvZHVjdCB0byBhZGQuXG4gICAqIEBwYXJhbSBbcXVhbnRpdHldIE9wdGlvbmFsIHF1YW50aXR5IG9mIHRoZSBwcm9kdWN0IHRvIGFkZC5cbiAgICovXG4gIGFkZEVjb21tZXJjZUl0ZW0oXG4gICAgcHJvZHVjdFNLVTogc3RyaW5nLFxuICAgIHByb2R1Y3ROYW1lPzogc3RyaW5nLFxuICAgIHByb2R1Y3RDYXRlZ29yeT86IHN0cmluZyxcbiAgICBwcmljZT86IG51bWJlcixcbiAgICBxdWFudGl0eT86IG51bWJlclxuICApOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgYXJnczogYW55W10gPSBbcHJvZHVjdFNLVV07XG4gICAgICBpZiAoISFwcm9kdWN0TmFtZSkge1xuICAgICAgICBhcmdzLnB1c2gocHJvZHVjdE5hbWUpO1xuICAgICAgICBpZiAoISFwcm9kdWN0Q2F0ZWdvcnkpIHtcbiAgICAgICAgICBhcmdzLnB1c2gocHJvZHVjdENhdGVnb3J5KTtcbiAgICAgICAgICBpZiAodHlwZW9mIHByaWNlID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgYXJncy5wdXNoKHByaWNlKTtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgcXVhbnRpdHkgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICAgIGFyZ3MucHVzaChxdWFudGl0eSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnYWRkRWNvbW1lcmNlSXRlbScsIC4uLmFyZ3NdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZXMgdGhlIHNwZWNpZmllZCBwcm9kdWN0IGZyb20gdGhlIHVudHJhY2tlZCBlY29tbWVyY2Ugb3JkZXIuXG4gICAqXG4gICAqIEBwYXJhbSBwcm9kdWN0U0tVIFNLVSBvZiB0aGUgcHJvZHVjdCB0byByZW1vdmUuXG4gICAqL1xuICByZW1vdmVFY29tbWVyY2VJdGVtKHByb2R1Y3RTS1U6IHN0cmluZyk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBhcmdzOiBhbnlbXSA9IFtwcm9kdWN0U0tVXTtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydyZW1vdmVFY29tbWVyY2VJdGVtJywgLi4uYXJnc10pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlcyBhbGwgcHJvZHVjdHMgaW4gdGhlIHVudHJhY2tlZCBlY29tbWVyY2Ugb3JkZXIuPGJyIC8+XG4gICAqIE5vdGU6IHRoaXMgaXMgZG9uZSBhdXRvbWF0aWNhbGx5IGFmdGVyIHRyYWNrRWNvbW1lcmNlT3JkZXIoKSBpcyBjYWxsZWQuXG4gICAqL1xuICBjbGVhckVjb21tZXJjZUNhcnQoKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydjbGVhckVjb21tZXJjZUNhcnQnXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGFsbCBlY29tbWVyY2UgaXRlbXMgY3VycmVudGx5IGluIHRoZSB1bnRyYWNrZWQgZWNvbW1lcmNlIG9yZGVyLlxuICAgKiBUaGUgcmV0dXJuZWQgYXJyYXkgd2lsbCBiZSBhIGNvcHksIHNvIGNoYW5naW5nIGl0IHdvbid0IGFmZmVjdCB0aGUgZWNvbW1lcmNlIG9yZGVyLjxiciAvPlxuICAgKiBUbyBhZmZlY3Qgd2hhdCBnZXRzIHRyYWNrZWQsIHVzZSB0aGUgYWRkRWNvbW1lcmNlSXRlbSgpL3JlbW92ZUVjb21tZXJjZUl0ZW0oKS9jbGVhckVjb21tZXJjZUNhcnQoKSBtZXRob2RzLjxiciAvPlxuICAgKiBVc2UgdGhpcyBtZXRob2QgdG8gc2VlIHdoYXQgd2lsbCBiZSB0cmFja2VkIGJlZm9yZSB5b3UgdHJhY2sgYW4gb3JkZXIgb3IgY2FydCB1cGRhdGUuXG4gICAqL1xuICBnZXRFY29tbWVyY2VJdGVtcygpOiBQcm9taXNlPFxuICAgIEFycmF5PHtcbiAgICAgIHByb2R1Y3RTS1U6IHN0cmluZztcbiAgICAgIHByb2R1Y3ROYW1lPzogc3RyaW5nO1xuICAgICAgcHJvZHVjdENhdGVnb3J5Pzogc3RyaW5nO1xuICAgICAgcHJpY2U/OiBudW1iZXI7XG4gICAgICBxdWFudGl0eT86IG51bWJlcjtcbiAgICB9PlxuICA+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbXG4gICAgICAgICAgZnVuY3Rpb24gKHRoaXM6IGFueSk6IHZvaWQge1xuICAgICAgICAgICAgcmVzb2x2ZSh0aGlzLmdldEVjb21tZXJjZUl0ZW1zKCkpO1xuICAgICAgICAgIH0sXG4gICAgICAgIF0pO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogVHJhY2tzIGEgc2hvcHBpbmcgY2FydC48YnIgLz5cbiAgICogQ2FsbCB0aGlzIGZ1bmN0aW9uIGV2ZXJ5IHRpbWUgYSB1c2VyIGlzIGFkZGluZywgdXBkYXRpbmcgb3IgZGVsZXRpbmcgYSBwcm9kdWN0IGZyb20gdGhlIGNhcnQuXG4gICAqXG4gICAqIEBwYXJhbSBncmFuZFRvdGFsIEdyYW5kIHRvdGFsIG9mIHRoZSBzaG9wcGluZyBjYXJ0LlxuICAgKi9cbiAgdHJhY2tFY29tbWVyY2VDYXJ0VXBkYXRlKGdyYW5kVG90YWw6IG51bWJlcik6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsndHJhY2tFY29tbWVyY2VDYXJ0VXBkYXRlJywgZ3JhbmRUb3RhbF0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVHJhY2tzIGFuIEVjb21tZXJjZSBvcmRlciwgaW5jbHVkaW5nIGFueSBlQ29tbWVyY2UgaXRlbSBwcmV2aW91c2x5IGFkZGVkIHRvIHRoZSBvcmRlci48YnIgLz5cbiAgICogb3JkZXJJZCBhbmQgZ3JhbmRUb3RhbCAoaWUucmV2ZW51ZSkgYXJlIHJlcXVpcmVkIHBhcmFtZXRlcnMuXG4gICAqXG4gICAqIEBwYXJhbSBvcmRlcklkIElEIG9mIHRoZSB0cmFja2VkIG9yZGVyLlxuICAgKiBAcGFyYW0gZ3JhbmRUb3RhbCBHcmFuZCB0b3RhbCBvZiB0aGUgdHJhY2tlZCBvcmRlci5cbiAgICogQHBhcmFtIFtzdWJUb3RhbF0gU3ViIHRvdGFsIG9mIHRoZSB0cmFja2VkIG9yZGVyLlxuICAgKiBAcGFyYW0gW3RheF0gVGF4ZXMgZm9yIHRoZSB0cmFja2VkIG9yZGVyLlxuICAgKiBAcGFyYW0gW3NoaXBwaW5nXSBTaGlwcGluZyBmZWVzIGZvciB0aGUgdHJhY2tlZCBvcmRlci5cbiAgICogQHBhcmFtIFtkaXNjb3VudF0gRGlzY291bnQgZ3JhbnRlZCBmb3IgdGhlIHRyYWNrZWQgb3JkZXIuXG4gICAqL1xuICB0cmFja0Vjb21tZXJjZU9yZGVyKFxuICAgIG9yZGVySWQ6IHN0cmluZyxcbiAgICBncmFuZFRvdGFsOiBudW1iZXIsXG4gICAgc3ViVG90YWw/OiBudW1iZXIsXG4gICAgdGF4PzogbnVtYmVyLFxuICAgIHNoaXBwaW5nPzogbnVtYmVyLFxuICAgIGRpc2NvdW50PzogbnVtYmVyIHwgYm9vbGVhblxuICApOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgYXJnczogYW55W10gPSBbb3JkZXJJZCwgZ3JhbmRUb3RhbF07XG4gICAgICBpZiAodHlwZW9mIHN1YlRvdGFsID09PSAnbnVtYmVyJykge1xuICAgICAgICBhcmdzLnB1c2goc3ViVG90YWwpO1xuICAgICAgICBpZiAodHlwZW9mIHRheCA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICBhcmdzLnB1c2godGF4KTtcbiAgICAgICAgICBpZiAodHlwZW9mIHNoaXBwaW5nID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgYXJncy5wdXNoKHNoaXBwaW5nKTtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZGlzY291bnQgPT09ICdudW1iZXInIHx8IHR5cGVvZiBkaXNjb3VudCA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICAgIGFyZ3MucHVzaChkaXNjb3VudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsndHJhY2tFY29tbWVyY2VPcmRlcicsIC4uLmFyZ3NdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEJ5IGRlZmF1bHQgdGhlIE1hdG9tbyB0cmFja2VyIGFzc3VtZXMgY29uc2VudCB0byB0cmFja2luZy5cbiAgICogVG8gY2hhbmdlIHRoaXMgYmVoYXZpb3Igc28gbm90aGluZyBpcyB0cmFja2VkIHVudGlsIGEgdXNlciBjb25zZW50cywgeW91IG11c3QgY2FsbCByZXF1aXJlQ29uc2VudC5cbiAgICovXG4gIHJlcXVpcmVDb25zZW50KCk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsncmVxdWlyZUNvbnNlbnQnXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXF1aXJlIHVzZXIgY29va2llIGNvbnNlbnQgYmVmb3JlIHN0b3JpbmcgYW5kIHVzaW5nIGFueSBjb29raWVzLlxuICAgKi9cbiAgcmVxdWlyZUNvb2tpZUNvbnNlbnQoKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydyZXF1aXJlQ29va2llQ29uc2VudCddKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE1hcmtzIHRoYXQgdGhlIGN1cnJlbnQgdXNlciBoYXMgY29uc2VudGVkLjxiciAvPlxuICAgKiBUaGUgY29uc2VudCBpcyBvbmUtdGltZSBvbmx5LCBzbyBpbiBhIHN1YnNlcXVlbnQgYnJvd3NlciBzZXNzaW9uLCB0aGUgdXNlciB3aWxsIGhhdmUgdG8gY29uc2VudCBhZ2Fpbi48YnIgLz5cbiAgICogVG8gcmVtZW1iZXIgY29uc2VudCwgc2VlIHRoZSBtZXRob2QgYmVsb3c6IHJlbWVtYmVyQ29uc2VudEdpdmVuLlxuICAgKi9cbiAgc2V0Q29uc2VudEdpdmVuKCk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnc2V0Q29uc2VudEdpdmVuJ10pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTWFya3MgdGhhdCB0aGUgY3VycmVudCB1c2VyIGhhcyBjb25zZW50ZWQgdG8gc3RvcmUgYW5kIHVzZSBjb29raWVzLjxiciAvPlxuICAgKiBUaGUgY29uc2VudCBpcyBvbmUtdGltZSBvbmx5LCBzbyBpbiBhIHN1YnNlcXVlbnQgYnJvd3NlciBzZXNzaW9uLCB0aGUgdXNlciB3aWxsIGhhdmUgdG8gY29uc2VudCBhZ2Fpbi48YnIgLz5cbiAgICogVG8gcmVtZW1iZXIgY29uc2VudCwgc2VlIHRoZSBtZXRob2QgYmVsb3c6IHJlbWVtYmVyQ29va2llQ29uc2VudEdpdmVuLlxuICAgKi9cbiAgc2V0Q29va2llQ29uc2VudEdpdmVuKCk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnc2V0Q29va2llQ29uc2VudEdpdmVuJ10pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTWFya3MgdGhhdCB0aGUgY3VycmVudCB1c2VyIGhhcyBjb25zZW50ZWQsIGFuZCByZW1lbWJlcnMgdGhpcyBjb25zZW50IHRocm91Z2ggYSBicm93c2VyIGNvb2tpZS48YnIgLz5cbiAgICogVGhlIG5leHQgdGltZSB0aGUgdXNlciB2aXNpdHMgdGhlIHNpdGUsIE1hdG9tbyB3aWxsIHJlbWVtYmVyIHRoYXQgdGhleSBjb25zZW50ZWQsIGFuZCB0cmFjayB0aGVtLjxiciAvPlxuICAgKiBJZiB5b3UgY2FsbCB0aGlzIG1ldGhvZCwgeW91IGRvIG5vdCBuZWVkIHRvIGNhbGwgc2V0Q29uc2VudEdpdmVuLlxuICAgKlxuICAgKiBAcGFyYW0gaG91cnNUb0V4cGlyZSBFeHBpcnkgcGVyaW9kIGZvciB5b3VyIHVzZXIgY29uc2VudC5cbiAgICovXG4gIHJlbWVtYmVyQ29uc2VudEdpdmVuKGhvdXJzVG9FeHBpcmU/OiBudW1iZXIpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgYXJnczogbnVtYmVyW10gPSBbXTtcbiAgICAgIGlmICh0eXBlb2YgaG91cnNUb0V4cGlyZSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgYXJncy5wdXNoKGhvdXJzVG9FeHBpcmUpO1xuICAgICAgfVxuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3JlbWVtYmVyQ29uc2VudEdpdmVuJywgLi4uYXJnc10pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTWFya3MgdGhhdCB0aGUgY3VycmVudCB1c2VyIGhhcyBjb25zZW50ZWQsIGFuZCByZW1lbWJlcnMgdGhpcyBjb25zZW50IHRocm91Z2ggYSBicm93c2VyIGNvb2tpZS48YnIgLz5cbiAgICogVGhlIG5leHQgdGltZSB0aGUgdXNlciB2aXNpdHMgdGhlIHNpdGUsIE1hdG9tbyB3aWxsIHJlbWVtYmVyIHRoYXQgdGhleSBjb25zZW50ZWQsIGFuZCB0cmFjayB0aGVtLjxiciAvPlxuICAgKiBJZiB5b3UgY2FsbCB0aGlzIG1ldGhvZCwgeW91IGRvIG5vdCBuZWVkIHRvIGNhbGwgc2V0Q29va2llQ29uc2VudEdpdmVuLlxuICAgKlxuICAgKiBAcGFyYW0gaG91cnNUb0V4cGlyZSBFeHBpcnkgcGVyaW9kIGZvciB5b3VyIHVzZXIgY29uc2VudC5cbiAgICovXG4gIHJlbWVtYmVyQ29va2llQ29uc2VudEdpdmVuKGhvdXJzVG9FeHBpcmU/OiBudW1iZXIpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgYXJnczogbnVtYmVyW10gPSBbXTtcbiAgICAgIGlmICh0eXBlb2YgaG91cnNUb0V4cGlyZSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgYXJncy5wdXNoKGhvdXJzVG9FeHBpcmUpO1xuICAgICAgfVxuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3JlbWVtYmVyQ29va2llQ29uc2VudEdpdmVuJywgLi4uYXJnc10pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlcyBhIHVzZXIncyBjb25zZW50LCBib3RoIGlmIHRoZSBjb25zZW50IHdhcyBvbmUtdGltZSBvbmx5IGFuZCBpZiB0aGUgY29uc2VudCB3YXMgcmVtZW1iZXJlZC48YnIgLz5cbiAgICogVGhpcyBtYWtlcyBzdXJlIHRoZSBjb29raWUgdGhhdCByZW1lbWJlcmVkIHRoZSBnaXZlbiBjb25zZW50IGlzIGRlbGV0ZWQuPGJyIC8+XG4gICAqIEFmdGVyIGNhbGxpbmcgdGhpcyBtZXRob2QsIHRoZSB1c2VyIHdpbGwgaGF2ZSB0byBjb25zZW50IGFnYWluIGluIG9yZGVyIHRvIGJlIHRyYWNrZWQuXG4gICAqL1xuICBmb3JnZXRDb25zZW50R2l2ZW4oKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydmb3JnZXRDb25zZW50R2l2ZW4nXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmVzIGEgdXNlcidzIGNvbnNlbnQsIGJvdGggaWYgdGhlIGNvbnNlbnQgd2FzIG9uZS10aW1lIG9ubHkgYW5kIGlmIHRoZSBjb25zZW50IHdhcyByZW1lbWJlcmVkLjxiciAvPlxuICAgKiBUaGlzIG1ha2VzIHN1cmUgdGhlIGNvb2tpZSB0aGF0IHJlbWVtYmVyZWQgdGhlIGdpdmVuIGNvbnNlbnQgaXMgZGVsZXRlZC48YnIgLz5cbiAgICogQWZ0ZXIgY2FsbGluZyB0aGlzIG1ldGhvZCwgdGhlIHVzZXIgd2lsbCBoYXZlIHRvIGNvbnNlbnQgYWdhaW4gaW4gb3JkZXIgdG8gYmUgdHJhY2tlZC5cbiAgICovXG4gIGZvcmdldENvb2tpZUNvbnNlbnRHaXZlbigpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ2ZvcmdldENvb2tpZUNvbnNlbnRHaXZlbiddKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgaWYgdG8gbm90IHRvIHRyYWNrIHVzZXJzIHdobyBvcHQgb3V0IG9mIHRyYWNraW5nIHVzaW5nIE1vemlsbGEncyAocHJvcG9zZWQpIERvIE5vdCBUcmFjayBzZXR0aW5nLlxuICAgKlxuICAgKiBAcGFyYW0gZG9Ob3RUcmFjayBJZiB0cnVlLCB1c2VycyB3aG8gb3B0ZWQgZm9yIERvIE5vdCBUcmFjayBpbiB0aGVpciBzZXR0aW5ncyB3b24ndCBiZSB0cmFja2VkLlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL3d3dy53My5vcmcvVFIvdHJhY2tpbmctZG50L31cbiAgICovXG4gIHNldERvTm90VHJhY2soZG9Ob3RUcmFjazogYm9vbGVhbik6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnc2V0RG9Ob3RUcmFjaycsIGRvTm90VHJhY2tdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERpc2FibGVzIGFsbCBmaXJzdCBwYXJ0eSBjb29raWVzLjxiciAvPlxuICAgKiBFeGlzdGluZyBNYXRvbW8gY29va2llcyBmb3IgdGhpcyB3ZWJzaXRlcyB3aWxsIGJlIGRlbGV0ZWQgb24gdGhlIG5leHQgcGFnZSB2aWV3LlxuICAgKi9cbiAgZGlzYWJsZUNvb2tpZXMoKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydkaXNhYmxlQ29va2llcyddKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIERlbGV0ZXMgdGhlIHRyYWNraW5nIGNvb2tpZXMgY3VycmVudGx5IHNldCAodXNlZnVsIHdoZW4gY3JlYXRpbmcgbmV3IHZpc2l0cykuXG4gICAqL1xuICBkZWxldGVDb29raWVzKCk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnZGVsZXRlQ29va2llcyddKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgd2hldGhlciBjb29raWVzIGFyZSBlbmFibGVkIGFuZCBzdXBwb3J0ZWQgYnkgdGhpcyBicm93c2VyLlxuICAgKlxuICAgKiBAcmV0dXJucyBQcm9taXNlIGZvciB0aGUgc3VwcG9ydCBhbmQgYWN0aXZhdGlvbiBvZiBjb29raWVzLlxuICAgKi9cbiAgaGFzQ29va2llcygpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbXG4gICAgICAgICAgZnVuY3Rpb24gKHRoaXM6IGFueSk6IHZvaWQge1xuICAgICAgICAgICAgcmVzb2x2ZSh0aGlzLmhhc0Nvb2tpZXMoKSk7XG4gICAgICAgICAgfSxcbiAgICAgICAgXSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgICByZWplY3QoZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSB0cmFja2luZyBjb29raWUgbmFtZSBwcmVmaXguPGJyIC8+XG4gICAqIERlZmF1bHQgcHJlZml4IGlzICdwaycuXG4gICAqXG4gICAqIEBwYXJhbSBwcmVmaXggUHJlZml4IGZvciB0aGUgdHJhY2tpbmcgY29va2llIG5hbWVzLlxuICAgKi9cbiAgc2V0Q29va2llTmFtZVByZWZpeChwcmVmaXg6IHN0cmluZyk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnc2V0Q29va2llTmFtZVByZWZpeCcsIHByZWZpeF0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGUgZG9tYWluIG9mIHRoZSB0cmFja2luZyBjb29raWVzLjxiciAvPlxuICAgKiBEZWZhdWx0IGlzIHRoZSBkb2N1bWVudCBkb21haW4uPGJyIC8+XG4gICAqIElmIHlvdXIgd2Vic2l0ZSBjYW4gYmUgdmlzaXRlZCBhdCBib3RoIHd3dy5leGFtcGxlLmNvbSBhbmQgZXhhbXBsZS5jb20sIHlvdSB3b3VsZCB1c2U6IGAnLmV4YW1wbGUuY29tJ2Agb3IgYCcqLmV4YW1wbGUuY29tJ2AuXG4gICAqXG4gICAqIEBwYXJhbSBkb21haW4gRG9tYWluIG9mIHRoZSB0cmFja2luZyBjb29raWVzLlxuICAgKi9cbiAgc2V0Q29va2llRG9tYWluKGRvbWFpbjogc3RyaW5nKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydzZXRDb29raWVEb21haW4nLCBkb21haW5dKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdGhlIHBhdGggb2YgdGhlIHRyYWNraW5nIGNvb2tpZXMuPGJyIC8+XG4gICAqIERlZmF1bHQgaXMgJy8nLlxuICAgKlxuICAgKiBAcGFyYW0gcGF0aCBQYXRoIG9mIHRoZSB0cmFja2luZyBjb29raWVzLlxuICAgKi9cbiAgc2V0Q29va2llUGF0aChwYXRoOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3NldENvb2tpZVBhdGgnLCBwYXRoXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIGlmIG9yIG5vdCB0byBlbmFibGUgdGhlIFNlY3VyZSBjb29raWUgZmxhZyBvbiBhbGwgZmlyc3QgcGFydHkgY29va2llcy48YnIgLz5cbiAgICogVGhpcyBzaG91bGQgYmUgdXNlZCB3aGVuIHlvdXIgd2Vic2l0ZSBpcyBvbmx5IGF2YWlsYWJsZSB1bmRlciBIVFRQUyBzbyB0aGF0IGFsbCB0cmFja2luZyBjb29raWVzIGFyZSBhbHdheXMgc2VudFxuICAgKiBvdmVyIHNlY3VyZSBjb25uZWN0aW9uLlxuICAgKlxuICAgKiBAcGFyYW0gc2VjdXJlIElmIHRydWUsIHRoZSBzZWN1cmUgY29va2llIGZsYWcgd2lsbCBiZSBzZXQgb24gYWxsIGZpcnN0IHBhcnR5IGNvb2tpZXMuXG4gICAqL1xuICBzZXRTZWN1cmVDb29raWUoc2VjdXJlOiBib29sZWFuKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydzZXRTZWN1cmVDb29raWUnLCBzZWN1cmVdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdGhlIHZpc2l0b3IgY29va2llIHRpbWVvdXQuPGJyIC8+XG4gICAqIERlZmF1bHQgaXMgMTMgbW9udGhzLlxuICAgKlxuICAgKiBAcGFyYW0gdGltZW91dCBUaW1lb3V0LCBpbiBzZWNvbmRzLCBmb3IgdGhlIHZpc2l0b3IgY29va2llIHRpbWVvdXQuXG4gICAqL1xuICBzZXRWaXNpdG9yQ29va2llVGltZW91dCh0aW1lb3V0OiBudW1iZXIpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3NldFZpc2l0b3JDb29raWVUaW1lb3V0JywgdGltZW91dF0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGUgcmVmZXJyYWwgY29va2llIHRpbWVvdXQuPGJyIC8+XG4gICAqIERlZmF1bHQgaXMgNiBtb250aHMuXG4gICAqXG4gICAqIEBwYXJhbSB0aW1lb3V0IFRpbWVvdXQsIGluIHNlY29uZHMsIGZvciB0aGUgcmVmZXJyYWwgY29va2llIHRpbWVvdXQuXG4gICAqL1xuICBzZXRSZWZlcnJhbENvb2tpZVRpbWVvdXQodGltZW91dDogbnVtYmVyKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydzZXRSZWZlcnJhbENvb2tpZVRpbWVvdXQnLCB0aW1lb3V0XSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSBzZXNzaW9uIGNvb2tpZSB0aW1lb3V0LjxiciAvPlxuICAgKiBEZWZhdWx0IGlzIDMwIG1pbnV0ZXMuXG4gICAqXG4gICAqIEBwYXJhbSB0aW1lb3V0IFRpbWVvdXQsIGluIHNlY29uZHMsIGZvciB0aGUgc2Vzc2lvbiBjb29raWUgdGltZW91dC5cbiAgICovXG4gIHNldFNlc3Npb25Db29raWVUaW1lb3V0KHRpbWVvdXQ6IG51bWJlcik6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnc2V0U2Vzc2lvbkNvb2tpZVRpbWVvdXQnLCB0aW1lb3V0XSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGEgY2xpY2sgbGlzdGVuZXIgdG8gYSBzcGVjaWZpYyBsaW5rIGVsZW1lbnQuPGJyIC8+XG4gICAqIFdoZW4gY2xpY2tlZCwgTWF0b21vIHdpbGwgbG9nIHRoZSBjbGljayBhdXRvbWF0aWNhbGx5LlxuICAgKlxuICAgKiBAcGFyYW0gZWxlbWVudCBFbGVtZW50IG9uIHdoaWNoIHRvIGFkZCBhIGNsaWNrIGxpc3RlbmVyLlxuICAgKi9cbiAgYWRkTGlzdGVuZXIoZWxlbWVudDogRWxlbWVudCk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnYWRkTGlzdGVuZXInLCBlbGVtZW50XSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSByZXF1ZXN0IG1ldGhvZCB0byBlaXRoZXIgJ0dFVCcgb3IgJ1BPU1QnLiAoVGhlIGRlZmF1bHQgaXMgJ0dFVCcuKTxiciAvPlxuICAgKiBUbyB1c2UgdGhlIFBPU1QgcmVxdWVzdCBtZXRob2QsIGVpdGhlcjo8YnIgLz5cbiAgICogMSkgdGhlIE1hdG9tbyBob3N0IGlzIHRoZSBzYW1lIGFzIHRoZSB0cmFja2VkIHdlYnNpdGUgaG9zdCAoTWF0b21vIGluc3RhbGxlZCBpbiB0aGUgc2FtZSBkb21haW4gYXMgeW91ciB0cmFja2VkIHdlYnNpdGUpLCBvcjxiciAvPlxuICAgKiAyKSBpZiBNYXRvbW8gaXMgbm90IGluc3RhbGxlZCBvbiB0aGUgc2FtZSBob3N0IGFzIHlvdXIgd2Vic2l0ZSwgeW91IG5lZWQgdG8gZW5hYmxlIENPUlMgKENyb3NzIGRvbWFpbiByZXF1ZXN0cykuXG4gICAqXG4gICAqIEBwYXJhbSBtZXRob2QgSFRUUCBtZXRob2QgZm9yIHNlbmRpbmcgaW5mb3JtYXRpb24gdG8gdGhlIE1hdG9tbyBzZXJ2ZXIuXG4gICAqL1xuICBzZXRSZXF1ZXN0TWV0aG9kKG1ldGhvZDogJ0dFVCcgfCAnUE9TVCcpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3NldFJlcXVlc3RNZXRob2QnLCBtZXRob2RdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgYSBmdW5jdGlvbiB0aGF0IHdpbGwgcHJvY2VzcyB0aGUgcmVxdWVzdCBjb250ZW50LjxiciAvPlxuICAgKiBUaGUgZnVuY3Rpb24gd2lsbCBiZSBjYWxsZWQgb25jZSB0aGUgcmVxdWVzdCAocXVlcnkgcGFyYW1ldGVycyBzdHJpbmcpIGhhcyBiZWVuIHByZXBhcmVkLCBhbmQgYmVmb3JlIHRoZSByZXF1ZXN0IGNvbnRlbnQgaXMgc2VudC5cbiAgICpcbiAgICogQHBhcmFtIGNhbGxiYWNrIEZ1bmN0aW9uIHRoYXQgd2lsbCBwcm9jZXNzIHRoZSByZXF1ZXN0IGNvbnRlbnQuXG4gICAqL1xuICBzZXRDdXN0b21SZXF1ZXN0UHJvY2Vzc2luZyhjYWxsYmFjazogKHF1ZXJ5UGFyYW1ldGVyczogc3RyaW5nKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydzZXRDdXN0b21SZXF1ZXN0UHJvY2Vzc2luZycsIGNhbGxiYWNrXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHJlcXVlc3QgQ29udGVudC1UeXBlIGhlYWRlciB2YWx1ZS48YnIgLz5cbiAgICogQXBwbGljYWJsZSB3aGVuICdQT1NUJyByZXF1ZXN0IG1ldGhvZCBpcyB1c2VkIHZpYSBzZXRSZXF1ZXN0TWV0aG9kLlxuICAgKlxuICAgKiBAcGFyYW0gY29udGVudFR5cGUgVmFsdWUgZm9yIENvbnRlbnQtVHlwZSBIVFRQIGhlYWRlci5cbiAgICovXG4gIHNldFJlcXVlc3RDb250ZW50VHlwZShjb250ZW50VHlwZTogc3RyaW5nKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydzZXRSZXF1ZXN0Q29udGVudFR5cGUnLCBjb250ZW50VHlwZV0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRGlzYWJsZXMgdGhlIGZlYXR1cmUgd2hpY2ggZ3JvdXBzIHRvZ2V0aGVyIG11bHRpcGxlIHRyYWNraW5nIHJlcXVlc3RzIGFuZCBzZW5kIHRoZW0gYXMgYSBidWxrIFBPU1QgcmVxdWVzdC48YnIgLz5cbiAgICogRGlzYWJsaW5nIHRoaXMgZmVhdHVyZSBpcyB1c2VmdWwgd2hlbiB5b3Ugd2FudCB0byBiZSBhYmxlIHRvIHJlcGxheSBhbGwgbG9nczogb25lIG11c3QgdXNlIGRpc2FibGVRdWV1ZVJlcXVlc3RcbiAgICogdG8gZGlzYWJsZSB0aGlzIGJlaGF2aW9yIHRvIGxhdGVyIGJlIGFibGUgdG8gcmVwbGF5IGxvZ2dlZCBNYXRvbW8gbG9ncyAob3RoZXJ3aXNlIGEgc3Vic2V0IG9mIHRoZSByZXF1ZXN0c1xuICAgKiB3b3VsZG4ndCBiZSBhYmxlIHRvIGJlIHJlcGxheWVkKS5cbiAgICovXG4gIGRpc2FibGVRdWV1ZVJlcXVlc3QoKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydkaXNhYmxlUXVldWVSZXF1ZXN0J10pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cbiJdfQ==