projen
Version:
CDK for software projects
444 lines • 74.5 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.Release = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const posixPath = __importStar(require("node:path/posix"));
const publisher_1 = require("./publisher");
const release_trigger_1 = require("./release-trigger");
const consts_1 = require("../build/private/consts");
const component_1 = require("../component");
const github_1 = require("../github");
const constants_1 = require("../github/constants");
const util_1 = require("../github/private/util");
const workflows_model_1 = require("../github/workflows-model");
const runner_options_1 = require("../runner-options");
const name_1 = require("../util/name");
const path_1 = require("../util/path");
const version_1 = require("../version");
const BUILD_JOBID = "release";
const GIT_REMOTE_STEPID = "git_remote";
const TAG_EXISTS_STEPID = "check_tag_exists";
const UPLOAD_ARTIFACT_STEP = "upload_artifact";
const LATEST_COMMIT_OUTPUT = "latest_commit";
const TAG_EXISTS_OUTPUT = "tag_exists";
const ARTIFACT_ID_OUTPUT = "artifact_id";
/**
* Conditional (Github Workflow Job `if`) to check if a release job should be run.
*/
const DEPENDENT_JOB_CONDITIONAL = `needs.${BUILD_JOBID}.outputs.${TAG_EXISTS_OUTPUT} != 'true' && needs.${BUILD_JOBID}.outputs.${LATEST_COMMIT_OUTPUT} == github.sha`;
/**
* Manages releases (currently through GitHub workflows).
*
* By default, no branches are released. To add branches, call `addBranch()`.
*/
class Release extends component_1.Component {
static [JSII_RTTI_SYMBOL_1] = { fqn: "projen.release.Release", version: "0.103.12" };
static ANTI_TAMPER_CMD = "git diff --ignore-space-at-eol --exit-code";
/**
* Returns the `Release` component of a project or `undefined` if the project
* does not have a Release component.
*/
static of(project) {
const isRelease = (c) => c instanceof Release;
return project.components.find(isRelease);
}
/**
* Package publisher.
*/
publisher;
/**
* Location of build artifacts.
*/
artifactsDirectory;
buildTasks;
version;
postBuildSteps;
versionFile;
releaseTrigger;
preBuildSteps;
containerImage;
_branches = new Array();
jobs = {};
defaultBranch;
github;
runsOn;
runsOnGroup;
workflowPermissions;
releaseWorkflowEnv;
releaseTagFilePath;
_branchHooks;
/**
* @param scope should be part of the project the Release belongs to.
* @param options options to configure the Release Component.
*/
constructor(scope, options) {
super(scope);
if (Array.isArray(options.releaseBranches)) {
throw new Error('"releaseBranches" is no longer an array. See type annotations');
}
this.github = github_1.GitHub.of(this.project.root);
const runsOnConfig = this.github?.runsOnConfig({
runsOn: options.runsOn ?? options.workflowRunsOn,
runsOnGroup: options.runsOnGroup ?? options.workflowRunsOnGroup,
});
this.runsOn = runsOnConfig?.runsOn;
this.runsOnGroup = runsOnConfig?.runsOnGroup;
// Determine the tasks to use to create the release artifacts
if (options.tasks && options.tasks.length > 0) {
this.buildTasks = options.tasks;
}
else {
throw new Error("'tasks' must be provided.");
}
this.preBuildSteps = options.releaseWorkflowSetupSteps ?? [];
this.postBuildSteps = options.postBuildSteps ?? [];
this.artifactsDirectory =
options.artifactsDirectory ?? consts_1.DEFAULT_ARTIFACTS_DIRECTORY;
(0, path_1.ensureNotHiddenPath)(this.artifactsDirectory, "artifactsDirectory");
(0, path_1.ensurePathInsideProject)(this.artifactsDirectory, "artifactsDirectory", this.project.outdir);
this.versionFile = options.versionFile;
this.releaseTrigger = options.releaseTrigger ?? release_trigger_1.ReleaseTrigger.continuous();
this.containerImage = options.workflowContainerImage;
this.workflowPermissions = {
contents: workflows_model_1.JobPermission.WRITE,
...options.workflowPermissions,
};
this.releaseWorkflowEnv = options.releaseWorkflowEnv;
this._branchHooks = [];
this.version = new version_1.Version(this.project, {
versionInputFile: this.versionFile,
artifactsDirectory: this.artifactsDirectory,
versionrcOptions: options.versionrcOptions,
tagPrefix: options.releaseTagPrefix,
releasableCommits: options.releasableCommits,
bumpPackage: options.bumpPackage,
nextVersionCommand: options.nextVersionCommand,
});
this.releaseTagFilePath = posixPath.normalize(posixPath.join(this.artifactsDirectory, this.version.releaseTagFileName));
this.publisher = new publisher_1.Publisher(this.project, {
artifactName: this.artifactsDirectory,
condition: DEPENDENT_JOB_CONDITIONAL,
buildJobId: BUILD_JOBID,
publibVersion: options.jsiiReleaseVersion,
failureIssue: options.releaseFailureIssue,
failureIssueLabel: options.releaseFailureIssueLabel,
...(0, runner_options_1.filteredWorkflowRunsOnOptions)(this.runsOn, this.runsOnGroup),
publishTasks: options.publishTasks,
dryRun: options.publishDryRun,
workflowNodeVersion: options.workflowNodeVersion,
workflowContainerImage: options.workflowContainerImage,
});
const githubRelease = options.githubRelease ?? true;
if (githubRelease) {
this.publisher.publishToGitHubReleases({
changelogFile: posixPath.join(this.artifactsDirectory, this.version.changelogFileName),
versionFile: posixPath.join(this.artifactsDirectory, this.version.versionFileName),
releaseTagFile: posixPath.join(this.artifactsDirectory, this.version.releaseTagFileName),
});
}
// add the default branch (we need the internal method which does not require majorVersion)
this.defaultBranch = this._addBranch(options.branch, {
prerelease: options.prerelease,
githubReleaseLatest: options.githubReleaseLatest,
majorVersion: options.majorVersion,
minMajorVersion: options.minMajorVersion,
workflowName: options.releaseWorkflowName ??
(0, name_1.workflowNameForProject)("release", this.project),
environment: options.releaseEnvironment,
tagPrefix: options.releaseTagPrefix,
npmDistTag: options.npmDistTag,
});
for (const [name, opts] of Object.entries(options.releaseBranches ?? {})) {
this.addBranch(name, {
environment: options.releaseEnvironment,
...opts,
});
}
}
/**
* Add a hook that should be run for every branch (including those that will
* be added by future `addBranch` calls).
* @internal
*/
_forEachBranch(hook) {
for (const branch of this._branches) {
hook(branch.name);
}
this._branchHooks.push(hook);
}
/**
* Adds a release branch.
*
* It is a git branch from which releases are published. If a project has more than one release
* branch, we require that `majorVersion` is also specified for the primary branch in order to
* ensure branches always release the correct version.
*
* @param branch The branch to monitor (e.g. `main`, `v2.x`)
* @param options Branch definition
*/
addBranch(branch, options) {
this._addBranch(branch, options);
// run all branch hooks
for (const hook of this._branchHooks) {
hook(branch);
}
}
/**
* Adds a release branch.
*
* It is a git branch from which releases are published. If a project has more than one release
* branch, we require that `majorVersion` is also specified for the primary branch in order to
* ensure branches always release the correct version.
*
* @param branch The branch to monitor (e.g. `main`, `v2.x`)
* @param options Branch definition
*/
_addBranch(branch, options) {
if (this._branches.find((b) => b.name === branch)) {
throw new Error(`The release branch ${branch} is already defined`);
}
// if we add a branch, we require that the default branch will also define a
// major version.
if (this.defaultBranch &&
options.majorVersion &&
this.defaultBranch.majorVersion === undefined) {
throw new Error('you must specify "majorVersion" for the default branch when adding multiple release branches');
}
const releaseBranch = {
name: branch,
...options,
workflow: this.createWorkflow(branch, options),
};
this._branches.push(releaseBranch);
return releaseBranch;
}
preSynthesize() {
for (const branch of this._branches) {
if (!branch.workflow) {
continue;
}
branch.workflow.addJobs(this.publisher._renderJobsForBranch(branch.name, branch));
branch.workflow.addJobs(this.jobs);
}
}
/**
* Adds jobs to all release workflows.
* @param jobs The jobs to add (name => job)
*/
addJobs(jobs) {
for (const [name, job] of Object.entries(jobs)) {
this.jobs[name] = job;
}
}
/**
* Retrieve all release branch names
*/
get branches() {
return this._branches.map((b) => b.name);
}
/**
* @returns a workflow or `undefined` if github integration is disabled.
*/
createWorkflow(branchName, branch) {
const workflowName = branch.workflowName ??
(0, name_1.workflowNameForProject)(`release-${branchName}`, this.project);
// to avoid race conditions between two commits trying to release the same
// version, we check if the head sha is identical to the remote sha. if
// not, we will skip the release and just finish the build.
const noNewCommits = `\${{ steps.${GIT_REMOTE_STEPID}.outputs.${LATEST_COMMIT_OUTPUT} == github.sha }}`;
// The arrays are being cloned to avoid accumulating values from previous branches
const preBuildSteps = [...this.preBuildSteps];
const env = {
RELEASE: "true",
...this.version.envForBranch({
majorVersion: branch.majorVersion,
minorVersion: branch.minorVersion,
minMajorVersion: branch.minMajorVersion,
prerelease: branch.prerelease,
tagPrefix: branch.tagPrefix,
}),
};
// the "release" task prepares a release but does not publish anything. the
// output of the release task is: `dist`, `.version.txt`, and
// `.changelog.md`. this is what publish tasks expect.
// if this is the release for "main" or "master", just call it "release".
// otherwise, "release:BRANCH"
const releaseTaskName = branchName === "main" || branchName === "master"
? "release"
: `release:${branchName}`;
const releaseTask = this.project.addTask(releaseTaskName, {
description: `Prepare a release from "${branchName}" branch`,
env,
});
releaseTask.execArgs(["rm", "-fr", this.artifactsDirectory]);
releaseTask.spawn(this.version.bumpTask);
// Spawn all build tasks
for (const buildTask of this.buildTasks) {
releaseTask.spawn(buildTask);
}
releaseTask.spawn(this.version.unbumpTask);
// anti-tamper check (fails if there were changes to committed files)
// this will identify any non-committed files generated during build (e.g. test snapshots)
releaseTask.exec(Release.ANTI_TAMPER_CMD);
if (this.releaseTrigger.isManual) {
const publishTask = this.publisher.publishToGit({
changelogFile: posixPath.join(this.artifactsDirectory, this.version.changelogFileName),
versionFile: posixPath.join(this.artifactsDirectory, this.version.versionFileName),
releaseTagFile: posixPath.join(this.artifactsDirectory, this.version.releaseTagFileName),
projectChangelogFile: this.releaseTrigger.changelogPath,
gitBranch: branchName,
gitPushCommand: this.releaseTrigger.gitPushCommand,
});
releaseTask.spawn(publishTask);
}
const postBuildSteps = [...this.postBuildSteps];
// Read the releasetag, then check if it already exists.
// If it does, we will cancel this release
postBuildSteps.push(github_1.WorkflowSteps.tagExists(`$(cat ${this.releaseTagFilePath})`, {
name: "Check if version has already been tagged",
id: TAG_EXISTS_STEPID,
}));
// check if new commits were pushed to the repo while we were building.
// if new commits have been pushed, we will cancel this release
postBuildSteps.push({
name: "Check for new commits",
id: GIT_REMOTE_STEPID,
shell: "bash",
env: {
GITHUB_REF: "${{ github.ref }}",
},
run: [
`echo "${LATEST_COMMIT_OUTPUT}=$(git ls-remote origin -h "$GITHUB_REF" | cut -f1)" >> $GITHUB_OUTPUT`,
"cat $GITHUB_OUTPUT",
].join("\n"),
});
const projectPathRelativeToRoot = (0, util_1.projectPathRelativeToRepoRoot)(this.project);
postBuildSteps.push({
name: "Backup artifact permissions",
if: noNewCommits,
continueOnError: true,
run: `cd ${this.artifactsDirectory} && getfacl -R . > ${constants_1.PERMISSION_BACKUP_FILE}`,
}, github_1.WorkflowSteps.uploadArtifact({
id: UPLOAD_ARTIFACT_STEP,
if: noNewCommits,
with: {
name: constants_1.BUILD_ARTIFACT_NAME,
path: this.project.parent // is subproject
? posixPath.join(projectPathRelativeToRoot, this.artifactsDirectory)
: this.artifactsDirectory,
},
}));
if (this.github && !this.releaseTrigger.isManual) {
// Use target (possible parent) GitHub to create the workflow
const workflow = new github_1.GithubWorkflow(this.github, workflowName, {
// see https://github.com/projen/projen/issues/3761
limitConcurrency: true,
});
// When run-name evaluates to empty string, GitHub falls back to the
// default event-specific name (e.g. commit message for push events).
workflow.runName = `$\{{ inputs.dry_run && format('[DRY RUN] ${workflowName} by @{0}', github.actor) || '' }}`;
workflow.on({
schedule: this.releaseTrigger.schedule
? [{ cron: this.releaseTrigger.schedule }]
: undefined,
push: this.releaseTrigger.isContinuous || this.releaseTrigger.tags
? {
branches: [branchName],
tags: this.releaseTrigger.tags,
paths: this.releaseTrigger.paths,
}
: undefined,
workflowDispatch: {
inputs: {
dry_run: {
description: "Dry run (skip actual publishing)",
required: false,
type: "boolean",
},
},
},
});
// Create job based on child (only?) project GitHub
const taskjob = new github_1.TaskWorkflowJob(this, releaseTask, {
outputs: {
[LATEST_COMMIT_OUTPUT]: {
stepId: GIT_REMOTE_STEPID,
outputName: LATEST_COMMIT_OUTPUT,
},
[TAG_EXISTS_OUTPUT]: {
stepId: TAG_EXISTS_STEPID,
outputName: "exists",
},
[ARTIFACT_ID_OUTPUT]: {
stepId: UPLOAD_ARTIFACT_STEP,
outputName: "artifact-id",
},
},
container: this.containerImage
? { image: this.containerImage }
: undefined,
env: {
CI: "true",
...this.releaseWorkflowEnv,
},
permissions: this.workflowPermissions,
checkoutWith: {
// fetch-depth= indicates all history for all branches and tags
// we must use this in order to fetch all tags
// and to inspect the history to decide if we should release
fetchDepth: 0,
},
preBuildSteps,
postBuildSteps,
jobDefaults: this.project.parent // is subproject
? {
run: {
workingDirectory: projectPathRelativeToRoot,
},
}
: undefined,
...(0, runner_options_1.filteredRunsOnOptions)(this.runsOn, this.runsOnGroup),
});
workflow.addJob(BUILD_JOBID, taskjob);
return workflow;
}
else {
return undefined;
}
}
}
exports.Release = Release;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVsZWFzZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9yZWxlYXNlL3JlbGVhc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLDJEQUE2QztBQUU3QywyQ0FBd0M7QUFDeEMsdURBQW1EO0FBQ25ELG9EQUFzRTtBQUN0RSw0Q0FBeUM7QUFDekMsc0NBS21CO0FBQ25CLG1EQUc2QjtBQUM3QixpREFBdUU7QUFFdkUsK0RBQTBEO0FBRzFELHNEQUcyQjtBQUUzQix1Q0FBc0Q7QUFDdEQsdUNBQTRFO0FBRTVFLHdDQUFxQztBQUVyQyxNQUFNLFdBQVcsR0FBRyxTQUFTLENBQUM7QUFDOUIsTUFBTSxpQkFBaUIsR0FBRyxZQUFZLENBQUM7QUFDdkMsTUFBTSxpQkFBaUIsR0FBRyxrQkFBa0IsQ0FBQztBQUM3QyxNQUFNLG9CQUFvQixHQUFHLGlCQUFpQixDQUFDO0FBRS9DLE1BQU0sb0JBQW9CLEdBQUcsZUFBZSxDQUFDO0FBQzdDLE1BQU0saUJBQWlCLEdBQUcsWUFBWSxDQUFDO0FBQ3ZDLE1BQU0sa0JBQWtCLEdBQUcsYUFBYSxDQUFDO0FBRXpDOztHQUVHO0FBQ0gsTUFBTSx5QkFBeUIsR0FBRyxTQUFTLFdBQVcsWUFBWSxpQkFBaUIsdUJBQXVCLFdBQVcsWUFBWSxvQkFBb0IsZ0JBQWdCLENBQUM7QUFnVXRLOzs7O0dBSUc7QUFDSCxNQUFhLE9BQVEsU0FBUSxxQkFBUzs7SUFDN0IsTUFBTSxDQUFVLGVBQWUsR0FDcEMsNENBQTRDLENBQUM7SUFFL0M7OztPQUdHO0lBQ0ksTUFBTSxDQUFDLEVBQUUsQ0FBQyxPQUFnQjtRQUMvQixNQUFNLFNBQVMsR0FBRyxDQUFDLENBQVksRUFBZ0IsRUFBRSxDQUFDLENBQUMsWUFBWSxPQUFPLENBQUM7UUFDdkUsT0FBTyxPQUFPLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUM1QyxD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QUFXLENBQUM7YUFDeEQsQ0FBQyxDQUFDO1lBRUgsUUFBUSxDQUFDLE1BQU0sQ0FBQyxXQUFXLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFFdEMsT0FBTyxRQUFRLENBQUM7UUFDbEIsQ0FBQzthQUFNLENBQUM7WUFDTixPQUFPLFNBQVMsQ0FBQztRQUNuQixDQUFDO0lBQ0gsQ0FBQzs7QUFyZEgsMEJBc2RDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgcG9zaXhQYXRoIGZyb20gXCJub2RlOnBhdGgvcG9zaXhcIjtcbmltcG9ydCB0eXBlIHsgSUNvbnN0cnVjdCB9IGZyb20gXCJjb25zdHJ1Y3RzXCI7XG5pbXBvcnQgeyBQdWJsaXNoZXIgfSBmcm9tIFwiLi9wdWJsaXNoZXJcIjtcbmltcG9ydCB7IFJlbGVhc2VUcmlnZ2VyIH0gZnJvbSBcIi4vcmVsZWFzZS10cmlnZ2VyXCI7XG5pbXBvcnQgeyBERUZBVUxUX0FSVElGQUNUU19ESVJFQ1RPUlkgfSBmcm9tIFwiLi4vYnVpbGQvcHJpdmF0ZS9jb25zdHNcIjtcbmltcG9ydCB7IENvbXBvbmVudCB9IGZyb20gXCIuLi9jb21wb25lbnRcIjtcbmltcG9ydCB7XG4gIEdpdEh1YixcbiAgR2l0aHViV29ya2Zsb3csXG4gIFRhc2tXb3JrZmxvd0pvYixcbiAgV29ya2Zsb3dTdGVwcyxcbn0gZnJvbSBcIi4uL2dpdGh1YlwiO1xuaW1wb3J0IHtcbiAgQlVJTERfQVJUSUZBQ1RfTkFNRSxcbiAgUEVSTUlTU0lPTl9CQUNLVVBfRklMRSxcbn0gZnJvbSBcIi4uL2dpdGh1Yi9jb25zdGFudHNcIjtcbmltcG9ydCB7IHByb2plY3RQYXRoUmVsYXRpdmVUb1JlcG9Sb290IH0gZnJvbSBcIi4uL2dpdGh1Yi9wcml2YXRlL3V0aWxcIjtcbmltcG9ydCB0eXBlIHsgSm9iLCBKb2JQZXJtaXNzaW9ucywgSm9iU3RlcCB9IGZyb20gXCIuLi9naXRodWIvd29ya2Zsb3dzLW1vZGVsXCI7XG5pbXBvcnQgeyBKb2JQZXJtaXNzaW9uIH0gZnJvbSBcIi4uL2dpdGh1Yi93b3JrZmxvd3MtbW9kZWxcIjtcbmltcG9ydCB0eXBlIHsgUHJvamVjdCB9IGZyb20gXCIuLi9wcm9qZWN0XCI7XG5pbXBvcnQgdHlwZSB7IEdyb3VwUnVubmVyT3B0aW9ucyB9IGZyb20gXCIuLi9ydW5uZXItb3B0aW9uc1wiO1xuaW1wb3J0IHtcbiAgZmlsdGVyZWRSdW5zT25PcHRpb25zLFxuICBmaWx0ZXJlZFdvcmtmbG93UnVuc09uT3B0aW9ucyxcbn0gZnJvbSBcIi4uL3J1bm5lci1vcHRpb25zXCI7XG5pbXBvcnQgdHlwZSB7IFRhc2sgfSBmcm9tIFwiLi4vdGFza1wiO1xuaW1wb3J0IHsgd29ya2Zsb3dOYW1lRm9yUHJvamVjdCB9IGZyb20gXCIuLi91dGlsL25hbWVcIjtcbmltcG9ydCB7IGVuc3VyZU5vdEhpZGRlblBhdGgsIGVuc3VyZVBhdGhJbnNpZGVQcm9qZWN0IH0gZnJvbSBcIi4uL3V0aWwvcGF0aFwiO1xuaW1wb3J0IHR5cGUgeyBSZWxlYXNhYmxlQ29tbWl0cyB9IGZyb20gXCIuLi92ZXJzaW9uXCI7XG5pbXBvcnQgeyBWZXJzaW9uIH0gZnJvbSBcIi4uL3ZlcnNpb25cIjtcblxuY29uc3QgQlVJTERfSk9CSUQgPSBcInJlbGVhc2VcIjtcbmNvbnN0IEdJVF9SRU1PVEVfU1RFUElEID0gXCJnaXRfcmVtb3RlXCI7XG5jb25zdCBUQUdfRVhJU1RTX1NURVBJRCA9IFwiY2hlY2tfdGFnX2V4aXN0c1wiO1xuY29uc3QgVVBMT0FEX0FSVElGQUNUX1NURVAgPSBcInVwbG9hZF9hcnRpZmFjdFwiO1xuXG5jb25zdCBMQVRFU1RfQ09NTUlUX09VVFBVVCA9IFwibGF0ZXN0X2NvbW1pdFwiO1xuY29uc3QgVEFHX0VYSVNUU19PVVRQVVQgPSBcInRhZ19leGlzdHNcIjtcbmNvbnN0IEFSVElGQUNUX0lEX09VVFBVVCA9IFwiYXJ0aWZhY3RfaWRcIjtcblxuLyoqXG4gKiBDb25kaXRpb25hbCAoR2l0aHViIFdvcmtmbG93IEpvYiBgaWZgKSB0byBjaGVjayBpZiBhIHJlbGVhc2Ugam9iIHNob3VsZCBiZSBydW4uXG4gKi9cbmNvbnN0IERFUEVOREVOVF9KT0JfQ09ORElUSU9OQUwgPSBgbmVlZHMuJHtCVUlMRF9KT0JJRH0ub3V0cHV0cy4ke1RBR19FWElTVFNfT1VUUFVUfSAhPSAndHJ1ZScgJiYgbmVlZHMuJHtCVUlMRF9KT0JJRH0ub3V0cHV0cy4ke0xBVEVTVF9DT01NSVRfT1VUUFVUfSA9PSBnaXRodWIuc2hhYDtcblxudHlwZSBCcmFuY2hIb29rID0gKGJyYW5jaDogc3RyaW5nKSA9PiB2b2lkO1xuXG4vKipcbiAqIFByb2plY3Qgb3B0aW9ucyBmb3IgcmVsZWFzZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZWxlYXNlUHJvamVjdE9wdGlvbnMge1xuICAvKipcbiAgICogVGhlIHJlbGVhc2UgdHJpZ2dlciB0byB1c2UuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gQ29udGludW91cyByZWxlYXNlcyAoYFJlbGVhc2VUcmlnZ2VyLmNvbnRpbnVvdXMoKWApXG4gICAqL1xuICByZWFkb25seSByZWxlYXNlVHJpZ2dlcj86IFJlbGVhc2VUcmlnZ2VyO1xuXG4gIC8qKlxuICAgKiBBIHNldCBvZiB3b3JrZmxvdyBzdGVwcyB0byBleGVjdXRlIGluIG9yZGVyIHRvIHNldHVwIHRoZSB3b3JrZmxvd1xuICAgKiBjb250YWluZXIuXG4gICAqL1xuICByZWFkb25seSByZWxlYXNlV29ya2Zsb3dTZXR1cFN0ZXBzPzogSm9iU3RlcFtdO1xuXG4gIC8qKlxuICAgKiBDb250YWluZXIgaW1hZ2UgdG8gdXNlIGZvciBHaXRIdWIgd29ya2Zsb3dzLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGRlZmF1bHQgaW1hZ2VcbiAgICovXG4gIHJlYWRvbmx5IHdvcmtmbG93Q29udGFpbmVySW1hZ2U/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFZlcnNpb24gcmVxdWlyZW1lbnQgb2YgYHB1YmxpYmAgd2hpY2ggaXMgdXNlZCB0byBwdWJsaXNoIG1vZHVsZXMgdG8gbnBtLlxuICAgKiBAZGVmYXVsdCBcImxhdGVzdFwiXG4gICAqL1xuICByZWFkb25seSBqc2lpUmVsZWFzZVZlcnNpb24/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFN0ZXBzIHRvIGV4ZWN1dGUgYWZ0ZXIgYnVpbGQgYXMgcGFydCBvZiB0aGUgcmVsZWFzZSB3b3JrZmxvdy5cbiAgICogQGRlZmF1bHQgW11cbiAgICovXG4gIHJlYWRvbmx5IHBvc3RCdWlsZFN0ZXBzPzogSm9iU3RlcFtdO1xuXG4gIC8qKlxuICAgKiBNYWpvciB2ZXJzaW9uIHRvIHJlbGVhc2UgZnJvbSB0aGUgZGVmYXVsdCBicmFuY2guXG4gICAqXG4gICAqIElmIHRoaXMgaXMgc3BlY2lmaWVkLCB3ZSBidW1wIHRoZSBsYXRlc3QgdmVyc2lvbiBvZiB0aGlzIG1ham9yIHZlcnNpb24gbGluZS5cbiAgICogSWYgbm90IHNwZWNpZmllZCwgd2UgYnVtcCB0aGUgZ2xvYmFsIGxhdGVzdCB2ZXJzaW9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE1ham9yIHZlcnNpb24gaXMgbm90IGVuZm9yY2VkLlxuICAgKi9cbiAgcmVhZG9ubHkgbWFqb3JWZXJzaW9uPzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBNaW5pbWFsIE1ham9yIHZlcnNpb24gdG8gcmVsZWFzZVxuICAgKlxuICAgKlxuICAgKiBUaGlzIGNhbiBiZSB1c2VmdWwgdG8gc2V0IHRvIDEsIGFzIGJyZWFraW5nIGNoYW5nZXMgYmVmb3JlIHRoZSAxLnggbWFqb3JcbiAgICogcmVsZWFzZSBhcmUgbm90IGluY3JlbWVudGluZyB0aGUgbWFqb3IgdmVyc2lvbiBudW1iZXIuXG4gICAqXG4gICAqIENhbiBub3QgYmUgc2V0IHRvZ2V0aGVyIHdpdGggYG1ham9yVmVyc2lvbmAuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gbWluaW11bSB2ZXJzaW9uIGlzIGJlaW5nIGVuZm9yY2VkXG4gICAqL1xuICByZWFkb25seSBtaW5NYWpvclZlcnNpb24/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIEJ1bXAgdmVyc2lvbnMgZnJvbSB0aGUgZGVmYXVsdCBicmFuY2ggYXMgcHJlLXJlbGVhc2VzIChlLmcuIFwiYmV0YVwiLFxuICAgKiBcImFscGhhXCIsIFwicHJlXCIpLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vcm1hbCBzZW1hbnRpYyB2ZXJzaW9uc1xuICAgKi9cbiAgcmVhZG9ubHkgcHJlcmVsZWFzZT86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIG5wbURpc3RUYWcgdG8gdXNlIHdoZW4gcHVibGlzaGluZyBmcm9tIHRoZSBkZWZhdWx0IGJyYW5jaC5cbiAgICpcbiAgICogVG8gc2V0IHRoZSBucG0gZGlzdC10YWcgZm9yIHJlbGVhc2UgYnJhbmNoZXMsIHNldCB0aGUgYG5wbURpc3RUYWdgIHByb3BlcnR5XG4gICAqIGZvciBlYWNoIGJyYW5jaC5cbiAgICpcbiAgICogQGRlZmF1bHQgXCJsYXRlc3RcIlxuICAgKi9cbiAgcmVhZG9ubHkgbnBtRGlzdFRhZz86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIGRlZmF1bHQgcmVsZWFzZSB3b3JrZmxvdy5cbiAgICpcbiAgICogQGRlZmF1bHQgXCJyZWxlYXNlXCJcbiAgICovXG4gIHJlYWRvbmx5IHJlbGVhc2VXb3JrZmxvd05hbWU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBHaXRIdWIgQWN0aW9ucyBlbnZpcm9ubWVudCB1c2VkIGZvciB0aGUgcmVsZWFzZS5cbiAgICpcbiAgICogVGhpcyBjYW4gYmUgdXNlZCB0byBhZGQgYW4gZXhwbGljaXQgYXBwcm92YWwgc3RlcCB0byB0aGUgcmVsZWFzZVxuICAgKiBvciBsaW1pdCB3aG8gY2FuIGluaXRpYXRlIGEgcmVsZWFzZSB0aHJvdWdoIGVudmlyb25tZW50IHByb3RlY3Rpb24gcnVsZXMuXG4gICAqXG4gICAqIFdoZW4gbXVsdGlwbGUgYXJ0aWZhY3RzIGFyZSByZWxlYXNlZCwgdGhlIGVudmlyb25tZW50IGNhbiBiZSBvdmVyd3JpdHRlblxuICAgKiBvbiBhIHBlciBhcnRpZmFjdCBiYXNpcy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBlbnZpcm9ubWVudCB1c2VkLCB1bmxlc3Mgc2V0IGF0IHRoZSBhcnRpZmFjdCBsZXZlbFxuICAgKi9cbiAgcmVhZG9ubHkgcmVsZWFzZUVudmlyb25tZW50Pzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBEZWZpbmVzIGFkZGl0aW9uYWwgcmVsZWFzZSBicmFuY2hlcy4gQSB3b3JrZmxvdyB3aWxsIGJlIGNyZWF0ZWQgZm9yIGVhY2hcbiAgICogcmVsZWFzZSBicmFuY2ggd2hpY2ggd2lsbCBwdWJsaXNoIHJlbGVhc2VzIGZyb20gY29tbWl0cyBpbiB0aGlzIGJyYW5jaC5cbiAgICogRWFjaCByZWxlYXNlIGJyYW5jaCBfbXVzdF8gYmUgYXNzaWduZWQgYSBtYWpvciB2ZXJzaW9uIG51bWJlciB3aGljaCBpcyB1c2VkXG4gICAqIHRvIGVuZm9yY2UgdGhhdCB2ZXJzaW9ucyBwdWJsaXNoZWQgZnJvbSB0aGF0IGJyYW5jaCBhbHdheXMgdXNlIHRoYXQgbWFqb3JcbiAgICogdmVyc2lvbi4gSWYgbXVsdGlwbGUgYnJhbmNoZXMgYXJlIHVzZWQsIHRoZSBgbWFqb3JWZXJzaW9uYCBmaWVsZCBtdXN0IGFsc29cbiAgICogYmUgcHJvdmlkZWQgZm9yIHRoZSBkZWZhdWx0IGJyYW5jaC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBhZGRpdGlvbmFsIGJyYW5jaGVzIGFyZSB1c2VkIGZvciByZWxlYXNlLiB5b3UgY2FuIHVzZVxuICAgKiBgYWRkQnJhbmNoKClgIHRvIGFkZCBhZGRpdGlvbmFsIGJyYW5jaGVzLlxuICAgKi9cbiAgcmVhZG9ubHkgcmVsZWFzZUJyYW5jaGVzPzogeyBbbmFtZTogc3RyaW5nXTogQnJhbmNoT3B0aW9ucyB9O1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIEdpdEh1YiBzaG91bGQgZXhwbGljaXRseSBtYXJrIHRoZSByZWxlYXNlIGZyb20gdGhlIGRlZmF1bHQgYnJhbmNoXG4gICAqIGFzIHRoZSBsYXRlc3QgcmVsZWFzZS5cbiAgICpcbiAgICogU2V0IHRvIGB0cnVlYCB0byBtYXJrIHRoZSByZWxlYXNlIGFzIGxhdGVzdCwgb3IgYGZhbHNlYCB0byBleHBsaWNpdGx5IG5vdFxuICAgKiBtYXJrIGl0IGFzIGxhdGVzdC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBHaXRIdWIgZGV0ZXJtaW5lcyB0aGUgbGF0ZXN0IHJlbGVhc2UgYmFzZWQgb24gZGF0ZSBhbmQgc2VtYW50aWMgdmVyc2lvbi5cbiAgICovXG4gIHJlYWRvbmx5IGdpdGh1YlJlbGVhc2VMYXRlc3Q/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBnaXRodWIgaXNzdWUgb24gZXZlcnkgZmFpbGVkIHB1Ymxpc2hpbmcgdGFzay5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IHJlbGVhc2VGYWlsdXJlSXNzdWU/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBUaGUgbGFiZWwgdG8gYXBwbHkgdG8gaXNzdWVzIGluZGljYXRpbmcgcHVibGlzaCBmYWlsdXJlcy5cbiAgICogT25seSBhcHBsaWVzIGlmIGByZWxlYXNlRmFpbHVyZUlzc3VlYCBpcyB0cnVlLlxuICAgKlxuICAgKiBAZGVmYXVsdCBcImZhaWxlZC1yZWxlYXNlXCJcbiAgICovXG4gIHJlYWRvbmx5IHJlbGVhc2VGYWlsdXJlSXNzdWVMYWJlbD86IHN0cmluZztcblxuICAvKipcbiAgICogQXV0b21hdGljYWxseSBhZGQgdGhlIGdpdmVuIHByZWZpeCB0byByZWxlYXNlIHRhZ3MuXG4gICAqIFVzZWZ1bCBpZiB5b3UgYXJlIHJlbGVhc2luZyBvbiBtdWx0aXBsZSBicmFuY2hlcyB3aXRoIG92ZXJsYXBwaW5nXG4gICAqIHZlcnNpb24gbnVtYmVycy5cbiAgICpcbiAgICogTm90ZTogdGhpcyBwcmVmaXggaXMgdXNlZCB0byBkZXRlY3QgdGhlIGxhdGVzdCB0YWdnZWQgdmVyc2lvblxuICAgKiB3aGVuIGJ1bXBpbmcsIHNvIGlmIHlvdSBjaGFuZ2UgdGhpcyBvbiBhIHByb2plY3Qgd2l0aCBhbiBleGlzdGluZyB2ZXJzaW9uXG4gICAqIGhpc3RvcnksIHlvdSBtYXkgbmVlZCB0byBtYW51YWxseSB0YWcgeW91ciBsYXRlc3QgcmVsZWFzZVxuICAgKiB3aXRoIHRoZSBuZXcgcHJlZml4LlxuICAgKlxuICAgKiBAZGVmYXVsdCBcInZcIlxuICAgKi9cbiAgcmVhZG9ubHkgcmVsZWFzZVRhZ1ByZWZpeD86IHN0cmluZztcblxuICAvKipcbiAgICogQ3VzdG9tIGNvbmZpZ3VyYXRpb24gdXNlZCB3aGVuIGNyZWF0aW5nIGNoYW5nZWxvZyB3aXRoIGNvbW1pdC1hbmQtdGFnLXZlcnNpb24gcGFja2FnZS5cbiAgICogR2l2ZW4gdmFsdWVzIGVpdGhlciBhcHBlbmQgdG8gZGVmYXVsdCBjb25maWd1cmF0aW9uIG9yIG92ZXJ3cml0ZSB2YWx1ZXMgaW4gaXQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gc3RhbmRhcmQgY29uZmlndXJhdGlvbiBhcHBsaWNhYmxlIGZvciBHaXRIdWIgcmVwb3NpdG9yaWVzXG4gICAqL1xuICByZWFkb25seSB2ZXJzaW9ucmNPcHRpb25zPzogUmVjb3JkPHN0cmluZywgYW55PjtcblxuICAvKipcbiAgICogR2l0aHViIFJ1bm5lciBzZWxlY3Rpb24gbGFiZWxzXG4gICAqIEBkZWZhdWx0IFtcInVidW50dS1sYXRlc3RcIl1cbiAgICogQGRlc2NyaXB0aW9uIERlZmluZXMgYSB0YXJnZXQgUnVubmVyIGJ5IGxhYmVsc1xuICAgKiBAdGhyb3dzIHtFcnJvcn0gaWYgYm90aCBgcnVuc09uYCBhbmQgYHJ1bnNPbkdyb3VwYCBhcmUgc3BlY2lmaWVkXG4gICAqIEBkZXByZWNhdGVkIHVzZSBgZ2l0aHViT3B0aW9ucy53b3JrZmxvd1J1bnNPbmAgb24gdGhlIHByb2plY3QsIG9yIGBydW5zT25gIG9uIGBSZWxlYXNlT3B0aW9uc2BcbiAgICovXG4gIHJlYWRvbmx5IHdvcmtmbG93UnVuc09uPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIEdpdGh1YiBSdW5uZXIgR3JvdXAgc2VsZWN0aW9uIG9wdGlvbnNcbiAgICogQGRlc2NyaXB0aW9uIERlZmluZXMgYSB0YXJnZXQgUnVubmVyIEdyb3VwIGJ5IG5hbWUgYW5kL29yIGxhYmVsc1xuICAgKiBAdGhyb3dzIHtFcnJvcn0gaWYgYm90aCBgcnVuc09uYCBhbmQgYHJ1bnNPbkdyb3VwYCBhcmUgc3BlY2lmaWVkXG4gICAqIEBkZXByZWNhdGVkIHVzZSBgZ2l0aHViT3B0aW9ucy53b3JrZmxvd1J1bnNPbkdyb3VwYCBvbiB0aGUgcHJvamVjdCwgb3IgYHJ1bnNPbkdyb3VwYCBvbiBgUmVsZWFzZU9wdGlvbnNgXG4gICAqL1xuICByZWFkb25seSB3b3JrZmxvd1J1bnNPbkdyb3VwPzogR3JvdXBSdW5uZXJPcHRpb25zO1xuXG4gIC8qKlxuICAgKiBEZWZpbmUgcHVibGlzaGluZyB0YXNrcyB0aGF0IGNhbiBiZSBleGVjdXRlZCBtYW51YWxseSBhcyB3ZWxsIGFzIHdvcmtmbG93cy5cbiAgICpcbiAgICogTm9ybWFsbHksIHB1Ymxpc2hpbmcgb25seSBoYXBwZW5zIHdpdGhpbiBhdXRvbWF0ZWQgd29ya2Zsb3dzLiBFbmFibGUgdGhpc1xuICAgKiBpbiBvcmRlciB0byBjcmVhdGUgYSBwdWJsaXNoaW5nIHRhc2sgZm9yIGVhY2ggcHVibGlzaGluZyBhY3Rpdml0eS5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IHB1Ymxpc2hUYXNrcz86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEluc3RlYWQgb2YgYWN0dWFsbHkgcHVibGlzaGluZyB0byBwYWNrYWdlIG1hbmFnZXJzLCBqdXN0IHByaW50IHRoZSBwdWJsaXNoaW5nIGNvbW1hbmQuXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBwdWJsaXNoRHJ5UnVuPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogRmluZCBjb21taXRzIHRoYXQgc2hvdWxkIGJlIGNvbnNpZGVyZWQgcmVsZWFzYWJsZVxuICAgKiBVc2VkIHRvIGRlY2lkZSBpZiBhIHJlbGVhc2UgaXMgcmVxdWlyZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IFJlbGVhc2FibGVDb21taXRzLmV2ZXJ5Q29tbWl0KClcbiAgICovXG4gIHJlYWRvbmx5IHJlbGVhc2FibGVDb21taXRzPzogUmVsZWFzYWJsZUNvbW1pdHM7XG5cbiAgLyoqXG4gICAqIEJ1aWxkIGVudmlyb25tZW50IHZhcmlhYmxlcyBmb3IgcmVsZWFzZSB3b3JrZmxvd3MuXG4gICAqXG4gICAqIEBkZWZhdWx0IHt9XG4gICAqL1xuICByZWFkb25seSByZWxlYXNlV29ya2Zsb3dFbnY/OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9O1xuXG4gIC8qKlxuICAgKiBUaGUgYGNvbW1pdC1hbmQtdGFnLXZlcnNpb25gIGNvbXBhdGlibGUgcGFja2FnZSB1c2VkIHRvIGJ1bXAgdGhlIHBhY2thZ2UgdmVyc2lvbiwgYXMgYSBkZXBlbmRlbmN5IHN0cmluZy5cbiAgICpcbiAgICogVGhpcyBjYW4gYmUgYW55IGNvbXBhdGlibGUgcGFja2FnZSB2ZXJzaW9uLCBpbmNsdWRpbmcgdGhlIGRlcHJlY2F0ZWQgYHN0YW5kYXJkLXZlcnNpb25AOWAuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gQSByZWNlbnQgdmVyc2lvbiBvZiBcImNvbW1pdC1hbmQtdGFnLXZlcnNpb25cIlxuICAgKi9cbiAgcmVhZG9ubHkgYnVtcFBhY2thZ2U/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEEgc2hlbGwgY29tbWFuZCB0byBjb250cm9sIHRoZSBuZXh0IHZlcnNpb24gdG8gcmVsZWFzZS5cbiAgICpcbiAgICogSWYgcHJlc2VudCwgdGhpcyBzaGVsbCBjb21tYW5kIHdpbGwgYmUgcnVuIGJlZm9yZSB0aGUgYnVtcCBpcyBleGVjdXRlZCwgYW5kXG4gICAqIGl0IGRldGVybWluZXMgd2hhdCB2ZXJzaW9uIHRvIHJlbGVhc2UuIEl0IHdpbGwgYmUgZXhlY3V0ZWQgaW4gdGhlIGZvbGxvd2luZ1xuICAgKiBlbnZpcm9ubWVudDpcbiAgICpcbiAgICogLSBXb3JraW5nIGRpcmVjdG9yeTogdGhlIHByb2plY3QgZGlyZWN0b3J5LlxuICAgKiAtIGAkVkVSU0lPTmA6IHRoZSBjdXJyZW50IHZlcnNpb24uIExvb2tzIGxpa2UgYDEuMi4zYC5cbiAgICogLSBgJExBVEVTVF9UQUdgOiB0aGUgbW9zdCByZWNlbnQgdGFnLiBMb29rcyBsaWtlIGBwcmVmaXgtdjEuMi4zYCwgb3IgbWF5IGJlIHVuc2V0LlxuICAgKiAtIGAkU1VHR0VTVEVEX0JVTVBgOiB0aGUgc3VnZ2VzdGVkIGJ1bXAgYWN0aW9uIGJhc2VkIG9uIGNvbW1pdHMuIE9uZSBvZiBgbWFqb3J8bWlub3J8cGF0Y2h8bm9uZWAuXG4gICAqXG4gICAqIFRoZSBjb21tYW5kIHNob3VsZCBwcmludCBvbmUgb2YgdGhlIGZvbGxvd2luZyB0byBgc3Rkb3V0YDpcbiAgICpcbiAgICogLSBOb3RoaW5nOiB0aGUgbmV4dCB2ZXJzaW9uIG51bWJlciB3aWxsIGJlIGRldGVybWluZWQgYmFzZWQgb24gY29tbWl0IGhpc3RvcnkuXG4gICAqIC0gYHgueS56YDogdGhlIG5leHQgdmVyc2lvbiBudW1iZXIgd2lsbCBiZSBgeC55LnpgLlxuICAgKiAtIGBtYWpvcnxtaW5vcnxwYXRjaGA6IHRoZSBuZXh0IHZlcnNpb24gbnVtYmVyIHdpbGwgYmUgdGhlIGN1cnJlbnQgdmVyc2lvbiBudW1iZXJcbiAgICogICB3aXRoIHRoZSBpbmRpY2F0ZWQgY29tcG9uZW50IGJ1bXBlZC5cbiAgICpcbiAgICogVGhpcyBzZXR0aW5nIGNhbm5vdCBiZSBzcGVjaWZpZWQgdG9nZXRoZXIgd2l0aCBgbWluTWFqb3JWZXJzaW9uYDsgdGhlIGludm9rZWRcbiAgICogc2NyaXB0IGNhbiBiZSB1c2VkIHRvIGFjaGlldmUgdGhlIGVmZmVjdHMgb2YgYG1pbk1ham9yVmVyc2lvbmAuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gVGhlIG5leHQgdmVyc2lvbiB3aWxsIGJlIGRldGVybWluZWQgYmFzZWQgb24gdGhlIGNvbW1pdCBoaXN0b3J5IGFuZCBwcm9qZWN0IHNldHRpbmdzLlxuICAgKi9cbiAgcmVhZG9ubHkgbmV4dFZlcnNpb25Db21tYW5kPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIE9wdGlvbnMgZm9yIGBSZWxlYXNlYC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZWxlYXNlT3B0aW9ucyBleHRlbmRzIFJlbGVhc2VQcm9qZWN0T3B0aW9ucyB7XG4gIC8qKlxuICAgKiBHaXRodWIgUnVubmVyIHNlbGVjdGlvbiBsYWJlbHNcbiAgICogQGRlZmF1bHQgW1widWJ1bnR1LWxhdGVzdFwiXVxuICAgKiBAZGVzY3JpcHRpb24gRGVmaW5lcyBhIHRhcmdldCBSdW5uZXIgYnkgbGFiZWxzXG4gICAqIEB0aHJvd3Mge0Vycm9yfSBpZiBib3RoIGBydW5zT25gIGFuZCBgcnVuc09uR3JvdXBgIGFyZSBzcGVjaWZpZWRcbiAgICovXG4gIHJlYWRvbmx5IHJ1bnNPbj86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBHaXRodWIgUnVubmVyIEdyb3VwIHNlbGVjdGlvbiBvcHRpb25zXG4gICAqIEBkZXNjcmlwdGlvbiBEZWZpbmVzIGEgdGFyZ2V0IFJ1bm5lciBHcm91cCBieSBuYW1lIGFuZC9vciBsYWJlbHNcbiAgICogQHRocm93cyB7RXJyb3J9IGlmIGJvdGggYHJ1bnNPbmAgYW5kIGBydW5zT25Hcm91cGAgYXJlIHNwZWNpZmllZFxuICAgKi9cbiAgcmVhZG9ubHkgcnVuc09uR3JvdXA/OiBHcm91cFJ1bm5lck9wdGlvbnM7XG5cbiAgLyoqXG4gICAqIFRoZSB0YXNrcyB0byBleGVjdXRlIGluIG9yZGVyIHRvIGNyZWF0ZSB0aGUgcmVsZWFzZSBhcnRpZmFjdHMuIEFydGlmYWN0cyBhcmVcbiAgICogZXhwZWN0ZWQgdG8gcmVzaWRlIHVuZGVyIGBhcnRpZmFjdHNEaXJlY3RvcnlgIChkZWZhdWx0cyB0byBgZGlzdC9gKSBvbmNlXG4gICAqIGJ1aWxkIGlzIGNvbXBsZXRlLlxuICAgKi9cbiAgcmVhZG9ubHkgdGFza3M/OiBUYXNrW107XG5cbiAgLyoqXG4gICAqIEEgbmFtZSBvZiBhIC5qc29uIGZpbGUgdG8gc2V0IHRoZSBgdmVyc2lvbmAgZmllbGQgaW4gYWZ0ZXIgYSBidW1wLlxuICAgKlxuICAgKiBAZXhhbXBsZSBcInBhY2thZ2UuanNvblwiXG4gICAqL1xuICByZWFkb25seSB2ZXJzaW9uRmlsZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgZGVmYXVsdCBicmFuY2ggbmFtZSB0byByZWxlYXNlIGZyb20uXG4gICAqXG4gICAqIFVzZSBgbWFqb3JWZXJzaW9uYCB0byByZXN0cmljdCB0aGlzIGJyYW5jaCB0byBvbmx5IHB1Ymxpc2ggcmVsZWFzZXMgd2l0aCBhXG4gICAqIHNwZWNpZmljIG1ham9yIHZlcnNpb24uXG4gICAqXG4gICAqIFlvdSBjYW4gYWRkIGFkZGl0aW9uYWwgYnJhbmNoZXMgdXNpbmcgYGFkZEJyYW5jaCgpYC5cbiAgICovXG4gIHJlYWRvbmx5IGJyYW5jaDogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBHaXRIdWIgcmVsZWFzZSBmb3IgZWFjaCByZWxlYXNlLlxuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSBnaXRodWJSZWxlYXNlPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogQSBkaXJlY3Rvcnkgd2hpY2ggd2lsbCBjb250YWluIGJ1aWxkIGFydGlmYWN0cy5cbiAgICpcbiAgICogQGRlZmF1bHQgXCJkaXN0XCJcbiAgICovXG4gIHJlYWRvbmx5IGFydGlmYWN0c0RpcmVjdG9yeTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBOb2RlIHZlcnNpb24gdG8gc2V0dXAgaW4gR2l0SHViIHdvcmtmbG93cyBpZiBhbnkgbm9kZS1iYXNlZCBDTEkgdXRpbGl0aWVzXG4gICAqIGFyZSBuZWVkZWQuIEZvciBleGFtcGxlIGBwdWJsaWJgLCB0aGUgQ0xJIHByb2plbiB1c2VzIHRvIHB1Ymxpc2ggcmVsZWFzZXMsXG4gICAqIGlzIGFuIG5wbSBsaWJyYXJ5LlxuICAgKlxuICAgKiBAZGVmYXVsdCBcImx0cy8qXCJcIlxuICAgKi9cbiAgcmVhZG9ubHkgd29ya2Zsb3dOb2RlVmVyc2lvbj86IHN0cmluZztcblxuICAvKipcbiAgICogUGVybWlzc2lvbnMgZ3JhbnRlZCB0byB0aGUgcmVsZWFzZSB3b3JrZmxvdyBqb2JcbiAgICogQGRlZmF1bHQgYHsgY29udGVudHM6IEpvYlBlcm1pc3Npb24uV1JJVEUgfWBcbiAgICovXG4gIHJlYWRvbmx5IHdvcmtmbG93UGVybWlzc2lvbnM/OiBKb2JQZXJtaXNzaW9ucztcbn1cblxuLyoqXG4gKiBNYW5hZ2VzIHJlbGVhc2VzIChjdXJyZW50bHkgdGhyb3VnaCBHaXRIdWIgd29ya2Zsb3dzKS5cbiAqXG4gKiBCeSBkZWZhdWx0LCBubyBicmFuY2hlcyBhcmUgcmVsZWFzZWQuIFRvIGFkZCBicmFuY2hlcywgY2FsbCBgYWRkQnJhbmNoKClgLlxuICovXG5leHBvcnQgY2xhc3MgUmVsZWFzZSBleHRlbmRzIENvbXBvbmVudCB7XG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgQU5USV9UQU1QRVJfQ01EID1cbiAgICBcImdpdCBkaWZmIC0taWdub3JlLXNwYWNlLWF0LWVvbCAtLWV4aXQtY29kZVwiO1xuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBgUmVsZWFzZWAgY29tcG9uZW50IG9mIGEgcHJvamVjdCBvciBgdW5kZWZpbmVkYCBpZiB0aGUgcHJvamVjdFxuICAgKiBkb2VzIG5vdCBoYXZlIGEgUmVsZWFzZSBjb21wb25lbnQuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIG9mKHByb2plY3Q6IFByb2plY3QpOiBSZWxlYXNlIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBpc1JlbGVhc2UgPSAoYzogQ29tcG9uZW50KTogYyBpcyBSZWxlYXNlID0+IGMgaW5zdGFuY2VvZiBSZWxlYXNlO1xuICAgIHJldHVybiBwcm9qZWN0LmNvbXBvbmVudHMuZmluZChpc1JlbGVhc2UpO1xuICB9XG5cbiAgLyoqXG4gICAqIFBhY2thZ2UgcHVibGlzaGVyLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHB1Ymxpc2hlcjogUHVibGlzaGVyO1xuXG4gIC8qKlxuICAgKiBMb2NhdGlvbiBvZiBidWlsZCBhcnRpZmFjdHMuXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgYXJ0aWZhY3RzRGlyZWN0b3J5OiBzdHJpbmc7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBidWlsZFRhc2tzOiBUYXNrW107XG4gIHByaXZhdGUgcmVhZG9ubHkgdmVyc2lvbjogVmVyc2lvbjtcbiAgcHJpdmF0ZSByZWFkb25seSBwb3N0QnVpbGRTdGVwczogSm9iU3RlcFtdO1xuICBwcml2YXRlIHJlYWRvbmx5IHZlcnNpb25GaWxlOiBzdHJpbmc7XG4gIHByaXZhdGUgcmVhZG9ubHkgcmVsZWFzZVRyaWdnZXI6IFJlbGVhc2VUcmlnZ2VyO1xuICBwcml2YXRlIHJlYWRvbmx5IHByZUJ1aWxkU3RlcHM6IEpvYlN0ZXBbXTtcbiAgcHJpdmF0ZSByZWFkb25seSBjb250YWluZXJJbWFnZT86IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBfYnJhbmNoZXMgPSBuZXcgQXJyYXk8UmVsZWFzZUJyYW5jaD4oKTtcbiAgcHJpdmF0ZSByZWFkb25seSBqb2JzOiBSZWNvcmQ8c3RyaW5nLCBKb2I+ID0ge307XG4gIHByaXZhdGUgcmVhZG9ubHkgZGVmYXVsdEJyYW5jaDogUmVsZWFzZUJyYW5jaDtcbiAgcHJpdmF0ZSByZWFkb25seSBnaXRodWI/OiBHaXRIdWI7XG4gIHByaXZhdGUgcmVhZG9ubHkgcnVuc09uPzogc3RyaW5nW107XG4gIHByaXZhdGUgcmVhZG9ubHkgcnVuc09uR3JvdXA/OiBHcm91cFJ1bm5lck9wdGlvbnM7XG4gIHByaXZhdGUgcmVhZG9ubHkgd29ya2Zsb3dQZXJtaXNzaW9uczogSm9iUGVybWlzc2lvbnM7XG4gIHByaXZhdGUgcmVhZG9ubHkgcmVsZWFzZVdvcmtmbG93RW52PzogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfTtcbiAgcHJpdmF0ZSByZWFkb25seSByZWxlYXNlVGFnRmlsZVBhdGg6IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBfYnJhbmNoSG9va3M6IEJyYW5jaEhvb2tbXTtcblxuICAvKipcbiAgICogQHBhcmFtIHNjb3BlIHNob3VsZCBiZSBwYXJ0IG9mIHRoZSBwcm9qZWN0IHRoZSBSZWxlYXNlIGJlbG9uZ3MgdG8uXG4gICAqIEBwYXJhbSBvcHRpb25zIG9wdGlvbnMgdG8gY29uZmlndXJlIHRoZSBSZWxlYXNlIENvbXBvbmVudC5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBJQ29uc3RydWN0LCBvcHRpb25zOiBSZWxlYXNlT3B0aW9ucykge1xuICAgIHN1cGVyKHNjb3BlKTtcblxuICAgIGlmIChBcnJheS5pc0FycmF5KG9wdGlvbnMucmVsZWFzZUJyYW5jaGVzKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnXCJyZWxlYXNlQnJhbmNoZXNcIiBpcyBubyBsb25nZXIgYW4gYXJyYXkuIFNlZSB0eXBlIGFubm90YXRpb25zJyxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgdGhpcy5naXRodWIgPSBHaXRIdWIub2YodGhpcy5wcm9qZWN0LnJvb3QpO1xuICAgIGNvbnN0IHJ1bnNPbkNvbmZpZyA9IHRoaXMuZ2l0aHViPy5ydW5zT25Db25maWcoe1xuICAgICAgcnVuc09uOiBvcHRpb25zLnJ1bnNPbiA/PyBvcHRpb25zLndvcmtmbG93UnVuc09uLFxuICAgICAgcnVuc09uR3JvdXA6IG9wdGlvbnMucnVuc09uR3JvdXAgPz8gb3B0aW9ucy53b3JrZmxvd1J1bnNPbkdyb3VwLFxuICAgIH0pO1xuICAgIHRoaXMucnVuc09uID0gcnVuc09uQ29uZmlnPy5ydW5zT247XG4gICAgdGhpcy5ydW5zT25Hcm91cCA9IHJ1bnNPbkNvbmZpZz8ucnVuc09uR3JvdXA7XG5cbiAgICAvLyBEZXRlcm1pbmUgdGhlIHRhc2tzIHRvIHVzZSB0byBjcmVhdGUgdGhlIHJlbGVhc2UgYXJ0aWZhY3RzXG4gICAgaWYgKG9wdGlvbnMudGFza3MgJiYgb3B0aW9ucy50YXNrcy5sZW5ndGggPiAwKSB7XG4gICAgICB0aGlzLmJ1aWxkVGFza3MgPSBvcHRpb25zLnRhc2tzO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCIndGFza3MnIG11c3QgYmUgcHJvdmlkZWQuXCIpO1xuICAgIH1cblxuICAgIHRoaXMucHJlQnVpbGRTdGVwcyA9IG9wdGlvbnMucmVsZWFzZVdvcmtmbG93U2V0dXBTdGVwcyA/PyBbXTtcbiAgICB0aGlzLnBvc3RCdWlsZFN0ZXBzID0gb3B0aW9ucy5wb3N0QnVpbGRTdGVwcyA/PyBbXTtcbiAgICB0aGlzLmFydGlmYWN0c0RpcmVjdG9yeSA9XG4gICAgICBvcHRpb25zLmFydGlmYWN0c0RpcmVjdG9yeSA/PyBERUZBVUxUX0FSVElGQUNUU19ESVJFQ1RPUlk7XG4gICAgZW5zdXJlTm90SGlkZGVuUGF0aCh0aGlzLmFydGlmYWN0c0RpcmVjdG9yeSwgXCJhcnRpZmFjdHNEaXJlY3RvcnlcIik7XG4gICAgZW5zdXJlUGF0aEluc2lkZVByb2plY3QoXG4gICAgICB0aGlzLmFydGlmYWN0c0RpcmVjdG9yeSxcbiAgICAgIFwiYXJ0aWZhY3RzRGlyZWN0b3J5XCIsXG4gICAgICB0aGlzLnByb2plY3Qub3V0ZGlyLFxuICAgICk7XG4gICAgdGhpcy52ZXJzaW9uRmlsZSA9IG9wdGlvbnMudmVyc2lvbkZpbGU7XG4gICAgdGhpcy5yZWxlYXNlVHJpZ2dlciA9IG9wdGlvbnMucmVsZWFzZVRyaWdnZXIgPz8gUmVsZWFzZVRyaWdnZXIuY29udGludW91cygpO1xuICAgIHRoaXMuY29udGFpbmVySW1hZ2UgPSBvcHRpb25zLndvcmtmbG93Q29udGFpbmVySW1hZ2U7XG4gICAgdGhpcy53b3JrZmxvd1Blcm1pc3Npb25zID0ge1xuICAgICAgY29udGVudHM6IEpvYlBlcm1pc3Npb24uV1JJVEUsXG4gICAgICAuLi5vcHRpb25zLndvcmtmbG93UGVybWlzc2lvbnMsXG4gICAgfTtcbiAgICB0aGlzLnJlbGVhc2VXb3JrZmxvd0VudiA9IG9wdGlvbnMucmVsZWFzZVdvcmtmbG93RW52O1xuICAgIHRoaXMuX2JyYW5jaEhvb2tzID0gW107XG5cbiAgICB0aGlzLnZlcnNpb24gPSBuZXcgVmVyc2lvbih0aGlzLnByb2plY3QsIHtcbiAgICAgIHZlcnNpb25JbnB1dEZpbGU6IHRoaXMudmVyc2lvbkZpbGUsXG4gICAgICBhcnRpZmFjdHNEaXJlY3Rvcnk6IHRoaXMuYXJ0aWZhY3RzRGlyZWN0b3J5LFxuICAgICAgdmVyc2lvbnJjT3B0aW9uczogb3B0aW9ucy52ZXJzaW9ucmNPcHRpb25zLFxuICAgICAgdGFnUHJlZml4OiBvcHRpb25zLnJlbGVhc2VUYWdQcmVmaXgsXG4gICAgICByZWxlYXNhYmxlQ29tbWl0czogb3B0aW9ucy5yZWxlYXNhYmxlQ29tbWl0cyxcbiAgICAgIGJ1bXBQYWNrYWdlOiBvcHRpb25zLmJ1bXBQYWNrYWdlLFxuICAgICAgbmV4dFZlcnNpb25Db21tYW5kOiBvcHRpb25zLm5leHRWZXJzaW9uQ29tbWFuZCxcbiAgICB9KTtcblxuICAgIHRoaXMucmVsZWFzZVRhZ0ZpbGVQYXRoID0gcG9zaXhQYXRoLm5vcm1hbGl6ZShcbiAgICAgIHBvc2l4UGF0aC5qb2luKHRoaXMuYXJ0aWZhY3RzRGlyZWN0b3J5LCB0aGlzLnZlcnNpb24ucmVsZWFzZVRhZ0ZpbGVOYW1lKSxcbiAgICApO1xuXG4gICAgdGhpcy5wdWJsaXNoZXIgPSBuZXcgUHVibGlzaGVyKHRoaXMucHJvamVjdCwge1xuICAgICAgYXJ0aWZhY3ROYW1lOiB0aGlzLmFydGlmYWN0c0RpcmVjdG9yeSxcbiAgICAgIGNvbmRpdGlvbjogREVQRU5ERU5UX0pPQl9DT05ESVRJT05BTCxcbiAgICAgIGJ1aWxkSm9iSWQ6IEJVSUxEX0pPQklELFxuICAgICAgcHVibGliVmVyc2lvbjogb3B0aW9ucy5qc2lpUmVsZWFzZVZlcnNpb24sXG4gICAgICBmYWlsdXJlSXNzdWU6IG9wdGlvbnMucmVsZWFzZUZhaWx1cmVJc3N1ZSxcbiAgICAgIGZhaWx1cmVJc3N1ZUxhYmVsOiBvcHRpb25zLnJlbGVhc2VGYWlsdXJlSXNzdWVMYWJlbCxcbiAgICAgIC4uLmZpbHRlcmVkV29ya2Zsb3dSdW5zT25PcHRpb25zKHRoaXMucnVuc09uLCB0aGlzLnJ1bnNPbkdyb3VwKSxcbiAgICAgIHB1Ymxpc2hUYXNrczogb3B0aW9ucy5wdWJsaXNoVGFza3MsXG4gICAgICBkcnlSdW46IG9wdGlvbnMucHVibGlzaERyeVJ1bixcbiAgICAgIHdvcmtmbG93Tm9kZVZlcnNpb246IG9wdGlvbnMud29ya2Zsb3dOb2RlVmVyc2lvbixcbiAgICAgIHdvcmtmbG93Q29udGFpbmVySW1hZ2U6IG9wdGlvbnMud29ya2Zsb3dDb250YWluZXJJbWFnZSxcbiAgICB9KTtcblxuICAgIGNvbnN0IGdpdGh1YlJlbGVhc2UgPSBvcHRpb25zLmdpdGh1YlJlbGVhc2UgPz8gdHJ1ZTtcbiAgICBpZiAoZ2l0aHViUmVsZWFzZSkge1xuICAgICAgdGhpcy5wdWJsaXNoZXIucHVibGlzaFRvR2l0SHViUmVsZWFzZXMoe1xuICAgICAgICBjaGFuZ2Vsb2dGaWxlOiBwb3NpeFBhdGguam9pbihcbiAgICAgICAgICB0aGlzLmFydGlmYWN0c0RpcmVjdG9yeSxcbiAgICAgICAgICB0aGlzLnZlcnNpb24uY2hhbmdlbG9nRmlsZU5hbWUsXG4gICAgICAgICksXG4gICAgICAgIHZlcnNpb25GaWxlOiBwb3NpeFBhdGguam9pbihcbiAgICAgICAgICB0aGlzLmFydGlmYWN0c0RpcmVjdG9yeSxcbiAgICAgICAgICB0aGlzLnZlcnNpb24udmVyc2lvbkZpbGVOYW1lLFxuICAgICAgICApLFxuICAgICAgICByZWxlYXNlVGFnRmlsZTogcG9zaXhQYXRoLmpvaW4oXG4gICAgICAgICAgdGhpcy5hcnRpZmFjdHNEaXJlY3RvcnksXG4gICAgICAgICAgdGhpcy52ZXJzaW9uLnJlbGVhc2VUYWdGaWxlTmFtZSxcbiAgICAgICAgKSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIGFkZCB0aGUgZGVmYXVsdCBicmFuY2ggKHdlIG5lZWQgdGhlIGludGVybmFsIG1ldGhvZCB3aGljaCBkb2VzIG5vdCByZXF1aXJlIG1ham9yVmVyc2lvbilcbiAgICB0aGlzLmRlZmF1bHRCcmFuY2ggPSB0aGlzLl9hZGRCcmFuY2gob3B0aW9ucy5icmFuY2gsIHtcbiAgICAgIHByZXJlbGVhc2U6IG9wdGlvbnMucHJlcmVsZWFzZSxcbiAgICAgIGdpdGh1YlJlbGVhc2VMYXRlc3Q6IG9wdGlvbnMuZ2l0aHViUmVsZWFzZUxhdGVzdCxcbiAgICAgIG1ham9yVmVyc2lvbjogb3B0aW9ucy5tYWpvclZlcnNpb24sXG4gICAgICBtaW5NYWpvclZlcnNpb246IG9wdGlvbnMubWluTWFqb3JWZXJzaW9uLFxuICAgICAgd29ya2Zsb3dOYW1lOlxuICAgICAgICBvcHRpb25zLnJlbGVhc2VXb3JrZmxvd05hbWUgPz9cbiAgICAgICAgd29ya2Zsb3dOYW1lRm9yUHJvamVjdChcInJlbGVhc2VcIiwgdGhpcy5wcm9qZWN0KSxcbiAgICAgIGVudmlyb25tZW50OiBvcHRpb25zLnJlbGVhc2VFbnZpcm9ubWVudCxcbiAgICAgIHRhZ1ByZWZpeDogb3B0aW9ucy5yZWxlYXNlVGFnUHJlZml4LFxuICAgICAgbnBtRGlzdFRhZzogb3B0aW9ucy5ucG1EaXN0VGFnLFxuICAgIH0pO1xuXG4gICAgZm9yIChjb25zdCBbbmFtZSwgb3B0c10gb2YgT2JqZWN0LmVudHJpZXMob3B0aW9ucy5yZWxlYXNlQnJhbmNoZXMgPz8ge30pKSB7XG4gICAgICB0aGlzLmFkZEJyYW5jaChuYW1lLCB7XG4gICAgICAgIGVudmlyb25tZW50OiBvcHRpb25zLnJlbGVhc2VFbnZpcm9ubWVudCxcbiAgICAgICAgLi4ub3B0cyxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgYSBob29rIHRoYXQgc2hvdWxkIGJlIHJ1biBmb3IgZXZlcnkgYnJhbmNoIChpbmNsdWRpbmcgdGhvc2UgdGhhdCB3aWxsXG4gICAqIGJlIGFkZGVkIGJ5IGZ1dHVyZSBgYWRkQnJhbmNoYCBjYWxscykuXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHVibGljIF9mb3JFYWNoQnJhbmNoKGhvb2s6IEJyYW5jaEhvb2spIHtcbiAgICBmb3IgKGNvbnN0IGJyYW5jaCBvZiB0aGlzLl9icmFuY2hlcykge1xuICAgICAgaG9vayhicmFuY2gubmFtZSk7XG4gICAgfVxuICAgIHRoaXMuX2JyYW5jaEhvb2tzLnB1c2goaG9vayk7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhIHJlbGVhc2UgYnJhbmNoLlxuICAgKlxuICAgKiBJdCBpcyBhIGdpdCBicmFuY2ggZnJvbSB3aGljaCByZWxlYXNlcyBhcmUgcHVibGlzaGVkLiBJZiBhIHByb2plY3QgaGFzIG1vcmUgdGhhbiBvbmUgcmVsZWFzZVxuICAgKiBicmFuY2gsIHdlIHJlcXVpcmUgdGhhdCBgbWFqb3JWZXJzaW9uYCBpcyBhbHNvIHNwZWNpZmllZCBmb3IgdGhlIHByaW1hcnkgYnJhbmNoIGluIG9yZGVyIHRvXG4gICAqIGVuc3VyZSBicmFuY2hlcyBhbHdheXMgcmVsZWFzZSB0aGUgY29ycmVjdCB2ZXJzaW9uLlxuICAgKlxuICAgKiBAcGFyYW0gYnJhbmNoIFRoZSBicmFuY2ggdG8gbW9uaXRvciAoZS5nLiBgbWFpbmAsIGB2Mi54YClcbiAgICogQHBhcmFtIG9wdGlvbnMgQnJhbmNoIGRlZmluaXRpb25cbiAgICovXG4gIHB1YmxpYyBhZGRCcmFuY2goYnJhbmNoOiBzdHJpbmcsIG9wdGlvbnM6IEJyYW5jaE9wdGlvbnMpIHtcbiAgICB0aGlzLl9hZGRCcmFuY2goYnJhbmNoLCBvcHRpb25zKTtcblxuICAgIC8vIHJ1biBhbGwgYnJhbmNoIGhvb2tzXG4gICAgZm9yIChjb25zdCBob29rIG9mIHRoaXMuX2JyYW5jaEhvb2tzKSB7XG4gICAgICBob29rKGJyYW5jaCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYSByZWxlYXNlIGJyYW5jaC5cbiAgICpcbiAgICogSXQgaXMgYSBnaXQgYnJhbmNoIGZyb20gd2hpY2ggcmVsZWFzZXMgYXJlIHB1Ymxpc2hlZC4gSWYgYSBwcm9qZWN0IGhhcyBtb3JlIHRoYW4gb25lIHJlbGVhc2VcbiAgICogYnJhbmNoLCB3ZSByZXF1aXJlIHRoYXQgYG1ham9yVmVyc2lvbmAgaXMgYWxzbyBzcGVjaWZpZWQgZm9yIHRoZSBwcmltYXJ5IGJyYW5jaCBpbiBvcmRlciB0b1xuICAgKiBlbnN1cmUgYnJhbmNoZXMgYWx3YXlzIHJlbGVhc2UgdGhlIGNvcnJlY3QgdmVyc2lvbi5cbiAgICpcbiAgICogQHBhcmFtIGJyYW5jaCBUaGUgYnJhbmNoIHRvIG1vbml0b3IgKGUuZy4gYG1haW5gLCBgdjIueGApXG4gICAqIEBwYXJhbSBvcHRpb25zIEJyYW5jaCBkZWZpbml0aW9uXG4gICAqL1xuICBwcml2YXRlIF9hZGRCcmFuY2goXG4gICAgYnJhbmNoOiBzdHJpbmcsXG4gICAgb3B0aW9uczogUGFydGlhbDxCcmFuY2hPcHRpb25zPixcbiAgKTogUmVsZWFzZUJyYW5jaCB7XG4gICAgaWYgKHRoaXMuX2JyYW5jaGVzLmZpbmQoKGIpID0+IGIubmFtZSA9PT0gYnJhbmNoKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBUaGUgcmVsZWFzZSBicmFuY2ggJHticmFuY2h9IGlzIGFscmVhZHkgZGVmaW5lZGApO1xuICAgIH1cblxuICAgIC8vIGlmIHdlIGFkZCBhIGJyYW5jaCwgd2UgcmVxdWlyZSB0aGF0IHRoZSBkZWZhdWx0IGJyYW5jaCB3aWxsIGFsc28gZGVmaW5lIGFcbiAgICAvLyBtYWpvciB2ZXJzaW9uLlxuICAgIGlmIChcbiAgICAgIHRoaXMuZGVmYXVsdEJyYW5jaCAmJlxuICAgICAgb3B0aW9ucy5tYWpvclZlcnNpb24gJiZcbiAgICAgIHRoaXMuZGVmYXVsdEJyYW5jaC5tYWpvclZlcnNpb24gPT09IHVuZGVmaW5lZFxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAneW91IG11c3Qgc3BlY2lmeSBcIm1ham9yVmVyc2lvblwiIGZvciB0aGUgZGVmYXVsdCBicmFuY2ggd2hlbiBhZGRpbmcgbXVsdGlwbGUgcmVsZWFzZSBicmFuY2hlcycsXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IHJlbGVhc2VCcmFuY2g6IFJlbGVhc2VCcmFuY2ggPSB7XG4gICAgICBuYW1lOiBicmFuY2gsXG4gICAgICAuLi5vcHRpb25zLFxuICAgICAgd29ya2Zsb3c6IHRoaXMuY3JlYXRlV29ya2Zsb3coYnJhbmNoLCBvcHRpb25zKSxcbiAgICB9O1xuXG4gICAgdGhpcy5fYnJhbmNoZXMucHVzaChyZWxlYXNlQnJhbmNoKTtcblxuICAgIHJldHVybiByZWxlYXNlQnJhbmNoO1xuICB9XG5cbiAgcHVibGljIHByZVN5bnRoZXNpemUoKSB7XG4gICAgZm9yIChjb25zdCBicmFuY2ggb2YgdGhpcy5fYnJhbmNoZXMpIHtcbiAgICAgIGlmICghYnJhbmNoLndvcmtmbG93KSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBicmFuY2gud29ya2Zsb3cuYWRkSm9icyhcbiAgICAgICAgdGhpcy5wdWJsaXNoZXIuX3JlbmRlckpvYnNGb3JCcmFuY2goYnJhbmNoLm5hbWUsIGJyYW5jaCksXG4gICAgICApO1xuICAgICAgYnJhbmNoLndvcmtmbG93LmFkZEpvYnModGhpcy5qb2JzKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBqb2JzIHRvIGFsbCByZWxlYXNlIHdvcmtmbG93cy5cbiAgICogQHBhcmFtIGpvYnMgVGhlIGpvYnMgdG8gYWRkIChuYW1lID0+IGpvYilcbiAgICovXG4gIHB1YmxpYyBhZGRKb2JzKGpvYnM6IFJlY29yZDxzdHJpbmcsIEpvYj4pIHtcbiAgICBmb3IgKGNvbnN0IFtuYW1lLCBqb2JdIG9mIE9iamVjdC5lbnRyaWVzKGpvYnMpKSB7XG4gICAgICB0aGlzLmpvYnNbbmFtZV0gPSBqb2I7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlIGFsbCByZWxlYXNlIGJyYW5jaCBuYW1lc1xuICAgKi9cbiAgcHVibGljIGdldCBicmFuY2hlcygpOiBzdHJpbmdbXSB7XG4gICAgcmV0dXJuIHRoaXMuX2JyYW5jaGVzLm1hcCgoYikgPT4gYi5uYW1lKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcmV0dXJucyBhIHdvcmtmbG93IG9yIGB1bmRlZmluZWRgIGlmIGdpdGh1YiBpbnRlZ3JhdGlvbiBpcyBkaXNhYmxlZC5cbiAgICovXG4gIHByaXZhdGUgY3JlYXRlV29ya2Zsb3coXG4gICAgYnJhbmNoTmFtZTogc3RyaW5nLFxuICAgIGJyYW5jaDogUGFydGlhbDxCcmFuY2hPcHRpb25zPixcbiAgKTogR2l0aHViV29ya2Zsb3cgfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IHdvcmtmbG93TmFtZSA9XG4gICAgICBicmFuY2gud29ya2Zsb3dOYW1lID8/XG4gICAgICB3b3JrZmxvd05hbWVGb3JQcm9qZWN0KGByZWxlYXNlLSR7YnJhbmNoTmFtZX1gLCB0aGlzLnByb2plY3QpO1xuXG4gICAgLy8gdG8gYXZvaWQgcmFjZSBjb25kaXRpb25zIGJldHdlZW4gdHdvIGNvbW1pdHMgdHJ5aW5nIHRvIHJlbGVhc2UgdGhlIHNhbWVcbiAgICAvLyB2ZXJzaW9uLCB3ZSBjaGVjayBpZiB0aGUgaGVhZCBzaGEgaXMgaWRlbnRpY2FsIHRvIHRoZSByZW1vdGUgc2hhLiBpZlxuICAgIC8vIG5vdCwgd2Ugd2lsbCBza2lwIHRoZSByZWxlYXNlIGFuZCBqdXN0IGZpbmlzaCB0aGUgYnVpbGQuXG4gICAgY29uc3Qgbm9OZXdDb21taXRzID0gYFxcJHt7IHN0ZXBzLiR7R0lUX1JFTU9URV9TVEVQSUR9Lm91dHB1dHMuJHtMQVRFU1RfQ09NTUlUX09VVFBVVH0gPT0gZ2l0aHViLnNoYSB9fWA7XG5cbiAgICAvLyBUaGUgYXJyYXlzIGFyZSBiZWluZyBjbG9uZWQgdG8gYXZvaWQgYWNjdW11bGF0aW5nIHZhbHVlcyBmcm9tIHByZXZpb3VzIGJyYW5jaGVzXG4gICAgY29uc3QgcHJlQnVpbGRTdGVwcyA9IFsuLi50aGlzLnByZUJ1aWxkU3RlcHNdO1xuXG4gICAgY29uc3QgZW52OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge1xuICAgICAgUkVMRUFTRTogXCJ0cnVlXCIsXG4gICAgICAuLi50aGlzLnZlcnNpb24uZW52Rm9yQnJhbmNoKHtcbiAgICAgICAgbWFqb3JWZXJzaW9uOiBicmFuY2gubWFqb3JWZXJzaW9uLFxuICAgICAgICBtaW5vclZlcnNpb246IGJyYW5jaC5taW5vclZlcnNpb24sXG4gICAgICAgIG1pbk1ham9yVmVyc2lvbjogYnJhbmNoLm1pbk1ham9yVmVyc2lvbixcbiAgICAgICAgcHJlcmVsZWFzZTogYnJhbmNoLnByZXJlbGVhc2UsXG4gICAgICAgIHRhZ1ByZWZpeDogYnJhbmNoLnRhZ1ByZWZpeCxcbiAgICAgIH0pLFxuICAgIH07XG5cbiAgICAvLyB0aGUgXCJyZWxlYXNlXCIgdGFzayBwcmVwYXJlcyBhIHJlbGVhc2UgYnV0IGRvZXMgbm90IHB1Ymxpc2ggYW55dGhpbmcuIHRoZVxuICAgIC8vIG91dHB1dCBvZiB0aGUgcmVsZWFzZSB0YXNrIGlzOiBgZGlzdGAsIGAudmVyc2lvbi50eHRgLCBhbmRcbiAgICAvLyBgLmNoYW5nZWxvZy5tZGAuIHRoaXMgaXMgd2hhdCBwdWJsaXNoIHRhc2tzIGV4cGVjdC5cblxuICAgIC8vIGlmIHRoaXMgaXMgdGhlIHJlbGVhc2UgZm9yIFwibWFpblwiIG9yIFwibWFzdGVyXCIsIGp1c3QgY2FsbCBpdCBcInJlbGVhc2VcIi5cbiAgICAvLyBvdGhlcndpc2UsIFwicmVsZWFzZTpCUkFOQ0hcIlxuICAgIGNvbnN0IHJlbGVhc2VUYXNrTmFtZSA9XG4gICAgICBicmFuY2hOYW1lID09PSBcIm1haW5cIiB8fCBicmFuY2hOYW1lID09PSBcIm1hc3RlclwiXG4gICAgICAgID8gXCJyZWxlYXNlXCJcbiAgICAgICAgOiBgcmVsZWFzZToke2JyYW5jaE5hbWV9YDtcbiAgICBjb25zdCByZWxlYXNlVGFzayA9IHRoaXMucHJvamVjdC5hZGRUYXNrKHJlbGVhc2VUYXNrTmFtZSwge1xuICAgICAgZGVzY3JpcHRpb246IGBQcmVwYXJlIGEgcmVsZWFzZSBmcm9tIFwiJHticmFuY2hOYW1lfVwiIGJyYW5jaGAsXG4gICAgICBlbnYsXG4gICAgfSk7XG5cbiAgICByZWxlYXNlVGFzay5leGVjQXJncyhbXCJybVwiLCBcIi1mclwiLCB0aGlzLmFydGlmYWN0c0RpcmVjdG9yeV0pO1xuICAgIHJlbGVhc2VUYXNrLnNwYXduKHRoaXMudmVyc2lvbi5idW1wVGFzayk7XG5cbiAgICAvLyBTcGF3biBhbGwgYnVpbGQgdGFza3NcbiAgICBmb3IgKGNvbnN0IGJ1aWxkVGFzayBvZiB0aGlzLmJ1aWxkVGFza3MpIHtcbiAgICAgIHJlbGVhc2VUYXNrLnNwYXduKGJ1aWxkVGFzayk7XG4gICAgfVxuXG4gICAgcmVsZWFzZVRhc2suc3Bhd24odGhpcy52ZXJzaW9uLnVuYnVtcFRhc2spO1xuXG4gICAgLy8gYW50aS10YW1wZXIgY2hlY2sgKGZhaWxzIGlmIHRoZXJlIHdlcmUgY2hhbmdlcyB0byBjb21taXR0ZWQgZmlsZXMpXG4gICAgLy8gdGhpcyB3aWxsIGlkZW50aWZ5IGFueSBub24tY29tbWl0dGVkIGZpbGVzIGdlbmVyYXRlZCBkdXJpbmcgYnVpbGQgKGUuZy4gdGVzdCBzbmFwc2hvdHMpXG4gICAgcmVsZWFzZVRhc2suZXhlYyhSZWxlYXNlLkFOVElfVEFNUEVSX0NNRCk7XG5cbiAgICBpZiAodGhpcy5yZWxlYXNlVHJpZ2dlci5pc01hbnVhbCkge1xuICAgICAgY29uc3QgcHVibGlzaFRhc2sgPSB0aGlzLnB1Ymxpc2hlci5wdWJsaXNoVG9HaXQoe1xuICAgICAgICBjaGFuZ2Vsb2dGaWxlOiBwb3NpeFBhdGguam9pbihcbiAgICAgICAgICB0aGlzLmFydGlmYWN0c0RpcmVjdG9yeSxcbiAgICAgICAgICB0aGlzLnZlcnNpb24uY2hhbmdlbG9nRmlsZU5hbWUsXG4gICAgICAgICksXG4gICAgICAgIHZlcnNpb25GaWxlOiBwb3NpeFBhdGguam9pbihcbiAgICAgICAgICB0aGlzLmFydGlmYWN0c0RpcmVjdG9yeSxcbiAgICAgICAgICB0aGlzLnZlcnNpb24udmVyc2lvbkZpbGVOYW1lLFxuICAgICAgICApLFxuICAgICAgICByZWxlYXNlVGFnRmlsZTogcG9zaXhQYXRoLmpvaW4oXG4gICAgICAgICAgdGhpcy5hcnRpZmFjdHNEaXJlY3RvcnksXG4gICAgICAgICAgdGhpcy52ZXJzaW9uLnJlbGVhc2VUYWdGaWxlTmFtZSxcbiAgICAgICAgKSxcbiAgICAgICAgcHJvamVjdENoYW5nZWxvZ0ZpbGU6IHRoaXMucmVsZWFzZVRyaWdnZXIuY2hhbmdlbG9nUGF0aCxcbiAgICAgICAgZ2l0QnJhbmNoOiBicmFuY2hOYW1lLFxuICAgICAgICBnaXRQdXNoQ29tbWFuZDogdGhpcy5yZWxlYXNlVHJpZ2dlci5naXRQdXNoQ29tbWFuZCxcbiAgICAgIH0pO1xuXG4gICAgICByZWxlYXNlVGFzay5zcGF3bihwdWJsaXNoVGFzayk7XG4gICAgfVxuXG4gICAgY29uc3QgcG9zdEJ1aWxkU3RlcHMgPSBbLi4udGhpcy5wb3N0QnVpbGRTdGVwc107XG5cbiAgICAvLyBSZWFkIHRoZSByZWxlYXNldGFnLCB0aGVuIGNoZWNrIGlmIGl0IGFscmVhZHkgZXhpc3RzLlxuICAgIC8vIElmIGl0IGRvZXMsIHdlIHdpbGwgY2FuY2VsIHRoaXMgcmVsZWFzZVxuICAgIHBvc3RCdWlsZFN0ZXBzLnB1c2goXG4gICAgICBXb3JrZmxvd1N0ZXBzLnRhZ0V4aXN0cyhgJChjYXQgJHt0aGlzLnJlbGVhc2VUYWdGaWxlUGF0aH0pYCwge1xuICAgICAgICBuYW1lOiBcIkNoZWNrIGlmIHZlcnNpb24gaGFzIGFscmVhZHkgYmVlbiB0YWdnZWRcIixcbiAgICAgICAgaWQ6IFRBR19FWElTVFNfU1RFUElELFxuICAgICAgfSksXG4gICAgKTtcblxuICAgIC8vIGNoZWNrIGlmIG5ldyBjb21taXRzIHdlcmUgcHVzaGVkIHRvIHRoZSByZXBvIHdoaWxlIHdlIHdlcmUgYnVpbGRpbmcuXG4gICAgLy8gaWYgbmV3IGNvbW1pdHMgaGF2ZSBiZWVuIHB1c2hlZCwgd2Ugd2lsbCBjYW5jZWwgdGhpcyByZWxlYXNlXG4gICAgcG9zdEJ1aWxkU3RlcHMucHVzaCh7XG4gICAgICBuYW1lOiBcIkNoZWNrIGZvciBuZXcgY29tbWl0c1wiLFxuICAgICAgaWQ6IEdJVF9SRU1PVEVfU1RFUElELFxuICAgICAgc2hlbGw6IFwiYmFzaFwiLFxuICAgICAgZW52OiB7XG4gICAgICAgIEdJVEhVQl9SRUY6IFwiJHt7IGdpdGh1Yi5yZWYgfX1cIixcbiAgICAgIH0sXG4gICAgICBydW46IFtcbiAgICAgICAgYGVjaG8gXCIke0xBVEVTVF9DT01NSVRfT1VUUFVUfT0kKGdpdCBscy1yZW1vdGUgb3JpZ2luIC1oIFwiJEdJVEhVQl9SRUZcIiB8IGN1dCAtZjEpXCIgPj4gJEdJVEhVQl9PVVRQVVRgLFxuICAgICAgICBcImNhdCAkR0lUSFVCX09VVFBVVFwiLFxuICAgICAgXS5qb2luKFwiXFxuXCIpLFxuICAgIH0pO1xuXG4gICAgY29uc3QgcHJvamVjdFBhdGhSZWxhdGl2ZVRvUm9vdCA9IHByb2plY3RQYXRoUmVsYXRpdmVUb1JlcG9Sb290KFxuICAgICAgdGhpcy5wcm9qZWN0LFxuICAgICk7XG5cbiAgICBwb3N0QnVpbGRTdGVwcy5wdXNoKFxuICAgICAge1xuICAgICAgICBuYW1lOiBcIkJhY2t1cCBhcnRpZmFjdCBwZXJtaXNzaW9uc1wiLFxuICAgICAgICBpZjogbm9OZXdDb21taXRzLFxuICAgICAgICBjb250aW51ZU9uRXJyb3I6IHRydWUsXG4gICAgICAgIHJ1bjogYGNkICR7dGhpcy5hcnRpZmFjdHNEaXJlY3Rvcnl9ICYmIGdldGZhY2wgLVIgLiA+ICR7UEVSTUlTU0lPTl9CQUNLVVBfRklMRX1gLFxuICAgICAgfSxcbiAgICAgIFdvcmtmbG93U3RlcHMudXBsb2FkQXJ0aWZhY3Qoe1xuICAgICAgICBpZDogVVBMT0FEX0FSVElGQUNUX1NURVAsXG4gICAgICAgIGlmOiBub05ld0NvbW1pdHMsXG4gICAgICAgIHdpdGg6IHtcbiAgICAgICAgICBuYW1lOiBCVUlMRF9BUlRJRkFDVF9OQU1FLFxuICAgICAgICAgIHBhdGg6IHRoaXMucHJvamVjdC5wYXJlbnQgLy8gaXMgc3VicHJvamVjdFxuICAgICAgICAgICAgPyBwb3NpeFBhdGguam9pbihwcm9qZWN0UGF0aFJlbGF0aXZlVG9Sb290LCB0aGlzLmFydGlmYWN0c0RpcmVjdG9yeSlcbiAgICAgICAgICAgIDogdGhpcy5hcnRpZmFjdHNEaXJlY3RvcnksXG4gICAgICAgIH0sXG4gICAgICB9KSxcbiAgICApO1xuXG4gICAgaWYgKHRoaXMuZ2l0aHViICYmICF0aGlzLnJlbGVhc2VUcmlnZ2VyLmlzTWFudWFsKSB7XG4gICAgICAvLyBVc2UgdGFyZ2V0IChwb3NzaWJsZSBwYXJlbnQpIEdpdEh1YiB0byBjcmVhdGUgdGhlIHdvcmtmbG93XG4gICAgICBjb25zdCB3b3JrZmxvdyA9IG5ldyBHaXRodWJXb3JrZmxvdyh0aGlzLmdpdGh1Yiwgd29ya2Zsb3dOYW1lLCB7XG4gICAgICAgIC8vIHNlZSBodHRwczovL2dpdGh1Yi5jb20vcHJvamVuL3Byb2plbi9pc3N1ZXMvMzc2MVxuICAgICAgICBsaW1pdENvbmN1cnJlbmN5OiB0cnVlLFxuICAgICAgfSk7XG4gICAgICAvLyBXaGVuIHJ1bi1uYW1lIGV2YWx1YXRlcyB0byBlbXB0eSBzdHJpbmcsIEdpdEh1YiBmYWxscyBiYWNrIHRvIHRoZVxuICAgICAgLy8gZGVmYXVsdCBldmVudC1zcGVjaWZpYyBuYW1lIChlLmcuIGNvbW1pdCBtZXNzYWdlIGZvciBwdXNoIGV2ZW50cykuXG4gICAgICB3b3JrZmxvdy5ydW5OYW1lID0gYCRcXHt7IGlucHV0cy5kcnlfcnVuICYmIGZvcm1hdCgnW0RSWSBSVU5dICR7d29ya2Zsb3dOYW1lfSBieSBAezB9JywgZ2l0aHViLmFjdG9yKSB8fCAnJyB9fWA7XG4gICAgICB3b3JrZmxvdy5vbih7XG4gICAgICAgIHNjaGVkdWxlOiB0aGlzLnJlbGVhc2VUcmlnZ2VyLnNjaGVkdWxlXG4gICAgICAgICAgPyBbeyBjcm9uOiB0aGlzLnJlbGVhc2VUcmlnZ2VyLnNjaGVkdWxlIH1dXG4gICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICAgIHB1c2g6XG4gICAgICAgICAgdGhpcy5yZWxlYXNlVHJpZ2dlci5pc0NvbnRpbnVvdXMgfHwgdGhpcy5yZWxlYXNlVHJpZ2dlci50YWdzXG4gICAgICAgICAgICA/IHtcbiAgICAgICAgICAgICAgICBicmFuY2hlczogW2JyYW5jaE5hbWVdLFxuICAgICAgICAgICAgICAgIHRhZ3M6IHRoaXMucmVsZWFzZVRyaWdnZXIudGFncyxcbiAgICAgICAgICAgICAgICBwYXRoczogdGhpcy5yZWxlYXNlVHJpZ2dlci5wYXRocyxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICAgIHdvcmtmbG93RGlzcGF0Y2g6IHtcbiAgICAgICAgICBpbnB1dHM6IHtcbiAgICAgICAgICAgIGRyeV9ydW46IHtcbiAgICAgICAgICAgICAgZGVzY3JpcHRpb246IFwiRHJ5IHJ1biAoc2tpcCBhY3R1YWwgcHVibGlzaGluZylcIixcbiAgICAgICAgICAgICAgcmVxdWlyZWQ6IGZhbHNlLFxuICAgICAgICAgICAgICB0eXBlOiBcImJvb2xlYW5cIixcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuXG4gICAgICAvLyBDcmVhdGUgam9iIGJhc2VkIG9uIGNoaWxkIChvbmx5PykgcHJvamVjdCBHaXRIdWJcbiAgICAgIGNvbnN0IHRhc2tqb2IgPSBuZXcgVGFza1dvcmtmbG93Sm9iKHRoaXMsIHJlbGVhc2VUYXNrLCB7XG4gICAgICAgIG91dHB1dHM6IHtcbiAgICAgICAgICBbTEFURVNUX0NPTU1JVF9PVVRQVVRdOiB7XG4gICAgICAgICAgICBzdGVwSWQ6IEdJVF9SRU1PVEVfU1RFUElELFxuICAgICAgICAgICAgb3V0cHV0TmFtZTogTEFURVNUX0NPTU1JVF9PVVRQVVQsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBbVEFHX0VYSVNUU19PVVRQVVRdOiB7XG4gICAgICAgICAgICBzdGVwSWQ6IFRBR19FWElTVFNfU1RFUElELFxuICAgICAgICAgICAgb3V0cHV0TmFtZTogXCJleGlzdHNcIixcbiAgICAgICAgICB9LFxuICAgICAgICAgIFtBUlRJRkFDVF9JRF9PVVRQVVRdOiB7XG4gICAgICAgICAgICBzdGVwSWQ6IFVQTE9BRF9BUlRJRkFDVF9TVEVQLFxuICAgICAgICAgICAgb3V0cHV0TmFtZTogXCJhcnRpZmFjdC1pZFwiLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIGNvbnRhaW5lcjogdGhpcy5jb250YWluZXJJbWFnZVxuICAgICAgICAgID8geyBpbWFnZTogdGhpcy5jb250YWluZXJJbWFnZSB9XG4gICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICAgIGVudjoge1xuICAgICAgICAgIENJOiBcInRydWVcIixcbiAgICAgICAgICAuLi50aGlzLnJlbGVhc2VXb3JrZmxvd0VudixcbiAgICAgICAgfSxcbiAgICAgICAgcGVybWlzc2lvbnM6IHRoaXMud29ya2Zsb3dQZXJtaXNzaW9ucyxcbiAgICAgICAgY2hlY2tvdXRXaXRoOiB7XG4gICAgICAgICAgLy8gZmV0Y2gtZGVwdGg9IGluZGljYXRlcyBhbGwgaGlzdG9yeSBmb3IgYWxsIGJyYW5jaGVzIGFuZCB0YWdzXG4gICAgICAgICAgLy8gd2UgbXVzdCB1c2UgdGhpcyBpbiBvcmRlciB0byBmZXRjaCBhbGwgdGFnc1xuICAgICAgICAgIC8vIGFuZCB0byBpbnNwZWN0IHRoZSBoaXN0b3J5IHRvIGRlY2lkZSBpZiB3ZSBzaG91bGQgcmVsZWFzZVxuICAgICAgICAgIGZldGNoRGVwdGg6IDAsXG4gICAgICAgIH0sXG4gICAgICAgIHByZUJ1aWxkU3RlcHMsXG4gICAgICAgIHBvc3RCdWlsZFN0ZXBzLFxuICAgICAgICBqb2JEZWZhdWx0czogdGhpcy5wcm9qZWN0LnBhcmVudCAvLyBpcyBzdWJwcm9qZWN0XG4gICAgICAgICAgPyB7XG4gICAgICAgICAgICAgIHJ1bjoge1xuICAgICAgICAgICAgICAgIHdvcmtpbmdEaXJlY3Rvcnk6IHByb2plY3RQYXRoUmVsYXRpdmVUb1Jvb3QsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9XG4gICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICAgIC4uLmZpbHRlcmVkUnVuc09uT3B0aW9ucyh0aGlzLnJ1bnNPbiwgdGhpcy5ydW5zT25Hcm91cCksXG4gICAgICB9KTtcblxuICAgICAgd29ya2Zsb3cuYWRkSm9iKEJVSUxEX0pPQklELCB0YXNram9iKTtcblxuICAgICAgcmV0dXJuIHdvcmtmbG93O1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIE9wdGlvbnMgZm9yIGEgcmVsZWFzZSBicmFuY2guXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQnJhbmNoT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgcmVsZWFzZSB3b3JrZmxvdy5cbiAgICogQGRlZmF1bHQgXCJyZWxlYXNlLUJSQU5DSFwiXG4gICAqL1xuICByZWFkb25seSB3b3JrZmxvd05hbWU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBHaXRIdWIgQWN0aW9ucyBlbnZpcm9ubWVudCB1c2VkIGZvciB0aGUgcmVsZWFzZS5cbiAgICpcbiAgICogVGhpcyBjYW4gYmUgdXNlZCB0byBhZGQgYW4gZXhwbGljaXQgYXBwcm92YWwgc3RlcCB0byB0aGUgcmVsZWFzZVxuICAgKiBvciBsaW1pdCB3aG8gY2FuIGluaXRpYXRlIGEgcmVsZWFzZSB0aHJvdWdoIGVudmlyb25tZW50IHByb3RlY3Rpb24gcnVsZXMuXG4gICAqXG4gICAqIFdoZW4gbXVsdGlwbGUgYXJ0aWZhY3RzIGFyZSByZWxlYXNlZCwgdGhlIGVudmlyb25tZW50IGNhbiBiZSBvdmVyd3JpdHRlblxuICAgKiBvbiBhIHBlciBhcnRpZmFjdCBiYXNpcy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBlbnZpcm9ubWVudCB1c2VkLCB1bmxlc3Mgc2V0IGF0IHRoZSBhcnRpZmFjdCBsZXZlbFxuICAgKi9cbiAgcmVhZG9ubHkgZW52aXJvbm1lbnQ/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBtYWpvciB2ZXJzaW9ucyByZWxlYXNlZCBmcm9tIHRoaXMgYnJhbmNoLlxuICAgKi9cbiAgcmVhZG9ubHkgbWFqb3JWZXJzaW9uOiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFRoZSBtaW5pbXVtIG1ham9yIHZlcnNpb24gdG8gcmVsZWFzZS5cbiAgICovXG4gIHJlYWRvbmx5IG1pbk1ham9yVmVyc2lvbj86IG51bWJlcjtcblxuICAvKipcbiAgICogVGhlIG1pbm9yIHZlcnNpb25zIHJlbGVhc2VkIGZyb20gdGhpcyBicmFuY2guXG4gICAqL1xuICByZWFkb25seSBtaW5vclZlcnNpb24/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIEJ1bXAgdGhlIHZlcnNpb24gYXMgYSBwcmUtcmVsZWFzZSB0YWcuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm9ybWFsIHJlbGVhc2VzXG4gICAqL1xuICByZWFkb25seSBwcmVyZWxlYXNlPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIEdpdEh1YiBzaG91bGQgZXhwbGljaXRseSBtYXJrIHRoZSByZWxlYXNlIGZyb20gdGhpcyBicmFuY2ggYXMgdGhlXG4gICAqIGxhdGVzdCByZWxlYXNlLlxuICAgKlxuICAgKiBTZXQgdG8gYHRydWVgIHRvIG1hcmsgdGhlIHJlbGVhc2UgYXMgbGF0ZXN0LCBvciBgZmFsc2VgIHRvIGV4cGxpY2l0bHkgbm90XG4gICAqIG1hcmsgaXQgYXMgbGF0ZXN0LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIEdpdEh1YiBkZXRlcm1pbmVzIHRoZSBsYXRlc3QgcmVsZWFzZSBiYXNlZCBvbiBkYXRlIGFuZCBzZW1hbnRpYyB2ZXJzaW9uLlxuICAgKi9cbiAgcmVhZG9ubHkgZ2l0aHViUmVsZWFzZUxhdGVzdD86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEF1dG9tYXRpY2FsbHkgYWRkIHRoZSBnaXZlbiBwcmVmaXggdG8gcmVsZWFzZSB0YWdzLlxuICAgKiBVc2VmdWwgaWYgeW91IGFyZSByZWxlYXNpbmcgb24gbXVsdGlwbGUgYnJhbmNoZXMgd2l0aCBvdmVybGFwcGluZ1xuICAgKiB2ZXJzaW9uIG51bWJlcnMuXG4gICAqXG4gICAqIE5vdGU6IHRoaXMgcHJlZml4IGlzIHVzZWQgdG8gZGV0ZWN0IHRoZSBsYXRlc3QgdGFnZ2VkIHZlcnNpb25cbiAgICogd2hlbiBidW1waW5nLCBzbyBpZiB5b3UgY2hhbmdlIHRoaXMgb24gYSBwcm9qZWN0IHdpdGggYW4gZXhpc3RpbmcgdmVyc2lvblxuICAgKiBoaXN0b3J5LCB5b3UgbWF5IG5lZWQgdG8gbWFudWFsbHkgdGFnIHlvdXIgbGF0ZXN0IHJlbGVhc2VcbiAgICogd2l0aCB0aGUgbmV3IHByZWZpeC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBwcmVmaXhcbiAgICovXG4gIHJlYWRvbmx5IHRhZ1ByZWZpeD86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIG5wbSBkaXN0cmlidXRpb24gdGFnIHRvIHVzZSBmb3IgdGhpcyBicmFuY2guXG4gICAqXG4gICAqIEBkZWZhdWx0IFwibGF0ZXN0XCJcbiAgICovXG4gIHJlYWRvbmx5IG5wbURpc3RUYWc/OiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBSZWxlYXNlQnJhbmNoIGV4dGVuZHMgUGFydGlhbDxCcmFuY2hPcHRpb25zPiB7XG4gIHJlYWRvbmx5IHdvcmtmbG93PzogR2l0aHViV29ya2Zsb3c7XG4gIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcbn1cbiJdfQ==