UNPKG

44.9 kBJavaScriptView Raw
1"use strict";
2var _a, _b, _c, _d;
3Object.defineProperty(exports, "__esModule", { value: true });
4exports.AwsCustomResource = exports.AwsCustomResourcePolicy = exports.PhysicalResourceId = exports.PhysicalResourceIdReference = void 0;
5const jsiiDeprecationWarnings = require("../../.warnings.jsii.js");
6const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
7const fs = require("fs");
8const path = require("path");
9const iam = require("@aws-cdk/aws-iam");
10const lambda = require("@aws-cdk/aws-lambda");
11const cdk = require("@aws-cdk/core");
12const runtime_1 = require("./runtime");
13// keep this import separate from other imports to reduce chance for merge conflicts with v2-main
14// eslint-disable-next-line no-duplicate-imports, import/order
15const core_1 = require("@aws-cdk/core");
16/**
17 * Reference to the physical resource id that can be passed to the AWS operation as a parameter.
18 */
19class PhysicalResourceIdReference {
20 constructor() {
21 this.creationStack = cdk.captureStackTrace();
22 }
23 /**
24 * toJSON serialization to replace `PhysicalResourceIdReference` with a magic string.
25 */
26 toJSON() {
27 return runtime_1.PHYSICAL_RESOURCE_ID_REFERENCE;
28 }
29 resolve(_) {
30 return runtime_1.PHYSICAL_RESOURCE_ID_REFERENCE;
31 }
32 toString() {
33 return runtime_1.PHYSICAL_RESOURCE_ID_REFERENCE;
34 }
35}
36exports.PhysicalResourceIdReference = PhysicalResourceIdReference;
37_a = JSII_RTTI_SYMBOL_1;
38PhysicalResourceIdReference[_a] = { fqn: "@aws-cdk/custom-resources.PhysicalResourceIdReference", version: "1.191.0" };
39/**
40 * Physical ID of the custom resource.
41 */
42class PhysicalResourceId {
43 /**
44 * @param responsePath Path to a response data element to be used as the physical id.
45 * @param id Literal string to be used as the physical id.
46 */
47 constructor(responsePath, id) {
48 this.responsePath = responsePath;
49 this.id = id;
50 }
51 /**
52 * Extract the physical resource id from the path (dot notation) to the data in the API call response.
53 */
54 static fromResponse(responsePath) {
55 return new PhysicalResourceId(responsePath, undefined);
56 }
57 /**
58 * Explicit physical resource id.
59 */
60 static of(id) {
61 return new PhysicalResourceId(undefined, id);
62 }
63}
64exports.PhysicalResourceId = PhysicalResourceId;
65_b = JSII_RTTI_SYMBOL_1;
66PhysicalResourceId[_b] = { fqn: "@aws-cdk/custom-resources.PhysicalResourceId", version: "1.191.0" };
67/**
68 * The IAM Policy that will be applied to the different calls.
69 */
70class AwsCustomResourcePolicy {
71 /**
72 * @param statements statements for explicit policy.
73 * @param resources resources for auto-generated from SDK calls.
74 */
75 constructor(statements, resources) {
76 this.statements = statements;
77 this.resources = resources;
78 }
79 /**
80 * Explicit IAM Policy Statements.
81 *
82 * @param statements the statements to propagate to the SDK calls.
83 */
84 static fromStatements(statements) {
85 return new AwsCustomResourcePolicy(statements, undefined);
86 }
87 /**
88 * Generate IAM Policy Statements from the configured SDK calls.
89 *
90 * Each SDK call with be translated to an IAM Policy Statement in the form of: `call.service:call.action` (e.g `s3:PutObject`).
91 *
92 * This policy generator assumes the IAM policy name has the same name as the API
93 * call. This is true in 99% of cases, but there are exceptions (for example,
94 * S3's `PutBucketLifecycleConfiguration` requires
95 * `s3:PutLifecycleConfiguration` permissions, Lambda's `Invoke` requires
96 * `lambda:InvokeFunction` permissions). Use `fromStatements` if you want to
97 * do a call that requires different IAM action names.
98 *
99 * @param options options for the policy generation
100 */
101 static fromSdkCalls(options) {
102 try {
103 jsiiDeprecationWarnings._aws_cdk_custom_resources_SdkCallsPolicyOptions(options);
104 }
105 catch (error) {
106 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
107 Error.captureStackTrace(error, this.fromSdkCalls);
108 }
109 throw error;
110 }
111 return new AwsCustomResourcePolicy([], options.resources);
112 }
113}
114exports.AwsCustomResourcePolicy = AwsCustomResourcePolicy;
115_c = JSII_RTTI_SYMBOL_1;
116AwsCustomResourcePolicy[_c] = { fqn: "@aws-cdk/custom-resources.AwsCustomResourcePolicy", version: "1.191.0" };
117/**
118 * Use this constant to configure access to any resource.
119 */
120AwsCustomResourcePolicy.ANY_RESOURCE = ['*'];
121/**
122 * Defines a custom resource that is materialized using specific AWS API calls. These calls are created using
123 * a singleton Lambda function.
124 *
125 * Use this to bridge any gap that might exist in the CloudFormation Coverage.
126 * You can specify exactly which calls are invoked for the 'CREATE', 'UPDATE' and 'DELETE' life cycle events.
127 *
128 */
129class AwsCustomResource extends core_1.Construct {
130 // 'props' cannot be optional, even though all its properties are optional.
131 // this is because at least one sdk call must be provided.
132 constructor(scope, id, props) {
133 super(scope, id);
134 try {
135 jsiiDeprecationWarnings._aws_cdk_custom_resources_AwsCustomResourceProps(props);
136 }
137 catch (error) {
138 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
139 Error.captureStackTrace(error, AwsCustomResource);
140 }
141 throw error;
142 }
143 if (!props.onCreate && !props.onUpdate && !props.onDelete) {
144 throw new Error('At least `onCreate`, `onUpdate` or `onDelete` must be specified.');
145 }
146 for (const call of [props.onCreate, props.onUpdate]) {
147 if (call && !call.physicalResourceId) {
148 throw new Error('`physicalResourceId` must be specified for onCreate and onUpdate calls.');
149 }
150 }
151 for (const call of [props.onCreate, props.onUpdate, props.onDelete]) {
152 if (call?.physicalResourceId?.responsePath) {
153 AwsCustomResource.breakIgnoreErrorsCircuit([call], 'PhysicalResourceId.fromResponse');
154 }
155 }
156 if (includesPhysicalResourceIdRef(props.onCreate?.parameters)) {
157 throw new Error('`PhysicalResourceIdReference` must not be specified in `onCreate` parameters.');
158 }
159 this.props = props;
160 const provider = new lambda.SingletonFunction(this, 'Provider', {
161 code: lambda.Code.fromAsset(path.join(__dirname, 'runtime'), {
162 exclude: ['*.ts'],
163 }),
164 runtime: lambda.Runtime.NODEJS_14_X,
165 handler: 'index.handler',
166 uuid: '679f53fa-c002-430c-b0da-5b7982bd2287',
167 lambdaPurpose: 'AWS',
168 timeout: props.timeout || cdk.Duration.minutes(2),
169 role: props.role,
170 logRetention: props.logRetention,
171 functionName: props.functionName,
172 });
173 this.grantPrincipal = provider.grantPrincipal;
174 // Create the policy statements for the custom resource function role, or use the user-provided ones
175 const statements = [];
176 if (props.policy.statements.length !== 0) {
177 // Use custom statements provided by the user
178 for (const statement of props.policy.statements) {
179 statements.push(statement);
180 }
181 }
182 else {
183 // Derive statements from AWS SDK calls
184 for (const call of [props.onCreate, props.onUpdate, props.onDelete]) {
185 if (call && call.assumedRoleArn == null) {
186 const statement = new iam.PolicyStatement({
187 actions: [awsSdkToIamAction(call.service, call.action)],
188 resources: props.policy.resources,
189 });
190 statements.push(statement);
191 }
192 else if (call && call.assumedRoleArn != null) {
193 const statement = new iam.PolicyStatement({
194 actions: ['sts:AssumeRole'],
195 resources: [call.assumedRoleArn],
196 });
197 statements.push(statement);
198 }
199 }
200 }
201 const policy = new iam.Policy(this, 'CustomResourcePolicy', {
202 statements: statements,
203 });
204 if (provider.role !== undefined) {
205 policy.attachToRole(provider.role);
206 }
207 const create = props.onCreate || props.onUpdate;
208 this.customResource = new cdk.CustomResource(this, 'Resource', {
209 resourceType: props.resourceType || 'Custom::AWS',
210 serviceToken: provider.functionArn,
211 pascalCaseProperties: true,
212 properties: {
213 create: create && this.encodeJson(create),
214 update: props.onUpdate && this.encodeJson(props.onUpdate),
215 delete: props.onDelete && this.encodeJson(props.onDelete),
216 installLatestAwsSdk: props.installLatestAwsSdk ?? true,
217 },
218 });
219 // If the policy was deleted first, then the function might lose permissions to delete the custom resource
220 // This is here so that the policy doesn't get removed before onDelete is called
221 this.customResource.node.addDependency(policy);
222 }
223 static breakIgnoreErrorsCircuit(sdkCalls, caller) {
224 for (const call of sdkCalls) {
225 if (call?.ignoreErrorCodesMatching) {
226 throw new Error(`\`${caller}\`` + ' cannot be called along with `ignoreErrorCodesMatching`.');
227 }
228 }
229 }
230 /**
231 * Returns response data for the AWS SDK call.
232 *
233 * Example for S3 / listBucket : 'Buckets.0.Name'
234 *
235 * Use `Token.asXxx` to encode the returned `Reference` as a specific type or
236 * use the convenience `getDataString` for string attributes.
237 *
238 * Note that you cannot use this method if `ignoreErrorCodesMatching`
239 * is configured for any of the SDK calls. This is because in such a case,
240 * the response data might not exist, and will cause a CloudFormation deploy time error.
241 *
242 * @param dataPath the path to the data
243 */
244 getResponseFieldReference(dataPath) {
245 AwsCustomResource.breakIgnoreErrorsCircuit([this.props.onCreate, this.props.onUpdate], 'getData');
246 return this.customResource.getAtt(dataPath);
247 }
248 /**
249 * Returns response data for the AWS SDK call as string.
250 *
251 * Example for S3 / listBucket : 'Buckets.0.Name'
252 *
253 * Note that you cannot use this method if `ignoreErrorCodesMatching`
254 * is configured for any of the SDK calls. This is because in such a case,
255 * the response data might not exist, and will cause a CloudFormation deploy time error.
256 *
257 * @param dataPath the path to the data
258 */
259 getResponseField(dataPath) {
260 AwsCustomResource.breakIgnoreErrorsCircuit([this.props.onCreate, this.props.onUpdate], 'getDataString');
261 return this.customResource.getAttString(dataPath);
262 }
263 encodeJson(obj) {
264 return cdk.Lazy.uncachedString({ produce: () => cdk.Stack.of(this).toJsonString(obj) });
265 }
266}
267exports.AwsCustomResource = AwsCustomResource;
268_d = JSII_RTTI_SYMBOL_1;
269AwsCustomResource[_d] = { fqn: "@aws-cdk/custom-resources.AwsCustomResource", version: "1.191.0" };
270/**
271 * Gets awsSdkMetaData from file or from cache
272 */
273let getAwsSdkMetadata = (() => {
274 let _awsSdkMetadata;
275 return function () {
276 if (_awsSdkMetadata) {
277 return _awsSdkMetadata;
278 }
279 else {
280 return _awsSdkMetadata = JSON.parse(fs.readFileSync(path.join(__dirname, 'sdk-api-metadata.json'), 'utf-8'));
281 }
282 };
283})();
284/**
285 * Returns true if `obj` includes a `PhysicalResourceIdReference` in one of the
286 * values.
287 * @param obj Any object.
288 */
289function includesPhysicalResourceIdRef(obj) {
290 if (obj === undefined) {
291 return false;
292 }
293 let foundRef = false;
294 // we use JSON.stringify as a way to traverse all values in the object.
295 JSON.stringify(obj, (_, v) => {
296 if (v === runtime_1.PHYSICAL_RESOURCE_ID_REFERENCE) {
297 foundRef = true;
298 }
299 return v;
300 });
301 return foundRef;
302}
303/**
304 * Transform SDK service/action to IAM action using metadata from aws-sdk module.
305 * Example: CloudWatchLogs with putRetentionPolicy => logs:PutRetentionPolicy
306 *
307 * TODO: is this mapping correct for all services?
308 */
309function awsSdkToIamAction(service, action) {
310 const srv = service.toLowerCase();
311 const awsSdkMetadata = getAwsSdkMetadata();
312 const iamService = (awsSdkMetadata[srv] && awsSdkMetadata[srv].prefix) || srv;
313 const iamAction = action.charAt(0).toUpperCase() + action.slice(1);
314 return `${iamService}:${iamAction}`;
315}
316//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXdzLWN1c3RvbS1yZXNvdXJjZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImF3cy1jdXN0b20tcmVzb3VyY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEseUJBQXlCO0FBQ3pCLDZCQUE2QjtBQUM3Qix3Q0FBd0M7QUFDeEMsOENBQThDO0FBRTlDLHFDQUFxQztBQUVyQyx1Q0FBMkQ7QUFFM0QsaUdBQWlHO0FBQ2pHLDhEQUE4RDtBQUM5RCx3Q0FBMkQ7QUFFM0Q7O0dBRUc7QUFDSCxNQUFhLDJCQUEyQjtJQUF4QztRQUNrQixrQkFBYSxHQUFhLEdBQUcsQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO0tBZ0JuRTtJQWRDOztPQUVHO0lBQ0ksTUFBTTtRQUNYLE9BQU8sd0NBQThCLENBQUM7S0FDdkM7SUFFTSxPQUFPLENBQUMsQ0FBc0I7UUFDbkMsT0FBTyx3Q0FBOEIsQ0FBQztLQUN2QztJQUVNLFFBQVE7UUFDYixPQUFPLHdDQUE4QixDQUFDO0tBQ3ZDOztBQWhCSCxrRUFpQkM7OztBQUVEOztHQUVHO0FBQ0gsTUFBYSxrQkFBa0I7SUFnQjdCOzs7T0FHRztJQUNILFlBQW9DLFlBQXFCLEVBQWtCLEVBQVc7UUFBbEQsaUJBQVksR0FBWixZQUFZLENBQVM7UUFBa0IsT0FBRSxHQUFGLEVBQUUsQ0FBUztLQUFLO0lBbEIzRjs7T0FFRztJQUNJLE1BQU0sQ0FBQyxZQUFZLENBQUMsWUFBb0I7UUFDN0MsT0FBTyxJQUFJLGtCQUFrQixDQUFDLFlBQVksRUFBRSxTQUFTLENBQUMsQ0FBQztLQUN4RDtJQUVEOztPQUVHO0lBQ0ksTUFBTSxDQUFDLEVBQUUsQ0FBQyxFQUFVO1FBQ3pCLE9BQU8sSUFBSSxrQkFBa0IsQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDLENBQUM7S0FDOUM7O0FBZEgsZ0RBcUJDOzs7QUFzSEQ7O0dBRUc7QUFDSCxNQUFhLHVCQUF1QjtJQWtDbEM7OztPQUdHO0lBQ0gsWUFBb0MsVUFBaUMsRUFBa0IsU0FBb0I7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LENBQUMsQ0FBQyxDQUFDO1NBQzlHO0lBQ0gsQ0FBQyxDQUFDO0FBQ0osQ0FBQyxDQUFDLEVBQUUsQ0FBQztBQUVMOzs7O0dBSUc7QUFDSCxTQUFTLDZCQUE2QixDQUFDLEdBQW9CO0lBQ3pELElBQUksR0FBRyxLQUFLLFNBQVMsRUFBRTtRQUNyQixPQUFPLEtBQUssQ0FBQztLQUNkO0lBRUQsSUFBSSxRQUFRLEdBQUcsS0FBSyxDQUFDO0lBRXJCLHVFQUF1RTtJQUN2RSxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRTtRQUMzQixJQUFJLENBQUMsS0FBSyx3Q0FBOEIsRUFBRTtZQUN4QyxRQUFRLEdBQUcsSUFBSSxDQUFDO1NBQ2pCO1FBRUQsT0FBTyxDQUFDLENBQUM7SUFDWCxDQUFDLENBQUMsQ0FBQztJQUVILE9BQU8sUUFBUSxDQUFDO0FBQ2xCLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILFNBQVMsaUJBQWlCLENBQUMsT0FBZSxFQUFFLE1BQWM7SUFDeEQsTUFBTSxHQUFHLEdBQUcsT0FBTyxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ2xDLE1BQU0sY0FBYyxHQUFHLGlCQUFpQixFQUFFLENBQUM7SUFDM0MsTUFBTSxVQUFVLEdBQUcsQ0FBQyxjQUFjLENBQUMsR0FBRyxDQUFDLElBQUksY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEdBQUcsQ0FBQztJQUM5RSxNQUFNLFNBQVMsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLFdBQVcsRUFBRSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDbkUsT0FBTyxHQUFHLFVBQVUsSUFBSSxTQUFTLEVBQUUsQ0FBQztBQUN0QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgZnMgZnJvbSAnZnMnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCAqIGFzIGlhbSBmcm9tICdAYXdzLWNkay9hd3MtaWFtJztcbmltcG9ydCAqIGFzIGxhbWJkYSBmcm9tICdAYXdzLWNkay9hd3MtbGFtYmRhJztcbmltcG9ydCAqIGFzIGxvZ3MgZnJvbSAnQGF3cy1jZGsvYXdzLWxvZ3MnO1xuaW1wb3J0ICogYXMgY2RrIGZyb20gJ0Bhd3MtY2RrL2NvcmUnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBQSFlTSUNBTF9SRVNPVVJDRV9JRF9SRUZFUkVOQ0UgfSBmcm9tICcuL3J1bnRpbWUnO1xuXG4vLyBrZWVwIHRoaXMgaW1wb3J0IHNlcGFyYXRlIGZyb20gb3RoZXIgaW1wb3J0cyB0byByZWR1Y2UgY2hhbmNlIGZvciBtZXJnZSBjb25mbGljdHMgd2l0aCB2Mi1tYWluXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tZHVwbGljYXRlLWltcG9ydHMsIGltcG9ydC9vcmRlclxuaW1wb3J0IHsgQ29uc3RydWN0IGFzIENvcmVDb25zdHJ1Y3QgfSBmcm9tICdAYXdzLWNkay9jb3JlJztcblxuLyoqXG4gKiBSZWZlcmVuY2UgdG8gdGhlIHBoeXNpY2FsIHJlc291cmNlIGlkIHRoYXQgY2FuIGJlIHBhc3NlZCB0byB0aGUgQVdTIG9wZXJhdGlvbiBhcyBhIHBhcmFtZXRlci5cbiAqL1xuZXhwb3J0IGNsYXNzIFBoeXNpY2FsUmVzb3VyY2VJZFJlZmVyZW5jZSBpbXBsZW1lbnRzIGNkay5JUmVzb2x2YWJsZSB7XG4gIHB1YmxpYyByZWFkb25seSBjcmVhdGlvblN0YWNrOiBzdHJpbmdbXSA9IGNkay5jYXB0dXJlU3RhY2tUcmFjZSgpO1xuXG4gIC8qKlxuICAgKiB0b0pTT04gc2VyaWFsaXphdGlvbiB0byByZXBsYWNlIGBQaHlzaWNhbFJlc291cmNlSWRSZWZlcmVuY2VgIHdpdGggYSBtYWdpYyBzdHJpbmcuXG4gICAqL1xuICBwdWJsaWMgdG9KU09OKCkge1xuICAgIHJldHVybiBQSFlTSUNBTF9SRVNPVVJDRV9JRF9SRUZFUkVOQ0U7XG4gIH1cblxuICBwdWJsaWMgcmVzb2x2ZShfOiBjZGsuSVJlc29sdmVDb250ZXh0KTogYW55IHtcbiAgICByZXR1cm4gUEhZU0lDQUxfUkVTT1VSQ0VfSURfUkVGRVJFTkNFO1xuICB9XG5cbiAgcHVibGljIHRvU3RyaW5nKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIFBIWVNJQ0FMX1JFU09VUkNFX0lEX1JFRkVSRU5DRTtcbiAgfVxufVxuXG4vKipcbiAqIFBoeXNpY2FsIElEIG9mIHRoZSBjdXN0b20gcmVzb3VyY2UuXG4gKi9cbmV4cG9ydCBjbGFzcyBQaHlzaWNhbFJlc291cmNlSWQge1xuXG4gIC8qKlxuICAgKiBFeHRyYWN0IHRoZSBwaHlzaWNhbCByZXNvdXJjZSBpZCBmcm9tIHRoZSBwYXRoIChkb3Qgbm90YXRpb24pIHRvIHRoZSBkYXRhIGluIHRoZSBBUEkgY2FsbCByZXNwb25zZS5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZnJvbVJlc3BvbnNlKHJlc3BvbnNlUGF0aDogc3RyaW5nKTogUGh5c2ljYWxSZXNvdXJjZUlkIHtcbiAgICByZXR1cm4gbmV3IFBoeXNpY2FsUmVzb3VyY2VJZChyZXNwb25zZVBhdGgsIHVuZGVmaW5lZCk7XG4gIH1cblxuICAvKipcbiAgICogRXhwbGljaXQgcGh5c2ljYWwgcmVzb3VyY2UgaWQuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIG9mKGlkOiBzdHJpbmcpOiBQaHlzaWNhbFJlc291cmNlSWQge1xuICAgIHJldHVybiBuZXcgUGh5c2ljYWxSZXNvdXJjZUlkKHVuZGVmaW5lZCwgaWQpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBwYXJhbSByZXNwb25zZVBhdGggUGF0aCB0byBhIHJlc3BvbnNlIGRhdGEgZWxlbWVudCB0byBiZSB1c2VkIGFzIHRoZSBwaHlzaWNhbCBpZC5cbiAgICogQHBhcmFtIGlkIExpdGVyYWwgc3RyaW5nIHRvIGJlIHVzZWQgYXMgdGhlIHBoeXNpY2FsIGlkLlxuICAgKi9cbiAgcHJpdmF0ZSBjb25zdHJ1Y3RvcihwdWJsaWMgcmVhZG9ubHkgcmVzcG9uc2VQYXRoPzogc3RyaW5nLCBwdWJsaWMgcmVhZG9ubHkgaWQ/OiBzdHJpbmcpIHsgfVxufVxuXG4vKipcbiAqIEFuIEFXUyBTREsgY2FsbC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBd3NTZGtDYWxsIHtcbiAgLyoqXG4gICAqIFRoZSBzZXJ2aWNlIHRvIGNhbGxcbiAgICpcbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTSmF2YVNjcmlwdFNESy9sYXRlc3QvaW5kZXguaHRtbFxuICAgKi9cbiAgcmVhZG9ubHkgc2VydmljZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgc2VydmljZSBhY3Rpb24gdG8gY2FsbFxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NKYXZhU2NyaXB0U0RLL2xhdGVzdC9pbmRleC5odG1sXG4gICAqL1xuICByZWFkb25seSBhY3Rpb246IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIHBhcmFtZXRlcnMgZm9yIHRoZSBzZXJ2aWNlIGFjdGlvblxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIHBhcmFtZXRlcnNcbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTSmF2YVNjcmlwdFNESy9sYXRlc3QvaW5kZXguaHRtbFxuICAgKi9cbiAgcmVhZG9ubHkgcGFyYW1ldGVycz86IGFueTtcblxuICAvKipcbiAgICogVGhlIHBoeXNpY2FsIHJlc291cmNlIGlkIG9mIHRoZSBjdXN0b20gcmVzb3VyY2UgZm9yIHRoaXMgY2FsbC5cbiAgICogTWFuZGF0b3J5IGZvciBvbkNyZWF0ZSBvciBvblVwZGF0ZSBjYWxscy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBwaHlzaWNhbCByZXNvdXJjZSBpZFxuICAgKi9cbiAgcmVhZG9ubHkgcGh5c2ljYWxSZXNvdXJjZUlkPzogUGh5c2ljYWxSZXNvdXJjZUlkO1xuXG4gIC8qKlxuICAgKiBUaGUgcmVnZXggcGF0dGVybiB0byB1c2UgdG8gY2F0Y2ggQVBJIGVycm9ycy4gVGhlIGBjb2RlYCBwcm9wZXJ0eSBvZiB0aGVcbiAgICogYEVycm9yYCBvYmplY3Qgd2lsbCBiZSB0ZXN0ZWQgYWdhaW5zdCB0aGlzIHBhdHRlcm4uIElmIHRoZXJlIGlzIGEgbWF0Y2ggYW5cbiAgICogZXJyb3Igd2lsbCBub3QgYmUgdGhyb3duLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGRvIG5vdCBjYXRjaCBlcnJvcnNcbiAgICovXG4gIHJlYWRvbmx5IGlnbm9yZUVycm9yQ29kZXNNYXRjaGluZz86IHN0cmluZztcblxuICAvKipcbiAgICogQVBJIHZlcnNpb24gdG8gdXNlIGZvciB0aGUgc2VydmljZVxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9zZGstZm9yLWphdmFzY3JpcHQvdjIvZGV2ZWxvcGVyLWd1aWRlL2xvY2tpbmctYXBpLXZlcnNpb25zLmh0bWxcbiAgICogQGRlZmF1bHQgLSB1c2UgbGF0ZXN0IGF2YWlsYWJsZSBBUEkgdmVyc2lvblxuICAgKi9cbiAgcmVhZG9ubHkgYXBpVmVyc2lvbj86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIHJlZ2lvbiB0byBzZW5kIHNlcnZpY2UgcmVxdWVzdHMgdG8uXG4gICAqICoqTm90ZTogQ3Jvc3MtcmVnaW9uIG9wZXJhdGlvbnMgYXJlIGdlbmVyYWxseSBjb25zaWRlcmVkIGFuIGFudGktcGF0dGVybi4qKlxuICAgKiAqKkNvbnNpZGVyIGZpcnN0IGRlcGxveWluZyBhIHN0YWNrIGluIHRoYXQgcmVnaW9uLioqXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gdGhlIHJlZ2lvbiB3aGVyZSB0aGlzIGN1c3RvbSByZXNvdXJjZSBpcyBkZXBsb3llZFxuICAgKi9cbiAgcmVhZG9ubHkgcmVnaW9uPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBSZXN0cmljdCB0aGUgZGF0YSByZXR1cm5lZCBieSB0aGUgY3VzdG9tIHJlc291cmNlIHRvIGEgc3BlY2lmaWMgcGF0aCBpblxuICAgKiB0aGUgQVBJIHJlc3BvbnNlLiBVc2UgdGhpcyB0byBsaW1pdCB0aGUgZGF0YSByZXR1cm5lZCBieSB0aGUgY3VzdG9tXG4gICAqIHJlc291cmNlIGlmIHdvcmtpbmcgd2l0aCBBUEkgY2FsbHMgdGhhdCBjb3VsZCBwb3RlbnRpYWxseSByZXN1bHQgaW4gY3VzdG9tXG4gICAqIHJlc3BvbnNlIG9iamVjdHMgZXhjZWVkaW5nIHRoZSBoYXJkIGxpbWl0IG9mIDQwOTYgYnl0ZXMuXG4gICAqXG4gICAqIEV4YW1wbGUgZm9yIEVDUyAvIHVwZGF0ZVNlcnZpY2U6ICdzZXJ2aWNlLmRlcGxveW1lbnRDb25maWd1cmF0aW9uLm1heGltdW1QZXJjZW50J1xuICAgKlxuICAgKiBAZGVmYXVsdCAtIHJldHVybiBhbGwgZGF0YVxuICAgKlxuICAgKiBAZGVwcmVjYXRlZCB1c2Ugb3V0cHV0UGF0aHMgaW5zdGVhZFxuICAgKi9cbiAgcmVhZG9ubHkgb3V0cHV0UGF0aD86IHN0cmluZztcblxuICAvKipcbiAgICogUmVzdHJpY3QgdGhlIGRhdGEgcmV0dXJuZWQgYnkgdGhlIGN1c3RvbSByZXNvdXJjZSB0byBzcGVjaWZpYyBwYXRocyBpblxuICAgKiB0aGUgQVBJIHJlc3BvbnNlLiBVc2UgdGhpcyB0byBsaW1pdCB0aGUgZGF0YSByZXR1cm5lZCBieSB0aGUgY3VzdG9tXG4gICAqIHJlc291cmNlIGlmIHdvcmtpbmcgd2l0aCBBUEkgY2FsbHMgdGhhdCBjb3VsZCBwb3RlbnRpYWxseSByZXN1bHQgaW4gY3VzdG9tXG4gICAqIHJlc3BvbnNlIG9iamVjdHMgZXhjZWVkaW5nIHRoZSBoYXJkIGxpbWl0IG9mIDQwOTYgYnl0ZXMuXG4gICAqXG4gICAqIEV4YW1wbGUgZm9yIEVDUyAvIHVwZGF0ZVNlcnZpY2U6IFsnc2VydmljZS5kZXBsb3ltZW50Q29uZmlndXJhdGlvbi5tYXhpbXVtUGVyY2VudCddXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gcmV0dXJuIGFsbCBkYXRhXG4gICAqL1xuICByZWFkb25seSBvdXRwdXRQYXRocz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBVc2VkIGZvciBydW5uaW5nIHRoZSBTREsgY2FsbHMgaW4gdW5kZXJseWluZyBsYW1iZGEgd2l0aCBhIGRpZmZlcmVudCByb2xlXG4gICAqIENhbiBiZSB1c2VkIHByaW1hcmlseSBmb3IgY3Jvc3MtYWNjb3VudCByZXF1ZXN0cyB0byBmb3IgZXhhbXBsZSBjb25uZWN0XG4gICAqIGhvc3RlZHpvbmUgd2l0aCBhIHNoYXJlZCB2cGNcbiAgICpcbiAgICogRXhhbXBsZSBmb3IgUm91dGU1MyAvIGFzc29jaWF0ZVZQQ1dpdGhIb3N0ZWRab25lXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gcnVuIHdpdGhvdXQgYXNzdW1pbmcgcm9sZVxuICAgKi9cbiAgcmVhZG9ubHkgYXNzdW1lZFJvbGVBcm4/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogT3B0aW9ucyBmb3IgdGhlIGF1dG8tZ2VuZXJhdGlvbiBvZiBwb2xpY2llcyBiYXNlZCBvbiB0aGUgY29uZmlndXJlZCBTREsgY2FsbHMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2RrQ2FsbHNQb2xpY3lPcHRpb25zIHtcblxuICAvKipcbiAgICogVGhlIHJlc291cmNlcyB0aGF0IHRoZSBjYWxscyB3aWxsIGhhdmUgYWNjZXNzIHRvLlxuICAgKlxuICAgKiBJdCBpcyBiZXN0IHRvIHVzZSBzcGVjaWZpYyByZXNvdXJjZSBBUk4ncyB3aGVuIHBvc3NpYmxlLiBIb3dldmVyLCB5b3UgY2FuIGFsc28gdXNlIGBBd3NDdXN0b21SZXNvdXJjZVBvbGljeS5BTllfUkVTT1VSQ0VgXG4gICAqIHRvIGFsbG93IGFjY2VzcyB0byBhbGwgcmVzb3VyY2VzLiBGb3IgZXhhbXBsZSwgd2hlbiBgb25DcmVhdGVgIGlzIHVzZWQgdG8gY3JlYXRlIGEgcmVzb3VyY2Ugd2hpY2ggeW91IGRvbid0XG4gICAqIGtub3cgdGhlIHBoeXNpY2FsIG5hbWUgb2YgaW4gYWR2YW5jZS5cbiAgICpcbiAgICogTm90ZSB0aGF0IHdpbGwgYXBwbHkgdG8gQUxMIFNESyBjYWxscy5cbiAgICovXG4gIHJlYWRvbmx5IHJlc291cmNlczogc3RyaW5nW11cblxufVxuXG4vKipcbiAqIFRoZSBJQU0gUG9saWN5IHRoYXQgd2lsbCBiZSBhcHBsaWVkIHRvIHRoZSBkaWZmZXJlbnQgY2FsbHMuXG4gKi9cbmV4cG9ydCBjbGFzcyBBd3NDdXN0b21SZXNvdXJjZVBvbGljeSB7XG5cbiAgLyoqXG4gICAqIFVzZSB0aGlzIGNvbnN0YW50IHRvIGNvbmZpZ3VyZSBhY2Nlc3MgdG8gYW55IHJlc291cmNlLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBBTllfUkVTT1VSQ0UgPSBbJyonXTtcblxuICAvKipcbiAgICogRXhwbGljaXQgSUFNIFBvbGljeSBTdGF0ZW1lbnRzLlxuICAgKlxuICAgKiBAcGFyYW0gc3RhdGVtZW50cyB0aGUgc3RhdGVtZW50cyB0byBwcm9wYWdhdGUgdG8gdGhlIFNESyBjYWxscy5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZnJvbVN0YXRlbWVudHMoc3RhdGVtZW50czogaWFtLlBvbGljeVN0YXRlbWVudFtdKSB7XG4gICAgcmV0dXJuIG5ldyBBd3NDdXN0b21SZXNvdXJjZVBvbGljeShzdGF0ZW1lbnRzLCB1bmRlZmluZWQpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdlbmVyYXRlIElBTSBQb2xpY3kgU3RhdGVtZW50cyBmcm9tIHRoZSBjb25maWd1cmVkIFNESyBjYWxscy5cbiAgICpcbiAgICogRWFjaCBTREsgY2FsbCB3aXRoIGJlIHRyYW5zbGF0ZWQgdG8gYW4gSUFNIFBvbGljeSBTdGF0ZW1lbnQgaW4gdGhlIGZvcm0gb2Y6IGBjYWxsLnNlcnZpY2U6Y2FsbC5hY3Rpb25gIChlLmcgYHMzOlB1dE9iamVjdGApLlxuICAgKlxuICAgKiBUaGlzIHBvbGljeSBnZW5lcmF0b3IgYXNzdW1lcyB0aGUgSUFNIHBvbGljeSBuYW1lIGhhcyB0aGUgc2FtZSBuYW1lIGFzIHRoZSBBUElcbiAgICogY2FsbC4gVGhpcyBpcyB0cnVlIGluIDk5JSBvZiBjYXNlcywgYnV0IHRoZXJlIGFyZSBleGNlcHRpb25zIChmb3IgZXhhbXBsZSxcbiAgICogUzMncyBgUHV0QnVja2V0TGlmZWN5Y2xlQ29uZmlndXJhdGlvbmAgcmVxdWlyZXNcbiAgICogYHMzOlB1dExpZmVjeWNsZUNvbmZpZ3VyYXRpb25gIHBlcm1pc3Npb25zLCBMYW1iZGEncyBgSW52b2tlYCByZXF1aXJlc1xuICAgKiBgbGFtYmRhOkludm9rZUZ1bmN0aW9uYCBwZXJtaXNzaW9ucykuIFVzZSBgZnJvbVN0YXRlbWVudHNgIGlmIHlvdSB3YW50IHRvXG4gICAqIGRvIGEgY2FsbCB0aGF0IHJlcXVpcmVzIGRpZmZlcmVudCBJQU0gYWN0aW9uIG5hbWVzLlxuICAgKlxuICAgKiBAcGFyYW0gb3B0aW9ucyBvcHRpb25zIGZvciB0aGUgcG9saWN5IGdlbmVyYXRpb25cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZnJvbVNka0NhbGxzKG9wdGlvbnM6IFNka0NhbGxzUG9saWN5T3B0aW9ucykge1xuICAgIHJldHVybiBuZXcgQXdzQ3VzdG9tUmVzb3VyY2VQb2xpY3koW10sIG9wdGlvbnMucmVzb3VyY2VzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0gc3RhdGVtZW50cyBzdGF0ZW1lbnRzIGZvciBleHBsaWNpdCBwb2xpY3kuXG4gICAqIEBwYXJhbSByZXNvdXJjZXMgcmVzb3VyY2VzIGZvciBhdXRvLWdlbmVyYXRlZCBmcm9tIFNESyBjYWxscy5cbiAgICovXG4gIHByaXZhdGUgY29uc3RydWN0b3IocHVibGljIHJlYWRvbmx5IHN0YXRlbWVudHM6IGlhbS5Qb2xpY3lTdGF0ZW1lbnRbXSwgcHVibGljIHJlYWRvbmx5IHJlc291cmNlcz86IHN0cmluZ1tdKSB7fVxufVxuXG4vKipcbiAqIFByb3BlcnRpZXMgZm9yIEF3c0N1c3RvbVJlc291cmNlLlxuICpcbiAqIE5vdGUgdGhhdCBhdCBsZWFzdCBvbkNyZWF0ZSwgb25VcGRhdGUgb3Igb25EZWxldGUgbXVzdCBiZSBzcGVjaWZpZWQuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQXdzQ3VzdG9tUmVzb3VyY2VQcm9wcyB7XG4gIC8qKlxuICAgKiBDbG91ZGZvcm1hdGlvbiBSZXNvdXJjZSB0eXBlLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIEN1c3RvbTo6QVdTXG4gICAqL1xuICByZWFkb25seSByZXNvdXJjZVR5cGU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBBV1MgU0RLIGNhbGwgdG8gbWFrZSB3aGVuIHRoZSByZXNvdXJjZSBpcyBjcmVhdGVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIHRoZSBjYWxsIHdoZW4gdGhlIHJlc291cmNlIGlzIHVwZGF0ZWRcbiAgICovXG4gIHJlYWRvbmx5IG9uQ3JlYXRlPzogQXdzU2RrQ2FsbDtcblxuICAvKipcbiAgICogVGhlIEFXUyBTREsgY2FsbCB0byBtYWtlIHdoZW4gdGhlIHJlc291cmNlIGlzIHVwZGF0ZWRcbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBjYWxsXG4gICAqL1xuICByZWFkb25seSBvblVwZGF0ZT86IEF3c1Nka0NhbGw7XG5cbiAgLyoqXG4gICAqIFRoZSBBV1MgU0RLIGNhbGwgdG8gbWFrZSB3aGVuIHRoZSByZXNvdXJjZSBpcyBkZWxldGVkXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm8gY2FsbFxuICAgKi9cbiAgcmVhZG9ubHkgb25EZWxldGU/OiBBd3NTZGtDYWxsO1xuXG4gIC8qKlxuICAgKiBUaGUgcG9saWN5IHRoYXQgd2lsbCBiZSBhZGRlZCB0byB0aGUgZXhlY3V0aW9uIHJvbGUgb2YgdGhlIExhbWJkYVxuICAgKiBmdW5jdGlvbiBpbXBsZW1lbnRpbmcgdGhpcyBjdXN0b20gcmVzb3VyY2UgcHJvdmlkZXIuXG4gICAqXG4gICAqIFRoZSBjdXN0b20gcmVzb3VyY2UgYWxzbyBpbXBsZW1lbnRzIGBpYW0uSUdyYW50YWJsZWAsIG1ha2luZyBpdCBwb3NzaWJsZVxuICAgKiB0byB1c2UgdGhlIGBncmFudFh4eCgpYCBtZXRob2RzLlxuICAgKlxuICAgKiBBcyB0aGlzIGN1c3RvbSByZXNvdXJjZSB1c2VzIGEgc2luZ2xldG9uIExhbWJkYSBmdW5jdGlvbiwgaXQncyBpbXBvcnRhbnRcbiAgICogdG8gbm90ZSB0aGUgdGhhdCBmdW5jdGlvbidzIHJvbGUgd2lsbCBldmVudHVhbGx5IGFjY3VtdWxhdGUgdGhlXG4gICAqIHBlcm1pc3Npb25zL2dyYW50cyBmcm9tIGFsbCByZXNvdXJjZXMuXG4gICAqXG4gICAqIEBzZWUgUG9saWN5LmZyb21TdGF0ZW1lbnRzXG4gICAqIEBzZWUgUG9saWN5LmZyb21TZGtDYWxsc1xuICAgKi9cbiAgcmVhZG9ubHkgcG9saWN5OiBBd3NDdXN0b21SZXNvdXJjZVBvbGljeTtcblxuICAvKipcbiAgICogVGhlIGV4ZWN1dGlvbiByb2xlIGZvciB0aGUgc2luZ2xldG9uIExhbWJkYSBmdW5jdGlvbiBpbXBsZW1lbnRpbmcgdGhpcyBjdXN0b21cbiAgICogcmVzb3VyY2UgcHJvdmlkZXIuIFRoaXMgcm9sZSB3aWxsIGFwcGx5IHRvIGFsbCBgQXdzQ3VzdG9tUmVzb3VyY2VgXG4gICAqIGluc3RhbmNlcyBpbiB0aGUgc3RhY2suIFRoZSByb2xlIG11c3QgYmUgYXNzdW1hYmxlIGJ5IHRoZVxuICAgKiBgbGFtYmRhLmFtYXpvbmF3cy5jb21gIHNlcnZpY2UgcHJpbmNpcGFsLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGEgbmV3IHJvbGUgaXMgY3JlYXRlZFxuICAgKi9cbiAgcmVhZG9ubHkgcm9sZT86IGlhbS5JUm9sZTtcblxuICAvKipcbiAgICogVGhlIHRpbWVvdXQgZm9yIHRoZSBzaW5nbGV0b24gTGFtYmRhIGZ1bmN0aW9uIGltcGxlbWVudGluZyB0aGlzIGN1c3RvbSByZXNvdXJjZS5cbiAgICpcbiAgICogQGRlZmF1bHQgRHVyYXRpb24ubWludXRlcygyKVxuICAgKi9cbiAgcmVhZG9ubHkgdGltZW91dD86IGNkay5EdXJhdGlvblxuXG4gIC8qKlxuICAgKiBUaGUgbnVtYmVyIG9mIGRheXMgbG9nIGV2ZW50cyBvZiB0aGUgc2luZ2xldG9uIExhbWJkYSBmdW5jdGlvbiBpbXBsZW1lbnRpbmdcbiAgICogdGhpcyBjdXN0b20gcmVzb3VyY2UgYXJlIGtlcHQgaW4gQ2xvdWRXYXRjaCBMb2dzLlxuICAgKlxuICAgKiBAZGVmYXVsdCBsb2dzLlJldGVudGlvbkRheXMuSU5GSU5JVEVcbiAgICovXG4gIHJlYWRvbmx5IGxvZ1JldGVudGlvbj86IGxvZ3MuUmV0ZW50aW9uRGF5cztcblxuICAvKipcbiAgICogV2hldGhlciB0byBpbnN0YWxsIHRoZSBsYXRlc3QgQVdTIFNESyB2Mi4gQWxsb3dzIHRvIHVzZSB0aGUgbGF0ZXN0IEFQSVxuICAgKiBjYWxscyBkb2N1bWVudGVkIGF0IGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BV1NKYXZhU2NyaXB0U0RLL2xhdGVzdC9pbmRleC5odG1sLlxuICAgKlxuICAgKiBUaGUgaW5zdGFsbGF0aW9uIHRha2VzIGFyb3VuZCA2MCBzZWNvbmRzLlxuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSBpbnN0YWxsTGF0ZXN0QXdzU2RrPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogQSBuYW1lIGZvciB0aGUgc2luZ2xldG9uIExhbWJkYSBmdW5jdGlvbiBpbXBsZW1lbnRpbmcgdGhpcyBjdXN0b20gcmVzb3VyY2UuXG4gICAqIFRoZSBmdW5jdGlvbiBuYW1lIHdpbGwgcmVtYWluIHRoZSBzYW1lIGFmdGVyIHRoZSBmaXJzdCBBd3NDdXN0b21SZXNvdXJjZSBpcyBjcmVhdGVkIGluIGEgc3RhY2suXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gQVdTIENsb3VkRm9ybWF0aW9uIGdlbmVyYXRlcyBhIHVuaXF1ZSBwaHlzaWNhbCBJRCBhbmQgdXNlcyB0aGF0XG4gICAqIElEIGZvciB0aGUgZnVuY3Rpb24ncyBuYW1lLiBGb3IgbW9yZSBpbmZvcm1hdGlvbiwgc2VlIE5hbWUgVHlwZS5cbiAgICovXG4gIHJlYWRvbmx5IGZ1bmN0aW9uTmFtZT86IHN0cmluZztcbn1cblxuLyoqXG4gKiBEZWZpbmVzIGEgY3VzdG9tIHJlc291cmNlIHRoYXQgaXMgbWF0ZXJpYWxpemVkIHVzaW5nIHNwZWNpZmljIEFXUyBBUEkgY2FsbHMuIFRoZXNlIGNhbGxzIGFyZSBjcmVhdGVkIHVzaW5nXG4gKiBhIHNpbmdsZXRvbiBMYW1iZGEgZnVuY3Rpb24uXG4gKlxuICogVXNlIHRoaXMgdG8gYnJpZGdlIGFueSBnYXAgdGhhdCBtaWdodCBleGlzdCBpbiB0aGUgQ2xvdWRGb3JtYXRpb24gQ292ZXJhZ2UuXG4gKiBZb3UgY2FuIHNwZWNpZnkgZXhhY3RseSB3aGljaCBjYWxscyBhcmUgaW52b2tlZCBmb3IgdGhlICdDUkVBVEUnLCAnVVBEQVRFJyBhbmQgJ0RFTEVURScgbGlmZSBjeWNsZSBldmVudHMuXG4gKlxuICovXG5leHBvcnQgY2xhc3MgQXdzQ3VzdG9tUmVzb3VyY2UgZXh0ZW5kcyBDb3JlQ29uc3RydWN0IGltcGxlbWVudHMgaWFtLklHcmFudGFibGUge1xuXG4gIHByaXZhdGUgc3RhdGljIGJyZWFrSWdub3JlRXJyb3JzQ2lyY3VpdChzZGtDYWxsczogQXJyYXk8QXdzU2RrQ2FsbCB8IHVuZGVmaW5lZD4sIGNhbGxlcjogc3RyaW5nKSB7XG5cbiAgICBmb3IgKGNvbnN0IGNhbGwgb2Ygc2RrQ2FsbHMpIHtcbiAgICAgIGlmIChjYWxsPy5pZ25vcmVFcnJvckNvZGVzTWF0Y2hpbmcpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBcXGAke2NhbGxlcn1cXGBgICsgJyBjYW5ub3QgYmUgY2FsbGVkIGFsb25nIHdpdGggYGlnbm9yZUVycm9yQ29kZXNNYXRjaGluZ2AuJyk7XG4gICAgICB9XG4gICAgfVxuXG4gIH1cblxuICBwdWJsaWMgcmVhZG9ubHkgZ3JhbnRQcmluY2lwYWw6IGlhbS5JUHJpbmNpcGFsO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgY3VzdG9tUmVzb3VyY2U6IGNkay5DdXN0b21SZXNvdXJjZTtcbiAgcHJpdmF0ZSByZWFkb25seSBwcm9wczogQXdzQ3VzdG9tUmVzb3VyY2VQcm9wcztcblxuICAvLyAncHJvcHMnIGNhbm5vdCBiZSBvcHRpb25hbCwgZXZlbiB0aG91Z2ggYWxsIGl0cyBwcm9wZXJ0aWVzIGFyZSBvcHRpb25hbC5cbiAgLy8gdGhpcyBpcyBiZWNhdXNlIGF0IGxlYXN0IG9uZSBzZGsgY2FsbCBtdXN0IGJlIHByb3ZpZGVkLlxuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogQXdzQ3VzdG9tUmVzb3VyY2VQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICBpZiAoIXByb3BzLm9uQ3JlYXRlICYmICFwcm9wcy5vblVwZGF0ZSAmJiAhcHJvcHMub25EZWxldGUpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignQXQgbGVhc3QgYG9uQ3JlYXRlYCwgYG9uVXBkYXRlYCBvciBgb25EZWxldGVgIG11c3QgYmUgc3BlY2lmaWVkLicpO1xuICAgIH1cblxuICAgIGZvciAoY29uc3QgY2FsbCBvZiBbcHJvcHMub25DcmVhdGUsIHByb3BzLm9uVXBkYXRlXSkge1xuICAgICAgaWYgKGNhbGwgJiYgIWNhbGwucGh5c2ljYWxSZXNvdXJjZUlkKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignYHBoeXNpY2FsUmVzb3VyY2VJZGAgbXVzdCBiZSBzcGVjaWZpZWQgZm9yIG9uQ3JlYXRlIGFuZCBvblVwZGF0ZSBjYWxscy4nKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IGNhbGwgb2YgW3Byb3BzLm9uQ3JlYXRlLCBwcm9wcy5vblVwZGF0ZSwgcHJvcHMub25EZWxldGVdKSB7XG4gICAgICBpZiAoY2FsbD8ucGh5c2ljYWxSZXNvdXJjZUlkPy5yZXNwb25zZVBhdGgpIHtcbiAgICAgICAgQXdzQ3VzdG9tUmVzb3VyY2UuYnJlYWtJZ25vcmVFcnJvcnNDaXJjdWl0KFtjYWxsXSwgJ1BoeXNpY2FsUmVzb3VyY2VJZC5mcm9tUmVzcG9uc2UnKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoaW5jbHVkZXNQaHlzaWNhbFJlc291cmNlSWRSZWYocHJvcHMub25DcmVhdGU/LnBhcmFtZXRlcnMpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ2BQaHlzaWNhbFJlc291cmNlSWRSZWZlcmVuY2VgIG11c3Qgbm90IGJlIHNwZWNpZmllZCBpbiBgb25DcmVhdGVgIHBhcmFtZXRlcnMuJyk7XG4gICAgfVxuXG4gICAgdGhpcy5wcm9wcyA9IHByb3BzO1xuXG4gICAgY29uc3QgcHJvdmlkZXIgPSBuZXcgbGFtYmRhLlNpbmdsZXRvbkZ1bmN0aW9uKHRoaXMsICdQcm92aWRlcicsIHtcbiAgICAgIGNvZGU6IGxhbWJkYS5Db2RlLmZyb21Bc3NldChwYXRoLmpvaW4oX19kaXJuYW1lLCAncnVudGltZScpLCB7XG4gICAgICAgIGV4Y2x1ZGU6IFsnKi50cyddLFxuICAgICAgfSksXG4gICAgICBydW50aW1lOiBsYW1iZGEuUnVudGltZS5OT0RFSlNfMTRfWCxcbiAgICAgIGhhbmRsZXI6ICdpbmRleC5oYW5kbGVyJyxcbiAgICAgIHV1aWQ6ICc2NzlmNTNmYS1jMDAyLTQzMGMtYjBkYS01Yjc5ODJiZDIyODcnLFxuICAgICAgbGFtYmRhUHVycG9zZTogJ0FXUycsXG4gICAgICB0aW1lb3V0OiBwcm9wcy50aW1lb3V0IHx8IGNkay5EdXJhdGlvbi5taW51dGVzKDIpLFxuICAgICAgcm9sZTogcHJvcHMucm9sZSxcbiAgICAgIGxvZ1JldGVudGlvbjogcHJvcHMubG9nUmV0ZW50aW9uLFxuICAgICAgZnVuY3Rpb25OYW1lOiBwcm9wcy5mdW5jdGlvbk5hbWUsXG4gICAgfSk7XG4gICAgdGhpcy5ncmFudFByaW5jaXBhbCA9IHByb3ZpZGVyLmdyYW50UHJpbmNpcGFsO1xuXG4gICAgLy8gQ3JlYXRlIHRoZSBwb2xpY3kgc3RhdGVtZW50cyBmb3IgdGhlIGN1c3RvbSByZXNvdXJjZSBmdW5jdGlvbiByb2xlLCBvciB1c2UgdGhlIHVzZXItcHJvdmlkZWQgb25lc1xuICAgIGNvbnN0IHN0YXRlbWVudHMgPSBbXTtcbiAgICBpZiAocHJvcHMucG9saWN5LnN0YXRlbWVudHMubGVuZ3RoICE9PSAwKSB7XG4gICAgICAvLyBVc2UgY3VzdG9tIHN0YXRlbWVudHMgcHJvdmlkZWQgYnkgdGhlIHVzZXJcbiAgICAgIGZvciAoY29uc3Qgc3RhdGVtZW50IG9mIHByb3BzLnBvbGljeS5zdGF0ZW1lbnRzKSB7XG4gICAgICAgIHN0YXRlbWVudHMucHVzaChzdGF0ZW1lbnQpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBEZXJpdmUgc3RhdGVtZW50cyBmcm9tIEFXUyBTREsgY2FsbHNcbiAgICAgIGZvciAoY29uc3QgY2FsbCBvZiBbcHJvcHMub25DcmVhdGUsIHByb3BzLm9uVXBkYXRlLCBwcm9wcy5vbkRlbGV0ZV0pIHtcbiAgICAgICAgaWYgKGNhbGwgJiYgY2FsbC5hc3N1bWVkUm9sZUFybiA9PSBudWxsKSB7XG4gICAgICAgICAgY29uc3Qgc3RhdGVtZW50ID0gbmV3IGlhbS5Qb2xpY3lTdGF0ZW1lbnQoe1xuICAgICAgICAgICAgYWN0aW9uczogW2F3c1Nka1RvSWFtQWN0aW9uKGNhbGwuc2VydmljZSwgY2FsbC5hY3Rpb24pXSxcbiAgICAgICAgICAgIHJlc291cmNlczogcHJvcHMucG9saWN5LnJlc291cmNlcyxcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBzdGF0ZW1lbnRzLnB1c2goc3RhdGVtZW50KTtcbiAgICAgICAgfSBlbHNlIGlmIChjYWxsICYmIGNhbGwuYXNzdW1lZFJvbGVBcm4gIT0gbnVsbCkge1xuICAgICAgICAgIGNvbnN0IHN0YXRlbWVudCA9IG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgICAgIGFjdGlvbnM6IFsnc3RzOkFzc3VtZVJvbGUnXSxcbiAgICAgICAgICAgIHJlc291cmNlczogW2NhbGwuYXNzdW1lZFJvbGVBcm5dLFxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHN0YXRlbWVudHMucHVzaChzdGF0ZW1lbnQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIGNvbnN0IHBvbGljeSA9IG5ldyBpYW0uUG9saWN5KHRoaXMsICdDdXN0b21SZXNvdXJjZVBvbGljeScsIHtcbiAgICAgIHN0YXRlbWVudHM6IHN0YXRlbWVudHMsXG4gICAgfSk7XG4gICAgaWYgKHByb3ZpZGVyLnJvbGUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgcG9saWN5LmF0dGFjaFRvUm9sZShwcm92aWRlci5yb2xlKTtcbiAgICB9XG4gICAgY29uc3QgY3JlYXRlID0gcHJvcHMub25DcmVhdGUgfHwgcHJvcHMub25VcGRhdGU7XG4gICAgdGhpcy5jdXN0b21SZXNvdXJjZSA9IG5ldyBjZGsuQ3VzdG9tUmVzb3VyY2UodGhpcywgJ1Jlc291cmNlJywge1xuICAgICAgcmVzb3VyY2VUeXBlOiBwcm9wcy5yZXNvdXJjZVR5cGUgfHwgJ0N1c3RvbTo6QVdTJyxcbiAgICAgIHNlcnZpY2VUb2tlbjogcHJvdmlkZXIuZnVuY3Rpb25Bcm4sXG4gICAgICBwYXNjYWxDYXNlUHJvcGVydGllczogdHJ1ZSxcbiAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgY3JlYXRlOiBjcmVhdGUgJiYgdGhpcy5lbmNvZGVKc29uKGNyZWF0ZSksXG4gICAgICAgIHVwZGF0ZTogcHJvcHMub25VcGRhdGUgJiYgdGhpcy5lbmNvZGVKc29uKHByb3BzLm9uVXBkYXRlKSxcbiAgICAgICAgZGVsZXRlOiBwcm9wcy5vbkRlbGV0ZSAmJiB0aGlzLmVuY29kZUpzb24ocHJvcHMub25EZWxldGUpLFxuICAgICAgICBpbnN0YWxsTGF0ZXN0QXdzU2RrOiBwcm9wcy5pbnN0YWxsTGF0ZXN0QXdzU2RrID8/IHRydWUsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgLy8gSWYgdGhlIHBvbGljeSB3YXMgZGVsZXRlZCBmaXJzdCwgdGhlbiB0aGUgZnVuY3Rpb24gbWlnaHQgbG9zZSBwZXJtaXNzaW9ucyB0byBkZWxldGUgdGhlIGN1c3RvbSByZXNvdXJjZVxuICAgIC8vIFRoaXMgaXMgaGVyZSBzbyB0aGF0IHRoZSBwb2xpY3kgZG9lc24ndCBnZXQgcmVtb3ZlZCBiZWZvcmUgb25EZWxldGUgaXMgY2FsbGVkXG4gICAgdGhpcy5jdXN0b21SZXNvdXJjZS5ub2RlLmFkZERlcGVuZGVuY3kocG9saWN5KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHJlc3BvbnNlIGRhdGEgZm9yIHRoZSBBV1MgU0RLIGNhbGwuXG4gICAqXG4gICAqIEV4YW1wbGUgZm9yIFMzIC8gbGlzdEJ1Y2tldCA6ICdCdWNrZXRzLjAuTmFtZSdcbiAgICpcbiAgICogVXNlIGBUb2tlbi5hc1h4eGAgdG8gZW5jb2RlIHRoZSByZXR1cm5lZCBgUmVmZXJlbmNlYCBhcyBhIHNwZWNpZmljIHR5cGUgb3JcbiAgICogdXNlIHRoZSBjb252ZW5pZW5jZSBgZ2V0RGF0YVN0cmluZ2AgZm9yIHN0cmluZyBhdHRyaWJ1dGVzLlxuICAgKlxuICAgKiBOb3RlIHRoYXQgeW91IGNhbm5vdCB1c2UgdGhpcyBtZXRob2QgaWYgYGlnbm9yZUVycm9yQ29kZXNNYXRjaGluZ2BcbiAgICogaXMgY29uZmlndXJlZCBmb3IgYW55IG9mIHRoZSBTREsgY2FsbHMuIFRoaXMgaXMgYmVjYXVzZSBpbiBzdWNoIGEgY2FzZSxcbiAgICogdGhlIHJlc3BvbnNlIGRhdGEgbWlnaHQgbm90IGV4aXN0LCBhbmQgd2lsbCBjYXVzZSBhIENsb3VkRm9ybWF0aW9uIGRlcGxveSB0aW1lIGVycm9yLlxuICAgKlxuICAgKiBAcGFyYW0gZGF0YVBhdGggdGhlIHBhdGggdG8gdGhlIGRhdGFcbiAgICovXG4gIHB1YmxpYyBnZXRSZXNwb25zZUZpZWxkUmVmZXJlbmNlKGRhdGFQYXRoOiBzdHJpbmcpIHtcbiAgICBBd3NDdXN0b21SZXNvdXJjZS5icmVha0lnbm9yZUVycm9yc0NpcmN1aXQoW3RoaXMucHJvcHMub25DcmVhdGUsIHRoaXMucHJvcHMub25VcGRhdGVdLCAnZ2V0RGF0YScpO1xuICAgIHJldHVybiB0aGlzLmN1c3RvbVJlc291cmNlLmdldEF0dChkYXRhUGF0aCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyByZXNwb25zZSBkYXRhIGZvciB0aGUgQVdTIFNESyBjYWxsIGFzIHN0cmluZy5cbiAgICpcbiAgICogRXhhbXBsZSBmb3IgUzMgLyBsaXN0QnVja2V0IDogJ0J1Y2tldHMuMC5OYW1lJ1xuICAgKlxuICAgKiBOb3RlIHRoYXQgeW91IGNhbm5vdCB1c2UgdGhpcyBtZXRob2QgaWYgYGlnbm9yZUVycm9yQ29kZXNNYXRjaGluZ2BcbiAgICogaXMgY29uZmlndXJlZCBmb3IgYW55IG9mIHRoZSBTREsgY2FsbHMuIFRoaXMgaXMgYmVjYXVzZSBpbiBzdWNoIGEgY2FzZSxcbiAgICogdGhlIHJlc3BvbnNlIGRhdGEgbWlnaHQgbm90IGV4aXN0LCBhbmQgd2lsbCBjYXVzZSBhIENsb3VkRm9ybWF0aW9uIGRlcGxveSB0aW1lIGVycm9yLlxuICAgKlxuICAgKiBAcGFyYW0gZGF0YVBhdGggdGhlIHBhdGggdG8gdGhlIGRhdGFcbiAgICovXG4gIHB1YmxpYyBnZXRSZXNwb25zZUZpZWxkKGRhdGFQYXRoOiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIEF3c0N1c3RvbVJlc291cmNlLmJyZWFrSWdub3JlRXJyb3JzQ2lyY3VpdChbdGhpcy5wcm9wcy5vbkNyZWF0ZSwgdGhpcy5wcm9wcy5vblVwZGF0ZV0sICdnZXREYXRhU3RyaW5nJyk7XG4gICAgcmV0dXJuIHRoaXMuY3VzdG9tUmVzb3VyY2UuZ2V0QXR0U3RyaW5nKGRhdGFQYXRoKTtcbiAgfVxuXG4gIHByaXZhdGUgZW5jb2RlSnNvbihvYmo6IGFueSkge1xuICAgIHJldHVybiBjZGsuTGF6eS51bmNhY2hlZFN0cmluZyh7IHByb2R1Y2U6ICgpID0+IGNkay5TdGFjay5vZih0aGlzKS50b0pzb25TdHJpbmcob2JqKSB9KTtcbiAgfVxufVxuXG4vKipcbiAqIEFXUyBTREsgc2VydmljZSBtZXRhZGF0YS5cbiAqL1xuZXhwb3J0IHR5cGUgQXdzU2RrTWV0YWRhdGEgPSB7W2tleTogc3RyaW5nXTogYW55fTtcblxuLyoqXG4gKiBHZXRzIGF3c1Nka01ldGFEYXRhIGZyb20gZmlsZSBvciBmcm9tIGNhY2hlXG4gKi9cbmxldCBnZXRBd3NTZGtNZXRhZGF0YSA9ICgoKSA9PiB7XG4gIGxldCBfYXdzU2RrTWV0YWRhdGE6IEF3c1Nka01ldGFkYXRhO1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIGlmIChfYXdzU2RrTWV0YWRhdGEpIHtcbiAgICAgIHJldHVybiBfYXdzU2RrTWV0YWRhdGE7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBfYXdzU2RrTWV0YWRhdGEgPSBKU09OLnBhcnNlKGZzLnJlYWRGaWxlU3luYyhwYXRoLmpvaW4oX19kaXJuYW1lLCAnc2RrLWFwaS1tZXRhZGF0YS5qc29uJyksICd1dGYtOCcpKTtcbiAgICB9XG4gIH07XG59KSgpO1xuXG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiBgb2JqYCBpbmNsdWRlcyBhIGBQaHlzaWNhbFJlc291cmNlSWRSZWZlcmVuY2VgIGluIG9uZSBvZiB0aGVcbiAqIHZhbHVlcy5cbiAqIEBwYXJhbSBvYmogQW55IG9iamVjdC5cbiAqL1xuZnVuY3Rpb24gaW5jbHVkZXNQaHlzaWNhbFJlc291cmNlSWRSZWYob2JqOiBhbnkgfCB1bmRlZmluZWQpIHtcbiAgaWYgKG9iaiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgbGV0IGZvdW5kUmVmID0gZmFsc2U7XG5cbiAgLy8gd2UgdXNlIEpTT04uc3RyaW5naWZ5IGFzIGEgd2F5IHRvIHRyYXZlcnNlIGFsbCB2YWx1ZXMgaW4gdGhlIG9iamVjdC5cbiAgSlNPTi5zdHJpbmdpZnkob2JqLCAoXywgdikgPT4ge1xuICAgIGlmICh2ID09PSBQSFlTSUNBTF9SRVNPVVJDRV9JRF9SRUZFUkVOQ0UpIHtcbiAgICAgIGZvdW5kUmVmID0gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdjtcbiAgfSk7XG5cbiAgcmV0dXJuIGZvdW5kUmVmO1xufVxuXG4vKipcbiAqIFRyYW5zZm9ybSBTREsgc2VydmljZS9hY3Rpb24gdG8gSUFNIGFjdGlvbiB1c2luZyBtZXRhZGF0YSBmcm9tIGF3cy1zZGsgbW9kdWxlLlxuICogRXhhbXBsZTogQ2xvdWRXYXRjaExvZ3Mgd2l0aCBwdXRSZXRlbnRpb25Qb2xpY3kgPT4gbG9nczpQdXRSZXRlbnRpb25Qb2xpY3lcbiAqXG4gKiBUT0RPOiBpcyB0aGlzIG1hcHBpbmcgY29ycmVjdCBmb3IgYWxsIHNlcnZpY2VzP1xuICovXG5mdW5jdGlvbiBhd3NTZGtUb0lhbUFjdGlvbihzZXJ2aWNlOiBzdHJpbmcsIGFjdGlvbjogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3Qgc3J2ID0gc2VydmljZS50b0xvd2VyQ2FzZSgpO1xuICBjb25zdCBhd3NTZGtNZXRhZGF0YSA9IGdldEF3c1Nka01ldGFkYXRhKCk7XG4gIGNvbnN0IGlhbVNlcnZpY2UgPSAoYXdzU2RrTWV0YWRhdGFbc3J2XSAmJiBhd3NTZGtNZXRhZGF0YVtzcnZdLnByZWZpeCkgfHwgc3J2O1xuICBjb25zdCBpYW1BY3Rpb24gPSBhY3Rpb24uY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyBhY3Rpb24uc2xpY2UoMSk7XG4gIHJldHVybiBgJHtpYW1TZXJ2aWNlfToke2lhbUFjdGlvbn1gO1xufVxuIl19
\No newline at end of file