@aws-cdk/aws-apigateway
Version:
The CDK Construct Library for AWS::ApiGateway
654 lines • 76.7 kB
JavaScript
"use strict";
var _a, _b, _c;
Object.defineProperty(exports, "__esModule", { value: true });
exports.EndpointType = exports.ApiKeySourceType = exports.RestApi = exports.SpecRestApi = exports.RestApiBase = void 0;
const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const cloudwatch = require("@aws-cdk/aws-cloudwatch");
const iam = require("@aws-cdk/aws-iam");
const core_1 = require("@aws-cdk/core");
const api_key_1 = require("./api-key");
const apigateway_canned_metrics_generated_1 = require("./apigateway-canned-metrics.generated");
const apigateway_generated_1 = require("./apigateway.generated");
const deployment_1 = require("./deployment");
const domain_name_1 = require("./domain-name");
const gateway_response_1 = require("./gateway-response");
const model_1 = require("./model");
const requestvalidator_1 = require("./requestvalidator");
const resource_1 = require("./resource");
const stage_1 = require("./stage");
const usage_plan_1 = require("./usage-plan");
const RESTAPI_SYMBOL = Symbol.for('@aws-cdk/aws-apigateway.RestApiBase');
/**
* Base implementation that are common to various implementations of IRestApi
*/
class RestApiBase extends core_1.Resource {
constructor(scope, id, props = {}) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_apigateway_RestApiBaseProps(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, RestApiBase);
}
throw error;
}
const restApiName = props.restApiName ?? id;
super(scope, id, {
physicalName: restApiName,
});
this.restApiName = restApiName;
Object.defineProperty(this, RESTAPI_SYMBOL, { value: true });
}
/**
* Checks if the given object is an instance of RestApiBase.
* @internal
*/
static _isRestApiBase(x) {
return x !== null && typeof (x) === 'object' && RESTAPI_SYMBOL in x;
}
/**
* API Gateway deployment that represents the latest changes of the API.
* This resource will be automatically updated every time the REST API model changes.
* This will be undefined if `deploy` is false.
*/
get latestDeployment() {
return this._latestDeployment;
}
/**
* The first domain name mapped to this API, if defined through the `domainName`
* configuration prop, or added via `addDomainName`
*/
get domainName() {
return this._domainName;
}
/**
* Returns the URL for an HTTP path.
*
* Fails if `deploymentStage` is not set either by `deploy` or explicitly.
*/
urlForPath(path = '/') {
if (!this.deploymentStage) {
throw new Error('Cannot determine deployment stage for API from "deploymentStage". Use "deploy" or explicitly set "deploymentStage"');
}
return this.deploymentStage.urlForPath(path);
}
/**
* Defines an API Gateway domain name and maps it to this API.
* @param id The construct id
* @param options custom domain options
*/
addDomainName(id, options) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_apigateway_DomainNameOptions(options);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.addDomainName);
}
throw error;
}
const domainName = new domain_name_1.DomainName(this, id, {
...options,
mapping: this,
});
if (!this._domainName) {
this._domainName = domainName;
}
return domainName;
}
/**
* Adds a usage plan.
*/
addUsagePlan(id, props = {}) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_apigateway_UsagePlanProps(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.addUsagePlan);
}
throw error;
}
return new usage_plan_1.UsagePlan(this, id, props);
}
arnForExecuteApi(method = '*', path = '/*', stage = '*') {
if (!core_1.Token.isUnresolved(path) && !path.startsWith('/')) {
throw new Error(`"path" must begin with a "/": '${path}'`);
}
if (method.toUpperCase() === 'ANY') {
method = '*';
}
return core_1.Stack.of(this).formatArn({
service: 'execute-api',
resource: this.restApiId,
arnFormat: core_1.ArnFormat.SLASH_RESOURCE_NAME,
resourceName: `${stage}/${method}${path}`,
});
}
/**
* Adds a new gateway response.
*/
addGatewayResponse(id, options) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_apigateway_GatewayResponseOptions(options);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.addGatewayResponse);
}
throw error;
}
return new gateway_response_1.GatewayResponse(this, id, {
restApi: this,
...options,
});
}
/**
* Add an ApiKey
*/
addApiKey(id, options) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_apigateway_ApiKeyOptions(options);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.addApiKey);
}
throw error;
}
return new api_key_1.ApiKey(this, id, {
resources: [this],
...options,
});
}
/**
* Returns the given named metric for this API
*/
metric(metricName, props) {
return new cloudwatch.Metric({
namespace: 'AWS/ApiGateway',
metricName,
dimensionsMap: { ApiName: this.restApiName },
...props,
}).attachTo(this);
}
/**
* Metric for the number of client-side errors captured in a given period.
*
* Default: sum over 5 minutes
*/
metricClientError(props) {
return this.cannedMetric(apigateway_canned_metrics_generated_1.ApiGatewayMetrics._4XxErrorSum, props);
}
/**
* Metric for the number of server-side errors captured in a given period.
*
* Default: sum over 5 minutes
*/
metricServerError(props) {
return this.cannedMetric(apigateway_canned_metrics_generated_1.ApiGatewayMetrics._5XxErrorSum, props);
}
/**
* Metric for the number of requests served from the API cache in a given period.
*
* Default: sum over 5 minutes
*/
metricCacheHitCount(props) {
return this.cannedMetric(apigateway_canned_metrics_generated_1.ApiGatewayMetrics.cacheHitCountSum, props);
}
/**
* Metric for the number of requests served from the backend in a given period,
* when API caching is enabled.
*
* Default: sum over 5 minutes
*/
metricCacheMissCount(props) {
return this.cannedMetric(apigateway_canned_metrics_generated_1.ApiGatewayMetrics.cacheMissCountSum, props);
}
/**
* Metric for the total number API requests in a given period.
*
* Default: sample count over 5 minutes
*/
metricCount(props) {
return this.cannedMetric(apigateway_canned_metrics_generated_1.ApiGatewayMetrics.countSum, {
statistic: 'SampleCount',
...props,
});
}
/**
* Metric for the time between when API Gateway relays a request to the backend
* and when it receives a response from the backend.
*
* Default: average over 5 minutes.
*/
metricIntegrationLatency(props) {
return this.cannedMetric(apigateway_canned_metrics_generated_1.ApiGatewayMetrics.integrationLatencyAverage, props);
}
/**
* The time between when API Gateway receives a request from a client
* and when it returns a response to the client.
* The latency includes the integration latency and other API Gateway overhead.
*
* Default: average over 5 minutes.
*/
metricLatency(props) {
return this.cannedMetric(apigateway_canned_metrics_generated_1.ApiGatewayMetrics.latencyAverage, props);
}
/**
* Internal API used by `Method` to keep an inventory of methods at the API
* level for validation purposes.
*
* @internal
*/
_attachMethod(method) {
ignore(method);
}
/**
* Associates a Deployment resource with this REST API.
*
* @internal
*/
_attachDeployment(deployment) {
ignore(deployment);
}
/**
* Associates a Stage with this REST API
*
* @internal
*/
_attachStage(stage) {
if (this.cloudWatchAccount) {
stage.node.addDependency(this.cloudWatchAccount);
}
}
/**
* @internal
*/
_configureCloudWatchRole(apiResource) {
const role = new iam.Role(this, 'CloudWatchRole', {
assumedBy: new iam.ServicePrincipal('apigateway.amazonaws.com'),
managedPolicies: [iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AmazonAPIGatewayPushToCloudWatchLogs')],
});
this.cloudWatchAccount = new apigateway_generated_1.CfnAccount(this, 'Account', {
cloudWatchRoleArn: role.roleArn,
});
this.cloudWatchAccount.node.addDependency(apiResource);
}
/**
* @deprecated This method will be made internal. No replacement
*/
configureCloudWatchRole(apiResource) {
try {
jsiiDeprecationWarnings.print("@aws-cdk/aws-apigateway.RestApiBase#configureCloudWatchRole", "This method will be made internal. No replacement");
jsiiDeprecationWarnings._aws_cdk_aws_apigateway_CfnRestApi(apiResource);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.configureCloudWatchRole);
}
throw error;
}
this._configureCloudWatchRole(apiResource);
}
/**
* @deprecated This method will be made internal. No replacement
*/
configureDeployment(props) {
try {
jsiiDeprecationWarnings.print("@aws-cdk/aws-apigateway.RestApiBase#configureDeployment", "This method will be made internal. No replacement");
jsiiDeprecationWarnings._aws_cdk_aws_apigateway_RestApiBaseProps(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.configureDeployment);
}
throw error;
}
this._configureDeployment(props);
}
/**
* @internal
*/
_configureDeployment(props) {
const deploy = props.deploy ?? true;
if (deploy) {
this._latestDeployment = new deployment_1.Deployment(this, 'Deployment', {
description: 'Automatically created by the RestApi construct',
api: this,
retainDeployments: props.retainDeployments,
});
// encode the stage name into the construct id, so if we change the stage name, it will recreate a new stage.
// stage name is part of the endpoint, so that makes sense.
const stageName = (props.deployOptions && props.deployOptions.stageName) || 'prod';
this.deploymentStage = new stage_1.Stage(this, `DeploymentStage.${stageName}`, {
deployment: this._latestDeployment,
...props.deployOptions,
});
new core_1.CfnOutput(this, 'Endpoint', { exportName: props.endpointExportName, value: this.urlForPath() });
}
else {
if (props.deployOptions) {
throw new Error('Cannot set \'deployOptions\' if \'deploy\' is disabled');
}
}
}
/**
* @internal
*/
_configureEndpoints(props) {
if (props.endpointTypes && props.endpointConfiguration) {
throw new Error('Only one of the RestApi props, endpointTypes or endpointConfiguration, is allowed');
}
if (props.endpointConfiguration) {
return {
types: props.endpointConfiguration.types,
vpcEndpointIds: props.endpointConfiguration?.vpcEndpoints?.map(vpcEndpoint => vpcEndpoint.vpcEndpointId),
};
}
if (props.endpointTypes) {
return { types: props.endpointTypes };
}
return undefined;
}
cannedMetric(fn, props) {
return new cloudwatch.Metric({
...fn({ ApiName: this.restApiName }),
...props,
}).attachTo(this);
}
}
exports.RestApiBase = RestApiBase;
_a = JSII_RTTI_SYMBOL_1;
RestApiBase[_a] = { fqn: "@aws-cdk/aws-apigateway.RestApiBase", version: "1.204.0" };
/**
* Represents a REST API in Amazon API Gateway, created with an OpenAPI specification.
*
* Some properties normally accessible on @see {@link RestApi} - such as the description -
* must be declared in the specification. All Resources and Methods need to be defined as
* part of the OpenAPI specification file, and cannot be added via the CDK.
*
* By default, the API will automatically be deployed and accessible from a
* public endpoint.
*
*
* @resource AWS::ApiGateway::RestApi
*/
class SpecRestApi extends RestApiBase {
constructor(scope, id, props) {
super(scope, id, props);
try {
jsiiDeprecationWarnings._aws_cdk_aws_apigateway_SpecRestApiProps(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, SpecRestApi);
}
throw error;
}
const apiDefConfig = props.apiDefinition.bind(this);
const resource = new apigateway_generated_1.CfnRestApi(this, 'Resource', {
name: this.restApiName,
policy: props.policy,
failOnWarnings: props.failOnWarnings,
body: apiDefConfig.inlineDefinition ?? undefined,
bodyS3Location: apiDefConfig.inlineDefinition ? undefined : apiDefConfig.s3Location,
endpointConfiguration: this._configureEndpoints(props),
parameters: props.parameters,
});
props.apiDefinition.bindAfterCreate(this, this);
this.node.defaultChild = resource;
this.restApiId = resource.ref;
this.restApiRootResourceId = resource.attrRootResourceId;
this.root = new RootResource(this, {}, this.restApiRootResourceId);
this._configureDeployment(props);
if (props.domainName) {
this.addDomainName('CustomDomain', props.domainName);
}
const cloudWatchRole = props.cloudWatchRole ?? true;
if (cloudWatchRole) {
this._configureCloudWatchRole(resource);
}
}
}
exports.SpecRestApi = SpecRestApi;
_b = JSII_RTTI_SYMBOL_1;
SpecRestApi[_b] = { fqn: "@aws-cdk/aws-apigateway.SpecRestApi", version: "1.204.0" };
/**
* Represents a REST API in Amazon API Gateway.
*
* Use `addResource` and `addMethod` to configure the API model.
*
* By default, the API will automatically be deployed and accessible from a
* public endpoint.
*/
class RestApi extends RestApiBase {
constructor(scope, id, props = {}) {
super(scope, id, props);
/**
* The list of methods bound to this RestApi
*/
this.methods = new Array();
/**
* This list of deployments bound to this RestApi
*/
this.deployments = new Array();
try {
jsiiDeprecationWarnings._aws_cdk_aws_apigateway_RestApiProps(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, RestApi);
}
throw error;
}
const resource = new apigateway_generated_1.CfnRestApi(this, 'Resource', {
name: this.physicalName,
description: props.description,
policy: props.policy,
failOnWarnings: props.failOnWarnings,
minimumCompressionSize: props.minimumCompressionSize,
binaryMediaTypes: props.binaryMediaTypes,
endpointConfiguration: this._configureEndpoints(props),
apiKeySourceType: props.apiKeySourceType,
cloneFrom: props.cloneFrom?.restApiId,
parameters: props.parameters,
disableExecuteApiEndpoint: props.disableExecuteApiEndpoint,
});
this.node.defaultChild = resource;
this.restApiId = resource.ref;
const cloudWatchRole = props.cloudWatchRole ?? true;
if (cloudWatchRole) {
this._configureCloudWatchRole(resource);
}
this._configureDeployment(props);
if (props.domainName) {
this.addDomainName('CustomDomain', props.domainName);
}
this.root = new RootResource(this, props, resource.attrRootResourceId);
this.restApiRootResourceId = resource.attrRootResourceId;
}
/**
* Import an existing RestApi.
*/
static fromRestApiId(scope, id, restApiId) {
class Import extends RestApiBase {
constructor() {
super(...arguments);
this.restApiId = restApiId;
}
get root() {
throw new Error('root is not configured when imported using `fromRestApiId()`. Use `fromRestApiAttributes()` API instead.');
}
get restApiRootResourceId() {
throw new Error('restApiRootResourceId is not configured when imported using `fromRestApiId()`. Use `fromRestApiAttributes()` API instead.');
}
}
return new Import(scope, id);
}
/**
* Import an existing RestApi that can be configured with additional Methods and Resources.
*/
static fromRestApiAttributes(scope, id, attrs) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_apigateway_RestApiAttributes(attrs);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.fromRestApiAttributes);
}
throw error;
}
class Import extends RestApiBase {
constructor() {
super(...arguments);
this.restApiId = attrs.restApiId;
this.restApiRootResourceId = attrs.rootResourceId;
this.root = new RootResource(this, {}, this.restApiRootResourceId);
}
}
return new Import(scope, id);
}
/**
* The deployed root URL of this REST API.
*/
get url() {
return this.urlForPath();
}
/**
* Adds a new model.
*/
addModel(id, props) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_apigateway_ModelOptions(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.addModel);
}
throw error;
}
return new model_1.Model(this, id, {
...props,
restApi: this,
});
}
/**
* Adds a new request validator.
*/
addRequestValidator(id, props) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_apigateway_RequestValidatorOptions(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.addRequestValidator);
}
throw error;
}
return new requestvalidator_1.RequestValidator(this, id, {
...props,
restApi: this,
});
}
/**
* Internal API used by `Method` to keep an inventory of methods at the API
* level for validation purposes.
*
* @internal
*/
_attachMethod(method) {
this.methods.push(method);
// add this method as a dependency to all deployments defined for this api
// when additional deployments are added, _attachDeployment is called and
// this method will be added there.
for (const dep of this.deployments) {
dep._addMethodDependency(method);
}
}
/**
* Attaches a deployment to this REST API.
*
* @internal
*/
_attachDeployment(deployment) {
this.deployments.push(deployment);
// add all methods that were already defined as dependencies of this
// deployment when additional methods are added, _attachMethod is called and
// it will be added as a dependency to this deployment.
for (const method of this.methods) {
deployment._addMethodDependency(method);
}
}
/**
* Performs validation of the REST API.
*/
validate() {
if (this.methods.length === 0) {
return ["The REST API doesn't contain any methods"];
}
return [];
}
}
exports.RestApi = RestApi;
_c = JSII_RTTI_SYMBOL_1;
RestApi[_c] = { fqn: "@aws-cdk/aws-apigateway.RestApi", version: "1.204.0" };
var ApiKeySourceType;
(function (ApiKeySourceType) {
/**
* To read the API key from the `X-API-Key` header of a request.
*/
ApiKeySourceType["HEADER"] = "HEADER";
/**
* To read the API key from the `UsageIdentifierKey` from a custom authorizer.
*/
ApiKeySourceType["AUTHORIZER"] = "AUTHORIZER";
})(ApiKeySourceType = exports.ApiKeySourceType || (exports.ApiKeySourceType = {}));
var EndpointType;
(function (EndpointType) {
/**
* For an edge-optimized API and its custom domain name.
*/
EndpointType["EDGE"] = "EDGE";
/**
* For a regional API and its custom domain name.
*/
EndpointType["REGIONAL"] = "REGIONAL";
/**
* For a private API and its custom domain name.
*/
EndpointType["PRIVATE"] = "PRIVATE";
})(EndpointType = exports.EndpointType || (exports.EndpointType = {}));
class RootResource extends resource_1.ResourceBase {
constructor(api, props, resourceId) {
super(api, 'Default');
this.parentResource = undefined;
this.defaultIntegration = props.defaultIntegration;
this.defaultMethodOptions = props.defaultMethodOptions;
this.defaultCorsPreflightOptions = props.defaultCorsPreflightOptions;
this.api = api;
this.resourceId = resourceId;
this.path = '/';
if (api instanceof RestApi) {
this._restApi = api;
}
if (this.defaultCorsPreflightOptions) {
this.addCorsPreflight(this.defaultCorsPreflightOptions);
}
}
/**
* Get the RestApi associated with this Resource.
* @deprecated - Throws an error if this Resource is not associated with an instance of `RestApi`. Use `api` instead.
*/
get restApi() {
if (!this._restApi) {
throw new Error('RestApi is not available on Resource not connected to an instance of RestApi. Use `api` instead');
}
return this._restApi;
}
}
function ignore(_x) {
return;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVzdGFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbInJlc3RhcGkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBQUEsc0RBQXNEO0FBRXRELHdDQUF3QztBQUN4Qyx3Q0FBeUc7QUFHekcsdUNBQTJEO0FBQzNELCtGQUEwRTtBQUMxRSxpRUFBZ0U7QUFFaEUsNkNBQTBDO0FBQzFDLCtDQUE4RDtBQUM5RCx5REFBNkU7QUFHN0UsbUNBQThDO0FBQzlDLHlEQUErRTtBQUMvRSx5Q0FBc0U7QUFDdEUsbUNBQThDO0FBQzlDLDZDQUF5RDtBQUV6RCxNQUFNLGNBQWMsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLHFDQUFxQyxDQUFDLENBQUM7QUE0T3pFOztHQUVHO0FBQ0gsTUFBc0IsV0FBWSxTQUFRLGVBQVE7SUErRGhELFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsUUFBMEIsRUFBRzs7Ozs7OytDQS9EbkQsV0FBVzs7OztRQWdFN0IsTUFBTSxXQUFXLEdBQUcsS0FBSyxDQUFDLFdBQVcsSUFBSSxFQUFFLENBQUM7UUFDNUMsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLEVBQUU7WUFDZixZQUFZLEVBQUUsV0FBVztTQUMxQixDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsV0FBVyxHQUFHLFdBQVcsQ0FBQztRQUUvQixNQUFNLENBQUMsY0FBYyxDQUFDLElBQUksRUFBRSxjQUFjLEVBQUUsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztLQUM5RDtJQXRFRDs7O09BR0c7SUFDSSxNQUFNLENBQUMsY0FBYyxDQUFDLENBQU07UUFDakMsT0FBTyxDQUFDLEtBQUssSUFBSSxJQUFJLE9BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxRQUFRLElBQUksY0FBYyxJQUFJLENBQUMsQ0FBQztLQUNwRTtJQUVEOzs7O09BSUc7SUFDSCxJQUFXLGdCQUFnQjtRQUN6QixPQUFPLElBQUksQ0FBQyxpQkFBaUIsQ0FBQztLQUMvQjtJQUVE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Iiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgY2xvdWR3YXRjaCBmcm9tICdAYXdzLWNkay9hd3MtY2xvdWR3YXRjaCc7XG5pbXBvcnQgeyBJVnBjRW5kcG9pbnQgfSBmcm9tICdAYXdzLWNkay9hd3MtZWMyJztcbmltcG9ydCAqIGFzIGlhbSBmcm9tICdAYXdzLWNkay9hd3MtaWFtJztcbmltcG9ydCB7IEFybkZvcm1hdCwgQ2ZuT3V0cHV0LCBJUmVzb3VyY2UgYXMgSVJlc291cmNlQmFzZSwgUmVzb3VyY2UsIFN0YWNrLCBUb2tlbiB9IGZyb20gJ0Bhd3MtY2RrL2NvcmUnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBBcGlEZWZpbml0aW9uIH0gZnJvbSAnLi9hcGktZGVmaW5pdGlvbic7XG5pbXBvcnQgeyBBcGlLZXksIEFwaUtleU9wdGlvbnMsIElBcGlLZXkgfSBmcm9tICcuL2FwaS1rZXknO1xuaW1wb3J0IHsgQXBpR2F0ZXdheU1ldHJpY3MgfSBmcm9tICcuL2FwaWdhdGV3YXktY2FubmVkLW1ldHJpY3MuZ2VuZXJhdGVkJztcbmltcG9ydCB7IENmbkFjY291bnQsIENmblJlc3RBcGkgfSBmcm9tICcuL2FwaWdhdGV3YXkuZ2VuZXJhdGVkJztcbmltcG9ydCB7IENvcnNPcHRpb25zIH0gZnJvbSAnLi9jb3JzJztcbmltcG9ydCB7IERlcGxveW1lbnQgfSBmcm9tICcuL2RlcGxveW1lbnQnO1xuaW1wb3J0IHsgRG9tYWluTmFtZSwgRG9tYWluTmFtZU9wdGlvbnMgfSBmcm9tICcuL2RvbWFpbi1uYW1lJztcbmltcG9ydCB7IEdhdGV3YXlSZXNwb25zZSwgR2F0ZXdheVJlc3BvbnNlT3B0aW9ucyB9IGZyb20gJy4vZ2F0ZXdheS1yZXNwb25zZSc7XG5pbXBvcnQgeyBJbnRlZ3JhdGlvbiB9IGZyb20gJy4vaW50ZWdyYXRpb24nO1xuaW1wb3J0IHsgTWV0aG9kLCBNZXRob2RPcHRpb25zIH0gZnJvbSAnLi9tZXRob2QnO1xuaW1wb3J0IHsgTW9kZWwsIE1vZGVsT3B0aW9ucyB9IGZyb20gJy4vbW9kZWwnO1xuaW1wb3J0IHsgUmVxdWVzdFZhbGlkYXRvciwgUmVxdWVzdFZhbGlkYXRvck9wdGlvbnMgfSBmcm9tICcuL3JlcXVlc3R2YWxpZGF0b3InO1xuaW1wb3J0IHsgSVJlc291cmNlLCBSZXNvdXJjZUJhc2UsIFJlc291cmNlT3B0aW9ucyB9IGZyb20gJy4vcmVzb3VyY2UnO1xuaW1wb3J0IHsgU3RhZ2UsIFN0YWdlT3B0aW9ucyB9IGZyb20gJy4vc3RhZ2UnO1xuaW1wb3J0IHsgVXNhZ2VQbGFuLCBVc2FnZVBsYW5Qcm9wcyB9IGZyb20gJy4vdXNhZ2UtcGxhbic7XG5cbmNvbnN0IFJFU1RBUElfU1lNQk9MID0gU3ltYm9sLmZvcignQGF3cy1jZGsvYXdzLWFwaWdhdGV3YXkuUmVzdEFwaUJhc2UnKTtcblxuZXhwb3J0IGludGVyZmFjZSBJUmVzdEFwaSBleHRlbmRzIElSZXNvdXJjZUJhc2Uge1xuICAvKipcbiAgICogVGhlIElEIG9mIHRoaXMgQVBJIEdhdGV3YXkgUmVzdEFwaS5cbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcmVhZG9ubHkgcmVzdEFwaUlkOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSByZXNvdXJjZSBJRCBvZiB0aGUgcm9vdCByZXNvdXJjZS5cbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcmVhZG9ubHkgcmVzdEFwaVJvb3RSZXNvdXJjZUlkOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEFQSSBHYXRld2F5IGRlcGxveW1lbnQgdGhhdCByZXByZXNlbnRzIHRoZSBsYXRlc3QgY2hhbmdlcyBvZiB0aGUgQVBJLlxuICAgKiBUaGlzIHJlc291cmNlIHdpbGwgYmUgYXV0b21hdGljYWxseSB1cGRhdGVkIGV2ZXJ5IHRpbWUgdGhlIFJFU1QgQVBJIG1vZGVsIGNoYW5nZXMuXG4gICAqIGB1bmRlZmluZWRgIHdoZW4gbm8gZGVwbG95bWVudCBpcyBjb25maWd1cmVkLlxuICAgKi9cbiAgcmVhZG9ubHkgbGF0ZXN0RGVwbG95bWVudD86IERlcGxveW1lbnQ7XG5cbiAgLyoqXG4gICAqIEFQSSBHYXRld2F5IHN0YWdlIHRoYXQgcG9pbnRzIHRvIHRoZSBsYXRlc3QgZGVwbG95bWVudCAoaWYgZGVmaW5lZCkuXG4gICAqL1xuICBkZXBsb3ltZW50U3RhZ2U6IFN0YWdlO1xuXG4gIC8qKlxuICAgKiBSZXByZXNlbnRzIHRoZSByb290IHJlc291cmNlIChcIi9cIikgb2YgdGhpcyBBUEkuIFVzZSBpdCB0byBkZWZpbmUgdGhlIEFQSSBtb2RlbDpcbiAgICpcbiAgICogICAgYXBpLnJvb3QuYWRkTWV0aG9kKCdBTlknLCByZWRpcmVjdFRvSG9tZVBhZ2UpOyAvLyBcIkFOWSAvXCJcbiAgICogICAgYXBpLnJvb3QuYWRkUmVzb3VyY2UoJ2ZyaWVuZHMnKS5hZGRNZXRob2QoJ0dFVCcsIGdldEZyaWVuZHNIYW5kbGVyKTsgLy8gXCJHRVQgL2ZyaWVuZHNcIlxuICAgKlxuICAgKi9cbiAgcmVhZG9ubHkgcm9vdDogSVJlc291cmNlO1xuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBcImV4ZWN1dGUtYXBpXCIgQVJOXG4gICAqIEByZXR1cm5zIFRoZSBcImV4ZWN1dGUtYXBpXCIgQVJOLlxuICAgKiBAZGVmYXVsdCBcIipcIiByZXR1cm5zIHRoZSBleGVjdXRlIEFQSSBBUk4gZm9yIGFsbCBtZXRob2RzL3Jlc291cmNlcyBpblxuICAgKiB0aGlzIEFQSS5cbiAgICogQHBhcmFtIG1ldGhvZCBUaGUgbWV0aG9kIChkZWZhdWx0IGAqYClcbiAgICogQHBhcmFtIHBhdGggVGhlIHJlc291cmNlIHBhdGguIE11c3Qgc3RhcnQgd2l0aCAnLycgKGRlZmF1bHQgYCpgKVxuICAgKiBAcGFyYW0gc3RhZ2UgVGhlIHN0YWdlIChkZWZhdWx0IGAqYClcbiAgICovXG4gIGFybkZvckV4ZWN1dGVBcGkobWV0aG9kPzogc3RyaW5nLCBwYXRoPzogc3RyaW5nLCBzdGFnZT86IHN0cmluZyk6IHN0cmluZztcbn1cblxuLyoqXG4gKiBSZXByZXNlbnRzIHRoZSBwcm9wcyB0aGF0IGFsbCBSZXN0IEFQSXMgc2hhcmVcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZXN0QXBpQmFzZVByb3BzIHtcbiAgLyoqXG4gICAqIEluZGljYXRlcyBpZiBhIERlcGxveW1lbnQgc2hvdWxkIGJlIGF1dG9tYXRpY2FsbHkgY3JlYXRlZCBmb3IgdGhpcyBBUEksXG4gICAqIGFuZCByZWNyZWF0ZWQgd2hlbiB0aGUgQVBJIG1vZGVsIChyZXNvdXJjZXMsIG1ldGhvZHMpIGNoYW5nZXMuXG4gICAqXG4gICAqIFNpbmNlIEFQSSBHYXRld2F5IGRlcGxveW1lbnRzIGFyZSBpbW11dGFibGUsIFdoZW4gdGhpcyBvcHRpb24gaXMgZW5hYmxlZFxuICAgKiAoYnkgZGVmYXVsdCksIGFuIEFXUzo6QXBpR2F0ZXdheTo6RGVwbG95bWVudCByZXNvdXJjZSB3aWxsIGF1dG9tYXRpY2FsbHlcbiAgICogY3JlYXRlZCB3aXRoIGEgbG9naWNhbCBJRCB0aGF0IGhhc2hlcyB0aGUgQVBJIG1vZGVsIChtZXRob2RzLCByZXNvdXJjZXNcbiAgICogYW5kIG9wdGlvbnMpLiBUaGlzIG1lYW5zIHRoYXQgd2hlbiB0aGUgbW9kZWwgY2hhbmdlcywgdGhlIGxvZ2ljYWwgSUQgb2ZcbiAgICogdGhpcyBDbG91ZEZvcm1hdGlvbiByZXNvdXJjZSB3aWxsIGNoYW5nZSwgYW5kIGEgbmV3IGRlcGxveW1lbnQgd2lsbCBiZVxuICAgKiBjcmVhdGVkLlxuICAgKlxuICAgKiBJZiB0aGlzIGlzIHNldCwgYGxhdGVzdERlcGxveW1lbnRgIHdpbGwgcmVmZXIgdG8gdGhlIGBEZXBsb3ltZW50YCBvYmplY3RcbiAgICogYW5kIGBkZXBsb3ltZW50U3RhZ2VgIHdpbGwgcmVmZXIgdG8gYSBgU3RhZ2VgIHRoYXQgcG9pbnRzIHRvIHRoaXNcbiAgICogZGVwbG95bWVudC4gVG8gY3VzdG9taXplIHRoZSBzdGFnZSBvcHRpb25zLCB1c2UgdGhlIGBkZXBsb3lPcHRpb25zYFxuICAgKiBwcm9wZXJ0eS5cbiAgICpcbiAgICogQSBDbG91ZEZvcm1hdGlvbiBPdXRwdXQgd2lsbCBhbHNvIGJlIGRlZmluZWQgd2l0aCB0aGUgcm9vdCBVUkwgZW5kcG9pbnRcbiAgICogb2YgdGhpcyBSRVNUIEFQSS5cbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgZGVwbG95PzogYm9vbGVhbjtcblxuICAvKipcbiAgICogT3B0aW9ucyBmb3IgdGhlIEFQSSBHYXRld2F5IHN0YWdlIHRoYXQgd2lsbCBhbHdheXMgcG9pbnQgdG8gdGhlIGxhdGVzdFxuICAgKiBkZXBsb3ltZW50IHdoZW4gYGRlcGxveWAgaXMgZW5hYmxlZC4gSWYgYGRlcGxveWAgaXMgZGlzYWJsZWQsXG4gICAqIHRoaXMgdmFsdWUgY2Fubm90IGJlIHNldC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBCYXNlZCBvbiBkZWZhdWx0cyBvZiBgU3RhZ2VPcHRpb25zYC5cbiAgICovXG4gIHJlYWRvbmx5IGRlcGxveU9wdGlvbnM/OiBTdGFnZU9wdGlvbnM7XG5cbiAgLyoqXG4gICAqIFJldGFpbnMgb2xkIGRlcGxveW1lbnQgcmVzb3VyY2VzIHdoZW4gdGhlIEFQSSBjaGFuZ2VzLiBUaGlzIGFsbG93c1xuICAgKiBtYW51YWxseSByZXZlcnRpbmcgc3RhZ2VzIHRvIHBvaW50IHRvIG9sZCBkZXBsb3ltZW50cyB2aWEgdGhlIEFXU1xuICAgKiBDb25zb2xlLlxuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgcmV0YWluRGVwbG95bWVudHM/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBBIG5hbWUgZm9yIHRoZSBBUEkgR2F0ZXdheSBSZXN0QXBpIHJlc291cmNlLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIElEIG9mIHRoZSBSZXN0QXBpIGNvbnN0cnVjdC5cbiAgICovXG4gIHJlYWRvbmx5IHJlc3RBcGlOYW1lPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBDdXN0b20gaGVhZGVyIHBhcmFtZXRlcnMgZm9yIHRoZSByZXF1ZXN0LlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9jbGkvbGF0ZXN0L3JlZmVyZW5jZS9hcGlnYXRld2F5L2ltcG9ydC1yZXN0LWFwaS5odG1sXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gcGFyYW1ldGVycy5cbiAgICovXG4gIHJlYWRvbmx5IHBhcmFtZXRlcnM/OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9O1xuXG4gIC8qKlxuICAgKiBBIHBvbGljeSBkb2N1bWVudCB0aGF0IGNvbnRhaW5zIHRoZSBwZXJtaXNzaW9ucyBmb3IgdGhpcyBSZXN0QXBpXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gcG9saWN5LlxuICAgKi9cbiAgcmVhZG9ubHkgcG9saWN5PzogaWFtLlBvbGljeURvY3VtZW50O1xuXG4gIC8qKlxuICAgKiBJbmRpY2F0ZXMgd2hldGhlciB0byByb2xsIGJhY2sgdGhlIHJlc291cmNlIGlmIGEgd2FybmluZyBvY2N1cnMgd2hpbGUgQVBJXG4gICAqIEdhdGV3YXkgaXMgY3JlYXRpbmcgdGhlIFJlc3RBcGkgcmVzb3VyY2UuXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBmYWlsT25XYXJuaW5ncz86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIENvbmZpZ3VyZSBhIGN1c3RvbSBkb21haW4gbmFtZSBhbmQgbWFwIGl0IHRvIHRoaXMgQVBJLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vIGRvbWFpbiBuYW1lIGlzIGRlZmluZWQsIHVzZSBgYWRkRG9tYWluTmFtZWAgb3IgZGlyZWN0bHkgZGVmaW5lIGEgYERvbWFpbk5hbWVgLlxuICAgKi9cbiAgcmVhZG9ubHkgZG9tYWluTmFtZT86IERvbWFpbk5hbWVPcHRpb25zO1xuXG4gIC8qKlxuICAgKiBBdXRvbWF0aWNhbGx5IGNvbmZpZ3VyZSBhbiBBV1MgQ2xvdWRXYXRjaCByb2xlIGZvciBBUEkgR2F0ZXdheS5cbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgY2xvdWRXYXRjaFJvbGU/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBFeHBvcnQgbmFtZSBmb3IgdGhlIENmbk91dHB1dCBjb250YWluaW5nIHRoZSBBUEkgZW5kcG9pbnRcbiAgICpcbiAgICogQGRlZmF1bHQgLSB3aGVuIG5vIGV4cG9ydCBuYW1lIGlzIGdpdmVuLCBvdXRwdXQgd2lsbCBiZSBjcmVhdGVkIHdpdGhvdXQgZXhwb3J0XG4gICAqL1xuICByZWFkb25seSBlbmRwb2ludEV4cG9ydE5hbWU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEEgbGlzdCBvZiB0aGUgZW5kcG9pbnQgdHlwZXMgb2YgdGhlIEFQSS4gVXNlIHRoaXMgcHJvcGVydHkgd2hlbiBjcmVhdGluZ1xuICAgKiBhbiBBUEkuXG4gICAqXG4gICAqIEBkZWZhdWx0IEVuZHBvaW50VHlwZS5FREdFXG4gICAqL1xuICByZWFkb25seSBlbmRwb2ludFR5cGVzPzogRW5kcG9pbnRUeXBlW107XG5cbiAgLyoqXG4gICAqIFNwZWNpZmllcyB3aGV0aGVyIGNsaWVudHMgY2FuIGludm9rZSB0aGUgQVBJIHVzaW5nIHRoZSBkZWZhdWx0IGV4ZWN1dGUtYXBpXG4gICAqIGVuZHBvaW50LiBUbyByZXF1aXJlIHRoYXQgY2xpZW50cyB1c2UgYSBjdXN0b20gZG9tYWluIG5hbWUgdG8gaW52b2tlIHRoZVxuICAgKiBBUEksIGRpc2FibGUgdGhlIGRlZmF1bHQgZW5kcG9pbnQuXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0Nsb3VkRm9ybWF0aW9uL2xhdGVzdC9Vc2VyR3VpZGUvYXdzLXJlc291cmNlLWFwaWdhdGV3YXktcmVzdGFwaS5odG1sXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBkaXNhYmxlRXhlY3V0ZUFwaUVuZHBvaW50PzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBSZXByZXNlbnRzIHRoZSBwcm9wcyB0aGF0IGFsbCBSZXN0IEFQSXMgc2hhcmUuXG4gKiBAZGVwcmVjYXRlZCAtIHN1cGVyc2VkZWQgYnkgYFJlc3RBcGlCYXNlUHJvcHNgXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVzdEFwaU9wdGlvbnMgZXh0ZW5kcyBSZXN0QXBpQmFzZVByb3BzLCBSZXNvdXJjZU9wdGlvbnMge1xufVxuXG4vKipcbiAqIFByb3BzIHRvIGNyZWF0ZSBhIG5ldyBpbnN0YW5jZSBvZiBSZXN0QXBpXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVzdEFwaVByb3BzIGV4dGVuZHMgUmVzdEFwaU9wdGlvbnMge1xuICAvKipcbiAgICogQSBkZXNjcmlwdGlvbiBvZiB0aGUgcHVycG9zZSBvZiB0aGlzIEFQSSBHYXRld2F5IFJlc3RBcGkgcmVzb3VyY2UuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gZGVzY3JpcHRpb24uXG4gICAqL1xuICByZWFkb25seSBkZXNjcmlwdGlvbj86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIGxpc3Qgb2YgYmluYXJ5IG1lZGlhIG1pbWUtdHlwZXMgdGhhdCBhcmUgc3VwcG9ydGVkIGJ5IHRoZSBSZXN0QXBpXG4gICAqIHJlc291cmNlLCBzdWNoIGFzIFwiaW1hZ2UvcG5nXCIgb3IgXCJhcHBsaWNhdGlvbi9vY3RldC1zdHJlYW1cIlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIFJlc3RBcGkgc3VwcG9ydHMgb25seSBVVEYtOC1lbmNvZGVkIHRleHQgcGF5bG9hZHMuXG4gICAqL1xuICByZWFkb25seSBiaW5hcnlNZWRpYVR5cGVzPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIEEgbnVsbGFibGUgaW50ZWdlciB0aGF0IGlzIHVzZWQgdG8gZW5hYmxlIGNvbXByZXNzaW9uICh3aXRoIG5vbi1uZWdhdGl2ZVxuICAgKiBiZXR3ZWVuIDAgYW5kIDEwNDg1NzYwICgxME0pIGJ5dGVzLCBpbmNsdXNpdmUpIG9yIGRpc2FibGUgY29tcHJlc3Npb25cbiAgICogKHdoZW4gdW5kZWZpbmVkKSBvbiBhbiBBUEkuIFdoZW4gY29tcHJlc3Npb24gaXMgZW5hYmxlZCwgY29tcHJlc3Npb24gb3JcbiAgICogZGVjb21wcmVzc2lvbiBpcyBub3QgYXBwbGllZCBvbiB0aGUgcGF5bG9hZCBpZiB0aGUgcGF5bG9hZCBzaXplIGlzXG4gICAqIHNtYWxsZXIgdGhhbiB0aGlzIHZhbHVlLiBTZXR0aW5nIGl0IHRvIHplcm8gYWxsb3dzIGNvbXByZXNzaW9uIGZvciBhbnlcbiAgICogcGF5bG9hZCBzaXplLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIENvbXByZXNzaW9uIGlzIGRpc2FibGVkLlxuICAgKi9cbiAgcmVhZG9ubHkgbWluaW11bUNvbXByZXNzaW9uU2l6ZT86IG51bWJlcjtcblxuICAvKipcbiAgICogVGhlIElEIG9mIHRoZSBBUEkgR2F0ZXdheSBSZXN0QXBpIHJlc291cmNlIHRoYXQgeW91IHdhbnQgdG8gY2xvbmUuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm9uZS5cbiAgICovXG4gIHJlYWRvbmx5IGNsb25lRnJvbT86IElSZXN0QXBpO1xuXG4gIC8qKlxuICAgKiBUaGUgc291cmNlIG9mIHRoZSBBUEkga2V5IGZvciBtZXRlcmluZyByZXF1ZXN0cyBhY2NvcmRpbmcgdG8gYSB1c2FnZVxuICAgKiBwbGFuLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE1ldGVyaW5nIGlzIGRpc2FibGVkLlxuICAgKi9cbiAgcmVhZG9ubHkgYXBpS2V5U291cmNlVHlwZT86IEFwaUtleVNvdXJjZVR5cGU7XG5cbiAgLyoqXG4gICAqIFRoZSBFbmRwb2ludENvbmZpZ3VyYXRpb24gcHJvcGVydHkgdHlwZSBzcGVjaWZpZXMgdGhlIGVuZHBvaW50IHR5cGVzIG9mIGEgUkVTVCBBUElcbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1hcGlnYXRld2F5LXJlc3RhcGktZW5kcG9pbnRjb25maWd1cmF0aW9uLmh0bWxcbiAgICpcbiAgICogQGRlZmF1bHQgRW5kcG9pbnRUeXBlLkVER0VcbiAgICovXG4gIHJlYWRvbmx5IGVuZHBvaW50Q29uZmlndXJhdGlvbj86IEVuZHBvaW50Q29uZmlndXJhdGlvbjtcbn1cblxuLyoqXG4gKiBQcm9wcyB0byBpbnN0YW50aWF0ZSBhIG5ldyBTcGVjUmVzdEFwaVxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNwZWNSZXN0QXBpUHJvcHMgZXh0ZW5kcyBSZXN0QXBpQmFzZVByb3BzIHtcbiAgLyoqXG4gICAqIEFuIE9wZW5BUEkgZGVmaW5pdGlvbiBjb21wYXRpYmxlIHdpdGggQVBJIEdhdGV3YXkuXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2FwaWdhdGV3YXkvbGF0ZXN0L2RldmVsb3Blcmd1aWRlL2FwaS1nYXRld2F5LWltcG9ydC1hcGkuaHRtbFxuICAgKi9cbiAgcmVhZG9ubHkgYXBpRGVmaW5pdGlvbjogQXBpRGVmaW5pdGlvbjtcbn1cblxuLyoqXG4gKiBCYXNlIGltcGxlbWVudGF0aW9uIHRoYXQgYXJlIGNvbW1vbiB0byB2YXJpb3VzIGltcGxlbWVudGF0aW9ucyBvZiBJUmVzdEFwaVxuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgUmVzdEFwaUJhc2UgZXh0ZW5kcyBSZXNvdXJjZSBpbXBsZW1lbnRzIElSZXN0QXBpIHtcbiAgLyoqXG4gICAqIENoZWNrcyBpZiB0aGUgZ2l2ZW4gb2JqZWN0IGlzIGFuIGluc3RhbmNlIG9mIFJlc3RBcGlCYXNlLlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIHB1Ym