ngx-matomo
Version:
Matomo (aka. Piwik) web analytics for Angular applications.
1,893 lines • 175 kB
JavaScript
import { Inject, Injectable } from '@angular/core';
import { MATOMO_CONFIGURATION } from './matomo-configuration';
import * as i0 from "@angular/core";
const heatmapSessionRecording = {
disableCaptureKeystrokes() {
try {
window['_paq'].push(['HeatmapSessionRecording::disableCaptureKeystrokes']);
}
catch (e) {
if (!(e instanceof ReferenceError)) {
throw e;
}
}
},
};
/**
* 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;
this.heatmapSessionRecording = heatmapSessionRecording;
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;
}
}
}
// xxxx(): void {
// try {
// window['_paq'].push(['HeatmapSessionRecording::disableCaptureKeystrokes']);
// } catch (e) {
// if (!(e instanceof ReferenceError)) {
// throw e;
// }
// }
// }
// xxxx(): void {
// try {
// window['_paq'].push(['HeatmapSessionRecording::disableAutoDetectNewPageView']);
// } catch (e) {
// if (!(e instanceof ReferenceError)) {
// throw e;
// }
// }
// }
// xxxx(): void {
// try {
// window['_paq'].push(['enableAutoDetectNewPageView']);
// } catch (e) {
// if (!(e instanceof ReferenceError)) {
// throw e;
// }
// }
// }
// xxxx(): void {
// try {
// window['_paq'].push(['disableRecordMovements']);
// } catch (e) {
// if (!(e instanceof ReferenceError)) {
// throw e;
// }
// }
// }
// xxxx(): void {
// try {
// window['_paq'].push(['enableRecordMovements']);
// } catch (e) {
// if (!(e instanceof ReferenceError)) {
// throw e;
// }
// }
// }
// xxxx(): void {
// try {
// window['_paq'].push(['setNewPageView + fetchConfig']);
// } catch (e) {
// if (!(e instanceof ReferenceError)) {
// throw e;
// }
// }
// }
// xxxx(): void {
// try {
// window['_paq'].push(['setMaxCaptureTime + maxTimeInSeconds']);
// } catch (e) {
// if (!(e instanceof ReferenceError)) {
// throw e;
// }
// }
// }
// xxxx(): void {
// try {
// window['_paq'].push(['setMaxTextInputLength + maxLengthCharacters']);
// } catch (e) {
// if (!(e instanceof ReferenceError)) {
// throw e;
// }
// }
// }
// xxxx(): void {
// try {
// window['_paq'].push(['disableCaptureKeystrokes']);
// } catch (e) {
// if (!(e instanceof ReferenceError)) {
// throw e;
// }
// }
// }
// xxxx(): void {
// try {
// window['_paq'].push(['enableCaptureKeystrokes']);
// } catch (e) {
// if (!(e instanceof ReferenceError)) {
// throw e;
// }
// }
// }
// xxxx(): void {
// try {
// window['_paq'].push(['setTrigger + shouldTriggerFunction']);
// } catch (e) {
// if (!(e instanceof ReferenceError)) {
// throw e;
// }
// }
// }
// xxxx(): void {
// try {
// window['_paq'].push(['matchTrackerUrl']);
// } catch (e) {
// if (!(e instanceof ReferenceError)) {
// throw e;
// }
// }
// }
// xxxx(): void {
// try {
// window['_paq'].push(['disable']);
// } catch (e) {
// if (!(e instanceof ReferenceError)) {
// throw e;
// }
// }
// }
// xxxx(): void {
// try {
// window['_paq'].push(['enable']);
// } catch (e) {
// if (!(e instanceof ReferenceError)) {
// throw e;
// }
// }
// }
// xxxx(): void {
// try {
// window['_paq'].push(['isEnabled']);
// } catch (e) {
// if (!(e instanceof ReferenceError)) {
// throw e;
// }
// }
// }
// xxxx(): void {
// try {
// window['_paq'].push(['enableDebugMode']);
// } catch (e) {
// if (!(e instanceof ReferenceError)) {
// throw e;
// }
// }
// }
// xxxx(): void {
// try {
// window['_paq'].push(['setMatomoTrackers']);
// } catch (e) {
// if (!(e instanceof ReferenceError)) {
// throw e;
// }
// }
// }
// xxxx(): void {
// try {
// window['_paq'].push(['getPiwikTrackers']);
// } 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;
}
}
}
}
MatomoTracker.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.0.5", ngImport: i0, type: MatomoTracker, deps: [{ token: MATOMO_CONFIGURATION }], target: i0.ɵɵFactoryTarget.Injectable });
MatomoTracker.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.0.5", ngImport: i0, type: MatomoTracker });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.0.5", ngImport: i0, type: MatomoTracker, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
type: Inject,
args: [MATOMO_CONFIGURATION]
}] }]; } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWF0b21vLXRyYWNrZXIuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1tYXRvbW8vc3JjL2xpYi9tYXRvbW8tdHJhY2tlci5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRW5ELE9BQU8sRUFBRSxvQkFBb0IsRUFBdUIsTUFBTSx3QkFBd0IsQ0FBQzs7QUFtQm5GLE1BQU0sdUJBQXVCLEdBQUc7SUFDOUIsd0JBQXdCO1FBQ3RCLElBQUk7WUFDRixNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsbURBQW1ELENBQUMsQ0FBQyxDQUFDO1NBQzVFO1FBQUMsT0FBTyxDQUFDLEVBQUU7WUFDVixJQUFJLENBQUMsQ0FBQyxDQUFDLFlBQVksY0FBYyxDQUFDLEVBQUU7Z0JBQ2xDLE1BQU0sQ0FBQyxDQUFDO2FBQ1Q7U0FDRjtJQUNILENBQUM7Q0FDRixDQUFDO0FBRUY7Ozs7R0FJRztBQUVILE1BQU0sT0FBTyxhQUFhO0lBR3hCOzs7O09BSUc7SUFDSCxZQUEyRCxhQUFrQztRQUFsQyxrQkFBYSxHQUFiLGFBQWEsQ0FBcUI7UUFQN0YsNEJBQXVCLEdBQUcsdUJBQXVCLENBQUM7UUFRaEQsSUFBSTtZQUNGLElBQUksT0FBTyxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssV0FBVyxFQUFFO2dCQUN6QyxPQUFPLENBQUMsSUFBSSxDQUFDLHNDQUFzQyxDQUFDLENBQUM7YUFDdEQ7U0FDRjtRQUFDLE9BQU8sQ0FBQyxFQUFFO1lBQ1YsSUFBSSxDQUFDLENBQUMsQ0FBQyxZQUFZLGNBQWMsQ0FBQyxFQUFFO2dCQUNsQyxNQUFNLENBQUMsQ0FBQzthQUNUO1NBQ0Y7SUFDSCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILGFBQWEsQ0FBQyxXQUFvQjtRQUNoQyxJQUFJO1lBQ0YsTUFB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a0JBUUosb0JBQW9COzhHQVI3QixhQUFhOzJGQUFiLGFBQWE7a0JBRHpCLFVBQVU7OzBCQVNJLE1BQU07MkJBQUMsb0JBQW9CIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0LCBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbmltcG9ydCB7IE1BVE9NT19DT05GSUdVUkFUSU9OLCBNYXRvbW9Db25maWd1cmF0aW9uIH0gZnJvbSAnLi9tYXRvbW8tY29uZmlndXJhdGlvbic7XG5cbi8qKlxuICogQWNjZXNzIHRvIHRoZSBnbG9iYWwgd2luZG93IHZhcmlhYmxlLlxuICovXG5kZWNsYXJlIHZhciB3aW5kb3c6IHtcbiAgW2tleTogc3RyaW5nXTogYW55O1xuICBwcm90b3R5cGU6IFdpbmRvdztcbiAgbmV3ICgpOiBXaW5kb3c7XG59O1xuLy8gZGVjbGFyZSBpbnRlcmZhY2UgV2luZG93IHtcbi8vICAgX3BhcTogYW55O1xuLy8gfVxuXG4vKipcbiAqIE1hdG9tbyBzY29wZVxuICovXG50eXBlIE1hdG9tb1Njb3BlID0gJ3BhZ2UnIHwgJ3Zpc2l0JyB8ICdldmVudCc7XG5cbmNvbnN0IGhlYXRtYXBTZXNzaW9uUmVjb3JkaW5nID0ge1xuICBkaXNhYmxlQ2FwdHVyZUtleXN0cm9rZXMoKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydIZWF0bWFwU2Vzc2lvblJlY29yZGluZzo6ZGlzYWJsZUNhcHR1cmVLZXlzdHJva2VzJ10pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH0sXG59O1xuXG4vKipcbiAqIFdyYXBwZXIgZm9yIGZ1bmN0aW9ucyBhdmFpbGFibGUgaW4gdGhlIE1hdG9tbyBKYXZhc2NyaXB0IHRyYWNrZXIuXG4gKlxuICogQGV4cG9ydFxuICovXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgTWF0b21vVHJhY2tlciB7XG4gIGhlYXRtYXBTZXNzaW9uUmVjb3JkaW5nID0gaGVhdG1hcFNlc3Npb25SZWNvcmRpbmc7XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgTWF0b21vVHJhY2tlci5cbiAgICpcbiAgICogQHBhcmFtIGNvbmZpZ3VyYXRpb24gTWF0b21vIGNvbmZpZ3VyYXRpb24gcHJvdmlkZWQgYnkgREkuXG4gICAqL1xuICBjb25zdHJ1Y3RvcihASW5qZWN0KE1BVE9NT19DT05GSUdVUkFUSU9OKSBwcml2YXRlIHJlYWRvbmx5IGNvbmZpZ3VyYXRpb246IE1hdG9tb0NvbmZpZ3VyYXRpb24pIHtcbiAgICB0cnkge1xuICAgICAgaWYgKHR5cGVvZiB3aW5kb3dbJ19wYXEnXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgY29uc29sZS53YXJuKCdNYXRvbW8gaGFzIG5vdCB5ZXQgYmVlbiBpbml0aWFsaXplZCEnKTtcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIExvZ3MgYSB2aXNpdCB0byB0aGlzIHBhZ2UuXG4gICAqXG4gICAqIEBwYXJhbSBbY3VzdG9tVGl0bGVdIE9wdGlvbmFsIHRpdGxlIG9mIHRoZSB2aXNpdGVkIHBhZ2UuXG4gICAqL1xuICB0cmFja1BhZ2VWaWV3KGN1c3RvbVRpdGxlPzogc3RyaW5nKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGFyZ3M6IGFueVtdID0gW107XG4gICAgICBpZiAoISFjdXN0b21UaXRsZSkge1xuICAgICAgICBhcmdzLnB1c2goY3VzdG9tVGl0bGUpO1xuICAgICAgfVxuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3RyYWNrUGFnZVZpZXcnLCAuLi5hcmdzXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBMb2dzIGFuIGV2ZW50IHdpdGggYW4gZXZlbnQgY2F0ZWdvcnkgKFZpZGVvcywgTXVzaWMsIEdhbWVz4oCmKSwgYW4gZXZlbnQgYWN0aW9uIChQbGF5LCBQYXVzZSwgRHVyYXRpb24sXG4gICAqIEFkZCBQbGF5bGlzdCwgRG93bmxvYWRlZCwgQ2xpY2tlZOKApiksIGFuZCBhbiBvcHRpb25hbCBldmVudCBuYW1lIGFuZCBvcHRpb25hbCBudW1lcmljIHZhbHVlLlxuICAgKlxuICAgKiBAcGFyYW0gY2F0ZWdvcnkgQ2F0ZWdvcnkgb2YgdGhlIGV2ZW50LlxuICAgKiBAcGFyYW0gYWN0aW9uIEFjdGlvbiBvZiB0aGUgZXZlbnQuXG4gICAqIEBwYXJhbSBbbmFtZV0gT3B0aW9uYWwgbmFtZSBvZiB0aGUgZXZlbnQuXG4gICAqIEBwYXJhbSBbdmFsdWVdIE9wdGlvbmFsIHZhbHVlIGZvciB0aGUgZXZlbnQuXG4gICAqL1xuICB0cmFja0V2ZW50KGNhdGVnb3J5OiBzdHJpbmcsIGFjdGlvbjogc3RyaW5nLCBuYW1lPzogc3RyaW5nLCB2YWx1ZT86IG51bWJlcik6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBhcmdzOiBhbnlbXSA9IFtjYXRlZ29yeSwgYWN0aW9uXTtcbiAgICAgIGlmICghIW5hbWUpIHtcbiAgICAgICAgYXJncy5wdXNoKG5hbWUpO1xuICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykge1xuICAgICAgICAgIGFyZ3MucHVzaCh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWyd0cmFja0V2ZW50JywgLi4uYXJnc10pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTG9ncyBhbiBpbnRlcm5hbCBzaXRlIHNlYXJjaCBmb3IgYSBzcGVjaWZpYyBrZXl3b3JkLCBpbiBhbiBvcHRpb25hbCBjYXRlZ29yeSxcbiAgICogc3BlY2lmeWluZyB0aGUgb3B0aW9uYWwgY291bnQgb2Ygc2VhcmNoIHJlc3VsdHMgaW4gdGhlIHBhZ2UuXG4gICAqXG4gICAqIEBwYXJhbSBrZXl3b3JkIEtleXdvcmRzIG9mIHRoZSBzZWFyY2ggcXVlcnkuXG4gICAqIEBwYXJhbSBbY2F0ZWdvcnldIE9wdGlvbmFsIGNhdGVnb3J5IG9mIHRoZSBzZWFyY2ggcXVlcnkuXG4gICAqIEBwYXJhbSBbcmVzdWx0c0NvdW50XSBPcHRpb25hbCBudW1iZXIgb2YgcmVzdWx0cyByZXR1cm5lZCBieSB0aGUgc2VhcmNoIHF1ZXJ5LlxuICAgKi9cbiAgdHJhY2tTaXRlU2VhcmNoKGtleXdvcmQ6IHN0cmluZywgY2F0ZWdvcnk/OiBzdHJpbmcsIHJlc3VsdHNDb3VudD86IG51bWJlcik6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBhcmdzOiBhbnlbXSA9IFtrZXl3b3JkXTtcbiAgICAgIGlmICghIWNhdGVnb3J5KSB7XG4gICAgICAgIGFyZ3MucHVzaChjYXRlZ29yeSk7XG4gICAgICAgIGlmICh0eXBlb2YgcmVzdWx0c0NvdW50ID09PSAnbnVtYmVyJykge1xuICAgICAgICAgIGFyZ3MucHVzaChyZXN1bHRzQ291bnQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsndHJhY2tTaXRlU2VhcmNoJywgLi4uYXJnc10pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTWFudWFsbHkgbG9ncyBhIGNvbnZlcnNpb24gZm9yIHRoZSBudW1lcmljIGdvYWwgSUQsIHdpdGggYW4gb3B0aW9uYWwgbnVtZXJpYyBjdXN0b20gcmV2ZW51ZSBjdXN0b21SZXZlbnVlLlxuICAgKlxuICAgKiBAcGFyYW0gaWRHb2FsIG51bWVyaWMgSUQgb2YgdGhlIGdvYWwgdG8gbG9nIGEgY29udmVyc2lvbiBmb3IuXG4gICAqIEBwYXJhbSBbY3VzdG9tUmV2ZW51ZV0gT3B0aW9uYWwgY3VzdG9tIHJldmVudWUgdG8gbG9nIGZvciB0aGUgZ29hbC5cbiAgICovXG4gIHRyYWNrR29hbChpZEdvYWw6IG51bWJlciwgY3VzdG9tUmV2ZW51ZT86IG51bWJlcik6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBhcmdzOiBhbnlbXSA9IFtpZEdvYWxdO1xuICAgICAgaWYgKHR5cGVvZiBjdXN0b21SZXZlbnVlID09PSAnbnVtYmVyJykge1xuICAgICAgICBhcmdzLnB1c2goY3VzdG9tUmV2ZW51ZSk7XG4gICAgICB9XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsndHJhY2tHb2FsJywgLi4uYXJnc10pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTWFudWFsbHkgbG9ncyBhIGNsaWNrIGZyb20geW91ciBvd24gY29kZS5cbiAgICpcbiAgICogQHBhcmFtIHVybCBGdWxsIFVSTCB3aGljaCBpcyB0byBiZSB0cmFja2VkIGFzIGEgY2xpY2suXG4gICAqIEBwYXJhbSBsaW5rVHlwZSBFaXRoZXIgJ2xpbmsnIGZvciBhbiBvdXRsaW5rIG9yICdkb3dubG9hZCcgZm9yIGEgZG93bmxvYWQuXG4gICAqL1xuICB0cmFja0xpbmsodXJsOiBzdHJpbmcsIGxpbmtUeXBlOiAnbGluaycgfCAnZG93bmxvYWQnKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWyd0cmFja0xpbmsnLCB1cmwsIGxpbmtUeXBlXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTY2FucyB0aGUgZW50aXJlIERPTSBmb3IgYWxsIGNvbnRlbnQgYmxvY2tzIGFuZCB0cmFja3MgYWxsIGltcHJlc3Npb25zIG9uY2UgdGhlIERPTSByZWFkeSBldmVudCBoYXMgYmVlbiB0cmlnZ2VyZWQuXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZGV2ZWxvcGVyLm1hdG9tby5vcmcvZ3VpZGVzL2NvbnRlbnQtdHJhY2tpbmd8Q29udGVudCBUcmFja2luZ31cbiAgICovXG4gIHRyYWNrQWxsQ29udGVudEltcHJlc3Npb25zKCk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsndHJhY2tBbGxDb250ZW50SW1wcmVzc2lvbnMnXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTY2FucyB0aGUgZW50aXJlIERPTSBmb3IgYWxsIGNvbnRlbnQgYmxvY2tzIGFzIHNvb24gYXMgdGhlIHBhZ2UgaXMgbG9hZGVkLjxiciAvPlxuICAgKiBJdCB0cmFja3MgYW4gaW1wcmVzc2lvbiBvbmx5IGlmIGEgY29udGVudCBibG9jayBpcyBhY3R1YWxseSB2aXNpYmxlLlxuICAgKlxuICAgKiBAcGFyYW0gY2hlY2tPblNjcm9sbCBJZiB0cnVlLCBjaGVja3MgZm9yIG5ldyBjb250ZW50IGJsb2NrcyB3aGlsZSBzY3JvbGxpbmcgdGhlIHBhZ2UuXG4gICAqIEBwYXJhbSB0aW1lSW50ZXJ2YWwgRHVyYXRpb24sIGluIG1pbGxpc2Vjb25kcywgYmV0d2VlbiB0d28gY2hlY2tzIHVwb24gc2Nyb2xsLlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL2RldmVsb3Blci5tYXRvbW8ub3JnL2d1aWRlcy9jb250ZW50LXRyYWNraW5nfENvbnRlbnQgVHJhY2tpbmd9XG4gICAqL1xuICB0cmFja1Zpc2libGVDb250ZW50SW1wcmVzc2lvbnMoY2hlY2tPblNjcm9sbDogYm9vbGVhbiwgdGltZUludGVydmFsOiBudW1iZXIpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3RyYWNrVmlzaWJsZUNvbnRlbnRJbXByZXNzaW9ucycsIGNoZWNrT25TY3JvbGwsIHRpbWVJbnRlcnZhbF0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2NhbnMgdGhlIGdpdmVuIERPTSBub2RlIGFuZCBpdHMgY2hpbGRyZW4gZm9yIGNvbnRlbnQgYmxvY2tzIGFuZCB0cmFja3MgYW4gaW1wcmVzc2lvbiBmb3IgdGhlbVxuICAgKiBpZiBubyBpbXByZXNzaW9uIHdhcyBhbHJlYWR5IHRyYWNrZWQgZm9yIGl0LlxuICAgKlxuICAgKiBAcGFyYW0gbm9kZSBET00gbm9kZSBpbiB3aGljaCB0byBsb29rIGZvciBjb250ZW50IGJsb2NrcyB3aGljaCBoYXZlIG5vdCBiZWVuIHByZXZpb3VzbHkgdHJhY2tlZC5cbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kZXZlbG9wZXIubWF0b21vLm9yZy9ndWlkZXMvY29udGVudC10cmFja2luZ3xDb250ZW50IFRyYWNraW5nfVxuICAgKi9cbiAgdHJhY2tDb250ZW50SW1wcmVzc2lvbnNXaXRoaW5Ob2RlKG5vZGU6IE5vZGUpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3RyYWNrQ29udGVudEltcHJlc3Npb25zV2l0aGluTm9kZScsIG5vZGVdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRyYWNrcyBhbiBpbnRlcmFjdGlvbiB3aXRoIHRoZSBnaXZlbiBET00gbm9kZS9jb250ZW50IGJsb2NrLlxuICAgKlxuICAgKiBAcGFyYW0gbm9kZSBET00gbm9kZSBmb3Igd2hpY2ggdG8gdHJhY2sgYSBjb250ZW50IGludGVyYWN0aW9uLlxuICAgKiBAcGFyYW0gY29udGVudEludGVyYWN0aW9uIE5hbWUgb2YgdGhlIGNvbnRlbnQgaW50ZXJhY3Rpb24uXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZGV2ZWxvcGVyLm1hdG9tby5vcmcvZ3VpZGVzL2NvbnRlbnQtdHJhY2tpbmd8Q29udGVudCBUcmFja2luZ31cbiAgICovXG4gIHRyYWNrQ29udGVudEludGVyYWN0aW9uTm9kZShub2RlOiBOb2RlLCBjb250ZW50SW50ZXJhY3Rpb246IHN0cmluZyk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsndHJhY2tDb250ZW50SW50ZXJhY3Rpb25Ob2RlJywgbm9kZSwgY29udGVudEludGVyYWN0aW9uXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUcmFja3MgYSBjb250ZW50IGltcHJlc3Npb24gdXNpbmcgdGhlIHNwZWNpZmllZCB2YWx1ZXMuXG4gICAqXG4gICAqIEBwYXJhbSBjb250ZW50TmFtZSBDb250ZW50IG5hbWUuXG4gICAqIEBwYXJhbSBjb250ZW50UGllY2UgQ29udGVudCBwaWVjZS5cbiAgICogQHBhcmFtIGNvbnRlbnRUYXJnZXQgQ29udGVudCB0YXJnZXQuXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZGV2ZWxvcGVyLm1hdG9tby5vcmcvZ3VpZGVzL2NvbnRlbnQtdHJhY2tpbmd8Q29udGVudCBUcmFja2luZ31cbiAgICovXG4gIHRyYWNrQ29udGVudEltcHJlc3Npb24oY29udGVudE5hbWU6IHN0cmluZywgY29udGVudFBpZWNlOiBzdHJpbmcsIGNvbnRlbnRUYXJnZXQ6IHN0cmluZyk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsndHJhY2tDb250ZW50SW1wcmVzc2lvbicsIGNvbnRlbnROYW1lLCBjb250ZW50UGllY2UsIGNvbnRlbnRUYXJnZXRdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFRyYWNrcyBhIGNvbnRlbnQgaW50ZXJhY3Rpb24gdXNpbmcgdGhlIHNwZWNpZmllZCB2YWx1ZXMuXG4gICAqXG4gICAqIEBwYXJhbSBjb250ZW50SW50ZXJhY3Rpb24gQ29udGVudCBpbnRlcmFjdGlvbi5cbiAgICogQHBhcmFtIGNvbnRlbnROYW1lIENvbnRlbnQgbmFtZS5cbiAgICogQHBhcmFtIGNvbnRlbnRQaWVjZSBDb250ZW50IHBpZWNlLlxuICAgKiBAcGFyYW0gY29udGVudFRhcmdldCBDb250ZW50IHRhcmdldC5cbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9kZXZlbG9wZXIubWF0b21vLm9yZy9ndWlkZXMvY29udGVudC10cmFja2luZ3xDb250ZW50IFRyYWNraW5nfVxuICAgKi9cbiAgdHJhY2tDb250ZW50SW50ZXJhY3Rpb24oXG4gICAgY29udGVudEludGVyYWN0aW9uOiBzdHJpbmcsXG4gICAgY29udGVudE5hbWU6IHN0cmluZyxcbiAgICBjb250ZW50UGllY2U6IHN0cmluZyxcbiAgICBjb250ZW50VGFyZ2V0OiBzdHJpbmdcbiAgKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goW1xuICAgICAgICAndHJhY2tDb250ZW50SW50ZXJhY3Rpb24nLFxuICAgICAgICBjb250ZW50SW50ZXJhY3Rpb24sXG4gICAgICAgIGNvbnRlbnROYW1lLFxuICAgICAgICBjb250ZW50UGllY2UsXG4gICAgICAgIGNvbnRlbnRUYXJnZXQsXG4gICAgICBdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIExvZ3MgYWxsIGZvdW5kIGNvbnRlbnQgYmxvY2tzIHdpdGhpbiBhIHBhZ2UgdG8gdGhlIGNvbnNvbGUuPGJyIC8+XG4gICAqIFRoaXMgaXMgdXNlZnVsIHRvIGRlYnVnIC8gdGVzdCBjb250ZW50IHRyYWNraW5nLlxuICAgKi9cbiAgbG9nQWxsQ29udGVudEJsb2Nrc09uUGFnZSgpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ2xvZ0FsbENvbnRlbnRCbG9ja3NPblBhZ2UnXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZW5kcyBhIHBpbmcgcmVxdWVzdC48YnIgLz5cbiAgICogUGluZyByZXF1ZXN0cyBkbyBub3QgdHJhY2sgbmV3IGFjdGlvbnMuXG4gICAqIElmIHRoZXkgYXJlIHNlbnQgd2l0aGluIHRoZSBzdGFuZGFyZCB2aXNpdCBsZW5ndGgsIHRoZXkgd2lsbCBleHRlbmQgdGhlIGV4aXN0aW5nIHZpc2l0IGFuZCB0aGUgY3VycmVudCBsYXN0IGFjdGlvbiBmb3IgdGhlIHZpc2l0LlxuICAgKiBJZiBzZW50IGFmdGVyIHRoZSBzdGFuZGFyZCB2aXNpdCBsZW5ndGgsIHBpbmcgcmVxdWVzdHMgd2lsbCBjcmVhdGUgYSBuZXcgdmlzaXQgdXNpbmcgdGhlIGxhc3QgYWN0aW9uIGluIHRoZSBsYXN0IGtub3duIHZpc2l0LjxiciAvPlxuICAgKiBTZWUgYWxzbyBlbmFibGVIZWFydEJlYXRUaW1lci5cbiAgICovXG4gIHBpbmcoKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydwaW5nJ10pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSW5zdGFsbHMgYSBIZWFydCBiZWF0IHRpbWVyIHRoYXQgd2lsbCByZWd1bGFybHkgc2VuZCByZXF1ZXN0cyB0byBNYXRvbW8gaW4gb3JkZXIgdG8gYmV0dGVyIG1lYXN1cmUgdGhlIHRpbWUgc3BlbnQgb24gdGhlIHBhZ2UuPGJyIC8+XG4gICAqIFRoZXNlIHJlcXVlc3RzIHdpbGwgYmUgc2VudCBvbmx5IHdoZW4gdGhlIHVzZXIgaXMgYWN0aXZlbHkgdmlld2luZyB0aGUgcGFnZSAod2hlbiB0aGUgdGFiIGlzIGFjdGl2ZSBhbmQgaW4gZm9jdXMpLjxiciAvPlxuICAgKiBUaGVzZSByZXF1ZXN0cyB3aWxsIG5vdCB0cmFjayBhZGRpdGlvbmFsIGFjdGlvbnMgb3IgcGFnZSB2aWV3cy48YnIgLz5cbiAgICogQnkgZGVmYXVsdCwgdGhlIGRlbGF5IGlzIHNldCB0byAxNSBzZWNvbmRzLlxuICAgKlxuICAgKiBAcGFyYW0gZGVsYXkgRGVsYXksIGluIHNlY29uZHMsIGJldHdlZW4gdHdvIGhlYXJ0IGJlYXRzIHRvIHRoZSBzZXJ2ZXIuXG4gICAqL1xuICBlbmFibGVIZWFydEJlYXRUaW1lcihkZWxheTogbnVtYmVyKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydlbmFibGVIZWFydEJlYXRUaW1lcicsIGRlbGF5XSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJbnN0YWxscyBsaW5rIHRyYWNraW5nIG9uIGFsbCBhcHBsaWNhYmxlIGxpbmsgZWxlbWVudHMuXG4gICAqXG4gICAqIEBwYXJhbSBbZW5hYmxlPWZhbHNlXSBTZXQgdG8gdHJ1ZSB0byB1c2UgcHNldWRvIGNsaWNrLWhhbmRsZXIgKHRyZWF0IG1pZGRsZSBjbGljayBhbmQgb3BlbiBjb250ZXh0bWVudSBhc1xuICAgKiBsZWZ0IGNsaWNrKS48YnIgLz5cbiAgICogQSByaWdodCBjbGljayAob3IgYW55IGNsaWNrIHRoYXQgb3BlbnMgdGhlIGNvbnRleHQgbWVudSkgb24gYSBsaW5rIHdpbGwgYmUgdHJhY2tlZCBhcyBjbGlja2VkIGV2ZW4gaWYgXCJPcGVuIGluIG5ldyB0YWJcIlxuICAgKiBpcyBub3Qgc2VsZWN0ZWQuPGJyIC8+XG4gICAqIElmIGZhbHNlIChkZWZhdWx0KSwgbm90aGluZyB3aWxsIGJlIHRyYWNrZWQgb24gb3BlbiBjb250ZXh0IG1lbnUgb3IgbWlkZGxlIGNsaWNrLlxuICAgKi9cbiAgZW5hYmxlTGlua1RyYWNraW5nKGVuYWJsZTogYm9vbGVhbiA9IGZhbHNlKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydlbmFibGVMaW5rVHJhY2tpbmcnLCBlbmFibGVdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEVuYWJsZXMgY3Jvc3MgZG9tYWluIGxpbmtpbmcuIEJ5IGRlZmF1bHQsIHRoZSB2aXNpdG9yIElEIHRoYXQgaWRlbnRpZmllcyBhIHVuaXF1ZSB2aXNpdG9yIGlzIHN0b3JlZCBpbiB0aGUgYnJvd3NlcidzXG4gICAqIGZpcnN0IHBhcnR5IGNvb2tpZXMuPGJyIC8+XG4gICAqIFRoaXMgbWVhbnMgdGhlIGNvb2tpZSBjYW4gb25seSBiZSBhY2Nlc3NlZCBieSBwYWdlcyBvbiB0aGUgc2FtZSBkb21haW4uPGJyIC8+XG4gICAqIElmIHlvdSBvd24gbXVsdGlwbGUgZG9tYWlucyBhbmQgd291bGQgbGlrZSB0byB0cmFjayBhbGwgdGhlIGFjdGlvbnMgYW5kIHBhZ2V2aWV3cyBvZiBhIHNwZWNpZmljIHZpc2l0b3IgaW50byB0aGUgc2FtZSB2aXNpdCxcbiAgICogeW91IG1heSBlbmFibGUgY3Jvc3MgZG9tYWluIGxpbmtpbmcuPGJyIC8+XG4gICAqIFdoZW5ldmVyIGEgdXNlciBjbGlja3Mgb24gYSBsaW5rIGl0IHdpbGwgYXBwZW5kIGEgVVJMIHBhcmFtZXRlciBwa192aWQgdG8gdGhlIGNsaWNrZWQgVVJMIHdoaWNoIGZvcndhcmRzIHRoZSBjdXJyZW50XG4gICAqIHZpc2l0b3IgSUQgdmFsdWUgdG8gdGhlIHBhZ2Ugb2YgdGhlIGRpZmZlcmVudCBkb21haW4uXG4gICAqXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vbWF0b21vLm9yZy9mYXEvaG93LXRvL2ZhcV8yMzY1NC98Q3Jvc3MgRG9tYWluIExpbmtpbmd9XG4gICAqL1xuICBlbmFibGVDcm9zc0RvbWFpbkxpbmtpbmcoKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydlbmFibGVDcm9zc0RvbWFpbkxpbmtpbmcnXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSBjcm9zcyBkb21haW4gbGlua2luZyB0aW1lb3V0LjxiciAvPlxuICAgKiBCeSBkZWZhdWx0LCB0aGUgdHdvIHZpc2l0cyBhY3Jvc3MgZG9tYWlucyB3aWxsIGJlIGxpbmtlZCB0b2dldGhlciB3aGVuIHRoZSBsaW5rIGlzIGNsaWNrZWQgYW5kIHRoZSBwYWdlIGlzIGxvYWRlZCB3aXRoaW5cbiAgICogYSAxODAgc2Vjb25kcyB0aW1lb3V0IHdpbmRvdy5cbiAgICpcbiAgICogQHBhcmFtIHRpbWVvdXQgVGltZW91dCwgaW4gc2Vjb25kcywgYmV0d2VlbiB0d28gYWN0aW9ucyBhY3Jvc3MgdHdvIGRvbWFpbnMgYmVmb3JlIGNyZWF0aW5nIGEgbmV3IHZpc2l0LlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL21hdG9tby5vcmcvZmFxL2hvdy10by9mYXFfMjM2NTQvfENyb3NzIERvbWFpbiBMaW5raW5nfVxuICAgKi9cbiAgc2V0Q3Jvc3NEb21haW5MaW5raW5nVGltZW91dCh0aW1lb3V0OiBudW1iZXIpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3NldENyb3NzRG9tYWluTGlua2luZ1RpbWVvdXQnLCB0aW1lb3V0XSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBxdWVyeSBwYXJhbWV0ZXIgdG8gYXBwZW5kIHRvIGxpbmtzIHRvIGhhbmRsZSBjcm9zcyBkb21haW4gbGlua2luZy48YnIgLz5cbiAgICogVXNlIHRoaXMgdG8gYWRkIGNyb3NzIGRvbWFpbiBzdXBwb3J0IGZvciBsaW5rcyB0aGF0IGFyZSBhZGRlZCB0byB0aGUgRE9NIGR5bmFtaWNhbGx5LlxuICAgKlxuICAgKiBAcmV0dXJucyBQcm9taXNlIGZvciB0aGUgYHBrX3ZpZGAgcXVlcnkgcGFyYW1ldGVyLlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL21hdG9tby5vcmcvZmFxL2hvdy10by9mYXFfMjM2NTQvfENyb3NzIERvbWFpbiBMaW5raW5nfVxuICAgKi9cbiAgZ2V0Q3Jvc3NEb21haW5MaW5raW5nVXJsUGFyYW1ldGVyKCk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goW1xuICAgICAgICAgIGZ1bmN0aW9uICh0aGlzOiBhbnkpOiB2b2lkIHtcbiAgICAgICAgICAgIHJlc29sdmUodGhpcy5nZXRDcm9zc0RvbWFpbkxpbmtpbmdVcmxQYXJhbWV0ZXIoKSk7XG4gICAgICAgICAgfSxcbiAgICAgICAgXSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgICByZWplY3QoZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBPdmVycmlkZXMgZG9jdW1lbnQudGl0bGVcbiAgICpcbiAgICogQHBhcmFtIHRpdGxlIFRpdGxlIG9mIHRoZSBkb2N1bWVudC5cbiAgICovXG4gIHNldERvY3VtZW50VGl0bGUodGl0bGU6IHN0cmluZyk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnc2V0RG9jdW1lbnRUaXRsZScsIHRpdGxlXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIGFycmF5IG9mIGhvc3RuYW1lcyBvciBkb21haW5zIHRvIGJlIHRyZWF0ZWQgYXMgbG9jYWwuPGJyIC8+XG4gICAqIEZvciB3aWxkY2FyZCBzdWJkb21haW5zLCB5b3UgY2FuIHVzZTogYHNldERvbWFpbnMoJy5leGFtcGxlLmNvbScpYDsgb3IgYHNldERvbWFpbnMoJyouZXhhbXBsZS5jb20nKTtgLjxiciAvPlxuICAgKiBZb3UgY2FuIGFsc28gc3BlY2lmeSBhIHBhdGggYWxvbmcgYSBkb21haW46IGBzZXREb21haW5zKCcqLmV4YW1wbGUuY29tL3N1YnNpdGUxJyk7YC5cbiAgICpcbiAgICogQHBhcmFtIGRvbWFpbnMgTGlzdCBvZiBob3N0bmFtZXMgb3IgZG9tYWlucywgd2l0aCBvciB3aXRob3V0IHBhdGgsIHRvIGJlIHRyZWF0ZWQgYXMgbG9jYWwuXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vbWF0b21vLm9yZy9mYXEvaG93LXRvL2ZhcV8yMzY1NC98Q3Jvc3MgRG9tYWluIExpbmtpbmd9XG4gICAqL1xuICBzZXREb21haW5zKGRvbWFpbnM6IHN0cmluZ1tdKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydzZXREb21haW5zJywgZG9tYWluc10pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogT3ZlcnJpZGUgdGhlIHBhZ2UncyByZXBvcnRlZCBVUkwuXG4gICAqXG4gICAqIEBwYXJhbSB1cmwgVVJMIHRvIGJlIHJlcG9ydGVkIGZvciB0aGUgcGFnZS5cbiAgICovXG4gIHNldEN1c3RvbVVybCh1cmw6IHN0cmluZyk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnc2V0Q3VzdG9tVXJsJywgdXJsXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBPdmVycmlkZXMgdGhlIGRldGVjdGVkIEh0dHAtUmVmZXJlci5cbiAgICpcbiAgICogQHBhcmFtIHVybCBVUkwgdG8gYmUgcmVwb3J0ZWQgZm9yIHRoZSByZWZlcmVyLlxuICAgKi9cbiAgc2V0UmVmZXJyZXJVcmwodXJsOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3NldFJlZmVycmVyVXJsJywgdXJsXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTcGVjaWZpZXMgdGhlIHdlYnNpdGUgSUQuPGJyIC8+XG4gICAqIFJlZHVuZGFudDogY2FuIGJlIHNwZWNpZmllZCBpbiBnZXRUcmFja2VyKCkgY29uc3RydWN0b3IuXG4gICAqXG4gICAqIC8vIFRPRE8gSW52ZXN0aWdhdGUgaWYgc2V0U2l0ZUlkIG5lZWRzIHRvIGJlIHJlbW92ZWQgZnJvbSBNYXRvbW9UcmFja2VyLlxuICAgKiBAcGFyYW0gc2l0ZUlkIFNpdGUgSUQgZm9yIHRoZSB0cmFja2VyLlxuICAgKi9cbiAgc2V0U2l0ZUlkKHNpdGVJZDogbnVtYmVyKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydzZXRTaXRlSWQnLCBzaXRlSWRdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNwZWNpZmllcyB0aGUgTWF0b21vIEhUVFAgQVBJIFVSTCBlbmRwb2ludC48YnIgLz5cbiAgICogUG9pbnRzIHRvIHRoZSByb290IGRpcmVjdG9yeSBvZiBNYXRvbW8sIGUuZy4gaHR0cDovL21hdG9tby5leGFtcGxlLm9yZy8gb3IgaHR0cHM6Ly9leGFtcGxlLm9yZy9tYXRvbW8vLjxiciAvPlxuICAgKiBUaGlzIGZ1bmN0aW9uIGlzIG9ubHkgdXNlZnVsIHdoZW4gdGhlICdPdmVybGF5JyByZXBvcnQgaXMgbm90IHdvcmtpbmcuPGJyIC8+XG4gICAqIEJ5IGRlZmF1bHQsIHlvdSBkbyBub3QgbmVlZCB0byB1c2UgdGhpcyBmdW5jdGlvbi5cbiAgICpcbiAgICogQHBhcmFtIHVybCBVUkwgZm9yIE1hdG9tbyBIVFRQIEFQSSBlbmRwb2ludC5cbiAgICovXG4gIHNldEFwaVVybCh1cmw6IHN0cmluZyk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnc2V0QXBpVXJsJywgdXJsXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTcGVjaWZpZXMgdGhlIE1hdG9tbyBzZXJ2ZXIgVVJMLjxiciAvPlxuICAgKiBSZWR1bmRhbnQ6IGNhbiBiZSBzcGVjaWZpZWQgaW4gZ2V0VHJhY2tlcigpIGNvbnN0cnVjdG9yLlxuICAgKlxuICAgKiAvLyBUT0RPIEludmVzdGlnYXRlIGlmIHNldFRyYWNrZXJVcmwgbmVlZHMgdG8gYmUgcmVtb3ZlZCBmcm9tIE1hdG9tb1RyYWNrZXIuXG4gICAqIEBwYXJhbSB1cmwgVVJMIGZvciB0aGUgTWF0b21vIHNlcnZlci5cbiAgICovXG4gIHNldFRyYWNrZXJVcmwodXJsOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3NldFRyYWNrZXJVcmwnLCB1cmxdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIE1hdG9tbyBzZXJ2ZXIgVVJMLlxuICAgKlxuICAgKiBAcmV0dXJucyBQcm9taXNlIGZvciB0aGUgTWF0b21vIHNlcnZlciBVUkwuXG4gICAqL1xuICBnZXRNYXRvbW9VcmwoKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbXG4gICAgICAgICAgZnVuY3Rpb24gKHRoaXM6IGFueSk6IHZvaWQge1xuICAgICAgICAgICAgcmVzb2x2ZSh0aGlzLmdldFBpd2lrVXJsKCkpO1xuICAgICAgICAgIH0sXG4gICAgICAgIF0pO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgY3VycmVudCB1cmwgb2YgdGhlIHBhZ2UgdGhhdCBpcyBjdXJyZW50bHkgYmVpbmcgdmlzaXRlZC48YnIgLz5cbiAgICogSWYgYSBjdXN0b20gVVJMIHdhcyBzZXQgYmVmb3JlIGNhbGxpbmcgdGhpcyBtZXRob2QsIHRoZSBjdXN0b20gVVJMIHdpbGwgYmUgcmV0dXJuZWQuXG4gICAqXG4gICAqIEByZXR1cm5zIFByb21pc2UgZm9yIHRoZSBVUkwgb2YgdGhlIGN1cnJlbnQgcGFnZS5cbiAgICovXG4gIGdldEN1cnJlbnRVcmwoKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbXG4gICAgICAgICAgZnVuY3Rpb24gKHRoaXM6IGFueSk6IHZvaWQge1xuICAgICAgICAgICAgcmVzb2x2ZSh0aGlzLmdldEN1cnJlbnRVcmwoKSk7XG4gICAgICAgICAgfSxcbiAgICAgICAgXSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgICByZWplY3QoZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIGNsYXNzZXMgdG8gYmUgdHJlYXRlZCBhcyBkb3dubG9hZHMgKGluIGFkZGl0aW9uIHRvIHBpd2lrX2Rvd25sb2FkKS5cbiAgICpcbiAgICogQHBhcmFtIGNsYXNzZXMgQ2xhc3MsIG9yIGxpc3Qgb2YgY2xhc3NlcyB0byBiZSB0cmVhdGVkIGFzIGRvd25sb2Fkcy5cbiAgICovXG4gIHNldERvd25sb2FkQ2xhc3NlcyhjbGFzc2VzOiBzdHJpbmcgfCBzdHJpbmdbXSk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnc2V0RG93bmxvYWRDbGFzc2VzJywgY2xhc3Nlc10pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2V0cyBmaWxlIGV4dGVuc2lvbnMgdG8gYmUgcmVjb2duaXplZCBhcyBkb3dubG9hZHMuPGJyIC8+XG4gICAqIEV4YW1wbGU6IGAnZG9jeCdgIG9yIGBbJ2RvY3gnLCAneGxzeCddYC5cbiAgICpcbiAgICogQHBhcmFtIGV4dGVuc2lvbnMgRXh0ZW5zaW9uLCBvciBsaXN0IG9mIGV4dGVuc2lvbnMgdG8gYmUgcmVjb2duaXplZCBhcyBkb3dubG9hZHMuXG4gICAqL1xuICBzZXREb3dubG9hZEV4dGVuc2lvbnMoZXh0ZW5zaW9uczogc3RyaW5nIHwgc3RyaW5nW10pOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3NldERvd25sb2FkQ2xhc3NlcycsIGV4dGVuc2lvbnNdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgYWRkaXRpb25hbCBmaWxlIGV4dGVuc2lvbnMgdG8gYmUgcmVjb2duaXplZCBhcyBkb3dubG9hZHMuPGJyIC8+XG4gICAqIEV4YW1wbGU6IGAnZG9jeCdgIG9yIGBbJ2RvY3gnLCAneGxzeCddYC5cbiAgICpcbiAgICogQHBhcmFtIGV4dGVuc2lvbnMgRXh0ZW5zaW9uLCBvciBsaXN0IG9mIGV4dGVuc2lvbnMgdG8gYmUgcmVjb2duaXplZCBhcyBkb3dubG9hZHMuXG4gICAqL1xuICBhZGREb3dubG9hZEV4dGVuc2lvbnMoZXh0ZW5zaW9uczogc3RyaW5nIHwgc3RyaW5nW10pOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3NldERvd25sb2FkQ2xhc3NlcycsIGV4dGVuc2lvbnNdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNwZWNpZmllcyBmaWxlIGV4dGVuc2lvbnMgdG8gYmUgcmVtb3ZlZCBmcm9tIHRoZSBsaXN0IG9mIGRvd25sb2FkIGZpbGUgZXh0ZW5zaW9ucy48YnIgLz5cbiAgICogRXhhbXBsZTogYCdkb2N4J2Agb3IgYFsnZG9jeCcsICd4bHN4J11gLlxuICAgKlxuICAgKiBAcGFyYW0gZXh0ZW5zaW9ucyBFeHRlbnNpb24sIG9yIGxpc3Qgb2YgZXh0ZW5zaW9ucyBub3QgdG8gYmUgcmVjb2duaXplZCBhcyBkb3dubG9hZHMuXG4gICAqL1xuICByZW1vdmVEb3dubG9hZEV4dGVuc2lvbnMoZXh0ZW5zaW9uczogc3RyaW5nIHwgc3RyaW5nW10pOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3NldERvd25sb2FkQ2xhc3NlcycsIGV4dGVuc2lvbnNdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgY2xhc3NlcyB0byBiZSBpZ25vcmVkIGlmIHByZXNlbnQgaW4gbGluayAoaW4gYWRkaXRpb24gdG8gcGl3aWtfaWdub3JlKS5cbiAgICpcbiAgICogQHBhcmFtIGNsYXNzZXMgQ2xhc3MsIG9yIGxpc3Qgb2YgY2xhc3NlcyB0byBiZSBpZ25vcmVkIGlmIHByZXNlbnQgaW4gbGluay5cbiAgICovXG4gIHNldElnbm9yZUNsYXNzZXMoY2xhc3Nlczogc3RyaW5nIHwgc3RyaW5nW10pOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3NldERvd25sb2FkQ2xhc3NlcycsIGNsYXNzZXNdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgY2xhc3NlcyB0byBiZSB0cmVhdGVkIGFzIG91dGxpbmtzIChpbiBhZGRpdGlvbiB0byBwaXdpa19saW5rKS5cbiAgICpcbiAgICogQHBhcmFtIGNsYXNzZXMgQ2xhc3MsIG9yIGxpc3Qgb2YgY2xhc3NlcyB0byBiZSB0cmVhdGVkIGFzIG91dGxpbmtzLlxuICAgKi9cbiAgc2V0TGlua0NsYXNzZXMoY2xhc3Nlczogc3RyaW5nIHwgc3RyaW5nW10pOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3NldERvd25sb2FkQ2xhc3NlcycsIGNsYXNzZXNdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgZGVsYXkgZm9yIGxpbmsgdHJhY2tpbmcgKGluIG1pbGxpc2Vjb25kcykuXG4gICAqXG4gICAqIEBwYXJhbSBkZWxheSBEZWxheSwgaW4gbWlsbGlzZWNvbmRzLCBmb3IgbGluayB0cmFja2luZy5cbiAgICovXG4gIHNldExpbmtUcmFja2luZ1RpbWVyKGRlbGF5OiBudW1iZXIpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3NldExpbmtUcmFja2luZ1RpbWVyJywgZGVsYXldKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgZGVsYXkgZm9yIGxpbmsgdHJhY2tpbmcuXG4gICAqXG4gICAqIEByZXR1cm5zIFByb21pc2UgZm9yIHRoZSBkZWxheSBpbiBtaWxsaXNlY29uZHMuXG4gICAqL1xuICBnZXRMaW5rVHJhY2tpbmdUaW1lcigpOiBQcm9taXNlPG51bWJlcj4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFtcbiAgICAgICAgICBmdW5jdGlvbiAodGhpczogYW55KTogdm9pZCB7XG4gICAgICAgICAgICByZXNvbHZlKHRoaXMuZ2V0TGlua1RyYWNraW5nVGltZXIoKSk7XG4gICAgICAgICAgfSxcbiAgICAgICAgXSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgICByZWplY3QoZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIGlmIG9yIG5vdCB0byByZWNvcmQgdGhlIGhhc2ggdGFnIChhbmNob3IpIHBvcnRpb24gb2YgVVJMcy5cbiAgICpcbiAgICogQHBhcmFtIHZhbHVlIElmIHRydWUsIHRoZSBoYXNoIHRhZyBwb3J0aW9uIG9mIHRoZSBVUkxzIHdvbid0IGJlIHJlY29yZGVkLlxuICAgKi9cbiAgZGlzY2FyZEhhc2hUYWcodmFsdWU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ2Rpc2NhcmRIYXNoVGFnJywgdmFsdWVdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEJ5IGRlZmF1bHQgTWF0b21vIHVzZXMgdGhlIGJyb3dzZXIgRE9NIFRpbWluZyBBUEkgdG8gYWNjdXJhdGVseSBkZXRlcm1pbmUgdGhlIHRpbWUgaXQgdGFrZXMgdG8gZ2VuZXJhdGUgYW5kIGRvd25sb2FkXG4gICAqIHRoZSBwYWdlLiBZb3UgbWF5IG92ZXJ3cml0ZSB0aGlzIHZhbHVlIHdpdGggdGhpcyBmdW5jdGlvbi5cbiAgICogVGhpcyBmdW5jdGlvbiBpcyBkZXByZWNhdGVkIGluIE1hdG9tbyA0LnguXG4gICAqXG4gICAqIEBwYXJhbSBnZW5lcmF0aW9uVGltZSBUaW1lLCBpbiBtaWxsaXNlY29uZHMsIG9mIHRoZSBwYWdlIGdlbmVyYXRpb24uXG4gICAqL1xuICBzZXRHZW5lcmF0aW9uVGltZU1zKGdlbmVyYXRpb25UaW1lOiBudW1iZXIpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5jb25maWd1cmF0aW9uLnNjcmlwdFZlcnNpb24gPCA0KSB7XG4gICAgICB0cnkge1xuICAgICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnc2V0R2VuZXJhdGlvblRpbWVNcycsIGdlbmVyYXRpb25UaW1lXSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgICB0aHJvdyBlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFwcGVuZHMgYSBjdXN0b20gc3RyaW5nIHRvIHRoZSBlbmQgb2YgdGhlIEhUVFAgcmVxdWVzdCB0byBwaXdpay5waHAuXG4gICAqXG4gICAqIEBwYXJhbSBhcHBlbmRUb1VybCBTdHJpbmcgdG8gYXBwZW5kIHRvIHRoZSBlbmQgb2YgdGhlIEhUVFAgcmVxdWVzdCB0byBwaXdpay5waHAvbWF0b21vLnBocC5cbiAgICovXG4gIGFwcGVuZFRvVHJhY2tpbmdVcmwoYXBwZW5kVG9Vcmw6IHN0cmluZyk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnYXBwZW5kVG9UcmFja2luZ1VybCcsIGFwcGVuZFRvVXJsXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBFbmFibGVzIGEgZnJhbWUtYnVzdGVyIHRvIHByZXZlbnQgdGhlIHRyYWNrZWQgd2ViIHBhZ2UgZnJvbSBiZWluZyBmcmFtZWQvaWZyYW1lZC5cbiAgICovXG4gIGtpbGxGcmFtZSgpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ2tpbGxGcmFtZSddKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEZvcmNlcyB0aGUgYnJvd3NlciB0byBsb2FkIHRoZSBsaXZlIFVSTCBpZiB0aGUgdHJhY2tlZCB3ZWIgcGFnZSBpcyBsb2FkZWQgZnJvbSBhIGxvY2FsIGZpbGVcbiAgICogKGUuZy4sIHNhdmVkIHRvIHNvbWVvbmUncyBkZXNrdG9wKS5cbiAgICpcbiAgICogQHBhcmFtIHVybCBVUkwgdG8gdHJhY2sgaW5zdGVhZCBvZiBmaWxlOi8vIFVSTHMuXG4gICAqL1xuICByZWRpcmVjdEZpbGUodXJsOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3JlZGlyZWN0RmlsZScsIHVybF0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVjb3JkcyBob3cgbG9uZyB0aGUgcGFnZSBoYXMgYmVlbiB2aWV3ZWQgaWYgdGhlIG1pbmltdW1WaXNpdExlbmd0aCBpcyBhdHRhaW5lZDtcbiAgICogdGhlIGhlYXJ0QmVhdERlbGF5IGRldGVybWluZXMgaG93IGZyZXF1ZW50bHkgdG8gdXBkYXRlIHRoZSBzZXJ2ZXIuXG4gICAqXG4gICAqIEBwYXJhbSBtaW5pbXVtVmlzaXRMZW5ndGggRHVyYXRpb24gYmVmb3JlIG5vdGlmeWluZyB0aGUgc2VydmVyIGZvciB0aGUgZHVyYXRpb24gb2YgdGhlIHZpc2l0IHRvIGEgcGFnZS5cbiAgICogQHBhcmFtIGhlYXJ0QmVhdERlbGF5IERlbGF5LCBpbiBzZWNvbmRzLCBiZXR3ZWVuIHR3byB1cGRhdGVzIHRvIHRoZSBzZXJ2ZXIuXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vZGV2ZWxvcGVyLm1hdG9tby5vcmcvZ3VpZGVzL3RyYWNraW5nLWphdmFzY3JpcHQtZ3VpZGUjYWNjdXJhdGVseS1tZWFzdXJlLXRoZS10aW1lLXNwZW50LW9uLWVhY2gtcGFnZX1cbiAgICovXG4gIHNldEhlYXJ0QmVhdFRpbWVyKG1pbmltdW1WaXNpdExlbmd0aDogbnVtYmVyLCBoZWFydEJlYXREZWxheTogbnVtYmVyKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydzZXRIZWFydEJlYXRUaW1lcicsIG1pbmltdW1WaXNpdExlbmd0aCwgaGVhcnRCZWF0RGVsYXldKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIDE2IGNoYXJhY3RlcnMgSUQgZm9yIHRoZSB2aXNpdG9yLlxuICAgKlxuICAgKiBAcmV0dXJucyBQcm9taXNlIGZvciB0aGUgdGhlIDE2IGNoYXJhY3RlcnMgSUQgZm9yIHRoZSB2aXNpdG9yLlxuICAgKi9cbiAgZ2V0VmlzaXRvcklkKCk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goW1xuICAgICAgICAgIGZ1bmN0aW9uICh0aGlzOiBhbnkpOiB2b2lkIHtcbiAgICAgICAgICAgIHJlc29sdmUodGhpcy5nZXRWaXNpdG9ySWQoKSk7XG4gICAgICAgICAgfSxcbiAgICAgICAgXSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgICByZWplY3QoZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSB2aXNpdG9yIGNvb2tpZSBjb250ZW50cyBpbiBhbiBhcnJheS5cbiAgICpcbiAgICogQHJldHVybnMgUHJvbWlzZSBmb3IgdGhlIGNvb2tpZSBjb250ZW50cyBpbiBhbiBhcnJheS5cbiAgICovXG4gIGdldFZpc2l0b3JJbmZvKCk6IFByb21pc2U8YW55W10+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbXG4gICAgICAgICAgZnVuY3Rpb24gKHRoaXM6IGFueSk6IHZvaWQge1xuICAgICAgICAgICAgcmVzb2x2ZSh0aGlzLmdldFZpc2l0b3JJbmZvKCkpO1xuICAgICAgICAgIH0sXG4gICAgICAgIF0pO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgdmlzaXRvciBhdHRyaWJ1dGlvbiBhcnJheSAoUmVmZXJlciBpbmZvcm1hdGlvbiBhbmQvb3IgQ2FtcGFpZ24gbmFtZSAmIGtleXdvcmQpLjxiciAvPlxuICAgKiBBdHRyaWJ1dGlvbiBpbmZvcm1hdGlvbiBpcyB1c2VkIGJ5IE1hdG9tbyB0byBjcmVkaXQgdGhlIGNvcnJlY3QgcmVmZXJyZXIgKGZpcnN0IG9yIGxhc3QgcmVmZXJyZXIpXG4gICAqIHVzZWQgd2hlbiBhIHVzZXIgdHJpZ2dlcnMgYSBnb2FsIGNvbnZlcnNpb24uXG4gICAqXG4gICAqIEByZXR1cm5zIFByb21pc2UgZm9yIHRoZSB2aXNpdG9yIGF0dHJpYnV0aW9uIGFycmF5IChSZWZlcmVyIGluZm9ybWF0aW9uIGFuZC9vciBDYW1wYWlnbiBuYW1lICYga2V5d29yZCkuXG4gICAqL1xuICBnZXRBdHRyaWJ1dGlvbkluZm8oKTogUHJvbWlzZTxhbnlbXT4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFtcbiAgICAgICAgICBmdW5jdGlvbiAodGhpczogYW55KTogdm9pZCB7XG4gICAgICAgICAgICByZXNvbHZlKHRoaXMuZ2V0QXR0cmlidXRpb25JbmZvKCkpO1xuICAgICAgICAgIH0sXG4gICAgICAgIF0pO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgYXR0cmlidXRpb24gY2FtcGFpZ24gbmFtZS5cbiAgICpcbiAgICogQHJldHVybnMgUHJvbWlzZSBmb3IgdGhlIHRoZSBhdHRyaWJ1dGlvbiBjYW1wYWlnbiBuYW1lLlxuICAgKi9cbiAgZ2V0QXR0cmlidXRpb25DYW1wYWlnbk5hbWUoKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbXG4gICAgICAgICAgZnVuY3Rpb24gKHRoaXM6IGFueSk6IHZvaWQge1xuICAgICAgICAgICAgcmVzb2x2ZSh0aGlzLmdldEF0dHJpYnV0aW9uQ2FtcGFpZ25OYW1lKCkpO1xuICAgICAgICAgIH0sXG4gICAgICAgIF0pO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgYXR0cmlidXRpb24gY2FtcGFpZ24ga2V5d29yZC5cbiAgICpcbiAgICogQHJldHVybnMgUHJvbWlzZSBmb3IgdGhlIGF0dHJpYnV0aW9uIGNhbXBhaWduIGtleXdvcmQuXG4gICAqL1xuICBnZXRBdHRyaWJ1dGlvbkNhbXBhaWduS2V5d29yZCgpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFtcbiAgICAgICAgICBmdW5jdGlvbiAodGhpczogYW55KTogdm9pZCB7XG4gICAgICAgICAgICByZXNvbHZlKHRoaXMuZ2V0QXR0cmlidXRpb25DYW1wYWlnbktleXdvcmQoKSk7XG4gICAgICAgICAgfSxcbiAgICAgICAgXSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgICByZWplY3QoZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBhdHRyaWJ1dGlvbiByZWZlcnJlciB0aW1lc3RhbXAuXG4gICAqXG4gICAqIEByZXR1cm5zIFByb21pc2UgZm9yIHRoZSBhdHRyaWJ1dGlvbiByZWZlcnJlciB0aW1lc3RhbXAgKGFzIHN0cmluZykuXG4gICAqL1xuICBnZXRBdHRyaWJ1dGlvblJlZmVycmVyVGltZXN0YW1wKCk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goW1xuICAgICAgICAgIGZ1bmN0aW9uICh0aGlzOiBhbnkpOiB2b2lkIHtcbiAgICAgICAgICAgIHJlc29sdmUodGhpcy5nZXRBdHRyaWJ1dGlvblJlZmVycmVyVGltZXN0YW1wKCkpO1xuICAgICAgICAgIH0sXG4gICAgICAgIF0pO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgYXR0cmlidXRpb24gcmVmZXJyZXIgVVJMLlxuICAgKlxuICAgKiBAcmV0dXJucyBQcm9taXNlIGZvciB0aGUgYXR0cmlidXRpb24gcmVmZXJyZXIgVVJMXG4gICAqL1xuICBnZXRBdHRyaWJ1dGlvblJlZmVycmVyVXJsKCk6IFByb21pc2U8c3RyaW5nPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goW1xuICAgICAgICAgIGZ1bmN0aW9uICh0aGlzOiBhbnkpOiB2b2lkIHtcbiAgICAgICAgICAgIHJlc29sdmUodGhpcy5nZXRBdHRyaWJ1dGlvblJlZmVycmVyVXJsKCkpO1xuICAgICAgICAgIH0sXG4gICAgICAgIF0pO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgVXNlciBJRCBzdHJpbmcgaWYgaXQgd2FzIHNldC5cbiAgICpcbiAgICogQHJldHVybnMgUHJvbWlzZSBmb3IgdGhlIFVzZXIgSUQgZm9yIHRoZSB2aXNpdG9yLlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL21hdG9tby5vcmcvZG9jcy91c2VyLWlkL3xNYXRvbW8gVXNlciBJRH1cbiAgICovXG4gIGdldFVzZXJJZCgpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFtcbiAgICAgICAgICBmdW5jdGlvbiAodGhpczogYW55KTogdm9pZCB7XG4gICAgICAgICAgICByZXNvbHZlKHRoaXMuZ2V0VXNlcklkKCkpO1xuICAgICAgICAgIH0sXG4gICAgICAgIF0pO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyBhIFVzZXIgSUQgdG8gdGhpcyB1c2VyIChzdWNoIGFzIGFuIGVtYWlsIGFkZHJlc3Mgb3IgYSB1c2VybmFtZSkuXG4gICAqXG4gICAqIEBwYXJhbSB1c2VySWQgVXNlciBJRCB0byBzZXQgZm9yIHRoZSBjdXJyZW50IHZpc2l0b3IuXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vbWF0b21vLm9yZy9kb2NzL3VzZXItaWQvfE1hdG9tbyBVc2VyIElEfVxuICAgKi9cbiAgc2V0VXNlcklkKHVzZXJJZDogc3RyaW5nKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydzZXRVc2VySWQnLCB1c2VySWRdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlc2V0cyB0aGUgVXNlciBJRCB3aGljaCBhbHNvIGdlbmVyYXRlcyBhIG5ldyBWaXNpdG9yIElELlxuICAgKlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL21hdG9tby5vcmcvZG9jcy91c2VyLWlkL3xNYXRvbW8gVXNlciBJRH1cbiAgICovXG4gIHJlc2V0VXNlcklkKCk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsncmVzZXRVc2VySWQnXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIGEgY3VzdG9tIHZhcmlhYmxlLlxuICAgKlxuICAgKiBAcGFyYW0gaW5kZXggSW5kZXgsIHRoZSBudW1iZXIgZnJvbSAxIHRvIDUgd2hlcmUgdGhpcyBjdXN0b20gdmFyaWFibGUgbmFtZSBpcyBzdG9yZWQgZm9yIHRoZSBjdXJyZW50IHBhZ2Ugdmlldy5cbiAgICogQHBhcmFtIG5hbWUgTmFtZSwgdGhlIG5hbWUgb2YgdGhlIHZhcmlhYmxlLCBmb3IgZXhhbXBsZTogQ2F0ZWdvcnksIFN1Yi1jYXRlZ29yeSwgVXNlclR5cGUuXG4gICAqIEBwYXJhbSB2YWx1ZSBWYWx1ZSwgZm9yIGV4YW1wbGU6IFwiU3BvcnRzXCIsIFwiTmV3c1wiLCBcIldvcmxkXCIsIFwiQnVzaW5lc3NcIuKAplxuICAgKiBAcGFyYW0gc2NvcGUgU2NvcGUgb2YgdGhlIGN1c3RvbSB2YXJpYWJsZTo8YnIgLz5cbiAgICogLSAncGFnZScgbWVhbnMgdGhlIGN1c3RvbSB2YXJpYWJsZSBhcHBsaWVzIHRvIHRoZSBjdXJyZW50IHBhZ2Ugdmlldy5cbiAgICogLSAndmlzaXQnIG1lYW5zIHRoZSBjdXN0b20gdmFyaWFibGUgYXBwbGllcyB0byB0aGUgY3VycmVudCB2aXNpdG9yLlxuICAgKiAtICdldmVudCcgbWVhbnMgdGhlIGN1c3RvbSB2YXJpYWJsZSBhcHBsaWVzIHRvIHRoZSBjdXJyZW50IGV2ZW50LlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL21hdG9tby5vcmcvZG9jcy9jdXN0b20tdmFyaWFibGVzL3xDdXN0b20gVmFyaWFibGVzfVxuICAgKi9cbiAgc2V0Q3VzdG9tVmFyaWFibGUoaW5kZXg6IG51bWJlciwgbmFtZTogc3RyaW5nLCB2YWx1ZTogc3RyaW5nLCBzY29wZTogTWF0b21vU2NvcGUpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3NldEN1c3RvbVZhcmlhYmxlJywgaW5kZXgsIG5hbWUsIHZhbHVlLCBzY29wZV0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRGVsZXRlcyBhIGN1c3RvbSB2YXJpYWJsZS5cbiAgICpcbiAgICogQHBhcmFtIGluZGV4IEluZGV4IG9mIHRoZSBjdXN0b20gdmFyaWFibGUgdG8gZGVsZXRlLlxuICAgKiBAcGFyYW0gc2NvcGUgU2NvcGUgb2YgdGhlIGN1c3RvbSB2YXJpYWJsZSB0byBkZWxldGUuXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vbWF0b21vLm9yZy9kb2NzL2N1c3RvbS12YXJpYWJsZXMvfEN1c3RvbSBWYXJpYWJsZXN9XG4gICAqL1xuICBkZWxldGVDdXN0b21WYXJpYWJsZShpbmRleDogbnVtYmVyLCBzY29wZTogTWF0b21vU2NvcGUpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ2RlbGV0ZUN1c3RvbVZhcmlhYmxlJywgaW5kZXgsIHNjb3BlXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGVzIGFsbCBjdXN0b20gdmFyaWFibGVzLlxuICAgKlxuICAgKiBAcGFyYW0gc2NvcGUgU2NvcGUgb2YgdGhlIGN1c3RvbSB2YXJpYWJsZXMgdG8gZGVsZXRlLlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL21hdG9tby5vcmcvZG9jcy9jdXN0b20tdmFyaWFibGVzL3xDdXN0b20gVmFyaWFibGVzfVxuICAgKi9cbiAgZGVsZXRlQ3VzdG9tVmFyaWFibGVzKHNjb3BlOiBNYXRvbW9TY29wZSk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnZGVsZXRlQ3VzdG9tVmFyaWFibGVzJywgc2NvcGVdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlcyBhIGN1c3RvbSB2YXJpYWJsZS5cbiAgICpcbiAgICogQHBhcmFtIGluZGV4IEluZGV4IG9mIHRoZSBjdXN0b20gdmFyaWFibGUgdG8gcmV0cmlldmUuXG4gICAqIEBwYXJhbSBzY29wZSBTY29wZSBvZiB0aGUgY3VzdG9tIHZhcmlhYmxlIHRvIHJldHJpZXZlLlxuICAgKiBAcmV0dXJucyBQcm9taXNlIGZvciB0aGUgdmFsdWUgb2YgY3VzdG9tIHZhcmlhYmxlLlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL21hdG9tby5vcmcvZG9jcy9jdXN0b20tdmFyaWFibGVzL3xDdXN0b20gVmFyaWFibGVzfVxuICAgKi9cbiAgZ2V0Q3VzdG9tVmFyaWFibGUoaW5kZXg6IG51bWJlciwgc2NvcGU6IE1hdG9tb1Njb3BlKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbXG4gICAgICAgICAgZnVuY3Rpb24gKHRoaXM6IGFueSk6IHZvaWQge1xuICAgICAgICAgICAgcmVzb2x2ZSh0aGlzLmdldEN1c3RvbVZhcmlhYmxlKGluZGV4LCBzY29wZSkpO1xuICAgICAgICAgIH0sXG4gICAgICAgIF0pO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogV2hlbiBjYWxsZWQgdGhlbiB0aGUgQ3VzdG9tIFZhcmlhYmxlcyBvZiBzY29wZSAndmlzaXQnIHdpbGwgYmUgc3RvcmVkIChwZXJzaXN0ZWQpIGluIGEgZmlyc3QgcGFydHkgY29va2llXG4gICAqIGZvciB0aGUgZHVyYXRpb24gb2YgdGhlIHZpc2l0LjxiciAvPlxuICAgKiBUaGlzIGlzIHVzZWZ1bCBpZiB5b3Ugd2FudCB0byBjYWxsIGdldEN1c3RvbVZhcmlhYmxlIGxhdGVyIGluIHRoZSB2aXNpdC48YnIgLz5cbiAgICogKGJ5IGRlZmF1bHQgY3VzdG9tIHZhcmlhYmxlcyBhcmUgbm90IHN0b3JlZCBvbiB0aGUgdmlzaXRvcidzIGNvbXB1dGVyLilcbiAgICpcbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9tYXRvbW8ub3JnL2RvY3MvY3VzdG9tLXZhcmlhYmxlcy98Q3VzdG9tIFZhcmlhYmxlc31cbiAgICovXG4gIHN0b3JlQ3VzdG9tVmFyaWFibGVzSW5Db29raWUoKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydzdG9yZUN1c3RvbVZhcmlhYmxlc0luQ29va2llJ10pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2V0cyBhIGN1c3RvbSBkaW1lbnNpb24uPGJyIC8+XG4gICAqIChyZXF1aXJlcyBNYXRvbW8gMi4xNS4xICsgQ3VzdG9tIERpbWVuc2lvbnMgcGx1Z2luKVxuICAgKlxuICAgKiBAcGFyYW0gY3VzdG9tRGltZW5zaW9uSWQgSUQgb2YgdGhlIGN1c3RvbSBkaW1lbnNpb24gdG8gc2V0LlxuICAgKiBAcGFyYW0gY3VzdG9tRGltZW5zaW9uVmFsdWUgVmFsdWUgdG8gYmUgc2V0LlxuICAgKiBAc2VlIHtAbGluayBodHRwczovL3BsdWdpbnMucGl3aWsub3JnL0N1c3RvbURpbWVuc2lvbnN8Q3VzdG9tIERpbWVuc2lvbnN9XG4gICAqL1xuICBzZXRDdXN0b21EaW1lbnNpb24oY3VzdG9tRGltZW5zaW9uSWQ6IG51bWJlciwgY3VzdG9tRGltZW5zaW9uVmFsdWU6IHN0cmluZyk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnc2V0Q3VzdG9tRGltZW5zaW9uJywgY3VzdG9tRGltZW5zaW9uSWQsIGN1c3RvbURpbWVuc2lvblZhbHVlXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGVzIGEgY3VzdG9tIGRpbWVuc2lvbi48YnIgLz5cbiAgICogKHJlcXVpcmVzIE1hdG9tbyAyLjE1LjEgKyBDdXN0b20gRGltZW5zaW9ucyBwbHVnaW4pXG4gICAqXG4gICAqIEBwYXJhbSBjdXN0b21EaW1lbnNpb25JZCBJRCBvZiB0aGUgY3VzdG9tIGRpbWVuc2lvbiB0byBkZWxldGUuXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vcGx1Z2lucy5waXdpay5vcmcvQ3VzdG9tRGltZW5zaW9uc3xDdXN0b20gRGltZW5zaW9uc31cbiAgICovXG4gIGRlbGV0ZUN1c3RvbURpbWVuc2lvbihjdXN0b21EaW1lbnNpb25JZDogbnVtYmVyKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydkZWxldGVDdXN0b21EaW1lbnNpb24nLCBjdXN0b21EaW1lbnNpb25JZF0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmV0cmlldmUgYSBjdXN0b20gZGltZW5zaW9uLjxiciAvPlxuICAgKiAocmVxdWlyZXMgTWF0b21vIDIuMTUuMSArIEN1c3RvbSBEaW1lbnNpb25zIHBsdWdpbilcbiAgICpcbiAgICogQHBhcmFtIGN1c3RvbURpbWVuc2lvbklkIElEIG9mIHRoZSBjdXN0b20gZGltZW5zaW9uIHRvIHJldHJpZXZlLlxuICAgKiBAcmV0dXJucyBQcm9taXNlIGZvciB0aGUgdmFsdWUgZm9yIHRoZSByZXF1ZXN0ZWQgY3VzdG9tIGRpbWVuc2lvbi5cbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9wbHVnaW5zLnBpd2lrLm9yZy9DdXN0b21EaW1lbnNpb25zfEN1c3RvbSBEaW1lbnNpb25zfVxuICAgKi9cbiAgZ2V0Q3VzdG9tRGltZW5zaW9uKGN1c3RvbURpbWVuc2lvbklkOiBudW1iZXIpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFtcbiAgICAgICAgICBmdW5jdGlvbiAodGhpczogYW55KTogdm9pZCB7XG4gICAgICAgICAgICByZXNvbHZlKHRoaXMuZ2V0Q3VzdG9tRGltZW5zaW9uKGN1c3RvbURpbWVuc2lvbklkKSk7XG4gICAgICAgICAgfSxcbiAgICAgICAgXSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgICByZWplY3QoZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIGNhbXBhaWduIG5hbWUgcGFyYW1ldGVyKHMpLlxuICAgKlxuICAgKiBAcGFyYW0gbmFtZSBOYW1lIG9mIHRoZSBjYW1wYWlnblxuICAgKiBAc2VlIHtAbGluayBodHRwczovL21hdG9tby5vcmcvZG9jcy90cmFja2luZy1jYW1wYWlnbnMvfENhbXBhaWduc31cbiAgICovXG4gIHNldENhbXBhaWduTmFtZUtleShuYW1lOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3NldENhbXBhaWduTmFtZUtleScsIG5hbWVdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgY2FtcGFpZ24ga2V5d29yZCBwYXJhbWV0ZXIocykuXG4gICAqXG4gICAqIEBwYXJhbSBrZXl3b3JkIEtleXdvcmQgcGFyYW1ldGVyKHMpIG9mIHRoZSBjYW1wYWlnbi5cbiAgICogQHNlZSB7QGxpbmsgaHR0cHM6Ly9tYXRvbW8ub3JnL2RvY3MvdHJhY2tpbmctY2FtcGFpZ25zL3xDYW1wYWlnbnN9XG4gICAqL1xuICBzZXRDYW1wYWlnbktleXdvcmRLZXkoa2V5d29yZDogc3RyaW5nKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydzZXRDYW1wYWlnbktleXdvcmRLZXknLCBrZXl3b3JkXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIGlmIG9yIG5vdCB0byBhdHRyaWJ1dGUgYSBjb252ZXJzaW9uIHRvIHRoZSBmaXJzdCByZWZlcnJlci48YnIgLz5cbiAgICogQnkgZGVmYXVsdCwgY29udmVyc2lvbiBpcyBhdHRyaWJ1dGVkIHRvIHRoZSBtb3N0IHJlY2VudCByZWZlcnJlci5cbiAgICpcbiAgICogQHBhcmFtIGNvbnZlcnNpb25Ub0ZpcnN0UmVmZXJyZXIgSWYgdHJ1ZSwgTWF0b21vIHdpbGwgYXR0cmlidXRlIHRoZSBHb2FsIGNvbnZlcnNpb24gdG8gdGhlIGZpcnN0IHJlZmVycmVyIHVzZWRcbiAgICogaW5zdGVhZCBvZiB0aGUgbGFzdCBvbmUuXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vbWF0b21vLm9yZy9kb2NzL3RyYWNraW5nLWNhbXBhaWducy98Q2FtcGFpZ25zfVxuICAgKiBAc2VlIHtAbGluayBodHRwczovL21hdG9tby5vcmcvZmFxL2dlbmVyYWwvZmFxXzEwNi8jZmFxXzEwNnxDb252ZXJzaW9ucyB0byB0aGUgZmlyc3QgcmVmZXJyZXJ9XG4gICAqL1xuICBzZXRDb252ZXJzaW9uQXR0cmlidXRpb25GaXJzdFJlZmVycmVyKGNvbnZlcnNpb25Ub0ZpcnN0UmVmZXJyZXI6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3NldENvbnZlcnNpb25BdHRyaWJ1dGlvbkZpcnN0UmVmZXJyZXInLCBjb252ZXJzaW9uVG9GaXJzdFJlZmVycmVyXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSBjdXJyZW50IHBhZ2UgdmlldyBhcyBhIHByb2R1Y3Qgb3IgY2F0ZWdvcnkgcGFnZSB2aWV3LjxiciAvPlxuICAgKiBXaGVuIHlvdSBjYWxsIHNldEVjb21tZXJjZVZpZXcsIGl0IG11c3QgYmUgZm9sbG93ZWQgYnkgYSBjYWxsIHRvIHRyYWNrUGFnZVZpZXcgdG8gcmVjb3JkIHRoZSBwcm9kdWN0IG9yIGNhdGVnb3J5IHBhZ2Ugdmlldy5cbiAgICpcbiAgICogQHBhcmFtIHByb2R1Y3RTS1UgU0tVIG9mIHRoZSB2aWV3ZWQgcHJvZHVjdC5cbiAgICogQHBhcmFtIHByb2R1Y3ROYW1lIE5hbWUgb2YgdGhlIHZpZXdlZCBwcm9kdWN0LlxuICAgKiBAcGFyYW0gcHJvZHVjdENhdGVnb3J5IENhdGVnb3J5IG9mIHRoZSB2aWV3ZWQgcHJvZHVjdC5cbiAgICogQHBhcmFtIHByaWNlIFByaWNlIG9mIHRoZSB2aWV3ZWQgcHJvZHVjdC5cbiAgICovXG4gIHNldEVjb21tZXJjZVZpZXcoXG4gICAgcHJvZHVjdFNLVTogc3RyaW5nLFxuICAgIHByb2R1Y3ROYW1lOiBzdHJpbmcsXG4gICAgcHJvZHVjdENhdGVnb3J5OiBzdHJpbmcsXG4gICAgcHJpY2U6IG51bWJlclxuICApOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3NldEVjb21tZXJjZVZpZXcnLCBwcm9kdWN0U0tVLCBwcm9kdWN0TmFtZSwgcHJvZHVjdENhdGVnb3J5LCBwcmljZV0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhIHByb2R1Y3QgaW50byB0aGUgZUNvbW1lcmNlIG9yZGVyLjxiciAvPlxuICAgKiBNdXN0IGJlIGNhbGxlZCBmb3IgZWFjaCBwcm9kdWN0IGluIHRoZSBvcmRlci5cbiAgICpcbiAgICogQHBhcmFtIHByb2R1Y3RTS1UgU0tVIG9mIHRoZSBwcm9kdWN0IHRvIGFkZC5cbiAgICogQHBhcmFtIFtwcm9kdWN0TmFtZV0gT3B0aW9uYWwgbmFtZSBvZiB0aGUgcHJvZHVjdCB0byBhZGQuXG4gICAqIEBwYXJhbSBbcHJvZHVjdENhdGVnb3J5XSBPcHRpb25hbCBjYXRlZ29yeSBvZiB0aGUgcHJvZHVjdCB0byBhZGQuXG4gICAqIEBwYXJhbSBbcHJpY2VdIE9wdGlvbmFsIHByaWNlIG9mIHRoZSBwcm9kdWN0IHRvIGFkZC5cbiAgICogQHBhcmFtIFtxdWFudGl0eV0gT3B0aW9uYWwgcXVhbnRpdHkgb2YgdGhlIHByb2R1Y3QgdG8gYWRkLlxuICAgKi9cbiAgYWRkRWNvbW1lcmNlSXRlbShcbiAgICBwcm9kdWN0U0tVOiBzdHJpbmcsXG4gICAgcHJvZHVjdE5hbWU/OiBzdHJpbmcsXG4gICAgcHJvZHVjdENhdGVnb3J5Pzogc3RyaW5nLFxuICAgIHByaWNlPzogbnVtYmVyLFxuICAgIHF1YW50aXR5PzogbnVtYmVyXG4gICk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBhcmdzOiBhbnlbXSA9IFtwcm9kdWN0U0tVXTtcbiAgICAgIGlmICghIXByb2R1Y3ROYW1lKSB7XG4gICAgICAgIGFyZ3MucHVzaChwcm9kdWN0TmFtZSk7XG4gICAgICAgIGlmICghIXByb2R1Y3RDYXRlZ29yeSkge1xuICAgICAgICAgIGFyZ3MucHVzaChwcm9kdWN0Q2F0ZWdvcnkpO1xuICAgICAgICAgIGlmICh0eXBlb2YgcHJpY2UgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICBhcmdzLnB1c2gocHJpY2UpO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBxdWFudGl0eSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgICAgYXJncy5wdXNoKHF1YW50aXR5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydhZGRFY29tbWVyY2VJdGVtJywgLi4uYXJnc10pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVtb3ZlcyB0aGUgc3BlY2lmaWVkIHByb2R1Y3QgZnJvbSB0aGUgdW50cmFja2VkIGVjb21tZXJjZSBvcmRlci5cbiAgICpcbiAgICogQHBhcmFtIHByb2R1Y3RTS1UgU0tVIG9mIHRoZSBwcm9kdWN0IHRvIHJlbW92ZS5cbiAgICovXG4gIHJlbW92ZUVjb21tZXJjZUl0ZW0ocHJvZHVjdFNLVTogc3RyaW5nKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGFyZ3M6IGFueVtdID0gW3Byb2R1Y3RTS1VdO1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3JlbW92ZUVjb21tZXJjZUl0ZW0nLCAuLi5hcmdzXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmVzIGFsbCBwcm9kdWN0cyBpbiB0aGUgdW50cmFja2VkIGVjb21tZXJjZSBvcmRlci48YnIgLz5cbiAgICogTm90ZTogdGhpcyBpcyBkb25lIGF1dG9tYXRpY2FsbHkgYWZ0ZXIgdHJhY2tFY29tbWVyY2VPcmRlcigpIGlzIGNhbGxlZC5cbiAgICovXG4gIGNsZWFyRWNvbW1lcmNlQ2FydCgpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ2NsZWFyRWNvbW1lcmNlQ2FydCddKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYWxsIGVjb21tZXJjZSBpdGVtcyBjdXJyZW50bHkgaW4gdGhlIHVudHJhY2tlZCBlY29tbWVyY2Ugb3JkZXIuXG4gICAqIFRoZSByZXR1cm5lZCBhcnJheSB3aWxsIGJlIGEgY29weSwgc28gY2hhbmdpbmcgaXQgd29uJ3QgYWZmZWN0IHRoZSBlY29tbWVyY2Ugb3JkZXIuPGJyIC8+XG4gICAqIFRvIGFmZmVjdCB3aGF0IGdldHMgdHJhY2tlZCwgdXNlIHRoZSBhZGRFY29tbWVyY2VJdGVtKCkvcmVtb3ZlRWNvbW1lcmNlSXRlbSgpL2NsZWFyRWNvbW1lcmNlQ2FydCgpIG1ldGhvZHMuPGJyIC8+XG4gICAqIFVzZSB0aGlzIG1ldGhvZCB0byBzZWUgd2hhdCB3aWxsIGJlIHRyYWNrZWQgYmVmb3JlIHlvdSB0cmFjayBhbiBvcmRlciBvciBjYXJ0IHVwZGF0ZS5cbiAgICovXG4gIGdldEVjb21tZXJjZUl0ZW1zKCk6IFByb21pc2U8XG4gICAgQXJyYXk8e1xuICAgICAgcHJvZHVjdFNLVTogc3RyaW5nO1xuICAgICAgcHJvZHVjdE5hbWU/OiBzdHJpbmc7XG4gICAgICBwcm9kdWN0Q2F0ZWdvcnk/OiBzdHJpbmc7XG4gICAgICBwcmljZT86IG51bWJlcjtcbiAgICAgIHF1YW50aXR5PzogbnVtYmVyO1xuICAgIH0+XG4gID4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFtcbiAgICAgICAgICBmdW5jdGlvbiAodGhpczogYW55KTogdm9pZCB7XG4gICAgICAgICAgICByZXNvbHZlKHRoaXMuZ2V0RWNvbW1lcmNlSXRlbXMoKSk7XG4gICAgICAgICAgfSxcbiAgICAgICAgXSk7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgICByZWplY3QoZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUcmFja3MgYSBzaG9wcGluZyBjYXJ0LjxiciAvPlxuICAgKiBDYWxsIHRoaXMgZnVuY3Rpb24gZXZlcnkgdGltZSBhIHVzZXIgaXMgYWRkaW5nLCB1cGRhdGluZyBvciBkZWxldGluZyBhIHByb2R1Y3QgZnJvbSB0aGUgY2FydC5cbiAgICpcbiAgICogQHBhcmFtIGdyYW5kVG90YWwgR3JhbmQgdG90YWwgb2YgdGhlIHNob3BwaW5nIGNhcnQuXG4gICAqL1xuICB0cmFja0Vjb21tZXJjZUNhcnRVcGRhdGUoZ3JhbmRUb3RhbDogbnVtYmVyKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWyd0cmFja0Vjb21tZXJjZUNhcnRVcGRhdGUnLCBncmFuZFRvdGFsXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUcmFja3MgYW4gRWNvbW1lcmNlIG9yZGVyLCBpbmNsdWRpbmcgYW55IGVDb21tZXJjZSBpdGVtIHByZXZpb3VzbHkgYWRkZWQgdG8gdGhlIG9yZGVyLjxiciAvPlxuICAgKiBvcmRlcklkIGFuZCBncmFuZFRvdGFsIChpZS5yZXZlbnVlKSBhcmUgcmVxdWlyZWQgcGFyYW1ldGVycy5cbiAgICpcbiAgICogQHBhcmFtIG9yZGVySWQgSUQgb2YgdGhlIHRyYWNrZWQgb3JkZXIuXG4gICAqIEBwYXJhbSBncmFuZFRvdGFsIEdyYW5kIHRvdGFsIG9mIHRoZSB0cmFja2VkIG9yZGVyLlxuICAgKiBAcGFyYW0gW3N1YlRvdGFsXSBTdWIgdG90YWwgb2YgdGhlIHRyYWNrZWQgb3JkZXIuXG4gICAqIEBwYXJhbSBbdGF4XSBUYXhlcyBmb3IgdGhlIHRyYWNrZWQgb3JkZXIuXG4gICAqIEBwYXJhbSBbc2hpcHBpbmddIFNoaXBwaW5nIGZlZXMgZm9yIHRoZSB0cmFja2VkIG9yZGVyLlxuICAgKiBAcGFyYW0gW2Rpc2NvdW50XSBEaXNjb3VudCBncmFudGVkIGZvciB0aGUgdHJhY2tlZCBvcmRlci5cbiAgICovXG4gIHRyYWNrRWNvbW1lcmNlT3JkZXIoXG4gICAgb3JkZXJJZDogc3RyaW5nLFxuICAgIGdyYW5kVG90YWw6IG51bWJlcixcbiAgICBzdWJUb3RhbD86IG51bWJlcixcbiAgICB0YXg/OiBudW1iZXIsXG4gICAgc2hpcHBpbmc/OiBudW1iZXIsXG4gICAgZGlzY291bnQ/OiBudW1iZXIgfCBib29sZWFuXG4gICk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBhcmdzOiBhbnlbXSA9IFtvcmRlcklkLCBncmFuZFRvdGFsXTtcbiAgICAgIGlmICh0eXBlb2Ygc3ViVG90YWwgPT09ICdudW1iZXInKSB7XG4gICAgICAgIGFyZ3MucHVzaChzdWJUb3RhbCk7XG4gICAgICAgIGlmICh0eXBlb2YgdGF4ID09PSAnbnVtYmVyJykge1xuICAgICAgICAgIGFyZ3MucHVzaCh0YXgpO1xuICAgICAgICAgIGlmICh0eXBlb2Ygc2hpcHBpbmcgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICBhcmdzLnB1c2goc2hpcHBpbmcpO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBkaXNjb3VudCA9PT0gJ251bWJlcicgfHwgdHlwZW9mIGRpc2NvdW50ID09PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgYXJncy5wdXNoKGRpc2NvdW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWyd0cmFja0Vjb21tZXJjZU9yZGVyJywgLi4uYXJnc10pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyB4eHh4KCk6IHZvaWQge1xuICAvLyAgIHRyeSB7XG4gIC8vICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnSGVhdG1hcFNlc3Npb25SZWNvcmRpbmc6OmRpc2FibGVDYXB0dXJlS2V5c3Ryb2tlcyddKTtcbiAgLy8gICB9IGNhdGNoIChlKSB7XG4gIC8vICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gIC8vICAgICAgIHRocm93IGU7XG4gIC8vICAgICB9XG4gIC8vICAgfVxuICAvLyB9XG4gIC8vIHh4eHgoKTogdm9pZCB7XG4gIC8vICAgdHJ5IHtcbiAgLy8gICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydIZWF0bWFwU2Vzc2lvblJlY29yZGluZzo6ZGlzYWJsZUF1dG9EZXRlY3ROZXdQYWdlVmlldyddKTtcbiAgLy8gICB9IGNhdGNoIChlKSB7XG4gIC8vICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gIC8vICAgICAgIHRocm93IGU7XG4gIC8vICAgICB9XG4gIC8vICAgfVxuICAvLyB9XG4gIC8vIHh4eHgoKTogdm9pZCB7XG4gIC8vICAgdHJ5IHtcbiAgLy8gICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydlbmFibGVBdXRvRGV0ZWN0TmV3UGFnZVZpZXcnXSk7XG4gIC8vICAgfSBjYXRjaCAoZSkge1xuICAvLyAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAvLyAgICAgICB0aHJvdyBlO1xuICAvLyAgICAgfVxuICAvLyAgIH1cbiAgLy8gfVxuICAvLyB4eHh4KCk6IHZvaWQge1xuICAvLyAgIHRyeSB7XG4gIC8vICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnZGlzYWJsZVJlY29yZE1vdmVtZW50cyddKTtcbiAgLy8gICB9IGNhdGNoIChlKSB7XG4gIC8vICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gIC8vICAgICAgIHRocm93IGU7XG4gIC8vICAgICB9XG4gIC8vICAgfVxuICAvLyB9XG4gIC8vIHh4eHgoKTogdm9pZCB7XG4gIC8vICAgdHJ5IHtcbiAgLy8gICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydlbmFibGVSZWNvcmRNb3ZlbWVudHMnXSk7XG4gIC8vICAgfSBjYXRjaCAoZSkge1xuICAvLyAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAvLyAgICAgICB0aHJvdyBlO1xuICAvLyAgICAgfVxuICAvLyAgIH1cbiAgLy8gfVxuICAvLyB4eHh4KCk6IHZvaWQge1xuICAvLyAgIHRyeSB7XG4gIC8vICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnc2V0TmV3UGFnZVZpZXcgKyBmZXRjaENvbmZpZyddKTtcbiAgLy8gICB9IGNhdGNoIChlKSB7XG4gIC8vICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gIC8vICAgICAgIHRocm93IGU7XG4gIC8vICAgICB9XG4gIC8vICAgfVxuICAvLyB9XG4gIC8vIHh4eHgoKTogdm9pZCB7XG4gIC8vICAgdHJ5IHtcbiAgLy8gICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydzZXRNYXhDYXB0dXJlVGltZSArIG1heFRpbWVJblNlY29uZHMnXSk7XG4gIC8vICAgfSBjYXRjaCAoZSkge1xuICAvLyAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAvLyAgICAgICB0aHJvdyBlO1xuICAvLyAgICAgfVxuICAvLyAgIH1cbiAgLy8gfVxuICAvLyB4eHh4KCk6IHZvaWQge1xuICAvLyAgIHRyeSB7XG4gIC8vICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnc2V0TWF4VGV4dElucHV0TGVuZ3RoICsgbWF4TGVuZ3RoQ2hhcmFjdGVycyddKTtcbiAgLy8gICB9IGNhdGNoIChlKSB7XG4gIC8vICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gIC8vICAgICAgIHRocm93IGU7XG4gIC8vICAgICB9XG4gIC8vICAgfVxuICAvLyB9XG4gIC8vIHh4eHgoKTogdm9pZCB7XG4gIC8vICAgdHJ5IHtcbiAgLy8gICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydkaXNhYmxlQ2FwdHVyZUtleXN0cm9rZXMnXSk7XG4gIC8vICAgfSBjYXRjaCAoZSkge1xuICAvLyAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAvLyAgICAgICB0aHJvdyBlO1xuICAvLyAgICAgfVxuICAvLyAgIH1cbiAgLy8gfVxuICAvLyB4eHh4KCk6IHZvaWQge1xuICAvLyAgIHRyeSB7XG4gIC8vICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnZW5hYmxlQ2FwdHVyZUtleXN0cm9rZXMnXSk7XG4gIC8vICAgfSBjYXRjaCAoZSkge1xuICAvLyAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAvLyAgICAgICB0aHJvdyBlO1xuICAvLyAgICAgfVxuICAvLyAgIH1cbiAgLy8gfVxuICAvLyB4eHh4KCk6IHZvaWQge1xuICAvLyAgIHRyeSB7XG4gIC8vICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnc2V0VHJpZ2dlciArIHNob3VsZFRyaWdnZXJGdW5jdGlvbiddKTtcbiAgLy8gICB9IGNhdGNoIChlKSB7XG4gIC8vICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gIC8vICAgICAgIHRocm93IGU7XG4gIC8vICAgICB9XG4gIC8vICAgfVxuICAvLyB9XG4gIC8vIHh4eHgoKTogdm9pZCB7XG4gIC8vICAgdHJ5IHtcbiAgLy8gICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydtYXRjaFRyYWNrZXJVcmwnXSk7XG4gIC8vICAgfSBjYXRjaCAoZSkge1xuICAvLyAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAvLyAgICAgICB0aHJvdyBlO1xuICAvLyAgICAgfVxuICAvLyAgIH1cbiAgLy8gfVxuICAvLyB4eHh4KCk6IHZvaWQge1xuICAvLyAgIHRyeSB7XG4gIC8vICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnZGlzYWJsZSddKTtcbiAgLy8gICB9IGNhdGNoIChlKSB7XG4gIC8vICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gIC8vICAgICAgIHRocm93IGU7XG4gIC8vICAgICB9XG4gIC8vICAgfVxuICAvLyB9XG4gIC8vIHh4eHgoKTogdm9pZCB7XG4gIC8vICAgdHJ5IHtcbiAgLy8gICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydlbmFibGUnXSk7XG4gIC8vICAgfSBjYXRjaCAoZSkge1xuICAvLyAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAvLyAgICAgICB0aHJvdyBlO1xuICAvLyAgICAgfVxuICAvLyAgIH1cbiAgLy8gfVxuICAvLyB4eHh4KCk6IHZvaWQge1xuICAvLyAgIHRyeSB7XG4gIC8vICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnaXNFbmFibGVkJ10pO1xuICAvLyAgIH0gY2F0Y2ggKGUpIHtcbiAgLy8gICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgLy8gICAgICAgdGhyb3cgZTtcbiAgLy8gICAgIH1cbiAgLy8gICB9XG4gIC8vIH1cbiAgLy8geHh4eCgpOiB2b2lkIHtcbiAgLy8gICB0cnkge1xuICAvLyAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ2VuYWJsZURlYnVnTW9kZSddKTtcbiAgLy8gICB9IGNhdGNoIChlKSB7XG4gIC8vICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gIC8vICAgICAgIHRocm93IGU7XG4gIC8vICAgICB9XG4gIC8vICAgfVxuICAvLyB9XG4gIC8vIHh4eHgoKTogdm9pZCB7XG4gIC8vICAgdHJ5IHtcbiAgLy8gICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydzZXRNYXRvbW9UcmFja2VycyddKTtcbiAgLy8gICB9IGNhdGNoIChlKSB7XG4gIC8vICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gIC8vICAgICAgIHRocm93IGU7XG4gIC8vICAgICB9XG4gIC8vICAgfVxuICAvLyB9XG4gIC8vIHh4eHgoKTogdm9pZCB7XG4gIC8vICAgdHJ5IHtcbiAgLy8gICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydnZXRQaXdpa1RyYWNrZXJzJ10pO1xuICAvLyAgIH0gY2F0Y2ggKGUpIHtcbiAgLy8gICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgLy8gICAgICAgdGhyb3cgZTtcbiAgLy8gICAgIH1cbiAgLy8gICB9XG4gIC8vIH1cblxuICAvKipcbiAgICogQnkgZGVmYXVsdCB0aGUgTWF0b21vIHRyYWNrZXIgYXNzdW1lcyBjb25zZW50IHRvIHRyYWNraW5nLlxuICAgKiBUbyBjaGFuZ2UgdGhpcyBiZWhhdmlvciBzbyBub3RoaW5nIGlzIHRyYWNrZWQgdW50aWwgYSB1c2VyIGNvbnNlbnRzLCB5b3UgbXVzdCBjYWxsIHJlcXVpcmVDb25zZW50LlxuICAgKi9cbiAgcmVxdWlyZUNvbnNlbnQoKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydyZXF1aXJlQ29uc2VudCddKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlcXVpcmUgdXNlciBjb29raWUgY29uc2VudCBiZWZvcmUgc3RvcmluZyBhbmQgdXNpbmcgYW55IGNvb2tpZXMuXG4gICAqL1xuICByZXF1aXJlQ29va2llQ29uc2VudCgpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3JlcXVpcmVDb29raWVDb25zZW50J10pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTWFya3MgdGhhdCB0aGUgY3VycmVudCB1c2VyIGhhcyBjb25zZW50ZWQuPGJyIC8+XG4gICAqIFRoZSBjb25zZW50IGlzIG9uZS10aW1lIG9ubHksIHNvIGluIGEgc3Vic2VxdWVudCBicm93c2VyIHNlc3Npb24sIHRoZSB1c2VyIHdpbGwgaGF2ZSB0byBjb25zZW50IGFnYWluLjxiciAvPlxuICAgKiBUbyByZW1lbWJlciBjb25zZW50LCBzZWUgdGhlIG1ldGhvZCBiZWxvdzogcmVtZW1iZXJDb25zZW50R2l2ZW4uXG4gICAqL1xuICBzZXRDb25zZW50R2l2ZW4oKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydzZXRDb25zZW50R2l2ZW4nXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBNYXJrcyB0aGF0IHRoZSBjdXJyZW50IHVzZXIgaGFzIGNvbnNlbnRlZCB0byBzdG9yZSBhbmQgdXNlIGNvb2tpZXMuPGJyIC8+XG4gICAqIFRoZSBjb25zZW50IGlzIG9uZS10aW1lIG9ubHksIHNvIGluIGEgc3Vic2VxdWVudCBicm93c2VyIHNlc3Npb24sIHRoZSB1c2VyIHdpbGwgaGF2ZSB0byBjb25zZW50IGFnYWluLjxiciAvPlxuICAgKiBUbyByZW1lbWJlciBjb25zZW50LCBzZWUgdGhlIG1ldGhvZCBiZWxvdzogcmVtZW1iZXJDb29raWVDb25zZW50R2l2ZW4uXG4gICAqL1xuICBzZXRDb29raWVDb25zZW50R2l2ZW4oKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydzZXRDb29raWVDb25zZW50R2l2ZW4nXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBNYXJrcyB0aGF0IHRoZSBjdXJyZW50IHVzZXIgaGFzIGNvbnNlbnRlZCwgYW5kIHJlbWVtYmVycyB0aGlzIGNvbnNlbnQgdGhyb3VnaCBhIGJyb3dzZXIgY29va2llLjxiciAvPlxuICAgKiBUaGUgbmV4dCB0aW1lIHRoZSB1c2VyIHZpc2l0cyB0aGUgc2l0ZSwgTWF0b21vIHdpbGwgcmVtZW1iZXIgdGhhdCB0aGV5IGNvbnNlbnRlZCwgYW5kIHRyYWNrIHRoZW0uPGJyIC8+XG4gICAqIElmIHlvdSBjYWxsIHRoaXMgbWV0aG9kLCB5b3UgZG8gbm90IG5lZWQgdG8gY2FsbCBzZXRDb25zZW50R2l2ZW4uXG4gICAqXG4gICAqIEBwYXJhbSBob3Vyc1RvRXhwaXJlIEV4cGlyeSBwZXJpb2QgZm9yIHlvdXIgdXNlciBjb25zZW50LlxuICAgKi9cbiAgcmVtZW1iZXJDb25zZW50R2l2ZW4oaG91cnNUb0V4cGlyZT86IG51bWJlcik6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBhcmdzOiBudW1iZXJbXSA9IFtdO1xuICAgICAgaWYgKHR5cGVvZiBob3Vyc1RvRXhwaXJlID09PSAnbnVtYmVyJykge1xuICAgICAgICBhcmdzLnB1c2goaG91cnNUb0V4cGlyZSk7XG4gICAgICB9XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsncmVtZW1iZXJDb25zZW50R2l2ZW4nLCAuLi5hcmdzXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBNYXJrcyB0aGF0IHRoZSBjdXJyZW50IHVzZXIgaGFzIGNvbnNlbnRlZCwgYW5kIHJlbWVtYmVycyB0aGlzIGNvbnNlbnQgdGhyb3VnaCBhIGJyb3dzZXIgY29va2llLjxiciAvPlxuICAgKiBUaGUgbmV4dCB0aW1lIHRoZSB1c2VyIHZpc2l0cyB0aGUgc2l0ZSwgTWF0b21vIHdpbGwgcmVtZW1iZXIgdGhhdCB0aGV5IGNvbnNlbnRlZCwgYW5kIHRyYWNrIHRoZW0uPGJyIC8+XG4gICAqIElmIHlvdSBjYWxsIHRoaXMgbWV0aG9kLCB5b3UgZG8gbm90IG5lZWQgdG8gY2FsbCBzZXRDb29raWVDb25zZW50R2l2ZW4uXG4gICAqXG4gICAqIEBwYXJhbSBob3Vyc1RvRXhwaXJlIEV4cGlyeSBwZXJpb2QgZm9yIHlvdXIgdXNlciBjb25zZW50LlxuICAgKi9cbiAgcmVtZW1iZXJDb29raWVDb25zZW50R2l2ZW4oaG91cnNUb0V4cGlyZT86IG51bWJlcik6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBhcmdzOiBudW1iZXJbXSA9IFtdO1xuICAgICAgaWYgKHR5cGVvZiBob3Vyc1RvRXhwaXJlID09PSAnbnVtYmVyJykge1xuICAgICAgICBhcmdzLnB1c2goaG91cnNUb0V4cGlyZSk7XG4gICAgICB9XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsncmVtZW1iZXJDb29raWVDb25zZW50R2l2ZW4nLCAuLi5hcmdzXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmVzIGEgdXNlcidzIGNvbnNlbnQsIGJvdGggaWYgdGhlIGNvbnNlbnQgd2FzIG9uZS10aW1lIG9ubHkgYW5kIGlmIHRoZSBjb25zZW50IHdhcyByZW1lbWJlcmVkLjxiciAvPlxuICAgKiBUaGlzIG1ha2VzIHN1cmUgdGhlIGNvb2tpZSB0aGF0IHJlbWVtYmVyZWQgdGhlIGdpdmVuIGNvbnNlbnQgaXMgZGVsZXRlZC48YnIgLz5cbiAgICogQWZ0ZXIgY2FsbGluZyB0aGlzIG1ldGhvZCwgdGhlIHVzZXIgd2lsbCBoYXZlIHRvIGNvbnNlbnQgYWdhaW4gaW4gb3JkZXIgdG8gYmUgdHJhY2tlZC5cbiAgICovXG4gIGZvcmdldENvbnNlbnRHaXZlbigpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ2ZvcmdldENvbnNlbnRHaXZlbiddKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZXMgYSB1c2VyJ3MgY29uc2VudCwgYm90aCBpZiB0aGUgY29uc2VudCB3YXMgb25lLXRpbWUgb25seSBhbmQgaWYgdGhlIGNvbnNlbnQgd2FzIHJlbWVtYmVyZWQuPGJyIC8+XG4gICAqIFRoaXMgbWFrZXMgc3VyZSB0aGUgY29va2llIHRoYXQgcmVtZW1iZXJlZCB0aGUgZ2l2ZW4gY29uc2VudCBpcyBkZWxldGVkLjxiciAvPlxuICAgKiBBZnRlciBjYWxsaW5nIHRoaXMgbWV0aG9kLCB0aGUgdXNlciB3aWxsIGhhdmUgdG8gY29uc2VudCBhZ2FpbiBpbiBvcmRlciB0byBiZSB0cmFja2VkLlxuICAgKi9cbiAgZm9yZ2V0Q29va2llQ29uc2VudEdpdmVuKCk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnZm9yZ2V0Q29va2llQ29uc2VudEdpdmVuJ10pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2V0cyBpZiB0byBub3QgdG8gdHJhY2sgdXNlcnMgd2hvIG9wdCBvdXQgb2YgdHJhY2tpbmcgdXNpbmcgTW96aWxsYSdzIChwcm9wb3NlZCkgRG8gTm90IFRyYWNrIHNldHRpbmcuXG4gICAqXG4gICAqIEBwYXJhbSBkb05vdFRyYWNrIElmIHRydWUsIHVzZXJzIHdobyBvcHRlZCBmb3IgRG8gTm90IFRyYWNrIGluIHRoZWlyIHNldHRpbmdzIHdvbid0IGJlIHRyYWNrZWQuXG4gICAqIEBzZWUge0BsaW5rIGh0dHBzOi8vd3d3LnczLm9yZy9UUi90cmFja2luZy1kbnQvfVxuICAgKi9cbiAgc2V0RG9Ob3RUcmFjayhkb05vdFRyYWNrOiBib29sZWFuKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydzZXREb05vdFRyYWNrJywgZG9Ob3RUcmFja10pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRGlzYWJsZXMgYWxsIGZpcnN0IHBhcnR5IGNvb2tpZXMuPGJyIC8+XG4gICAqIEV4aXN0aW5nIE1hdG9tbyBjb29raWVzIGZvciB0aGlzIHdlYnNpdGVzIHdpbGwgYmUgZGVsZXRlZCBvbiB0aGUgbmV4dCBwYWdlIHZpZXcuXG4gICAqL1xuICBkaXNhYmxlQ29va2llcygpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ2Rpc2FibGVDb29raWVzJ10pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRGVsZXRlcyB0aGUgdHJhY2tpbmcgY29va2llcyBjdXJyZW50bHkgc2V0ICh1c2VmdWwgd2hlbiBjcmVhdGluZyBuZXcgdmlzaXRzKS5cbiAgICovXG4gIGRlbGV0ZUNvb2tpZXMoKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydkZWxldGVDb29raWVzJ10pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB3aGV0aGVyIGNvb2tpZXMgYXJlIGVuYWJsZWQgYW5kIHN1cHBvcnRlZCBieSB0aGlzIGJyb3dzZXIuXG4gICAqXG4gICAqIEByZXR1cm5zIFByb21pc2UgZm9yIHRoZSBzdXBwb3J0IGFuZCBhY3RpdmF0aW9uIG9mIGNvb2tpZXMuXG4gICAqL1xuICBoYXNDb29raWVzKCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFtcbiAgICAgICAgICBmdW5jdGlvbiAodGhpczogYW55KTogdm9pZCB7XG4gICAgICAgICAgICByZXNvbHZlKHRoaXMuaGFzQ29va2llcygpKTtcbiAgICAgICAgICB9LFxuICAgICAgICBdKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICAgIHJlamVjdChlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdGhlIHRyYWNraW5nIGNvb2tpZSBuYW1lIHByZWZpeC48YnIgLz5cbiAgICogRGVmYXVsdCBwcmVmaXggaXMgJ3BrJy5cbiAgICpcbiAgICogQHBhcmFtIHByZWZpeCBQcmVmaXggZm9yIHRoZSB0cmFja2luZyBjb29raWUgbmFtZXMuXG4gICAqL1xuICBzZXRDb29raWVOYW1lUHJlZml4KHByZWZpeDogc3RyaW5nKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydzZXRDb29raWVOYW1lUHJlZml4JywgcHJlZml4XSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSBkb21haW4gb2YgdGhlIHRyYWNraW5nIGNvb2tpZXMuPGJyIC8+XG4gICAqIERlZmF1bHQgaXMgdGhlIGRvY3VtZW50IGRvbWFpbi48YnIgLz5cbiAgICogSWYgeW91ciB3ZWJzaXRlIGNhbiBiZSB2aXNpdGVkIGF0IGJvdGggd3d3LmV4YW1wbGUuY29tIGFuZCBleGFtcGxlLmNvbSwgeW91IHdvdWxkIHVzZTogYCcuZXhhbXBsZS5jb20nYCBvciBgJyouZXhhbXBsZS5jb20nYC5cbiAgICpcbiAgICogQHBhcmFtIGRvbWFpbiBEb21haW4gb2YgdGhlIHRyYWNraW5nIGNvb2tpZXMuXG4gICAqL1xuICBzZXRDb29raWVEb21haW4oZG9tYWluOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3NldENvb2tpZURvbWFpbicsIGRvbWFpbl0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGUgcGF0aCBvZiB0aGUgdHJhY2tpbmcgY29va2llcy48YnIgLz5cbiAgICogRGVmYXVsdCBpcyAnLycuXG4gICAqXG4gICAqIEBwYXJhbSBwYXRoIFBhdGggb2YgdGhlIHRyYWNraW5nIGNvb2tpZXMuXG4gICAqL1xuICBzZXRDb29raWVQYXRoKHBhdGg6IHN0cmluZyk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnc2V0Q29va2llUGF0aCcsIHBhdGhdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgaWYgb3Igbm90IHRvIGVuYWJsZSB0aGUgU2VjdXJlIGNvb2tpZSBmbGFnIG9uIGFsbCBmaXJzdCBwYXJ0eSBjb29raWVzLjxiciAvPlxuICAgKiBUaGlzIHNob3VsZCBiZSB1c2VkIHdoZW4geW91ciB3ZWJzaXRlIGlzIG9ubHkgYXZhaWxhYmxlIHVuZGVyIEhUVFBTIHNvIHRoYXQgYWxsIHRyYWNraW5nIGNvb2tpZXMgYXJlIGFsd2F5cyBzZW50XG4gICAqIG92ZXIgc2VjdXJlIGNvbm5lY3Rpb24uXG4gICAqXG4gICAqIEBwYXJhbSBzZWN1cmUgSWYgdHJ1ZSwgdGhlIHNlY3VyZSBjb29raWUgZmxhZyB3aWxsIGJlIHNldCBvbiBhbGwgZmlyc3QgcGFydHkgY29va2llcy5cbiAgICovXG4gIHNldFNlY3VyZUNvb2tpZShzZWN1cmU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3NldFNlY3VyZUNvb2tpZScsIHNlY3VyZV0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB0aGUgdmlzaXRvciBjb29raWUgdGltZW91dC48YnIgLz5cbiAgICogRGVmYXVsdCBpcyAxMyBtb250aHMuXG4gICAqXG4gICAqIEBwYXJhbSB0aW1lb3V0IFRpbWVvdXQsIGluIHNlY29uZHMsIGZvciB0aGUgdmlzaXRvciBjb29raWUgdGltZW91dC5cbiAgICovXG4gIHNldFZpc2l0b3JDb29raWVUaW1lb3V0KHRpbWVvdXQ6IG51bWJlcik6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnc2V0VmlzaXRvckNvb2tpZVRpbWVvdXQnLCB0aW1lb3V0XSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTZXRzIHRoZSByZWZlcnJhbCBjb29raWUgdGltZW91dC48YnIgLz5cbiAgICogRGVmYXVsdCBpcyA2IG1vbnRocy5cbiAgICpcbiAgICogQHBhcmFtIHRpbWVvdXQgVGltZW91dCwgaW4gc2Vjb25kcywgZm9yIHRoZSByZWZlcnJhbCBjb29raWUgdGltZW91dC5cbiAgICovXG4gIHNldFJlZmVycmFsQ29va2llVGltZW91dCh0aW1lb3V0OiBudW1iZXIpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3NldFJlZmVycmFsQ29va2llVGltZW91dCcsIHRpbWVvdXRdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdGhlIHNlc3Npb24gY29va2llIHRpbWVvdXQuPGJyIC8+XG4gICAqIERlZmF1bHQgaXMgMzAgbWludXRlcy5cbiAgICpcbiAgICogQHBhcmFtIHRpbWVvdXQgVGltZW91dCwgaW4gc2Vjb25kcywgZm9yIHRoZSBzZXNzaW9uIGNvb2tpZSB0aW1lb3V0LlxuICAgKi9cbiAgc2V0U2Vzc2lvbkNvb2tpZVRpbWVvdXQodGltZW91dDogbnVtYmVyKTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydzZXRTZXNzaW9uQ29va2llVGltZW91dCcsIHRpbWVvdXRdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYSBjbGljayBsaXN0ZW5lciB0byBhIHNwZWNpZmljIGxpbmsgZWxlbWVudC48YnIgLz5cbiAgICogV2hlbiBjbGlja2VkLCBNYXRvbW8gd2lsbCBsb2cgdGhlIGNsaWNrIGF1dG9tYXRpY2FsbHkuXG4gICAqXG4gICAqIEBwYXJhbSBlbGVtZW50IEVsZW1lbnQgb24gd2hpY2ggdG8gYWRkIGEgY2xpY2sgbGlzdGVuZXIuXG4gICAqL1xuICBhZGRMaXN0ZW5lcihlbGVtZW50OiBFbGVtZW50KTogdm9pZCB7XG4gICAgdHJ5IHtcbiAgICAgIHdpbmRvd1snX3BhcSddLnB1c2goWydhZGRMaXN0ZW5lcicsIGVsZW1lbnRdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdGhlIHJlcXVlc3QgbWV0aG9kIHRvIGVpdGhlciAnR0VUJyBvciAnUE9TVCcuIChUaGUgZGVmYXVsdCBpcyAnR0VUJy4pPGJyIC8+XG4gICAqIFRvIHVzZSB0aGUgUE9TVCByZXF1ZXN0IG1ldGhvZCwgZWl0aGVyOjxiciAvPlxuICAgKiAxKSB0aGUgTWF0b21vIGhvc3QgaXMgdGhlIHNhbWUgYXMgdGhlIHRyYWNrZWQgd2Vic2l0ZSBob3N0IChNYXRvbW8gaW5zdGFsbGVkIGluIHRoZSBzYW1lIGRvbWFpbiBhcyB5b3VyIHRyYWNrZWQgd2Vic2l0ZSksIG9yPGJyIC8+XG4gICAqIDIpIGlmIE1hdG9tbyBpcyBub3QgaW5zdGFsbGVkIG9uIHRoZSBzYW1lIGhvc3QgYXMgeW91ciB3ZWJzaXRlLCB5b3UgbmVlZCB0byBlbmFibGUgQ09SUyAoQ3Jvc3MgZG9tYWluIHJlcXVlc3RzKS5cbiAgICpcbiAgICogQHBhcmFtIG1ldGhvZCBIVFRQIG1ldGhvZCBmb3Igc2VuZGluZyBpbmZvcm1hdGlvbiB0byB0aGUgTWF0b21vIHNlcnZlci5cbiAgICovXG4gIHNldFJlcXVlc3RNZXRob2QobWV0aG9kOiAnR0VUJyB8ICdQT1NUJyk6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICB3aW5kb3dbJ19wYXEnXS5wdXNoKFsnc2V0UmVxdWVzdE1ldGhvZCcsIG1ldGhvZF0pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghKGUgaW5zdGFuY2VvZiBSZWZlcmVuY2VFcnJvcikpIHtcbiAgICAgICAgdGhyb3cgZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2V0cyBhIGZ1bmN0aW9uIHRoYXQgd2lsbCBwcm9jZXNzIHRoZSByZXF1ZXN0IGNvbnRlbnQuPGJyIC8+XG4gICAqIFRoZSBmdW5jdGlvbiB3aWxsIGJlIGNhbGxlZCBvbmNlIHRoZSByZXF1ZXN0IChxdWVyeSBwYXJhbWV0ZXJzIHN0cmluZykgaGFzIGJlZW4gcHJlcGFyZWQsIGFuZCBiZWZvcmUgdGhlIHJlcXVlc3QgY29udGVudCBpcyBzZW50LlxuICAgKlxuICAgKiBAcGFyYW0gY2FsbGJhY2sgRnVuY3Rpb24gdGhhdCB3aWxsIHByb2Nlc3MgdGhlIHJlcXVlc3QgY29udGVudC5cbiAgICovXG4gIHNldEN1c3RvbVJlcXVlc3RQcm9jZXNzaW5nKGNhbGxiYWNrOiAocXVlcnlQYXJhbWV0ZXJzOiBzdHJpbmcpID0+IHZvaWQpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3NldEN1c3RvbVJlcXVlc3RQcm9jZXNzaW5nJywgY2FsbGJhY2tdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBpZiAoIShlIGluc3RhbmNlb2YgUmVmZXJlbmNlRXJyb3IpKSB7XG4gICAgICAgIHRocm93IGU7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgcmVxdWVzdCBDb250ZW50LVR5cGUgaGVhZGVyIHZhbHVlLjxiciAvPlxuICAgKiBBcHBsaWNhYmxlIHdoZW4gJ1BPU1QnIHJlcXVlc3QgbWV0aG9kIGlzIHVzZWQgdmlhIHNldFJlcXVlc3RNZXRob2QuXG4gICAqXG4gICAqIEBwYXJhbSBjb250ZW50VHlwZSBWYWx1ZSBmb3IgQ29udGVudC1UeXBlIEhUVFAgaGVhZGVyLlxuICAgKi9cbiAgc2V0UmVxdWVzdENvbnRlbnRUeXBlKGNvbnRlbnRUeXBlOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ3NldFJlcXVlc3RDb250ZW50VHlwZScsIGNvbnRlbnRUeXBlXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBEaXNhYmxlcyB0aGUgZmVhdHVyZSB3aGljaCBncm91cHMgdG9nZXRoZXIgbXVsdGlwbGUgdHJhY2tpbmcgcmVxdWVzdHMgYW5kIHNlbmQgdGhlbSBhcyBhIGJ1bGsgUE9TVCByZXF1ZXN0LjxiciAvPlxuICAgKiBEaXNhYmxpbmcgdGhpcyBmZWF0dXJlIGlzIHVzZWZ1bCB3aGVuIHlvdSB3YW50IHRvIGJlIGFibGUgdG8gcmVwbGF5IGFsbCBsb2dzOiBvbmUgbXVzdCB1c2UgZGlzYWJsZVF1ZXVlUmVxdWVzdFxuICAgKiB0byBkaXNhYmxlIHRoaXMgYmVoYXZpb3IgdG8gbGF0ZXIgYmUgYWJsZSB0byByZXBsYXkgbG9nZ2VkIE1hdG9tbyBsb2dzIChvdGhlcndpc2UgYSBzdWJzZXQgb2YgdGhlIHJlcXVlc3RzXG4gICAqIHdvdWxkbid0IGJlIGFibGUgdG8gYmUgcmVwbGF5ZWQpLlxuICAgKi9cbiAgZGlzYWJsZVF1ZXVlUmVxdWVzdCgpOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgd2luZG93WydfcGFxJ10ucHVzaChbJ2Rpc2FibGVRdWV1ZVJlcXVlc3QnXSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgaWYgKCEoZSBpbnN0YW5jZW9mIFJlZmVyZW5jZUVycm9yKSkge1xuICAgICAgICB0aHJvdyBlO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuIl19