@aws-cdk/aws-codebuild
Version:
The CDK Construct Library for AWS::CodeBuild
630 lines • 76.7 kB
JavaScript
"use strict";
var _a, _b;
Object.defineProperty(exports, "__esModule", { value: true });
exports.FilterGroup = exports.EventAction = exports.Source = void 0;
const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const iam = require("@aws-cdk/aws-iam");
const source_types_1 = require("./source-types");
/**
* Source provider definition for a CodeBuild Project.
*/
class Source {
constructor(props) {
this.badgeSupported = false;
try {
jsiiDeprecationWarnings._aws_cdk_aws_codebuild_SourceProps(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, Source);
}
throw error;
}
this.identifier = props.identifier;
}
static s3(props) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_codebuild_S3SourceProps(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.s3);
}
throw error;
}
return new S3Source(props);
}
static codeCommit(props) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_codebuild_CodeCommitSourceProps(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.codeCommit);
}
throw error;
}
return new CodeCommitSource(props);
}
static gitHub(props) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_codebuild_GitHubSourceProps(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.gitHub);
}
throw error;
}
return new GitHubSource(props);
}
static gitHubEnterprise(props) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_codebuild_GitHubEnterpriseSourceProps(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.gitHubEnterprise);
}
throw error;
}
return new GitHubEnterpriseSource(props);
}
static bitBucket(props) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_codebuild_BitBucketSourceProps(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.bitBucket);
}
throw error;
}
return new BitBucketSource(props);
}
/**
* Called by the project when the source is added so that the source can perform
* binding operations on the source. For example, it can grant permissions to the
* code build project to read from the S3 bucket.
*/
bind(_scope, _project) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_codebuild_IProject(_project);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.bind);
}
throw error;
}
return {
sourceProperty: {
sourceIdentifier: this.identifier,
type: this.type,
},
};
}
}
exports.Source = Source;
_a = JSII_RTTI_SYMBOL_1;
Source[_a] = { fqn: "@aws-cdk/aws-codebuild.Source", version: "1.204.0" };
/**
* A common superclass of all build sources that are backed by Git.
*/
class GitSource extends Source {
constructor(props) {
super(props);
this.cloneDepth = props.cloneDepth;
this.branchOrRef = props.branchOrRef;
this.fetchSubmodules = props.fetchSubmodules;
}
bind(_scope, _project) {
const superConfig = super.bind(_scope, _project);
return {
sourceVersion: this.branchOrRef,
sourceProperty: {
...superConfig.sourceProperty,
gitCloneDepth: this.cloneDepth,
gitSubmodulesConfig: this.fetchSubmodules ? {
fetchSubmodules: this.fetchSubmodules,
} : undefined,
},
};
}
}
/**
* The types of webhook event actions.
*/
var EventAction;
(function (EventAction) {
/**
* A push (of a branch, or a tag) to the repository.
*/
EventAction["PUSH"] = "PUSH";
/**
* Creating a Pull Request.
*/
EventAction["PULL_REQUEST_CREATED"] = "PULL_REQUEST_CREATED";
/**
* Updating a Pull Request.
*/
EventAction["PULL_REQUEST_UPDATED"] = "PULL_REQUEST_UPDATED";
/**
* Merging a Pull Request.
*/
EventAction["PULL_REQUEST_MERGED"] = "PULL_REQUEST_MERGED";
/**
* Re-opening a previously closed Pull Request.
* Note that this event is only supported for GitHub and GitHubEnterprise sources.
*/
EventAction["PULL_REQUEST_REOPENED"] = "PULL_REQUEST_REOPENED";
})(EventAction = exports.EventAction || (exports.EventAction = {}));
var WebhookFilterTypes;
(function (WebhookFilterTypes) {
WebhookFilterTypes["FILE_PATH"] = "FILE_PATH";
WebhookFilterTypes["COMMIT_MESSAGE"] = "COMMIT_MESSAGE";
WebhookFilterTypes["HEAD_REF"] = "HEAD_REF";
WebhookFilterTypes["ACTOR_ACCOUNT_ID"] = "ACTOR_ACCOUNT_ID";
WebhookFilterTypes["BASE_REF"] = "BASE_REF";
})(WebhookFilterTypes || (WebhookFilterTypes = {}));
/**
* An object that represents a group of filter conditions for a webhook.
* Every condition in a given FilterGroup must be true in order for the whole group to be true.
* You construct instances of it by calling the {@link #inEventOf} static factory method,
* and then calling various `andXyz` instance methods to create modified instances of it
* (this class is immutable).
*
* You pass instances of this class to the `webhookFilters` property when constructing a source.
*/
class FilterGroup {
constructor(actions, filters) {
if (actions.size === 0) {
throw new Error('A filter group must contain at least one event action');
}
this.actions = actions;
this.filters = filters;
}
/**
* Creates a new event FilterGroup that triggers on any of the provided actions.
*
* @param actions the actions to trigger the webhook on
*/
static inEventOf(...actions) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_codebuild_EventAction(actions);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.inEventOf);
}
throw error;
}
return new FilterGroup(new Set(actions), []);
}
/**
* Create a new FilterGroup with an added condition:
* the event must affect the given branch.
*
* @param branchName the name of the branch (can be a regular expression)
*/
andBranchIs(branchName) {
return this.addHeadBranchFilter(branchName, true);
}
/**
* Create a new FilterGroup with an added condition:
* the event must not affect the given branch.
*
* @param branchName the name of the branch (can be a regular expression)
*/
andBranchIsNot(branchName) {
return this.addHeadBranchFilter(branchName, false);
}
/**
* Create a new FilterGroup with an added condition:
* the event must affect a head commit with the given message.
*
* @param commitMessage the commit message (can be a regular expression)
*/
andCommitMessageIs(commitMessage) {
return this.addCommitMessageFilter(commitMessage, true);
}
/**
* Create a new FilterGroup with an added condition:
* the event must not affect a head commit with the given message.
*
* @param commitMessage the commit message (can be a regular expression)
*/
andCommitMessageIsNot(commitMessage) {
return this.addCommitMessageFilter(commitMessage, false);
}
/**
* Create a new FilterGroup with an added condition:
* the event must affect the given tag.
*
* @param tagName the name of the tag (can be a regular expression)
*/
andTagIs(tagName) {
return this.addHeadTagFilter(tagName, true);
}
/**
* Create a new FilterGroup with an added condition:
* the event must not affect the given tag.
*
* @param tagName the name of the tag (can be a regular expression)
*/
andTagIsNot(tagName) {
return this.addHeadTagFilter(tagName, false);
}
/**
* Create a new FilterGroup with an added condition:
* the event must affect a Git reference (ie., a branch or a tag)
* that matches the given pattern.
*
* @param pattern a regular expression
*/
andHeadRefIs(pattern) {
return this.addHeadRefFilter(pattern, true);
}
/**
* Create a new FilterGroup with an added condition:
* the event must not affect a Git reference (ie., a branch or a tag)
* that matches the given pattern.
*
* @param pattern a regular expression
*/
andHeadRefIsNot(pattern) {
return this.addHeadRefFilter(pattern, false);
}
/**
* Create a new FilterGroup with an added condition:
* the account ID of the actor initiating the event must match the given pattern.
*
* @param pattern a regular expression
*/
andActorAccountIs(pattern) {
return this.addActorAccountId(pattern, true);
}
/**
* Create a new FilterGroup with an added condition:
* the account ID of the actor initiating the event must not match the given pattern.
*
* @param pattern a regular expression
*/
andActorAccountIsNot(pattern) {
return this.addActorAccountId(pattern, false);
}
/**
* Create a new FilterGroup with an added condition:
* the Pull Request that is the source of the event must target the given base branch.
* Note that you cannot use this method if this Group contains the `PUSH` event action.
*
* @param branchName the name of the branch (can be a regular expression)
*/
andBaseBranchIs(branchName) {
return this.addBaseBranchFilter(branchName, true);
}
/**
* Create a new FilterGroup with an added condition:
* the Pull Request that is the source of the event must not target the given base branch.
* Note that you cannot use this method if this Group contains the `PUSH` event action.
*
* @param branchName the name of the branch (can be a regular expression)
*/
andBaseBranchIsNot(branchName) {
return this.addBaseBranchFilter(branchName, false);
}
/**
* Create a new FilterGroup with an added condition:
* the Pull Request that is the source of the event must target the given Git reference.
* Note that you cannot use this method if this Group contains the `PUSH` event action.
*
* @param pattern a regular expression
*/
andBaseRefIs(pattern) {
return this.addBaseRefFilter(pattern, true);
}
/**
* Create a new FilterGroup with an added condition:
* the Pull Request that is the source of the event must not target the given Git reference.
* Note that you cannot use this method if this Group contains the `PUSH` event action.
*
* @param pattern a regular expression
*/
andBaseRefIsNot(pattern) {
return this.addBaseRefFilter(pattern, false);
}
/**
* Create a new FilterGroup with an added condition:
* the push that is the source of the event must affect a file that matches the given pattern.
* Note that you can only use this method if this Group contains only the `PUSH` event action,
* and only for GitHub, Bitbucket and GitHubEnterprise sources.
*
* @param pattern a regular expression
*/
andFilePathIs(pattern) {
return this.addFilePathFilter(pattern, true);
}
/**
* Create a new FilterGroup with an added condition:
* the push that is the source of the event must not affect a file that matches the given pattern.
* Note that you can only use this method if this Group contains only the `PUSH` event action,
* and only for GitHub, Bitbucket and GitHubEnterprise sources.
*
* @param pattern a regular expression
*/
andFilePathIsNot(pattern) {
return this.addFilePathFilter(pattern, false);
}
/** @internal */
get _actions() {
return set2Array(this.actions);
}
/** @internal */
get _filters() {
return this.filters.slice();
}
/** @internal */
_toJson() {
const eventFilter = {
type: 'EVENT',
pattern: set2Array(this.actions).join(', '),
};
return [eventFilter].concat(this.filters);
}
addCommitMessageFilter(commitMessage, include) {
return this.addFilter(WebhookFilterTypes.COMMIT_MESSAGE, commitMessage, include);
}
addHeadBranchFilter(branchName, include) {
return this.addHeadRefFilter(`refs/heads/${branchName}`, include);
}
addHeadTagFilter(tagName, include) {
return this.addHeadRefFilter(`refs/tags/${tagName}`, include);
}
addHeadRefFilter(refName, include) {
return this.addFilter(WebhookFilterTypes.HEAD_REF, refName, include);
}
addActorAccountId(accountId, include) {
return this.addFilter(WebhookFilterTypes.ACTOR_ACCOUNT_ID, accountId, include);
}
addBaseBranchFilter(branchName, include) {
return this.addBaseRefFilter(`refs/heads/${branchName}`, include);
}
addBaseRefFilter(refName, include) {
if (this.actions.has(EventAction.PUSH)) {
throw new Error('A base reference condition cannot be added if a Group contains a PUSH event action');
}
return this.addFilter(WebhookFilterTypes.BASE_REF, refName, include);
}
addFilePathFilter(pattern, include) {
return this.addFilter(WebhookFilterTypes.FILE_PATH, pattern, include);
}
addFilter(type, pattern, include) {
return new FilterGroup(this.actions, this.filters.concat([{
type,
pattern,
excludeMatchedPattern: include ? undefined : true,
}]));
}
}
exports.FilterGroup = FilterGroup;
_b = JSII_RTTI_SYMBOL_1;
FilterGroup[_b] = { fqn: "@aws-cdk/aws-codebuild.FilterGroup", version: "1.204.0" };
/**
* A common superclass of all third-party build sources that are backed by Git.
*/
class ThirdPartyGitSource extends GitSource {
constructor(props) {
super(props);
this.badgeSupported = true;
this.webhook = props.webhook;
this.reportBuildStatus = props.reportBuildStatus ?? true;
this.webhookFilters = props.webhookFilters || [];
this.webhookTriggersBatchBuild = props.webhookTriggersBatchBuild;
this.buildStatusUrl = props.buildStatusUrl;
}
bind(_scope, project) {
const anyFilterGroupsProvided = this.webhookFilters.length > 0;
const webhook = this.webhook ?? (anyFilterGroupsProvided ? true : undefined);
if (!webhook && anyFilterGroupsProvided) {
throw new Error('`webhookFilters` cannot be used when `webhook` is `false`');
}
if (!webhook && this.webhookTriggersBatchBuild) {
throw new Error('`webhookTriggersBatchBuild` cannot be used when `webhook` is `false`');
}
const superConfig = super.bind(_scope, project);
if (this.webhookTriggersBatchBuild) {
project.enableBatchBuilds();
}
return {
sourceProperty: {
...superConfig.sourceProperty,
reportBuildStatus: this.reportBuildStatus,
},
sourceVersion: superConfig.sourceVersion,
buildTriggers: webhook === undefined ? undefined : {
webhook,
buildType: this.webhookTriggersBatchBuild ? 'BUILD_BATCH' : undefined,
filterGroups: anyFilterGroupsProvided ? this.webhookFilters.map(fg => fg._toJson()) : undefined,
},
};
}
}
/**
* CodeCommit Source definition for a CodeBuild project.
*/
class CodeCommitSource extends GitSource {
constructor(props) {
super(props);
this.badgeSupported = true;
this.type = source_types_1.CODECOMMIT_SOURCE_TYPE;
this.repo = props.repository;
}
bind(_scope, project) {
// https://docs.aws.amazon.com/codebuild/latest/userguide/setting-up.html
project.addToRolePolicy(new iam.PolicyStatement({
actions: ['codecommit:GitPull'],
resources: [this.repo.repositoryArn],
}));
const superConfig = super.bind(_scope, project);
return {
sourceProperty: {
...superConfig.sourceProperty,
location: this.repo.repositoryCloneUrlHttp,
},
sourceVersion: superConfig.sourceVersion,
};
}
}
/**
* S3 bucket definition for a CodeBuild project.
*/
class S3Source extends Source {
constructor(props) {
super(props);
this.type = source_types_1.S3_SOURCE_TYPE;
this.bucket = props.bucket;
this.path = props.path;
this.version = props.version;
}
bind(_scope, project) {
this.bucket.grantRead(project, this.path);
const superConfig = super.bind(_scope, project);
return {
sourceProperty: {
...superConfig.sourceProperty,
location: `${this.bucket.bucketName}/${this.path}`,
},
sourceVersion: this.version,
};
}
}
class CommonGithubSource extends ThirdPartyGitSource {
constructor(props) {
super(props);
this.buildStatusContext = props.buildStatusContext;
}
bind(scope, project) {
const superConfig = super.bind(scope, project);
return {
sourceProperty: {
...superConfig.sourceProperty,
buildStatusConfig: this.buildStatusContext !== undefined || this.buildStatusUrl !== undefined
? {
context: this.buildStatusContext,
targetUrl: this.buildStatusUrl,
}
: undefined,
},
sourceVersion: superConfig.sourceVersion,
buildTriggers: superConfig.buildTriggers,
};
}
}
/**
* GitHub Source definition for a CodeBuild project.
*/
class GitHubSource extends CommonGithubSource {
constructor(props) {
super(props);
this.type = source_types_1.GITHUB_SOURCE_TYPE;
this.httpsCloneUrl = `https://github.com/${props.owner}/${props.repo}.git`;
}
bind(_scope, project) {
const superConfig = super.bind(_scope, project);
return {
sourceProperty: {
...superConfig.sourceProperty,
location: this.httpsCloneUrl,
},
sourceVersion: superConfig.sourceVersion,
buildTriggers: superConfig.buildTriggers,
};
}
}
/**
* GitHub Enterprise Source definition for a CodeBuild project.
*/
class GitHubEnterpriseSource extends CommonGithubSource {
constructor(props) {
super(props);
this.type = source_types_1.GITHUB_ENTERPRISE_SOURCE_TYPE;
this.httpsCloneUrl = props.httpsCloneUrl;
this.ignoreSslErrors = props.ignoreSslErrors;
}
bind(_scope, _project) {
if (this.hasCommitMessageFilterAndPrEvent()) {
throw new Error('COMMIT_MESSAGE filters cannot be used with GitHub Enterprise Server pull request events');
}
if (this.hasFilePathFilterAndPrEvent()) {
throw new Error('FILE_PATH filters cannot be used with GitHub Enterprise Server pull request events');
}
const superConfig = super.bind(_scope, _project);
return {
sourceProperty: {
...superConfig.sourceProperty,
location: this.httpsCloneUrl,
insecureSsl: this.ignoreSslErrors,
},
sourceVersion: superConfig.sourceVersion,
buildTriggers: superConfig.buildTriggers,
};
}
hasCommitMessageFilterAndPrEvent() {
return this.webhookFilters.some(fg => (fg._filters.some(fp => fp.type === WebhookFilterTypes.COMMIT_MESSAGE) &&
this.hasPrEvent(fg._actions)));
}
hasFilePathFilterAndPrEvent() {
return this.webhookFilters.some(fg => (fg._filters.some(fp => fp.type === WebhookFilterTypes.FILE_PATH) &&
this.hasPrEvent(fg._actions)));
}
hasPrEvent(actions) {
return actions.includes(EventAction.PULL_REQUEST_CREATED ||
EventAction.PULL_REQUEST_MERGED ||
EventAction.PULL_REQUEST_REOPENED ||
EventAction.PULL_REQUEST_UPDATED);
}
}
/**
* BitBucket Source definition for a CodeBuild project.
*/
class BitBucketSource extends ThirdPartyGitSource {
constructor(props) {
super(props);
this.type = source_types_1.BITBUCKET_SOURCE_TYPE;
this.httpsCloneUrl = `https://bitbucket.org/${props.owner}/${props.repo}.git`;
this.buildStatusName = props.buildStatusName;
}
bind(_scope, _project) {
// BitBucket sources don't support the PULL_REQUEST_REOPENED event action
if (this.anyWebhookFilterContainsPrReopenedEventAction()) {
throw new Error('BitBucket sources do not support the PULL_REQUEST_REOPENED webhook event action');
}
const superConfig = super.bind(_scope, _project);
return {
sourceProperty: {
...superConfig.sourceProperty,
location: this.httpsCloneUrl,
buildStatusConfig: this.buildStatusName !== undefined || this.buildStatusUrl !== undefined
? {
context: this.buildStatusName,
targetUrl: this.buildStatusUrl,
}
: undefined,
},
sourceVersion: superConfig.sourceVersion,
buildTriggers: superConfig.buildTriggers,
};
}
anyWebhookFilterContainsPrReopenedEventAction() {
return this.webhookFilters.findIndex(fg => {
return fg._actions.findIndex(a => a === EventAction.PULL_REQUEST_REOPENED) !== -1;
}) !== -1;
}
}
function set2Array(set) {
const ret = [];
set.forEach(el => ret.push(el));
return ret;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic291cmNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsic291cmNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUNBLHdDQUF3QztBQUl4QyxpREFNd0I7QUErQ3hCOztHQUVHO0FBQ0gsTUFBc0IsTUFBTTtJQXlCMUIsWUFBc0IsS0FBa0I7UUFGeEIsbUJBQWMsR0FBWSxLQUFLLENBQUM7Ozs7OzsrQ0F2QjVCLE1BQU07Ozs7UUEwQnhCLElBQUksQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDLFVBQVUsQ0FBQztLQUNwQztJQTFCTSxNQUFNLENBQUMsRUFBRSxDQUFDLEtBQW9COzs7Ozs7Ozs7O1FBQ25DLE9BQU8sSUFBSSxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7S0FDNUI7SUFFTSxNQUFNLENBQUMsVUFBVSxDQUFDLEtBQTRCOzs7Ozs7Ozs7O1FBQ25ELE9BQU8sSUFBSSxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztLQUNwQztJQUVNLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBd0I7Ozs7Ozs7Ozs7UUFDM0MsT0FBTyxJQUFJLFlBQVksQ0FBQyxLQUFLLENBQUMsQ0FBQztLQUNoQztJQUVNLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFrQzs7Ozs7Ozs7OztRQUMvRCxPQUFPLElBQUksc0JBQXNCLENBQUMsS0FBSyxDQUFDLENBQUM7S0FDMUM7SUFFTSxNQUFNLENBQUMsU0FBUyxDQUFDLEtBQTJCOzs7Ozs7Ozs7O1FBQ2pELE9BQU8sSUFBSSxlQUFlLENBQUMsS0FBSyxDQUFDLENBQUM7S0FDbkM7SUFVRDs7OztPQUlHO0lBQ0ksSUFBSSxDQUFDLE1BQXFCLEVBQUUsUUFBa0I7Ozs7Ozs7Ozs7UUFDbkQsT0FBTztZQUNMLGNBQWMsRUFBRTtnQkFDZCxnQkFBZ0IsRUFBRSxJQUFJLENBQUMsVUFBVTtnQkFDakMsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJO2FBQ2hCO1NBQ0YsQ0FBQztLQUNIOztBQXpDSCx3QkEwQ0M7OztB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LE1BQU0sRUFBRSxRQUFRLENBQUMsQ0FBQztRQUNqRCxPQUFPO1lBQ0wsY0FBYyxFQUFFO2dCQUNkLEdBQUcsV0FBVyxDQUFDLGNBQWM7Z0JBQzdCLFFBQVEsRUFBRSxJQUFJLENBQUMsYUFBYTtnQkFDNUIsaUJBQWlCLEVBQUUsSUFBSSxDQUFDLGVBQWUsS0FBSyxTQUFTLElBQUksSUFBSSxDQUFDLGNBQWMsS0FBSyxTQUFTO29CQUN4RixDQUFDLENBQUM7d0JBQ0EsT0FBTyxFQUFFLElBQUksQ0FBQyxlQUFlO3dCQUM3QixTQUFTLEVBQUUsSUFBSSxDQUFDLGNBQWM7cUJBQy9CO29CQUNELENBQUMsQ0FBQyxTQUFTO2FBQ2Q7WUFDRCxhQUFhLEVBQUUsV0FBVyxDQUFDLGFBQWE7WUFDeEMsYUFBYSxFQUFFLFdBQVcsQ0FBQyxhQUFhO1NBQ3pDLENBQUM7S0FDSDtJQUVPLDZDQUE2QztRQUNuRCxPQUFPLElBQUksQ0FBQyxjQUFjLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxFQUFFO1lBQ3hDLE9BQU8sRUFBRSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEtBQUssV0FBVyxDQUFDLHFCQUFxQixDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7UUFDcEYsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7S0FDWDtDQUNGO0FBRUQsU0FBUyxTQUFTLENBQUksR0FBVztJQUMvQixNQUFNLEdBQUcsR0FBUSxFQUFFLENBQUM7SUFDcEIsR0FBRyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUNoQyxPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBjb2RlY29tbWl0IGZyb20gJ0Bhd3MtY2RrL2F3cy1jb2RlY29tbWl0JztcbmltcG9ydCAqIGFzIGlhbSBmcm9tICdAYXdzLWNkay9hd3MtaWFtJztcbmltcG9ydCAqIGFzIHMzIGZyb20gJ0Bhd3MtY2RrL2F3cy1zMyc7XG5pbXBvcnQgeyBDZm5Qcm9qZWN0IH0gZnJvbSAnLi9jb2RlYnVpbGQuZ2VuZXJhdGVkJztcbmltcG9ydCB7IElQcm9qZWN0IH0gZnJvbSAnLi9wcm9qZWN0JztcbmltcG9ydCB7XG4gIEJJVEJVQ0tFVF9TT1VSQ0VfVFlQRSxcbiAgQ09ERUNPTU1JVF9TT1VSQ0VfVFlQRSxcbiAgR0lUSFVCX0VOVEVSUFJJU0VfU09VUkNFX1RZUEUsXG4gIEdJVEhVQl9TT1VSQ0VfVFlQRSxcbiAgUzNfU09VUkNFX1RZUEUsXG59IGZyb20gJy4vc291cmNlLXR5cGVzJztcblxuLy8gdjIgLSBrZWVwIHRoaXMgaW1wb3J0IGFzIGEgc2VwYXJhdGUgc2VjdGlvbiB0byByZWR1Y2UgbWVyZ2UgY29uZmxpY3Qgd2hlbiBmb3J3YXJkIG1lcmdpbmcgd2l0aCB0aGUgdjIgYnJhbmNoLlxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG5pbXBvcnQgeyBDb25zdHJ1Y3QgYXMgQ29yZUNvbnN0cnVjdCB9IGZyb20gJ0Bhd3MtY2RrL2NvcmUnO1xuXG4vKipcbiAqIFRoZSB0eXBlIHJldHVybmVkIGZyb20ge0BsaW5rIElTb3VyY2UjYmluZH0uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU291cmNlQ29uZmlnIHtcbiAgcmVhZG9ubHkgc291cmNlUHJvcGVydHk6IENmblByb2plY3QuU291cmNlUHJvcGVydHk7XG5cbiAgcmVhZG9ubHkgYnVpbGRUcmlnZ2Vycz86IENmblByb2plY3QuUHJvamVjdFRyaWdnZXJzUHJvcGVydHk7XG5cbiAgLyoqXG4gICAqIGBBV1M6OkNvZGVCdWlsZDo6UHJvamVjdC5Tb3VyY2VWZXJzaW9uYFxuICAgKiBAc2VlIGh0dHA6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0Nsb3VkRm9ybWF0aW9uL2xhdGVzdC9Vc2VyR3VpZGUvYXdzLXJlc291cmNlLWNvZGVidWlsZC1wcm9qZWN0Lmh0bWwjY2ZuLWNvZGVidWlsZC1wcm9qZWN0LXNvdXJjZXZlcnNpb25cbiAgICogQGRlZmF1bHQgdGhlIGxhdGVzdCB2ZXJzaW9uXG4gICAqL1xuICByZWFkb25seSBzb3VyY2VWZXJzaW9uPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRoZSBhYnN0cmFjdCBpbnRlcmZhY2Ugb2YgYSBDb2RlQnVpbGQgc291cmNlLlxuICogSW1wbGVtZW50ZWQgYnkge0BsaW5rIFNvdXJjZX0uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSVNvdXJjZSB7XG4gIHJlYWRvbmx5IGlkZW50aWZpZXI/OiBzdHJpbmc7XG5cbiAgcmVhZG9ubHkgdHlwZTogc3RyaW5nO1xuXG4gIHJlYWRvbmx5IGJhZGdlU3VwcG9ydGVkOiBib29sZWFuO1xuXG4gIGJpbmQoc2NvcGU6IENvcmVDb25zdHJ1Y3QsIHByb2plY3Q6IElQcm9qZWN0KTogU291cmNlQ29uZmlnO1xufVxuXG4vKipcbiAqIFByb3BlcnRpZXMgY29tbW9uIHRvIGFsbCBTb3VyY2UgY2xhc3Nlcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTb3VyY2VQcm9wcyB7XG4gIC8qKlxuICAgKiBUaGUgc291cmNlIGlkZW50aWZpZXIuXG4gICAqIFRoaXMgcHJvcGVydHkgaXMgcmVxdWlyZWQgb24gc2Vjb25kYXJ5IHNvdXJjZXMuXG4gICAqL1xuICByZWFkb25seSBpZGVudGlmaWVyPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFNvdXJjZSBwcm92aWRlciBkZWZpbml0aW9uIGZvciBhIENvZGVCdWlsZCBQcm9qZWN0LlxuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgU291cmNlIGltcGxlbWVudHMgSVNvdXJjZSB7XG4gIHB1YmxpYyBzdGF0aWMgczMocHJvcHM6IFMzU291cmNlUHJvcHMpOiBJU291cmNlIHtcbiAgICByZXR1cm4gbmV3IFMzU291cmNlKHByb3BzKTtcbiAgfVxuXG4gIHB1YmxpYyBzdGF0aWMgY29kZUNvbW1pdChwcm9wczogQ29kZUNvbW1pdFNvdXJjZVByb3BzKTogSVNvdXJjZSB7XG4gICAgcmV0dXJuIG5ldyBDb2RlQ29tbWl0U291cmNlKHByb3BzKTtcbiAgfVxuXG4gIHB1YmxpYyBzdGF0aWMgZ2l0SHViKHByb3BzOiBHaXRIdWJTb3VyY2VQcm9wcyk6IElTb3VyY2Uge1xuICAgIHJldHVybiBuZXcgR2l0SHViU291cmNlKHByb3BzKTtcbiAgfVxuXG4gIHB1YmxpYyBzdGF0aWMgZ2l0SHViRW50ZXJwcmlzZShwcm9wczogR2l0SHViRW50ZXJwcmlzZVNvdXJjZVByb3BzKTogSVNvdXJjZSB7XG4gICAgcmV0dXJuIG5ldyBHaXRIdWJFbnRlcnByaXNlU291cmNlKHByb3BzKTtcbiAgfVxuXG4gIHB1YmxpYyBzdGF0aWMgYml0QnVja2V0KHByb3BzOiBCaXRCdWNrZXRTb3VyY2VQcm9wcyk6IElTb3VyY2Uge1xuICAgIHJldHVybiBuZXcgQml0QnVja2V0U291cmNlKHByb3BzKTtcbiAgfVxuXG4gIHB1YmxpYyByZWFkb25seSBpZGVudGlmaWVyPzogc3RyaW5nO1xuICBwdWJsaWMgYWJzdHJhY3QgcmVhZG9ubHkgdHlwZTogc3RyaW5nO1xuICBwdWJsaWMgcmVhZG9ubHkgYmFkZ2VTdXBwb3J0ZWQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuICBwcm90ZWN0ZWQgY29uc3RydWN0b3IocHJvcHM6IFNvdXJjZVByb3BzKSB7XG4gICAgdGhpcy5pZGVudGlmaWVyID0gcHJvcHMuaWRlbnRpZmllcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxsZWQgYnkgdGhlIHByb2plY3Qgd2hlbiB0aGUgc291cmNlIGlzIGFkZGVkIHNvIHRoYXQgdGhlIHNvdXJjZSBjYW4gcGVyZm9ybVxuICAgKiBiaW5kaW5nIG9wZXJhdGlvbnMgb24gdGhlIHNvdXJjZS4gRm9yIGV4YW1wbGUsIGl0IGNhbiBncmFudCBwZXJtaXNzaW9ucyB0byB0aGVcbiAgICogY29kZSBidWlsZCBwcm9qZWN0IHRvIHJlYWQgZnJvbSB0aGUgUzMgYnVja2V0LlxuICAgKi9cbiAgcHVibGljIGJpbmQoX3Njb3BlOiBDb3JlQ29uc3RydWN0LCBfcHJvamVjdDogSVByb2plY3QpOiBTb3VyY2VDb25maWcge1xuICAgIHJldHVybiB7XG4gICAgICBzb3VyY2VQcm9wZXJ0eToge1xuICAgICAgICBzb3VyY2VJZGVudGlmaWVyOiB0aGlzLmlkZW50aWZpZXIsXG4gICAgICAgIHR5cGU6IHRoaXMudHlwZSxcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxufVxuXG4vKipcbiAqIFRoZSBjb25zdHJ1Y3Rpb24gcHJvcGVydGllcyBjb21tb24gdG8gYWxsIGJ1aWxkIHNvdXJjZXMgdGhhdCBhcmUgYmFja2VkIGJ5IEdpdC5cbiAqL1xuaW50ZXJmYWNlIEdpdFNvdXJjZVByb3BzIGV4dGVuZHMgU291cmNlUHJvcHMge1xuICAvKipcbiAgICogVGhlIGRlcHRoIG9mIGhpc3RvcnkgdG8gZG93bmxvYWQuIE1pbmltdW0gdmFsdWUgaXMgMC5cbiAgICogSWYgdGhpcyB2YWx1ZSBpcyAwLCBncmVhdGVyIHRoYW4gMjUsIG9yIG5vdCBwcm92aWRlZCxcbiAgICogdGhlbiB0aGUgZnVsbCBoaXN0b3J5IGlzIGRvd25sb2FkZWQgd2l0aCBlYWNoIGJ1aWxkIG9mIHRoZSBwcm9qZWN0LlxuICAgKi9cbiAgcmVhZG9ubHkgY2xvbmVEZXB0aD86IG51bWJlcjtcblxuICAvKipcbiAgICogVGhlIGNvbW1pdCBJRCwgcHVsbCByZXF1ZXN0IElELCBicmFuY2ggbmFtZSwgb3IgdGFnIG5hbWUgdGhhdCBjb3JyZXNwb25kcyB0b1xuICAgKiB0aGUgdmVyc2lvbiBvZiB0aGUgc291cmNlIGNvZGUgeW91IHdhbnQgdG8gYnVpbGRcbiAgICpcbiAgICogQGV4YW1wbGUgJ215YnJhbmNoJ1xuICAgKiBAZGVmYXVsdCB0aGUgZGVmYXVsdCBicmFuY2gncyBIRUFEIGNvbW1pdCBJRCBpcyB1c2VkXG4gICAqL1xuICByZWFkb25seSBicmFuY2hPclJlZj86IHN0cmluZztcblxuICAvKipcbiAgICogV2hldGhlciB0byBmZXRjaCBzdWJtb2R1bGVzIHdoaWxlIGNsb25pbmcgZ2l0IHJlcG8uXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBmZXRjaFN1Ym1vZHVsZXM/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIEEgY29tbW9uIHN1cGVyY2xhc3Mgb2YgYWxsIGJ1aWxkIHNvdXJjZXMgdGhhdCBhcmUgYmFja2VkIGJ5IEdpdC5cbiAqL1xuYWJzdHJhY3QgY2xhc3MgR2l0U291cmNlIGV4dGVuZHMgU291cmNlIHtcbiAgcHJpdmF0ZSByZWFkb25seSBjbG9uZURlcHRoPzogbnVtYmVyO1xuICBwcml2YXRlIHJlYWRvbmx5IGJyYW5jaE9yUmVmPzogc3RyaW5nO1xuICBwcml2YXRlIHJlYWRvbmx5IGZldGNoU3VibW9kdWxlcz86IGJvb2xlYW47XG5cbiAgcHJvdGVjdGVkIGNvbnN0cnVjdG9yKHByb3BzOiBHaXRTb3VyY2VQcm9wcykge1xuICAgIHN1cGVyKHByb3BzKTtcblxuICAgIHRoaXMuY2xvbmVEZXB0aCA9IHByb3BzLmNsb25lRGVwdGg7XG4gICAgdGhpcy5icmFuY2hPclJlZiA9IHByb3BzLmJyYW5jaE9yUmVmO1xuICAgIHRoaXMuZmV0Y2hTdWJtb2R1bGVzID0gcHJvcHMuZmV0Y2hTdWJtb2R1bGVzO1xuICB9XG5cbiAgcHVibGljIGJpbmQoX3Njb3BlOiBDb3JlQ29uc3RydWN0LCBfcHJvamVjdDogSVByb2plY3QpOiBTb3VyY2VDb25maWcge1xuICAgIGNvbnN0IHN1cGVyQ29uZmlnID0gc3VwZXIuYmluZChfc2NvcGUsIF9wcm9qZWN0KTtcbiAgICByZXR1cm4ge1xuICAgICAgc291cmNlVmVyc2lvbjogdGhpcy5icmFuY2hPclJlZixcbiAgICAgIHNvdXJjZVByb3BlcnR5OiB7XG4gICAgICAgIC4uLnN1cGVyQ29uZmlnLnNvdXJjZVByb3BlcnR5LFxuICAgICAgICBnaXRDbG9uZURlcHRoOiB0aGlzLmNsb25lRGVwdGgsXG4gICAgICAgIGdpdFN1Ym1vZHVsZXNDb25maWc6IHRoaXMuZmV0Y2hTdWJtb2R1bGVzID8ge1xuICAgICAgICAgIGZldGNoU3VibW9kdWxlczogdGhpcy5mZXRjaFN1Ym1vZHVsZXMsXG4gICAgICAgIH0gOiB1bmRlZmluZWQsXG4gICAgICB9LFxuICAgIH07XG4gIH1cbn1cblxuLyoqXG4gKiBUaGUgdHlwZXMgb2Ygd2ViaG9vayBldmVudCBhY3Rpb25zLlxuICovXG5leHBvcnQgZW51bSBFdmVudEFjdGlvbiB7XG4gIC8qKlxuICAgKiBBIHB1c2ggKG9mIGEgYnJhbmNoLCBvciBhIHRhZykgdG8gdGhlIHJlcG9zaXRvcnkuXG4gICAqL1xuICBQVVNIID0gJ1BVU0gnLFxuXG4gIC8qKlxuICAgKiBDcmVhdGluZyBhIFB1bGwgUmVxdWVzdC5cbiAgICovXG4gIFBVTExfUkVRVUVTVF9DUkVBVEVEID0gJ1BVTExfUkVRVUVTVF9DUkVBVEVEJyxcblxuICAvKipcbiAgICogVXBkYXRpbmcgYSBQdWxsIFJlcXVlc3QuXG4gICAqL1xuICBQVUxMX1JFUVVFU1RfVVBEQVRFRCA9ICdQVUxMX1JFUVVFU1RfVVBEQVRFRCcsXG5cbiAgLyoqXG4gICAqIE1lcmdpbmcgYSBQdWxsIFJlcXVlc3QuXG4gICAqL1xuICBQVUxMX1JFUVVFU1RfTUVSR0VEID0gJ1BVTExfUkVRVUVTVF9NRVJHRUQnLFxuXG4gIC8qKlxuICAgKiBSZS1vcGVuaW5nIGEgcHJldmlvdXNseSBjbG9zZWQgUHVsbCBSZXF1ZXN0LlxuICAgKiBOb3RlIHRoYXQgdGhpcyBldmVudCBpcyBvbmx5IHN1cHBvcnRlZCBmb3IgR2l0SHViIGFuZCBHaXRIdWJFbnRlcnByaXNlIHNvdXJjZXMuXG4gICAqL1xuICBQVUxMX1JFUVVFU1RfUkVPUEVORUQgPSAnUFVMTF9SRVFVRVNUX1JFT1BFTkVEJyxcbn1cblxuZW51bSBXZWJob29rRmlsdGVyVHlwZXMge1xuICBGSUxFX1BBVEggPSAnRklMRV9QQVRIJyxcbiAgQ09NTUlUX01FU1NBR0UgPSAnQ09NTUlUX01FU1NBR0UnLFxuICBIRUFEX1JFRiA9ICdIRUFEX1JFRicsXG4gIEFDVE9SX0FDQ09VTlRfSUQgPSAnQUNUT1JfQUNDT1VOVF9JRCcsXG4gIEJBU0VfUkVGID0gJ0JBU0VfUkVGJyxcbn1cblxuLyoqXG4gKiBBbiBvYmplY3QgdGhhdCByZXByZXNlbnRzIGEgZ3JvdXAgb2YgZmlsdGVyIGNvbmRpdGlvbnMgZm9yIGEgd2ViaG9vay5cbiAqIEV2ZXJ5IGNvbmRpdGlvbiBpbiBhIGdpdmVuIEZpbHRlckdyb3VwIG11c3QgYmUgdHJ1ZSBpbiBvcmRlciBmb3IgdGhlIHdob2xlIGdyb3VwIHRvIGJlIHRydWUuXG4gKiBZb3UgY29uc3RydWN0IGluc3RhbmNlcyBvZiBpdCBieSBjYWxsaW5nIHRoZSB7QGxpbmsgI2luRXZlbnRPZn0gc3RhdGljIGZhY3RvcnkgbWV0aG9kLFxuICogYW5kIHRoZW4gY2FsbGluZyB2YXJpb3VzIGBhbmRYeXpgIGluc3RhbmNlIG1ldGhvZHMgdG8gY3JlYXRlIG1vZGlmaWVkIGluc3RhbmNlcyBvZiBpdFxuICogKHRoaXMgY2xhc3MgaXMgaW1tdXRhYmxlKS5cbiAqXG4gKiBZb3UgcGFzcyBpbnN0YW5jZXMgb2YgdGhpcyBjbGFzcyB0byB0aGUgYHdlYmhvb2tGaWx0ZXJzYCBwcm9wZXJ0eSB3aGVuIGNvbnN0cnVjdGluZyBhIHNvdXJjZS5cbiAqL1xuZXhwb3J0IGNsYXNzIEZpbHRlckdyb3VwIHtcbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBuZXcgZXZlbnQgRmlsdGVyR3JvdXAgdGhhdCB0cmlnZ2VycyBvbiBhbnkgb2YgdGhlIHByb3ZpZGVkIGFjdGlvbnMuXG4gICAqXG4gICAqIEBwYXJhbSBhY3Rpb25zIHRoZSBhY3Rpb25zIHRvIHRyaWdnZXIgdGhlIHdlYmhvb2sgb25cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgaW5FdmVudE9mKC4uLmFjdGlvbnM6IEV2ZW50QWN0aW9uW10pOiBGaWx0ZXJHcm91cCB7XG4gICAgcmV0dXJuIG5ldyBGaWx0ZXJHcm91cChuZXcgU2V0KGFjdGlvbnMpLCBbXSk7XG4gIH1cblxuICBwcml2YXRlIHJlYWRvbmx5IGFjdGlvbnM6IFNldDxFdmVudEFjdGlvbj47XG4gIHByaXZhdGUgcmVhZG9ubHkgZmlsdGVyczogQ2ZuUHJvamVjdC5XZWJob29rRmlsdGVyUHJvcGVydHlbXTtcblxuICBwcml2YXRlIGNvbnN0cnVjdG9yKGFjdGlvbnM6IFNldDxFdmVudEFjdGlvbj4sIGZpbHRlcnM6IENmblByb2plY3QuV2ViaG9va0ZpbHRlclByb3BlcnR5W10pIHtcbiAgICBpZiAoYWN0aW9ucy5zaXplID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0EgZmlsdGVyIGdyb3VwIG11c3QgY29udGFpbiBhdCBsZWFzdCBvbmUgZXZlbnQgYWN0aW9uJyk7XG4gICAgfVxuICAgIHRoaXMuYWN0aW9ucyA9IGFjdGlvbnM7XG4gICAgdGhpcy5maWx0ZXJzID0gZmlsdGVycztcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBuZXcgRmlsdGVyR3JvdXAgd2l0aCBhbiBhZGRlZCBjb25kaXRpb246XG4gICAqIHRoZSBldmVudCBtdXN0IGFmZmVjdCB0aGUgZ2l2ZW4gYnJhbmNoLlxuICAgKlxuICAgKiBAcGFyYW0gYnJhbmNoTmFtZSB0aGUgbmFtZSBvZiB0aGUgYnJhbmNoIChjYW4gYmUgYSByZWd1bGFyIGV4cHJlc3Npb24pXG4gICAqL1xuICBwdWJsaWMgYW5kQnJhbmNoSXMoYnJhbmNoTmFtZTogc3RyaW5nKTogRmlsdGVyR3JvdXAge1xuICAgIHJldHVybiB0aGlzLmFkZEhlYWRCcmFuY2hGaWx0ZXIoYnJhbmNoTmFtZSwgdHJ1ZSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgbmV3IEZpbHRlckdyb3VwIHdpdGggYW4gYWRkZWQgY29uZGl0aW9uOlxuICAgKiB0aGUgZXZlbnQgbXVzdCBub3QgYWZmZWN0IHRoZSBnaXZlbiBicmFuY2guXG4gICAqXG4gICAqIEBwYXJhbSBicmFuY2hOYW1lIHRoZSBuYW1lIG9mIHRoZSBicmFuY2ggKGNhbiBiZSBhIHJlZ3VsYXIgZXhwcmVzc2lvbilcbiAgICovXG4gIHB1YmxpYyBhbmRCcmFuY2hJc05vdChicmFuY2hOYW1lOiBzdHJpbmcpOiBGaWx0ZXJHcm91cCB7XG4gICAgcmV0dXJuIHRoaXMuYWRkSGVhZEJyYW5jaEZpbHRlcihicmFuY2hOYW1lLCBmYWxzZSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgbmV3IEZpbHRlckdyb3VwIHdpdGggYW4gYWRkZWQgY29uZGl0aW9uOlxuICAgKiB0aGUgZXZlbnQgbXVzdCBhZmZlY3QgYSBoZWFkIGNvbW1pdCB3aXRoIHRoZSBnaXZlbiBtZXNzYWdlLlxuICAgKlxuICAgKiBAcGFyYW0gY29tbWl0TWVzc2FnZSB0aGUgY29tbWl0IG1lc3NhZ2UgKGNhbiBiZSBhIHJlZ3VsYXIgZXhwcmVzc2lvbilcbiAgICovXG4gIHB1YmxpYyBhbmRDb21taXRNZXNzYWdlSXMoY29tbWl0TWVzc2FnZTogc3RyaW5nKTogRmlsdGVyR3JvdXAge1xuICAgIHJldHVybiB0aGlzLmFkZENvbW1pdE1lc3NhZ2VGaWx0ZXIoY29tbWl0TWVzc2FnZSwgdHJ1ZSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgbmV3IEZpbHRlckdyb3VwIHdpdGggYW4gYWRkZWQgY29uZGl0aW9uOlxuICAgKiB0aGUgZXZlbnQgbXVzdCBub3QgYWZmZWN0IGEgaGVhZCBjb21taXQgd2l0aCB0aGUgZ2l2ZW4gbWVzc2FnZS5cbiAgICpcbiAgICogQHBhcmFtIGNvbW1pdE1lc3NhZ2UgdGhlIGNvbW1pdCBtZXNzYWdlIChjYW4gYmUgYSByZWd1bGFyIGV4cHJlc3Npb24pXG4gICAqL1xuICBwdWJsaWMgYW5kQ29tbWl0TWVzc2FnZUlzTm90KGNvbW1pdE1lc3NhZ2U6IHN0cmluZyk6IEZpbHRlckdyb3VwIHtcbiAgICByZXR1cm4gdGhpcy5hZGRDb21taXRNZXNzYWdlRmlsdGVyKGNvbW1pdE1lc3NhZ2UsIGZhbHNlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBuZXcgRmlsdGVyR3JvdXAgd2l0aCBhbiBhZGRlZCBjb25kaXRpb246XG4gICAqIHRoZSBldmVudCBtdXN0IGFmZmVjdCB0aGUgZ2l2ZW4gdGFnLlxuICAgKlxuICAgKiBAcGFyYW0gdGFnTmFtZSB0aGUgbmFtZSBvZiB0aGUgdGFnIChjYW4gYmUgYSByZWd1bGFyIGV4cHJlc3Npb24pXG4gICAqL1xuICBwdWJsaWMgYW5kVGFnSXModGFnTmFtZTogc3RyaW5nKTogRmlsdGVyR3JvdXAge1xuICAgIHJldHVybiB0aGlzLmFkZEhlYWRUYWdGaWx0ZXIodGFnTmFtZSwgdHJ1ZSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgbmV3IEZpbHRlckdyb3VwIHdpdGggYW4gYWRkZWQgY29uZGl0aW9uOlxuICAgKiB0aGUgZXZlbnQgbXVzdCBub3QgYWZmZWN0IHRoZSBnaXZlbiB0YWcuXG4gICAqXG4gICAqIEBwYXJhbSB0YWdOYW1lIHRoZSBuYW1lIG9mIHRoZSB0YWcgKGNhbiBiZSBhIHJlZ3VsYXIgZXhwc