@aws-cdk/aws-cloudfront
Version:
The CDK Construct Library for AWS::CloudFront
387 lines • 69.6 kB
JavaScript
"use strict";
var _a, _b, _c;
Object.defineProperty(exports, "__esModule", { value: true });
exports.LambdaEdgeEventType = exports.CachedMethods = exports.AllowedMethods = exports.SecurityPolicyProtocol = exports.SSLMethod = exports.OriginProtocolPolicy = exports.ViewerProtocolPolicy = exports.PriceClass = exports.HttpVersion = exports.Distribution = void 0;
const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const s3 = require("@aws-cdk/aws-s3");
const core_1 = require("@aws-cdk/core");
const cx_api_1 = require("@aws-cdk/cx-api");
const cloudfront_generated_1 = require("./cloudfront.generated");
const cache_behavior_1 = require("./private/cache-behavior");
// v2 - keep this import as a separate section to reduce merge conflict when forward merging with the v2 branch.
// eslint-disable-next-line
const core_2 = require("@aws-cdk/core");
/**
* A CloudFront distribution with associated origin(s) and caching behavior(s).
*/
class Distribution extends core_1.Resource {
constructor(scope, id, props) {
super(scope, id);
this.additionalBehaviors = [];
this.boundOrigins = [];
this.originGroups = [];
try {
jsiiDeprecationWarnings._aws_cdk_aws_cloudfront_DistributionProps(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, Distribution);
}
throw error;
}
if (props.certificate) {
const certificateRegion = core_1.Stack.of(this).splitArn(props.certificate.certificateArn, core_1.ArnFormat.SLASH_RESOURCE_NAME).region;
if (!core_1.Token.isUnresolved(certificateRegion) && certificateRegion !== 'us-east-1') {
throw new Error(`Distribution certificates must be in the us-east-1 region and the certificate you provided is in ${certificateRegion}.`);
}
if ((props.domainNames ?? []).length === 0) {
throw new Error('Must specify at least one domain name to use a certificate with a distribution');
}
}
const originId = this.addOrigin(props.defaultBehavior.origin);
this.defaultBehavior = new cache_behavior_1.CacheBehavior(originId, { pathPattern: '*', ...props.defaultBehavior });
if (props.additionalBehaviors) {
Object.entries(props.additionalBehaviors).forEach(([pathPattern, behaviorOptions]) => {
this.addBehavior(pathPattern, behaviorOptions.origin, behaviorOptions);
});
}
this.certificate = props.certificate;
this.errorResponses = props.errorResponses ?? [];
// Comments have an undocumented limit of 128 characters
const trimmedComment = props.comment && props.comment.length > 128
? `${props.comment.slice(0, 128 - 3)}...`
: props.comment;
const distribution = new cloudfront_generated_1.CfnDistribution(this, 'Resource', {
distributionConfig: {
enabled: props.enabled ?? true,
origins: core_1.Lazy.any({ produce: () => this.renderOrigins() }),
originGroups: core_1.Lazy.any({ produce: () => this.renderOriginGroups() }),
defaultCacheBehavior: this.defaultBehavior._renderBehavior(),
aliases: props.domainNames,
cacheBehaviors: core_1.Lazy.any({ produce: () => this.renderCacheBehaviors() }),
comment: trimmedComment,
customErrorResponses: this.renderErrorResponses(),
defaultRootObject: props.defaultRootObject,
httpVersion: props.httpVersion ?? HttpVersion.HTTP2,
ipv6Enabled: props.enableIpv6 ?? true,
logging: this.renderLogging(props),
priceClass: props.priceClass ?? undefined,
restrictions: this.renderRestrictions(props.geoRestriction),
viewerCertificate: this.certificate ? this.renderViewerCertificate(this.certificate, props.minimumProtocolVersion, props.sslSupportMethod) : undefined,
webAclId: props.webAclId,
},
});
this.domainName = distribution.attrDomainName;
this.distributionDomainName = distribution.attrDomainName;
this.distributionId = distribution.ref;
}
/**
* Creates a Distribution construct that represents an external (imported) distribution.
*/
static fromDistributionAttributes(scope, id, attrs) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_cloudfront_DistributionAttributes(attrs);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.fromDistributionAttributes);
}
throw error;
}
return new class extends core_1.Resource {
constructor() {
super(scope, id);
this.domainName = attrs.domainName;
this.distributionDomainName = attrs.domainName;
this.distributionId = attrs.distributionId;
}
}();
}
/**
* Adds a new behavior to this distribution for the given pathPattern.
*
* @param pathPattern the path pattern (e.g., 'images/*') that specifies which requests to apply the behavior to.
* @param origin the origin to use for this behavior
* @param behaviorOptions the options for the behavior at this path.
*/
addBehavior(pathPattern, origin, behaviorOptions = {}) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_cloudfront_IOrigin(origin);
jsiiDeprecationWarnings._aws_cdk_aws_cloudfront_AddBehaviorOptions(behaviorOptions);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.addBehavior);
}
throw error;
}
if (pathPattern === '*') {
throw new Error('Only the default behavior can have a path pattern of \'*\'');
}
const originId = this.addOrigin(origin);
this.additionalBehaviors.push(new cache_behavior_1.CacheBehavior(originId, { pathPattern, ...behaviorOptions }));
}
addOrigin(origin, isFailoverOrigin = false) {
const ORIGIN_ID_MAX_LENGTH = 128;
const existingOrigin = this.boundOrigins.find(boundOrigin => boundOrigin.origin === origin);
if (existingOrigin) {
return existingOrigin.originGroupId ?? existingOrigin.originId;
}
else {
const originIndex = this.boundOrigins.length + 1;
const scope = new core_2.Construct(this, `Origin${originIndex}`);
const originId = core_1.Names.uniqueId(scope).slice(-ORIGIN_ID_MAX_LENGTH);
const originBindConfig = origin.bind(scope, { originId });
if (!originBindConfig.failoverConfig) {
this.boundOrigins.push({ origin, originId, ...originBindConfig });
}
else {
if (isFailoverOrigin) {
throw new Error('An Origin cannot use an Origin with its own failover configuration as its fallback origin!');
}
const groupIndex = this.originGroups.length + 1;
const originGroupId = core_1.Names.uniqueId(new core_2.Construct(this, `OriginGroup${groupIndex}`)).slice(-ORIGIN_ID_MAX_LENGTH);
this.boundOrigins.push({ origin, originId, originGroupId, ...originBindConfig });
const failoverOriginId = this.addOrigin(originBindConfig.failoverConfig.failoverOrigin, true);
this.addOriginGroup(originGroupId, originBindConfig.failoverConfig.statusCodes, originId, failoverOriginId);
return originGroupId;
}
return originId;
}
}
addOriginGroup(originGroupId, statusCodes, originId, failoverOriginId) {
statusCodes = statusCodes ?? [500, 502, 503, 504];
if (statusCodes.length === 0) {
throw new Error('fallbackStatusCodes cannot be empty');
}
this.originGroups.push({
failoverCriteria: {
statusCodes: {
items: statusCodes,
quantity: statusCodes.length,
},
},
id: originGroupId,
members: {
items: [
{ originId },
{ originId: failoverOriginId },
],
quantity: 2,
},
});
}
renderOrigins() {
const renderedOrigins = [];
this.boundOrigins.forEach(boundOrigin => {
if (boundOrigin.originProperty) {
renderedOrigins.push(boundOrigin.originProperty);
}
});
return renderedOrigins;
}
renderOriginGroups() {
return this.originGroups.length === 0
? undefined
: {
items: this.originGroups,
quantity: this.originGroups.length,
};
}
renderCacheBehaviors() {
if (this.additionalBehaviors.length === 0) {
return undefined;
}
return this.additionalBehaviors.map(behavior => behavior._renderBehavior());
}
renderErrorResponses() {
if (this.errorResponses.length === 0) {
return undefined;
}
return this.errorResponses.map(errorConfig => {
if (!errorConfig.responseHttpStatus && !errorConfig.ttl && !errorConfig.responsePagePath) {
throw new Error('A custom error response without either a \'responseHttpStatus\', \'ttl\' or \'responsePagePath\' is not valid.');
}
return {
errorCachingMinTtl: errorConfig.ttl?.toSeconds(),
errorCode: errorConfig.httpStatus,
responseCode: errorConfig.responsePagePath
? errorConfig.responseHttpStatus ?? errorConfig.httpStatus
: errorConfig.responseHttpStatus,
responsePagePath: errorConfig.responsePagePath,
};
});
}
renderLogging(props) {
if (!props.enableLogging && !props.logBucket) {
return undefined;
}
if (props.enableLogging === false && props.logBucket) {
throw new Error('Explicitly disabled logging but provided a logging bucket.');
}
const bucket = props.logBucket ?? new s3.Bucket(this, 'LoggingBucket', {
encryption: s3.BucketEncryption.S3_MANAGED,
});
return {
bucket: bucket.bucketRegionalDomainName,
includeCookies: props.logIncludesCookies,
prefix: props.logFilePrefix,
};
}
renderRestrictions(geoRestriction) {
return geoRestriction ? {
geoRestriction: {
restrictionType: geoRestriction.restrictionType,
locations: geoRestriction.locations,
},
} : undefined;
}
renderViewerCertificate(certificate, minimumProtocolVersionProp, sslSupportMethodProp) {
const defaultVersion = core_1.FeatureFlags.of(this).isEnabled(cx_api_1.CLOUDFRONT_DEFAULT_SECURITY_POLICY_TLS_V1_2_2021)
? SecurityPolicyProtocol.TLS_V1_2_2021 : SecurityPolicyProtocol.TLS_V1_2_2019;
const minimumProtocolVersion = minimumProtocolVersionProp ?? defaultVersion;
const sslSupportMethod = sslSupportMethodProp ?? SSLMethod.SNI;
return {
acmCertificateArn: certificate.certificateArn,
minimumProtocolVersion: minimumProtocolVersion,
sslSupportMethod: sslSupportMethod,
};
}
}
exports.Distribution = Distribution;
_a = JSII_RTTI_SYMBOL_1;
Distribution[_a] = { fqn: "@aws-cdk/aws-cloudfront.Distribution", version: "1.204.0" };
/** Maximum HTTP version to support */
var HttpVersion;
(function (HttpVersion) {
/** HTTP 1.1 */
HttpVersion["HTTP1_1"] = "http1.1";
/** HTTP 2 */
HttpVersion["HTTP2"] = "http2";
})(HttpVersion = exports.HttpVersion || (exports.HttpVersion = {}));
/**
* The price class determines how many edge locations CloudFront will use for your distribution.
* See https://aws.amazon.com/cloudfront/pricing/ for full list of supported regions.
*/
var PriceClass;
(function (PriceClass) {
/** USA, Canada, Europe, & Israel */
PriceClass["PRICE_CLASS_100"] = "PriceClass_100";
/** PRICE_CLASS_100 + South Africa, Kenya, Middle East, Japan, Singapore, South Korea, Taiwan, Hong Kong, & Philippines */
PriceClass["PRICE_CLASS_200"] = "PriceClass_200";
/** All locations */
PriceClass["PRICE_CLASS_ALL"] = "PriceClass_All";
})(PriceClass = exports.PriceClass || (exports.PriceClass = {}));
/**
* How HTTPs should be handled with your distribution.
*/
var ViewerProtocolPolicy;
(function (ViewerProtocolPolicy) {
/** HTTPS only */
ViewerProtocolPolicy["HTTPS_ONLY"] = "https-only";
/** Will redirect HTTP requests to HTTPS */
ViewerProtocolPolicy["REDIRECT_TO_HTTPS"] = "redirect-to-https";
/** Both HTTP and HTTPS supported */
ViewerProtocolPolicy["ALLOW_ALL"] = "allow-all";
})(ViewerProtocolPolicy = exports.ViewerProtocolPolicy || (exports.ViewerProtocolPolicy = {}));
/**
* Defines what protocols CloudFront will use to connect to an origin.
*/
var OriginProtocolPolicy;
(function (OriginProtocolPolicy) {
/** Connect on HTTP only */
OriginProtocolPolicy["HTTP_ONLY"] = "http-only";
/** Connect with the same protocol as the viewer */
OriginProtocolPolicy["MATCH_VIEWER"] = "match-viewer";
/** Connect on HTTPS only */
OriginProtocolPolicy["HTTPS_ONLY"] = "https-only";
})(OriginProtocolPolicy = exports.OriginProtocolPolicy || (exports.OriginProtocolPolicy = {}));
/**
* The SSL method CloudFront will use for your distribution.
*
* Server Name Indication (SNI) - is an extension to the TLS computer networking protocol by which a client indicates
* which hostname it is attempting to connect to at the start of the handshaking process. This allows a server to present
* multiple certificates on the same IP address and TCP port number and hence allows multiple secure (HTTPS) websites
* (or any other service over TLS) to be served by the same IP address without requiring all those sites to use the same certificate.
*
* CloudFront can use SNI to host multiple distributions on the same IP - which a large majority of clients will support.
*
* If your clients cannot support SNI however - CloudFront can use dedicated IPs for your distribution - but there is a prorated monthly charge for
* using this feature. By default, we use SNI - but you can optionally enable dedicated IPs (VIP).
*
* See the CloudFront SSL for more details about pricing : https://aws.amazon.com/cloudfront/custom-ssl-domains/
*
*/
var SSLMethod;
(function (SSLMethod) {
SSLMethod["SNI"] = "sni-only";
SSLMethod["VIP"] = "vip";
})(SSLMethod = exports.SSLMethod || (exports.SSLMethod = {}));
/**
* The minimum version of the SSL protocol that you want CloudFront to use for HTTPS connections.
* CloudFront serves your objects only to browsers or devices that support at least the SSL version that you specify.
*/
var SecurityPolicyProtocol;
(function (SecurityPolicyProtocol) {
SecurityPolicyProtocol["SSL_V3"] = "SSLv3";
SecurityPolicyProtocol["TLS_V1"] = "TLSv1";
SecurityPolicyProtocol["TLS_V1_2016"] = "TLSv1_2016";
SecurityPolicyProtocol["TLS_V1_1_2016"] = "TLSv1.1_2016";
SecurityPolicyProtocol["TLS_V1_2_2018"] = "TLSv1.2_2018";
SecurityPolicyProtocol["TLS_V1_2_2019"] = "TLSv1.2_2019";
SecurityPolicyProtocol["TLS_V1_2_2021"] = "TLSv1.2_2021";
})(SecurityPolicyProtocol = exports.SecurityPolicyProtocol || (exports.SecurityPolicyProtocol = {}));
/**
* The HTTP methods that the Behavior will accept requests on.
*/
class AllowedMethods {
constructor(methods) { this.methods = methods; }
}
exports.AllowedMethods = AllowedMethods;
_b = JSII_RTTI_SYMBOL_1;
AllowedMethods[_b] = { fqn: "@aws-cdk/aws-cloudfront.AllowedMethods", version: "1.204.0" };
/** HEAD and GET */
AllowedMethods.ALLOW_GET_HEAD = new AllowedMethods(['GET', 'HEAD']);
/** HEAD, GET, and OPTIONS */
AllowedMethods.ALLOW_GET_HEAD_OPTIONS = new AllowedMethods(['GET', 'HEAD', 'OPTIONS']);
/** All supported HTTP methods */
AllowedMethods.ALLOW_ALL = new AllowedMethods(['GET', 'HEAD', 'OPTIONS', 'PUT', 'PATCH', 'POST', 'DELETE']);
/**
* The HTTP methods that the Behavior will cache requests on.
*/
class CachedMethods {
constructor(methods) { this.methods = methods; }
}
exports.CachedMethods = CachedMethods;
_c = JSII_RTTI_SYMBOL_1;
CachedMethods[_c] = { fqn: "@aws-cdk/aws-cloudfront.CachedMethods", version: "1.204.0" };
/** HEAD and GET */
CachedMethods.CACHE_GET_HEAD = new CachedMethods(['GET', 'HEAD']);
/** HEAD, GET, and OPTIONS */
CachedMethods.CACHE_GET_HEAD_OPTIONS = new CachedMethods(['GET', 'HEAD', 'OPTIONS']);
/**
* The type of events that a Lambda@Edge function can be invoked in response to.
*/
var LambdaEdgeEventType;
(function (LambdaEdgeEventType) {
/**
* The origin-request specifies the request to the
* origin location (e.g. S3)
*/
LambdaEdgeEventType["ORIGIN_REQUEST"] = "origin-request";
/**
* The origin-response specifies the response from the
* origin location (e.g. S3)
*/
LambdaEdgeEventType["ORIGIN_RESPONSE"] = "origin-response";
/**
* The viewer-request specifies the incoming request
*/
LambdaEdgeEventType["VIEWER_REQUEST"] = "viewer-request";
/**
* The viewer-response specifies the outgoing response
*/
LambdaEdgeEventType["VIEWER_RESPONSE"] = "viewer-response";
})(LambdaEdgeEventType = exports.LambdaEdgeEventType || (exports.LambdaEdgeEventType = {}));
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGlzdHJpYnV0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiZGlzdHJpYnV0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUVBLHNDQUFzQztBQUN0Qyx3Q0FBa0g7QUFDbEgsNENBQW1GO0FBR25GLGlFQUF5RDtBQU16RCw2REFBeUQ7QUFHekQsZ0hBQWdIO0FBQ2hILDJCQUEyQjtBQUMzQix3Q0FBMkQ7QUFpTzNEOztHQUVHO0FBQ0gsTUFBYSxZQUFhLFNBQVEsZUFBUTtJQWdDeEMsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUF3QjtRQUNoRSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBUkYsd0JBQW1CLEdBQW9CLEVBQUUsQ0FBQztRQUMxQyxpQkFBWSxHQUFrQixFQUFFLENBQUM7UUFDakMsaUJBQVksR0FBMEMsRUFBRSxDQUFDOzs7Ozs7K0NBM0IvRCxZQUFZOzs7O1FBbUNyQixJQUFJLEtBQUssQ0FBQyxXQUFXLEVBQUU7WUFDckIsTUFBTSxpQkFBaUIsR0FBRyxZQUFLLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLGNBQWMsRUFBRSxnQkFBUyxDQUFDLG1CQUFtQixDQUFDLENBQUMsTUFBTSxDQUFDO1lBQzFILElBQUksQ0FBQyxZQUFLLENBQUMsWUFBWSxDQUFDLGlCQUFpQixDQUFDLElBQUksaUJBQWlCLEtBQUssV0FBVyxFQUFFO2dCQUMvRSxNQUFNLElBQUksS0FBSyxDQUFDLG9HQUFvRyxpQkFBaUIsR0FBRyxDQUFDLENBQUM7YUFDM0k7WUFFRCxJQUFJLENBQUMsS0FBSyxDQUFDLFdBQVcsSUFBSSxFQUFFLENBQUMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO2dCQUMxQyxNQUFNLElBQUksS0FBSyxDQUFDLGdGQUFnRixDQUFDLENBQUM7YUFDbkc7U0FDRjtRQUVELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxT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LE1BQWEsYUFBYTtJQVN4QixZQUFvQixPQUFpQixJQUFJLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDLEVBQUU7O0FBVHBFLHNDQVVDOzs7QUFUQyxtQkFBbUI7QUFDSSw0QkFBYyxHQUFHLElBQUksYUFBYSxDQUFDLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUM7QUFDM0UsNkJBQTZCO0FBQ04sb0NBQXNCLEdBQUcsSUFBSSxhQUFhLENBQUMsQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUM7QUF1Q2hHOztHQUVHO0FBQ0gsSUFBWSxtQkFzQlg7QUF0QkQsV0FBWSxtQkFBbUI7SUFDN0I7OztPQUdHO0lBQ0gsd0RBQWlDLENBQUE7SUFFakM7OztPQUdHO0lBQ0gsMERBQW1DLENBQUE7SUFFbkM7O09BRUc7SUFDSCx3REFBaUMsQ0FBQTtJQUVqQzs7T0FFRztJQUNILDBEQUFtQyxDQUFBO0FBQ3JDLENBQUMsRUF0QlcsbUJBQW1CLEdBQW5CLDJCQUFtQixLQUFuQiwyQkFBbUIsUUFzQjlCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgYWNtIGZyb20gJ0Bhd3MtY2RrL2F3cy1jZXJ0aWZpY2F0ZW1hbmFnZXInO1xuaW1wb3J0ICogYXMgbGFtYmRhIGZyb20gJ0Bhd3MtY2RrL2F3cy1sYW1iZGEnO1xuaW1wb3J0ICogYXMgczMgZnJvbSAnQGF3cy1jZGsvYXdzLXMzJztcbmltcG9ydCB7IEFybkZvcm1hdCwgSVJlc291cmNlLCBMYXp5LCBSZXNvdXJjZSwgU3RhY2ssIFRva2VuLCBEdXJhdGlvbiwgTmFtZXMsIEZlYXR1cmVGbGFncyB9IGZyb20gJ0Bhd3MtY2RrL2NvcmUnO1xuaW1wb3J0IHsgQ0xPVURGUk9OVF9ERUZBVUxUX1NFQ1VSSVRZX1BPTElDWV9UTFNfVjFfMl8yMDIxIH0gZnJvbSAnQGF3cy1jZGsvY3gtYXBpJztcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0IHsgSUNhY2hlUG9saWN5IH0gZnJvbSAnLi9jYWNoZS1wb2xpY3knO1xuaW1wb3J0IHsgQ2ZuRGlzdHJpYnV0aW9uIH0gZnJvbSAnLi9jbG91ZGZyb250LmdlbmVyYXRlZCc7XG5pbXBvcnQgeyBGdW5jdGlvbkFzc29jaWF0aW9uIH0gZnJvbSAnLi9mdW5jdGlvbic7XG5pbXBvcnQgeyBHZW9SZXN0cmljdGlvbiB9IGZyb20gJy4vZ2VvLXJlc3RyaWN0aW9uJztcbmltcG9ydCB7IElLZXlHcm91cCB9IGZyb20gJy4va2V5LWdyb3VwJztcbmltcG9ydCB7IElPcmlnaW4sIE9yaWdpbkJpbmRDb25maWcsIE9yaWdpbkJpbmRPcHRpb25zIH0gZnJvbSAnLi9vcmlnaW4nO1xuaW1wb3J0IHsgSU9yaWdpblJlcXVlc3RQb2xpY3kgfSBmcm9tICcuL29yaWdpbi1yZXF1ZXN0LXBvbGljeSc7XG5pbXBvcnQgeyBDYWNoZUJlaGF2aW9yIH0gZnJvbSAnLi9wcml2YXRlL2NhY2hlLWJlaGF2aW9yJztcbmltcG9ydCB7IElSZXNwb25zZUhlYWRlcnNQb2xpY3kgfSBmcm9tICcuL3Jlc3BvbnNlLWhlYWRlcnMtcG9saWN5JztcblxuLy8gdjIgLSBrZWVwIHRoaXMgaW1wb3J0IGFzIGEgc2VwYXJhdGUgc2VjdGlvbiB0byByZWR1Y2UgbWVyZ2UgY29uZmxpY3Qgd2hlbiBmb3J3YXJkIG1lcmdpbmcgd2l0aCB0aGUgdjIgYnJhbmNoLlxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG5pbXBvcnQgeyBDb25zdHJ1Y3QgYXMgQ29yZUNvbnN0cnVjdCB9IGZyb20gJ0Bhd3MtY2RrL2NvcmUnO1xuXG4vKipcbiAqIEludGVyZmFjZSBmb3IgQ2xvdWRGcm9udCBkaXN0cmlidXRpb25zXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSURpc3RyaWJ1dGlvbiBleHRlbmRzIElSZXNvdXJjZSB7XG4gIC8qKlxuICAgKiBUaGUgZG9tYWluIG5hbWUgb2YgdGhlIERpc3RyaWJ1dGlvbiwgc3VjaCBhcyBkMTExMTExYWJjZGVmOC5jbG91ZGZyb250Lm5ldC5cbiAgICpcbiAgICogQGF0dHJpYnV0ZVxuICAgKiBAZGVwcmVjYXRlZCAtIFVzZSBgZGlzdHJpYnV0aW9uRG9tYWluTmFtZWAgaW5zdGVhZC5cbiAgICovXG4gIHJlYWRvbmx5IGRvbWFpbk5hbWU6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIGRvbWFpbiBuYW1lIG9mIHRoZSBEaXN0cmlidXRpb24sIHN1Y2ggYXMgZDExMTExMWFiY2RlZjguY2xvdWRmcm9udC5uZXQuXG4gICAqXG4gICAqIEBhdHRyaWJ1dGVcbiAgICovXG4gIHJlYWRvbmx5IGRpc3RyaWJ1dGlvbkRvbWFpbk5hbWU6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIGRpc3RyaWJ1dGlvbiBJRCBmb3IgdGhpcyBkaXN0cmlidXRpb24uXG4gICAqXG4gICAqIEBhdHRyaWJ1dGVcbiAgICovXG4gIHJlYWRvbmx5IGRpc3RyaWJ1dGlvbklkOiBzdHJpbmc7XG59XG5cbi8qKlxuICogQXR0cmlidXRlcyB1c2VkIHRvIGltcG9ydCBhIERpc3RyaWJ1dGlvbi5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEaXN0cmlidXRpb25BdHRyaWJ1dGVzIHtcbiAgLyoqXG4gICAqIFRoZSBnZW5lcmF0ZWQgZG9tYWluIG5hbWUgb2YgdGhlIERpc3RyaWJ1dGlvbiwgc3VjaCBhcyBkMTExMTExYWJjZGVmOC5jbG91ZGZyb250Lm5ldC5cbiAgICpcbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcmVhZG9ubHkgZG9tYWluTmFtZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgZGlzdHJpYnV0aW9uIElEIGZvciB0aGlzIGRpc3RyaWJ1dGlvbi5cbiAgICpcbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcmVhZG9ubHkgZGlzdHJpYnV0aW9uSWQ6IHN0cmluZztcbn1cblxuaW50ZXJmYWNlIEJvdW5kT3JpZ2luIGV4dGVuZHMgT3JpZ2luQmluZE9wdGlvbnMsIE9yaWdpbkJpbmRDb25maWcge1xuICByZWFkb25seSBvcmlnaW46IElPcmlnaW47XG4gIHJlYWRvbmx5IG9yaWdpbkdyb3VwSWQ/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgYSBEaXN0cmlidXRpb25cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEaXN0cmlidXRpb25Qcm9wcyB7XG4gIC8qKlxuICAgKiBUaGUgZGVmYXVsdCBiZWhhdmlvciBmb3IgdGhlIGRpc3RyaWJ1dGlvbi5cbiAgICovXG4gIHJlYWRvbmx5IGRlZmF1bHRCZWhhdmlvcjogQmVoYXZpb3JPcHRpb25zO1xuXG4gIC8qKlxuICAgKiBBZGRpdGlvbmFsIGJlaGF2aW9ycyBmb3IgdGhlIGRpc3RyaWJ1dGlvbiwgbWFwcGVkIGJ5IHRoZSBwYXRoUGF0dGVybiB0aGF0IHNwZWNpZmllcyB3aGljaCByZXF1ZXN0cyB0byBhcHBseSB0aGUgYmVoYXZpb3IgdG8uXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm8gYWRkaXRpb25hbCBiZWhhdmlvcnMgYXJlIGFkZGVkLlxuICAgKi9cbiAgcmVhZG9ubHkgYWRkaXRpb25hbEJlaGF2aW9ycz86IFJlY29yZDxzdHJpbmcsIEJlaGF2aW9yT3B0aW9ucz47XG5cbiAgLyoqXG4gICAqIEEgY2VydGlmaWNhdGUgdG8gYXNzb2NpYXRlIHdpdGggdGhlIGRpc3RyaWJ1dGlvbi4gVGhlIGNlcnRpZmljYXRlIG11c3QgYmUgbG9jYXRlZCBpbiBOLiBWaXJnaW5pYSAodXMtZWFzdC0xKS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSB0aGUgQ2xvdWRGcm9udCB3aWxkY2FyZCBjZXJ0aWZpY2F0ZSAoKi5jbG91ZGZyb250Lm5ldCkgd2lsbCBiZSB1c2VkLlxuICAgKi9cbiAgcmVhZG9ubHkgY2VydGlmaWNhdGU/OiBhY20uSUNlcnRpZmljYXRlO1xuXG4gIC8qKlxuICAgKiBBbnkgY29tbWVudHMgeW91IHdhbnQgdG8gaW5jbHVkZSBhYm91dCB0aGUgZGlzdHJpYnV0aW9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIGNvbW1lbnRcbiAgICovXG4gIHJlYWRvbmx5IGNvbW1lbnQ/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBvYmplY3QgdGhhdCB5b3Ugd2FudCBDbG91ZEZyb250IHRvIHJlcXVlc3QgZnJvbSB5b3VyIG9yaWdpbiAoZm9yIGV4YW1wbGUsIGluZGV4Lmh0bWwpXG4gICAqIHdoZW4gYSB2aWV3ZXIgcmVxdWVzdHMgdGhlIHJvb3QgVVJMIGZvciB5b3VyIGRpc3RyaWJ1dGlvbi4gSWYgbm8gZGVmYXVsdCBvYmplY3QgaXMgc2V0LCB0aGVcbiAgICogcmVxdWVzdCBnb2VzIHRvIHRoZSBvcmlnaW4ncyByb290IChlLmcuLCBleGFtcGxlLmNvbS8pLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIGRlZmF1bHQgcm9vdCBvYmplY3RcbiAgICovXG4gIHJlYWRvbmx5IGRlZmF1bHRSb290T2JqZWN0Pzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBbHRlcm5hdGl2ZSBkb21haW4gbmFtZXMgZm9yIHRoaXMgZGlzdHJpYnV0aW9uLlxuICAgKlxuICAgKiBJZiB5b3Ugd2FudCB0byB1c2UgeW91ciBvd24gZG9tYWluIG5hbWUsIHN1Y2ggYXMgd3d3LmV4YW1wbGUuY29tLCBpbnN0ZWFkIG9mIHRoZSBjbG91ZGZyb250Lm5ldCBkb21haW4gbmFtZSxcbiAgICogeW91IGNhbiBhZGQgYW4gYWx0ZXJuYXRlIGRvbWFpbiBuYW1lIHRvIHlvdXIgZGlzdHJpYnV0aW9uLiBJZiB5b3UgYXR0YWNoIGEgY2VydGlmaWNhdGUgdG8gdGhlIGRpc3RyaWJ1dGlvbixcbiAgICogeW91IG11c3QgYWRkIChhdCBsZWFzdCBvbmUgb2YpIHRoZSBkb21haW4gbmFtZXMgb2YgdGhlIGNlcnRpZmljYXRlIHRvIHRoaXMgbGlzdC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBUaGUgZGlzdHJpYnV0aW9uIHdpbGwgb25seSBzdXBwb3J0IHRoZSBkZWZhdWx0IGdlbmVyYXRlZCBuYW1lIChlLmcuLCBkMTExMTExYWJjZGVmOC5jbG91ZGZyb250Lm5ldClcbiAgICovXG4gIHJlYWRvbmx5IGRvbWFpbk5hbWVzPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIEVuYWJsZSBvciBkaXNhYmxlIHRoZSBkaXN0cmlidXRpb24uXG4gICAqXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIHJlYWRvbmx5IGVuYWJsZWQ/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIENsb3VkRnJvbnQgd2lsbCByZXNwb25kIHRvIElQdjYgRE5TIHJlcXVlc3RzIHdpdGggYW4gSVB2NiBhZGRyZXNzLlxuICAgKlxuICAgKiBJZiB5b3Ugc3BlY2lmeSBmYWxzZSwgQ2xvdWRGcm9udCByZXNwb25kcyB0byBJUHY2IEROUyByZXF1ZXN0cyB3aXRoIHRoZSBETlMgcmVzcG9uc2UgY29kZSBOT0VSUk9SIGFuZCB3aXRoIG5vIElQIGFkZHJlc3Nlcy5cbiAgICogVGhpcyBhbGxvd3Mgdmlld2VycyB0byBzdWJtaXQgYSBzZWNvbmQgcmVxdWVzdCwgZm9yIGFuIElQdjQgYWRkcmVzcyBmb3IgeW91ciBkaXN0cmlidXRpb24uXG4gICAqXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIHJlYWRvbmx5IGVuYWJsZUlwdjY/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBFbmFibGUgYWNjZXNzIGxvZ2dpbmcgZm9yIHRoZSBkaXN0cmlidXRpb24uXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gZmFsc2UsIHVubGVzcyBgbG9nQnVja2V0YCBpcyBzcGVjaWZpZWQuXG4gICAqL1xuICByZWFkb25seSBlbmFibGVMb2dnaW5nPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogQ29udHJvbHMgdGhlIGNvdW50cmllcyBpbiB3aGljaCB5b3VyIGNvbnRlbnQgaXMgZGlzdHJpYnV0ZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gZ2VvZ3JhcGhpYyByZXN0cmljdGlvbnNcbiAgICovXG4gIHJlYWRvbmx5IGdlb1Jlc3RyaWN0aW9uPzogR2VvUmVzdHJpY3Rpb247XG5cbiAgLyoqXG4gICAqIFNwZWNpZnkgdGhlIG1heGltdW0gSFRUUCB2ZXJzaW9uIHRoYXQgeW91IHdhbnQgdmlld2VycyB0byB1c2UgdG8gY29tbXVuaWNhdGUgd2l0aCBDbG91ZEZyb250LlxuICAgKlxuICAgKiBGb3Igdmlld2VycyBhbmQgQ2xvdWRGcm9udCB0byB1c2UgSFRUUC8yLCB2aWV3ZXJzIG11c3Qgc3VwcG9ydCBUTFMgMS4yIG9yIGxhdGVyLCBhbmQgbXVzdCBzdXBwb3J0IHNlcnZlciBuYW1lIGlkZW50aWZpY2F0aW9uIChTTkkpLlxuICAgKlxuICAgKiBAZGVmYXVsdCBIdHRwVmVyc2lvbi5IVFRQMlxuICAgKi9cbiAgcmVhZG9ubHkgaHR0cFZlcnNpb24/OiBIdHRwVmVyc2lvbjtcblxuICAvKipcbiAgICogVGhlIEFtYXpvbiBTMyBidWNrZXQgdG8gc3RvcmUgdGhlIGFjY2VzcyBsb2dzIGluLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIEEgYnVja2V0IGlzIGNyZWF0ZWQgaWYgYGVuYWJsZUxvZ2dpbmdgIGlzIHRydWVcbiAgICovXG4gIHJlYWRvbmx5IGxvZ0J1Y2tldD86IHMzLklCdWNrZXQ7XG5cbiAgLyoqXG4gICAqIFNwZWNpZmllcyB3aGV0aGVyIHlvdSB3YW50IENsb3VkRnJvbnQgdG8gaW5jbHVkZSBjb29raWVzIGluIGFjY2VzcyBsb2dzXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBsb2dJbmNsdWRlc0Nvb2tpZXM/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBBbiBvcHRpb25hbCBzdHJpbmcgdGhhdCB5b3Ugd2FudCBDbG91ZEZyb250IHRvIHByZWZpeCB0byB0aGUgYWNjZXNzIGxvZyBmaWxlbmFtZXMgZm9yIHRoaXMgZGlzdHJpYnV0aW9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIHByZWZpeFxuICAgKi9cbiAgcmVhZG9ubHkgbG9nRmlsZVByZWZpeD86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIHByaWNlIGNsYXNzIHRoYXQgY29ycmVzcG9uZHMgd2l0aCB0aGUgbWF4aW11bSBwcmljZSB0aGF0IHlvdSB3YW50IHRvIHBheSBmb3IgQ2xvdWRGcm9udCBzZXJ2aWNlLlxuICAgKiBJZiB5b3Ugc3BlY2lmeSBQcmljZUNsYXNzX0FsbCwgQ2xvdWRGcm9udCByZXNwb25kcyB0byByZXF1ZXN0cyBmb3IgeW91ciBvYmplY3RzIGZyb20gYWxsIENsb3VkRnJvbnQgZWRnZSBsb2NhdGlvbnMuXG4gICAqIElmIHlvdSBzcGVjaWZ5IGEgcHJpY2UgY2xhc3Mgb3RoZXIgdGhhbiBQcmljZUNsYXNzX0FsbCwgQ2xvdWRGcm9udCBzZXJ2ZXMgeW91ciBvYmplY3RzIGZyb20gdGhlIENsb3VkRnJvbnQgZWRnZSBsb2NhdGlvblxuICAgKiB0aGF0IGhhcyB0aGUgbG93ZXN0IGxhdGVuY3kgYW1vbmcgdGhlIGVkZ2UgbG9jYXRpb25zIGluIHlvdXIgcHJpY2UgY2xhc3MuXG4gICAqXG4gICAqIEBkZWZhdWx0IFByaWNlQ2xhc3MuUFJJQ0VfQ0xBU1NfQUxMXG4gICAqL1xuICByZWFkb25seSBwcmljZUNsYXNzPzogUHJpY2VDbGFzcztcblxuICAvKipcbiAgICogVW5pcXVlIGlkZW50aWZpZXIgdGhhdCBzcGVjaWZpZXMgdGhlIEFXUyBXQUYgd2ViIEFDTCB0byBhc3NvY2lhdGUgd2l0aCB0aGlzIENsb3VkRnJvbnQgZGlzdHJpYnV0aW9uLlxuICAgKlxuICAgKiBUbyBzcGVjaWZ5IGEgd2ViIEFDTCBjcmVhdGVkIHVzaW5nIHRoZSBsYXRlc3QgdmVyc2lvbiBvZiBBV1MgV0FGLCB1c2UgdGhlIEFDTCBBUk4sIGZvciBleGFtcGxlXG4gICAqIGBhcm46YXdzOndhZnYyOnVzLWVhc3QtMToxMjM0NTY3ODkwMTI6Z2xvYmFsL3dlYmFjbC9FeGFtcGxlV2ViQUNMLzQ3M2U2NGZkLWYzMGItNDc2NS04MWEwLTYyYWQ5NmRkMTY3YWAuXG4gICAqIFRvIHNwZWNpZnkgYSB3ZWIgQUNMIGNyZWF0ZWQgdXNpbmcgQVdTIFdBRiBDbGFzc2ljLCB1c2UgdGhlIEFDTCBJRCwgZm9yIGV4YW1wbGUgYDQ3M2U2NGZkLWYzMGItNDc2NS04MWEwLTYyYWQ5NmRkMTY3YWAuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL3dhZi9sYXRlc3QvZGV2ZWxvcGVyZ3VpZGUvd2hhdC1pcy1hd3Mtd2FmLmh0bWxcbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vY2xvdWRmcm9udC9sYXRlc3QvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVEaXN0cmlidXRpb24uaHRtbCNBUElfQ3JlYXRlRGlzdHJpYnV0aW9uX1JlcXVlc3RQYXJhbWV0ZXJzLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIEFXUyBXZWIgQXBwbGljYXRpb24gRmlyZXdhbGwgd2ViIGFjY2VzcyBjb250cm9sIGxpc3QgKHdlYiBBQ0wpLlxuICAgKi9cbiAgcmVhZG9ubHkgd2ViQWNsSWQ/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEhvdyBDbG91ZEZyb250IHNob3VsZCBoYW5kbGUgcmVxdWVzdHMgdGhhdCBhcmUgbm90IHN1Y2Nlc3NmdWwgKGUuZy4sIFBhZ2VOb3RGb3VuZCkuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gY3VzdG9tIGVycm9yIHJlc3BvbnNlcy5cbiAgICovXG4gIHJlYWRvbmx5IGVycm9yUmVzcG9uc2VzPzogRXJyb3JSZXNwb25zZVtdO1xuXG4gIC8qKlxuICAgICogVGhlIG1pbmltdW0gdmVyc2lvbiBvZiB0aGUgU1NMIHByb3RvY29sIHRoYXQgeW91IHdhbnQgQ2xvdWRGcm9udCB0byB1c2UgZm9yIEhUVFBTIGNvbm5lY3Rpb25zLlxuICAgICpcbiAgICAqIENsb3VkRnJvbnQgc2VydmVzIHlvdXIgb2JqZWN0cyBvbmx5IHRvIGJyb3dzZXJzIG9yIGRldmljZXMgdGhhdCBzdXBwb3J0IGF0XG4gICAgKiBsZWFzdCB0aGUgU1NMIHZlcnNpb24gdGhhdCB5b3Ugc3BlY2lmeS5cbiAgICAqXG4gICAgKiBAZGVmYXVsdCAtIFNlY3VyaXR5UG9saWN5UHJvdG9jb2wuVExTX1YxXzJfMjAyMSBpZiB0aGUgJ0Bhd3MtY2RrL2F3cy1jbG91ZGZyb250OmRlZmF1bHRTZWN1cml0eVBvbGljeVRMU3YxLjJfMjAyMScgZmVhdHVyZSBmbGFnIGlzIHNldDsgb3RoZXJ3aXNlLCBTZWN1cml0eVBvbGljeVByb3RvY29sLlRMU19WMV8yXzIwMTkuXG4gICAgKi9cbiAgcmVhZG9ubHkgbWluaW11bVByb3RvY29sVmVyc2lvbj86IFNlY3VyaXR5UG9saWN5UHJvdG9jb2w7XG5cbiAgLyoqXG4gICAgKiBUaGUgU1NMIG1ldGhvZCBDbG91ZEZyb250IHdpbGwgdXNlIGZvciB5b3VyIGRpc3RyaWJ1dGlvbi5cbiAgICAqXG4gICAgKiBTZXJ2ZXIgTmFtZSBJbmRpY2F0aW9uIChTTkkpIC0gaXMgYW4gZXh0ZW5zaW9uIHRvIHRoZSBUTFMgY29tcHV0ZXIgbmV0d29ya2luZyBwcm90b2NvbCBieSB3aGljaCBhIGNsaWVudCBpbmRpY2F0ZXNcbiAgICAqIHdoaWNoIGhvc3RuYW1lIGl0IGlzIGF0dGVtcHRpbmcgdG8gY29ubmVjdCB0byBhdCB0aGUgc3RhcnQgb2YgdGhlIGhhbmRzaGFraW5nIHByb2Nlc3MuIFRoaXMgYWxsb3dzIGEgc2VydmVyIHRvIHByZXNlbnRcbiAgICAqIG11bHRpcGxlIGNlcnRpZmljYXRlcyBvbiB0aGUgc2FtZSBJUCBhZGRyZXNzIGFuZCBUQ1AgcG9ydCBudW1iZXIgYW5kIGhlbmNlIGFsbG93cyBtdWx0aXBsZSBzZWN1cmUgKEhUVFBTKSB3ZWJzaXRlc1xuICAgICogKG9yIGFueSBvdGhlciBzZXJ2aWNlIG92ZXIgVExTKSB0byBiZSBzZXJ2ZWQgYnkgdGhlIHNhbWUgSVAgYWRkcmVzcyB3aXRob3V0IHJlcXVpcmluZyBhbGwgdGhvc2Ugc2l0ZXMgdG8gdXNlIHRoZSBzYW1lIGNlcnRpZmljYXRlLlxuICAgICpcbiAgICAqIENsb3VkRnJvbnQgY2FuIHVzZSBTTkkgdG8gaG9zdCBtdWx0aXBsZSBkaXN0cmlidXRpb25zIG9uIHRoZSBzYW1lIElQIC0gd2hpY2ggYSBsYXJnZSBtYWpvcml0eSBvZiBjbGllbnRzIHdpbGwgc3VwcG9ydC5cbiAgICAqXG4gICAgKiBJZiB5b3VyIGNsaWVudHMgY2Fubm90IHN1cHBvcnQgU05JIGhvd2V2ZXIgLSBDbG91ZEZyb250IGNhbiB1c2UgZGVkaWNhdGVkIElQcyBmb3IgeW91ciBkaXN0cmlidXRpb24gLSBidXQgdGhlcmUgaXMgYSBwcm9yYXRlZCBtb250aGx5IGNoYXJnZSBmb3JcbiAgICAqIHVzaW5nIHRoaXMgZmVhdHVyZS4gQnkgZGVmYXVsdCwgd2UgdXNlIFNOSSAtIGJ1dCB5b3UgY2FuIG9wdGlvbmFsbHkgZW5hYmxlIGRlZGljYXRlZCBJUHMgKFZJUCkuXG4gICAgKlxuICAgICogU2VlIHRoZSBDbG91ZEZyb250IFNTTCBmb3IgbW9yZSBkZXRhaWxzIGFib3V0IHByaWNpbmcgOiBodHRwczovL2F3cy5hbWF6b24uY29tL2Nsb3VkZnJvbnQvY3VzdG9tLXNzbC1kb21haW5zL1xuICAgICpcbiAgICAqIEBkZWZhdWx0IFNTTE1ldGhvZC5TTklcbiAgICAqL1xuICByZWFkb25seSBzc2xTdXBwb3J0TWV0aG9kPzogU1NMTWV0aG9kO1xufVxuXG4vKipcbiAqIEEgQ2xvdWRGcm9udCBkaXN0cmlidXRpb24gd2l0aCBhc3NvY2lhdGVkIG9yaWdpbihzKSBhbmQgY2FjaGluZyBiZWhhdmlvcihzKS5cbiAqL1xuZXhwb3J0IGNsYXNzIERpc3RyaWJ1dGlvbiBleHRlbmRzIFJlc291cmNlIGltcGxlbWVudHMgSURpc3RyaWJ1dGlvbiB7XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBEaXN0cmlidXRpb24gY29uc3RydWN0IHRoYXQgcmVwcmVzZW50cyBhbiBleHRlcm5hbCAoaW1wb3J0ZWQpIGRpc3RyaWJ1dGlvbi5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZnJvbURpc3RyaWJ1dGlvbkF0dHJpYnV0ZXMoc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgYXR0cnM6IERpc3RyaWJ1dGlvbkF0dHJpYnV0ZXMpOiBJRGlzdHJpYnV0aW9uIHtcbiAgICByZXR1cm4gbmV3IGNsYXNzIGV4dGVuZHMgUmVzb3VyY2UgaW1wbGVtZW50cyBJRGlzdHJpYnV0aW9uIHtcbiAgICAgIHB1YmxpYyByZWFkb25seSBkb21haW5OYW1lOiBzdHJpbmc7XG4gICAgICBwdWJsaWMgcmVhZG9ubHkgZGlzdHJpYnV0aW9uRG9tYWluTmFtZTogc3RyaW5nO1xuICAgICAgcHVibGljIHJlYWRvbmx5IGRpc3RyaWJ1dGlvbklkOiBzdHJpbmc7XG5cbiAgICAgIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICBzdXBlcihzY29wZSwgaWQpO1xuICAgICAgICB0aGlzLmRvbWFpbk5hbWUgPSBhdHRycy5kb21haW5OYW1lO1xuICAgICAgICB0aGlzLmRpc3RyaWJ1dGlvbkRvbWFpbk5hbWUgPSBhdHRycy5kb21haW5OYW1lO1xuICAgICAgICB0aGlzLmRpc3RyaWJ1dGlvbklkID0gYXR0cnMuZGlzdHJpYnV0aW9uSWQ7XG4gICAgICB9XG4gICAgfSgpO1xuICB9XG5cbiAgcHVibGljIHJlYWRvbmx5IGRvbWFpbk5hbWU6IHN0cmluZztcbiAgcHVibGljIHJlYWRvbmx5IGRpc3RyaWJ1dGlvbkRvbWFpbk5hbWU6IHN0cmluZztcbiAgcHVibGljIHJlYWRvbmx5IGRpc3RyaWJ1dGlvbklkOiBzdHJpbmc7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBkZWZhdWx0QmVoYXZpb3I6IENhY2hlQmVoYXZpb3I7XG4gIHByaXZhdGUgcmVhZG9ubHkgYWRkaXRpb25hbEJlaGF2aW9yczogQ2FjaGVCZWhhdmlvcltdID0gW107XG4gIHByaXZhdGUgcmVhZG9ubHkgYm91bmRPcmlnaW5zOiBCb3VuZE9yaWdpbltdID0gW107XG4gIHByaXZhdGUgcmVhZG9ubHkgb3JpZ2luR3JvdXBzOiBDZm5EaXN0cmlidXRpb24uT3JpZ2luR3JvdXBQcm9wZXJ0eVtdID0gW107XG5cbiAgcHJpdmF0ZSByZWFkb25seSBlcnJvclJlc3BvbnNlczogRXJyb3JSZXNwb25zZVtdO1xuICBwcml2YXRlIHJlYWRvbmx5IGNlcnRpZmljYXRlPzogYWNtLklDZXJ0aWZpY2F0ZTtcblxuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogRGlzdHJpYnV0aW9uUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgaWYgKHByb3BzLmNlcnRpZmljYXRlKSB7XG4gICAgICBjb25zdCBjZXJ0aWZpY2F0ZVJlZ2lvbiA9IFN0YWNrLm9mKHRoaXMpLnNwbGl0QXJuKHByb3BzLmNlcnRpZmljYXRlLmNlcnRpZmljYXRlQXJuLCBBcm5Gb3JtYXQuU0xBU0hfUkVTT1VSQ0VfTkFNRSkucmVnaW9uO1xuICAgICAgaWYgKCFUb2tlbi5pc1VucmVzb2x2ZWQoY2VydGlmaWNhdGVSZWdpb24pICYmIGNlcnRpZmljYXRlUmVnaW9uICE9PSAndXMtZWFzdC0xJykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYERpc3RyaWJ1dGlvbiBjZXJ0aWZpY2F0ZXMgbXVzdCBiZSBpbiB0aGUgdXMtZWFzdC0xIHJlZ2lvbiBhbmQgdGhlIGNlcnRpZmljYXRlIHlvdSBwcm92aWRlZCBpcyBpbiAke2NlcnRpZmljYXRlUmVnaW9ufS5gKTtcbiAgICAgIH1cblxuICAgICAgaWYgKChwcm9wcy5kb21haW5OYW1lcyA/PyBbXSkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignTXVzdCBzcGVjaWZ5IGF0IGxlYXN0IG9uZSBkb21haW4gbmFtZSB0byB1c2UgYSBjZXJ0aWZpY2F0ZSB3aXRoIGEgZGlzdHJpYnV0aW9uJyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3Qgb3JpZ2luSWQgPSB0aGlzLmFkZE9yaWdpbihwcm9wcy5kZWZhdWx0QmVoYXZpb3Iub3JpZ2luKTtcbiAgICB0aGlzLmRlZmF1bHRCZWhhdmlvciA9IG5ldyBDYWNoZUJlaGF2aW9yKG9yaWdpbklkLCB7IHBhdGhQYXR0ZXJuOiAnKicsIC4uLnByb3BzLmRlZmF1bHRCZWhhdmlvciB9KTtcbiAgICBpZiAocHJvcHMuYWRkaXRpb25hbEJlaGF2aW9ycykge1xuICAgICAgT2JqZWN0LmVudHJpZXMocHJvcHMuYWRkaXRpb25hbEJlaGF2aW9ycykuZm9yRWFjaCgoW3BhdGhQYXR0ZXJuLCBiZWhhdmlvck9wdGlvbnNdKSA9PiB7XG4gICAgICAgIHRoaXMuYWRkQmVoYXZpb3IocGF0aFBhdHRlcm4sIGJlaGF2aW9yT3B0aW9ucy5vcmlnaW4sIGJlaGF2aW9yT3B0aW9ucyk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICB0aGlzLmNlcnRpZmljYXRlID0gcHJvcHMuY2VydGlmaWNhdGU7XG4gICAgdGhpcy5lcnJvclJlc3BvbnNlcyA9IHByb3BzLmVycm9yUmVzcG9uc2VzID8/IFtdO1xuXG4gICAgLy8gQ29tbWVudHMgaGF2ZSBhbiB1bmRvY3VtZW50ZWQgbGltaXQgb2YgMTI4IGNoYXJhY3RlcnNcbiAgICBjb25zdCB0cmltbWVkQ29tbWVudCA9XG4gICAgICBwcm9wcy5jb21tZW50ICYmIHByb3BzLmNvbW1lbnQubGVuZ3RoID4gMTI4XG4gICAgICAgID8gYCR7cHJvcHMuY29tbWVudC5zbGljZSgwLCAxMjggLSAzKX0uLi5gXG4gICAgICAgIDogcHJvcHMuY29tbWVudDtcblxuICAgIGNvbnN0IGRpc3RyaWJ1dGlvbiA9IG5ldyBDZm5EaXN0cmlidXRpb24odGhpcywgJ1Jlc291cmNlJywge1xuICAgICAgZGlzdHJpYnV0aW9uQ29uZmlnOiB7XG4gICAgICAgIGVuYWJsZWQ6IHByb3BzLmVuYWJsZWQgPz8gdHJ1ZSxcbiAgICAgICAgb3JpZ2luczogTGF6eS5hbnkoeyBwcm9kdWNlOiAoKSA9PiB0aGlzLnJlbmRlck9yaWdpbnMoKSB9KSxcbiAgICAgICAgb3JpZ2luR3JvdXBzOiBMYXp5LmFueSh7IHByb2R1Y2U6ICgpID0+IHRoaXMucmVuZGVyT3JpZ2luR3JvdXBzKCkgfSksXG4gICAgICAgIGRlZmF1bHRDYWNoZUJlaGF2aW9yOiB0aGlzLmRlZmF1bHRCZWhhdmlvci5fcmVuZGVyQmVoYXZpb3IoKSxcbiAgICAgICAgYWxpYXNlczogcHJvcHMuZG9tYWluTmFtZXMsXG4gICAgICAgIGNhY2hlQmVoYXZpb3JzOiBMYXp5LmFueSh7IHByb2R1Y2U6ICgpID0+IHRoaXMucmVuZGVyQ2FjaGVCZWhhdmlvcnMoKSB9KSxcbiAgICAgICAgY29tbWVudDogdHJpbW1lZENvbW1lbnQsXG4gICAgICAgIGN1c3RvbUVycm9yUmVzcG9uc2VzOiB0aGlzLnJlbmRlckVycm9yUmVzcG9uc2VzKCksXG4gICAgICAgIGRlZmF1bHRSb290T2JqZWN0OiBwcm9wcy5kZWZhdWx0Um9vdE9iamVjdCxcbiAgICAgICAgaHR0cFZlcnNpb246IHByb3BzLmh0dHBWZXJzaW9uID8/IEh0dHBWZXJzaW9uLkhUVFAyLFxuICAgICAgICBpcHY2RW5hYmxlZDogcHJvcHMuZW5hYmxlSXB2NiA/PyB0cnVlLFxuICAgICAgICBsb2dnaW5nOiB0aGlzLnJlbmRlckxvZ2dpbmcocHJvcHMpLFxuICAgICAgICBwcmljZUNsYXNzOiBwcm9wcy5wcmljZUNsYXNzID8/IHVuZGVmaW5lZCxcbiAgICAgICAgcmVzdHJpY3Rpb25zOiB0aGlzLnJlbmRlclJlc3RyaWN0aW9ucyhwcm9wcy5nZW9SZXN0cmljdGlvbiksXG4gICAgICAgIHZpZXdlckNlcnRpZmljYXRlOiB0aGlzLmNlcnRpZmljYXRlID8gdGhpcy5yZW5kZXJWaWV3ZXJDZXJ0aWZpY2F0ZSh0aGlzLmNlcnRpZmljYXRlLFxuICAgICAgICAgIHByb3BzLm1pbmltdW1Qcm90b2NvbFZlcnNpb24sIHByb3BzLnNzbFN1cHBvcnRNZXRob2QpIDogdW5kZWZpbmVkLFxuICAgICAgICB3ZWJBY2xJZDogcHJvcHMud2ViQWNsSWQsXG4gICAgICB9LFxuICAgIH0pO1xuXG4gICAgdGhpcy5kb21haW5OYW1lID0gZGlzdHJpYnV0aW9uLmF0dHJEb21haW5OYW1lO1xuICAgIHRoaXMuZGlzdHJpYnV0aW9uRG9tYWluTmFtZSA9IGRpc3RyaWJ1dGlvbi5hdHRyRG9tYWluTmFtZTtcbiAgICB0aGlzLmRpc3RyaWJ1dGlvbklkID0gZGlzdHJpYnV0aW9uLnJlZjtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGEgbmV3IGJlaGF2aW9yIHRvIHRoaXMgZGlzdHJpYnV0aW9uIGZvciB0aGUgZ2l2ZW4gcGF0aFBhdHRlcm4uXG4gICAqXG4gICAqIEBwYXJhbSBwYXRoUGF0dGVybiB0aGUgcGF0aCBwYXR0ZXJuIChlLmcuLCAnaW1hZ2VzLyonKSB0aGF0IHNwZWNpZmllcyB3aGljaCByZXF1ZXN0cyB0byBhcHBseSB0aGUgYmVoYXZpb3IgdG8uXG4gICAqIEBwYXJhbSBvcmlnaW4gdGhlIG9yaWdpbiB0byB1c2UgZm9yIHRoaXMgYmVoYXZpb3JcbiAgICogQHBhcmFtIGJlaGF2aW9yT3B0aW9ucyB0aGUgb3B0aW9ucyBmb3IgdGhlIGJlaGF2aW9yIGF0IHRoaXMgcGF0aC5cbiAgICovXG4gIHB1YmxpYyBhZGRCZWhhdmlvcihwYXRoUGF0dGVybjogc3RyaW5nLCBvcmlnaW46IElPcmlnaW4sIGJlaGF2aW9yT3B0aW9uczogQWRkQmVoYXZpb3JPcHRpb25zID0ge30pIHtcbiAgICBpZiAocGF0aFBhdHRlcm4gPT09ICcqJykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdPbmx5IHRoZSBkZWZhdWx0IGJlaGF2aW9yIGNhbiBoYXZlIGEgcGF0aCBwYXR0ZXJuIG9mIFxcJypcXCcnKTtcbiAgICB9XG4gICAgY29uc3Qgb3JpZ2luSWQgPSB0aGlzLmFkZE9yaWdpbihvcmlnaW4pO1xuICAgIHRoaXMuYWRkaXRpb25hbEJlaGF2aW9ycy5wdXNoKG5ldyBDYWNoZUJlaGF2aW9yKG9yaWdpbklkLCB7IHBhdGhQYXR0ZXJuLCAuLi5iZWhhdmlvck9wdGlvbnMgfSkpO1xuICB9XG5cbiAgcHJpdmF0ZSBhZGRPcmlnaW4ob3JpZ2luOiBJT3JpZ2luLCBpc0ZhaWxvdmVyT3JpZ2luOiBib29sZWFuID0gZmFsc2UpOiBzdHJpbmcge1xuICAgIGNvbnN0IE9SSUdJTl9JRF9NQVhfTEVOR1RIID0gMTI4O1xuXG4gICAgY29uc3QgZXhpc3RpbmdPcmlnaW4gPSB0aGlzLmJvdW5kT3JpZ2lucy5maW5kKGJvdW5kT3JpZ2luID0+IGJvdW5kT3JpZ2luLm9yaWdpbiA9PT0gb3JpZ2luKTtcbiAgICBpZiAoZXhpc3RpbmdPcmlnaW4pIHtcbiAgICAgIHJldHVybiBleGlzdGluZ09yaWdpbi5vcmlnaW5Hcm91cElkID8/IGV4aXN0aW5nT3JpZ2luLm9yaWdpbklkO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBvcmlnaW5JbmRleCA9IHRoaXMuYm91bmRPcmlnaW5zLmxlbmd0aCArIDE7XG4gICAgICBjb25zdCBzY29wZSA9IG5ldyBDb3JlQ29uc3RydWN0KHRoaXMsIGBPcmlnaW4ke29yaWdpbkluZGV4fWApO1xuICAgICAgY29uc3Qgb3JpZ2luSWQgPSBOYW1lcy51bmlxdWVJZChzY29wZSkuc2xpY2UoLU9SSUdJTl9JRF9NQVhfTEVOR1RIKTtcbiAgICAgIGNvbnN0IG9yaWdpbkJpbmRDb25maWcgPSBvcmlnaW4uYmluZChzY29wZSwgeyBvcmlnaW5JZCB9KTtcbiAgICAgIGlmICghb3JpZ2luQmluZENvbmZpZy5mYWlsb3Zlck