UNPKG

@aws-cdk/aws-cloudfront

Version:

The CDK Construct Library for AWS::CloudFront

387 lines 69.6 kB
"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