UNPKG

@aws-cdk/aws-apigateway

Version:

The CDK Construct Library for AWS::ApiGateway

470 lines 50.5 kB
"use strict"; var _a, _b, _c; Object.defineProperty(exports, "__esModule", { value: true }); exports.AccessLogFormat = exports.AccessLogField = exports.LogGroupLogDestination = void 0; const jsiiDeprecationWarnings = require("../.warnings.jsii.js"); const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); /** * Use CloudWatch Logs as a custom access log destination for API Gateway. */ class LogGroupLogDestination { constructor(logGroup) { this.logGroup = logGroup; } /** * Binds this destination to the CloudWatch Logs. */ bind(_stage) { try { jsiiDeprecationWarnings._aws_cdk_aws_apigateway_IStage(_stage); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.bind); } throw error; } return { destinationArn: this.logGroup.logGroupArn, }; } } exports.LogGroupLogDestination = LogGroupLogDestination; _a = JSII_RTTI_SYMBOL_1; LogGroupLogDestination[_a] = { fqn: "@aws-cdk/aws-apigateway.LogGroupLogDestination", version: "1.204.0" }; /** * $context variables that can be used to customize access log pattern. */ class AccessLogField { /** * The API owner's AWS account ID. */ static contextAccountId() { return '$context.identity.accountId'; } /** * The identifier API Gateway assigns to your API. */ static contextApiId() { return '$context.apiId'; } /** * A property of the claims returned from the Amazon Cognito user pool after the method caller is successfully authenticated. * @see https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-integrate-with-cognito.html * * @param property A property key of the claims. */ static contextAuthorizerClaims(property) { return `$context.authorizer.claims.${property}`; } /** * The principal user identification associated with the token sent by the client and returned * from an API Gateway Lambda authorizer (formerly known as a custom authorizer). * @see https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html */ static contextAuthorizerPrincipalId() { return '$context.authorizer.principalId'; } /** * The stringified value of the specified key-value pair of the `context` map returned from an API Gateway Lambda authorizer function. * @see https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html * @param property key of the context map. */ static contextAuthorizer(property) { return `$context.authorizer.${property}`; } /** * The AWS endpoint's request ID. */ static contextAwsEndpointRequestId() { return '$context.awsEndpointRequestId'; } /** * The full domain name used to invoke the API. This should be the same as the incoming `Host` header. */ static contextDomainName() { return '$context.domainName'; } /** * The first label of the `$context.domainName`. This is often used as a caller/customer identifier. */ static contextDomainPrefix() { return '$context.domainPrefix'; } /** * A string containing an API Gateway error message. */ static contextErrorMessage() { return '$context.error.message'; } /** * The quoted value of $context.error.message, namely "$context.error.message". */ static contextErrorMessageString() { return '$context.error.messageString'; } /** * A type of GatewayResponse. This variable can only be used for simple variable substitution in a GatewayResponse body-mapping template, * which is not processed by the Velocity Template Language engine, and in access logging. * * @see https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-websocket-api-logging.html * @see https://docs.aws.amazon.com/apigateway/latest/developerguide/customize-gateway-responses.html */ static contextErrorResponseType() { return '$context.error.responseType'; } /** * A string containing a detailed validation error message. */ static contextErrorValidationErrorString() { return '$context.error.validationErrorString'; } /** * The extended ID that API Gateway assigns to the API request, which contains more useful information for debugging/troubleshooting. */ static contextExtendedRequestId() { return '$context.extendedRequestId'; } /** * The HTTP method used. Valid values include: `DELETE`, `GET`, `HEAD`, `OPTIONS`, `PATCH`, `POST`, and `PUT`. */ static contextHttpMethod() { return '$context.httpMethod'; } /** * The AWS account ID associated with the request. */ static contextIdentityAccountId() { return '$context.identity.accountId'; } /** * For API methods that require an API key, this variable is the API key associated with the method request. * For methods that don't require an API key, this variable is * @see https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-api-usage-plans.html */ static contextIdentityApiKey() { return '$context.identity.apiKey'; } /** * The API key ID associated with an API request that requires an API key. */ static contextIdentityApiKeyId() { return '$context.identity.apiKeyId'; } /** * The principal identifier of the caller making the request. */ static contextIdentityCaller() { return '$context.identity.caller'; } /** * The Amazon Cognito authentication provider used by the caller making the request. * Available only if the request was signed with Amazon Cognito credentials. * @see https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-identity.html */ static contextIdentityCognitoAuthenticationProvider() { return '$context.identity.cognitoAuthenticationProvider'; } /** * The Amazon Cognito authentication type of the caller making the request. * Available only if the request was signed with Amazon Cognito credentials. */ static contextIdentityCognitoAuthenticationType() { return '$context.identity.cognitoAuthenticationType'; } /** * The Amazon Cognito identity ID of the caller making the request. Available only if the request was signed with Amazon Cognito credentials. */ static contextIdentityCognitoIdentityId() { return '$context.identity.cognitoIdentityId'; } /** * The Amazon Cognito identity pool ID of the caller making the request. * Available only if the request was signed with Amazon Cognito credentials. */ static contextIdentityCognitoIdentityPoolId() { return '$context.identity.cognitoIdentityPoolId'; } /** * The AWS organization ID. */ static contextIdentityPrincipalOrgId() { return '$context.identity.principalOrgId'; } /** * The source IP address of the TCP connection making the request to API Gateway. * Warning: You should not trust this value if there is any chance that the `X-Forwarded-For` header could be forged. */ static contextIdentitySourceIp() { return '$context.identity.sourceIp'; } /** * The principal identifier of the user making the request. Used in Lambda authorizers. * @see https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-lambda-authorizer-output.html */ static contextIdentityUser() { return '$context.identity.user'; } /** * The User-Agent header of the API caller. */ static contextIdentityUserAgent() { return '$context.identity.userAgent'; } /** * The Amazon Resource Name (ARN) of the effective user identified after authentication. * @see https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users.html */ static contextIdentityUserArn() { return '$context.identity.userArn'; } /** * The request path. * For example, for a non-proxy request URL of https://{rest-api-id.execute-api.{region}.amazonaws.com/{stage}/root/child, * this value is /{stage}/root/child. */ static contextPath() { return '$context.path'; } /** * The request protocol, for example, HTTP/1.1. */ static contextProtocol() { return '$context.protocol'; } /** * The ID that API Gateway assigns to the API request. */ static contextRequestId() { return '$context.requestId'; } /** * The request header override. * If this parameter is defined, it contains the headers to be used instead of the HTTP Headers that are defined in the Integration Request pane. * @see https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-override-request-response-parameters.html * * @param headerName */ static contextRequestOverrideHeader(headerName) { return `$context.requestOverride.header.${headerName}`; } /** * The request path override. If this parameter is defined, * it contains the request path to be used instead of the URL Path Parameters that are defined in the Integration Request pane. * @see https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-override-request-response-parameters.html * * @param pathName */ static contextRequestOverridePath(pathName) { return `$context.requestOverride.path.${pathName}`; } /** * The request query string override. * If this parameter is defined, it contains the request query strings to be used instead * of the URL Query String Parameters that are defined in the Integration Request pane. * * @param querystringName */ static contextRequestOverrideQuerystring(querystringName) { return `$context.requestOverride.querystring.${querystringName}`; } /** * The response header override. * If this parameter is defined, it contains the header to be returned instead of the Response header * that is defined as the Default mapping in the Integration Response pane. * @see https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-override-request-response-parameters.html * * @param headerName */ static contextResponseOverrideHeader(headerName) { return `$context.responseOverride.header.${headerName}`; } /** * The response status code override. * If this parameter is defined, it contains the status code to be returned instead of the Method response status * that is defined as the Default mapping in the Integration Response pane. * @see https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-override-request-response-parameters.html */ static contextResponseOverrideStatus() { return '$context.responseOverride.status'; } /** * The CLF-formatted request time (dd/MMM/yyyy:HH:mm:ss +-hhmm). */ static contextRequestTime() { return '$context.requestTime'; } /** * The Epoch-formatted request time. */ static contextRequestTimeEpoch() { return '$context.requestTimeEpoch'; } /** * The identifier that API Gateway assigns to your resource. */ static contextResourceId() { return '$context.resourceId'; } /** * The path to your resource. * For example, for the non-proxy request URI of `https://{rest-api-id.execute-api.{region}.amazonaws.com/{stage}/root/child`, * The $context.resourcePath value is `/root/child`. * @see https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-create-api-step-by-step.html */ static contextResourcePath() { return '$context.resourcePath'; } /** * The deployment stage of the API request (for example, `Beta` or `Prod`). */ static contextStage() { return '$context.stage'; } /** * The response received from AWS WAF: `WAF_ALLOW` or `WAF_BLOCK`. Will not be set if the stage is not associated with a web ACL. * @see https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-control-access-aws-waf.html */ static contextWafResponseCode() { return '$context.wafResponseCode'; } /** * The complete ARN of the web ACL that is used to decide whether to allow or block the request. * Will not be set if the stage is not associated with a web ACL. * @see https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-control-access-aws-waf.html */ static contextWebaclArn() { return '$context.webaclArn'; } /** * The trace ID for the X-Ray trace. * @see https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-enabling-xray.html */ static contextXrayTraceId() { return '$context.xrayTraceId'; } /** * The authorizer latency in ms. */ static contextAuthorizerIntegrationLatency() { return '$context.authorizer.integrationLatency'; } /** * The integration latency in ms. */ static contextIntegrationLatency() { return '$context.integrationLatency'; } /** * For Lambda proxy integration, this parameter represents the status code returned from AWS Lambda, * not from the backend Lambda function. */ static contextIntegrationStatus() { return '$context.integrationStatus'; } /** * The response latency in ms. */ static contextResponseLatency() { return '$context.responseLatency'; } /** * The response payload length. */ static contextResponseLength() { return '$context.responseLength'; } /** * The method response status. */ static contextStatus() { return '$context.status'; } } exports.AccessLogField = AccessLogField; _b = JSII_RTTI_SYMBOL_1; AccessLogField[_b] = { fqn: "@aws-cdk/aws-apigateway.AccessLogField", version: "1.204.0" }; /** * factory methods for access log format. */ class AccessLogFormat { constructor(format) { this.format = format; } /** * Custom log format. * You can create any log format string. You can easily get the $ context variable by using the methods of AccessLogField. * @param format * @example * * apigateway.AccessLogFormat.custom(JSON.stringify({ * requestId: apigateway.AccessLogField.contextRequestId(), * sourceIp: apigateway.AccessLogField.contextIdentitySourceIp(), * method: apigateway.AccessLogField.contextHttpMethod(), * userContext: { * sub: apigateway.AccessLogField.contextAuthorizerClaims('sub'), * email: apigateway.AccessLogField.contextAuthorizerClaims('email') * } * })) */ static custom(format) { return new AccessLogFormat(format); } /** * Generate Common Log Format. */ static clf() { const requester = [AccessLogField.contextIdentitySourceIp(), AccessLogField.contextIdentityCaller(), AccessLogField.contextIdentityUser()].join(' '); const requestTime = AccessLogField.contextRequestTime(); const request = [AccessLogField.contextHttpMethod(), AccessLogField.contextResourcePath(), AccessLogField.contextProtocol()].join(' '); const status = [AccessLogField.contextStatus(), AccessLogField.contextResponseLength(), AccessLogField.contextRequestId()].join(' '); return new AccessLogFormat(`${requester} [${requestTime}] "${request}" ${status}`); } /** * Access log will be produced in the JSON format with a set of fields most useful in the access log. All fields are turned on by default with the * option to turn off specific fields. */ static jsonWithStandardFields(fields = { ip: true, user: true, caller: true, requestTime: true, httpMethod: true, resourcePath: true, status: true, protocol: true, responseLength: true, }) { try { jsiiDeprecationWarnings._aws_cdk_aws_apigateway_JsonWithStandardFieldProps(fields); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.jsonWithStandardFields); } throw error; } return this.custom(JSON.stringify({ requestId: AccessLogField.contextRequestId(), ip: fields.ip ? AccessLogField.contextIdentitySourceIp() : undefined, user: fields.user ? AccessLogField.contextIdentityUser() : undefined, caller: fields.caller ? AccessLogField.contextIdentityCaller() : undefined, requestTime: fields.requestTime ? AccessLogField.contextRequestTime() : undefined, httpMethod: fields.httpMethod ? AccessLogField.contextHttpMethod() : undefined, resourcePath: fields.resourcePath ? AccessLogField.contextResourcePath() : undefined, status: fields.status ? AccessLogField.contextStatus() : undefined, protocol: fields.protocol ? AccessLogField.contextProtocol() : undefined, responseLength: fields.responseLength ? AccessLogField.contextResponseLength() : undefined, })); } /** * Output a format string to be used with CloudFormation. */ toString() { return this.format; } } exports.AccessLogFormat = AccessLogFormat; _c = JSII_RTTI_SYMBOL_1; AccessLogFormat[_c] = { fqn: "@aws-cdk/aws-apigateway.AccessLogFormat", version: "1.204.0" }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWNjZXNzLWxvZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImFjY2Vzcy1sb2cudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7O0FBdUJBOztHQUVHO0FBQ0gsTUFBYSxzQkFBc0I7SUFDakMsWUFBNkIsUUFBbUI7UUFBbkIsYUFBUSxHQUFSLFFBQVEsQ0FBVztLQUMvQztJQUVEOztPQUVHO0lBQ0ksSUFBSSxDQUFDLE1BQWM7Ozs7Ozs7Ozs7UUFDeEIsT0FBTztZQUNMLGNBQWMsRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLFdBQVc7U0FDMUMsQ0FBQztLQUNIOztBQVhILHdEQVlDOzs7QUFFRDs7R0FFRztBQUNILE1BQWEsY0FBYztJQUN6Qjs7T0FFRztJQUNJLE1BQU0sQ0FBQyxnQkFBZ0I7UUFDNUIsT0FBTyw2QkFBNkIsQ0FBQztLQUN0QztJQUVEOztPQUVHO0lBQ0ksTUFBTSxDQUFDLFlBQVk7UUFDeEIsT0FBTyxnQkFBZ0IsQ0FBQztLQUN6QjtJQUVEOzs7OztPQUtHO0lBQ0ksTUFBTSxDQUFDLHVCQUF1QixDQUFDLFFBQWdCO1FBQ3BELE9BQU8sOEJBQThCLFFBQVEsRUFBRSxDQUFDO0tBQ2pEO0lBRUQ7Ozs7T0FJRztJQUNJLE1BQU0sQ0FBQyw0QkFBNEI7UUFDeEMsT0FBTyxpQ0FBaUMsQ0FBQztLQUMxQztJQUVEOzs7O09BSUc7SUFDSSxNQUFNLENBQUMsaUJBQWlCLENBQUMsUUFBZ0I7UUFDOUMsT0FBTyx1QkFBdUIsUUFBUSxFQUFFLENBQUM7S0FDMUM7SUFFRDs7T0FFRztJQUNJLE1BQU0sQ0FBQywyQkFBMkI7UUFDdkMsT0FBTywrQkFBK0IsQ0FBQztLQUN4QztJQUVEOztPQUVHO0lBQ0ksTUFBTSxDQUFDLGlCQUFpQjtRQUM3QixPQUFPLHFCQUFxQixDQUFDO0tBQzlCO0lBRUQ7O09BRUc7SUFDSSxNQUFNLENBQUMsbUJBQW1CO1FBQy9CLE9BQU8sdUJBQXVCLENBQUM7S0FDaEM7SUFFRDs7T0FFRztJQUNJLE1BQU0s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QUFDLHFCQUFxQixFQUFFLENBQUMsQ0FBQyxDQUFDLFNBQVM7U0FDM0YsQ0FBQyxDQUFDLENBQUM7S0FDTDtJQVdEOztPQUVHO0lBQ0ksUUFBUTtRQUNiLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQztLQUNwQjs7QUE3RUgsMENBOEVDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSUxvZ0dyb3VwIH0gZnJvbSAnQGF3cy1jZGsvYXdzLWxvZ3MnO1xuaW1wb3J0IHsgSVN0YWdlIH0gZnJvbSAnLi9zdGFnZSc7XG5cbi8qKlxuICogQWNjZXNzIGxvZyBkZXN0aW5hdGlvbiBmb3IgYSBSZXN0QXBpIFN0YWdlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIElBY2Nlc3NMb2dEZXN0aW5hdGlvbiB7XG4gIC8qKlxuICAgKiBCaW5kcyB0aGlzIGRlc3RpbmF0aW9uIHRvIHRoZSBSZXN0QXBpIFN0YWdlLlxuICAgKi9cbiAgYmluZChzdGFnZTogSVN0YWdlKTogQWNjZXNzTG9nRGVzdGluYXRpb25Db25maWdcbn1cblxuLyoqXG4gKiBPcHRpb25zIHdoZW4gYmluZGluZyBhIGxvZyBkZXN0aW5hdGlvbiB0byBhIFJlc3RBcGkgU3RhZ2UuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQWNjZXNzTG9nRGVzdGluYXRpb25Db25maWcge1xuICAvKipcbiAgICogVGhlIEFtYXpvbiBSZXNvdXJjZSBOYW1lIChBUk4pIG9mIHRoZSBkZXN0aW5hdGlvbiByZXNvdXJjZVxuICAgKi9cbiAgcmVhZG9ubHkgZGVzdGluYXRpb25Bcm46IHN0cmluZztcbn1cblxuLyoqXG4gKiBVc2UgQ2xvdWRXYXRjaCBMb2dzIGFzIGEgY3VzdG9tIGFjY2VzcyBsb2cgZGVzdGluYXRpb24gZm9yIEFQSSBHYXRld2F5LlxuICovXG5leHBvcnQgY2xhc3MgTG9nR3JvdXBMb2dEZXN0aW5hdGlvbiBpbXBsZW1lbnRzIElBY2Nlc3NMb2dEZXN0aW5hdGlvbiB7XG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgbG9nR3JvdXA6IElMb2dHcm91cCkge1xuICB9XG5cbiAgLyoqXG4gICAqIEJpbmRzIHRoaXMgZGVzdGluYXRpb24gdG8gdGhlIENsb3VkV2F0Y2ggTG9ncy5cbiAgICovXG4gIHB1YmxpYyBiaW5kKF9zdGFnZTogSVN0YWdlKTogQWNjZXNzTG9nRGVzdGluYXRpb25Db25maWcge1xuICAgIHJldHVybiB7XG4gICAgICBkZXN0aW5hdGlvbkFybjogdGhpcy5sb2dHcm91cC5sb2dHcm91cEFybixcbiAgICB9O1xuICB9XG59XG5cbi8qKlxuICogJGNvbnRleHQgdmFyaWFibGVzIHRoYXQgY2FuIGJlIHVzZWQgdG8gY3VzdG9taXplIGFjY2VzcyBsb2cgcGF0dGVybi5cbiAqL1xuZXhwb3J0IGNsYXNzIEFjY2Vzc0xvZ0ZpZWxkIHtcbiAgLyoqXG4gICAqIFRoZSBBUEkgb3duZXIncyBBV1MgYWNjb3VudCBJRC5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY29udGV4dEFjY291bnRJZCgpIHtcbiAgICByZXR1cm4gJyRjb250ZXh0LmlkZW50aXR5LmFjY291bnRJZCc7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGlkZW50aWZpZXIgQVBJIEdhdGV3YXkgYXNzaWducyB0byB5b3VyIEFQSS5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY29udGV4dEFwaUlkKCkge1xuICAgIHJldHVybiAnJGNvbnRleHQuYXBpSWQnO1xuICB9XG5cbiAgLyoqXG4gICAqIEEgcHJvcGVydHkgb2YgdGhlIGNsYWltcyByZXR1cm5lZCBmcm9tIHRoZSBBbWF6b24gQ29nbml0byB1c2VyIHBvb2wgYWZ0ZXIgdGhlIG1ldGhvZCBjYWxsZXIgaXMgc3VjY2Vzc2Z1bGx5IGF1dGhlbnRpY2F0ZWQuXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2FwaWdhdGV3YXkvbGF0ZXN0L2RldmVsb3Blcmd1aWRlL2FwaWdhdGV3YXktaW50ZWdyYXRlLXdpdGgtY29nbml0by5odG1sXG4gICAqXG4gICAqIEBwYXJhbSBwcm9wZXJ0eSBBIHByb3BlcnR5IGtleSBvZiB0aGUgY2xhaW1zLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBjb250ZXh0QXV0aG9yaXplckNsYWltcyhwcm9wZXJ0eTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIGAkY29udGV4dC5hdXRob3JpemVyLmNsYWltcy4ke3Byb3BlcnR5fWA7XG4gIH1cblxuICAvKipcbiAgICogVGhlIHByaW5jaXBhbCB1c2VyIGlkZW50aWZpY2F0aW9uIGFzc29jaWF0ZWQgd2l0aCB0aGUgdG9rZW4gc2VudCBieSB0aGUgY2xpZW50IGFuZCByZXR1cm5lZFxuICAgKiBmcm9tIGFuIEFQSSBHYXRld2F5IExhbWJkYSBhdXRob3JpemVyIChmb3JtZXJseSBrbm93biBhcyBhIGN1c3RvbSBhdXRob3JpemVyKS5cbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vYXBpZ2F0ZXdheS9sYXRlc3QvZGV2ZWxvcGVyZ3VpZGUvYXBpZ2F0ZXdheS11c2UtbGFtYmRhLWF1dGhvcml6ZXIuaHRtbFxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBjb250ZXh0QXV0aG9yaXplclByaW5jaXBhbElkKCkge1xuICAgIHJldHVybiAnJGNvbnRleHQuYXV0aG9yaXplci5wcmluY2lwYWxJZCc7XG4gIH1cblxuICAvKipcbiAgICogVGhlIHN0cmluZ2lmaWVkIHZhbHVlIG9mIHRoZSBzcGVjaWZpZWQga2V5LXZhbHVlIHBhaXIgb2YgdGhlIGBjb250ZXh0YCBtYXAgcmV0dXJuZWQgZnJvbSBhbiBBUEkgR2F0ZXdheSBMYW1iZGEgYXV0aG9yaXplciBmdW5jdGlvbi5cbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vYXBpZ2F0ZXdheS9sYXRlc3QvZGV2ZWxvcGVyZ3VpZGUvYXBpZ2F0ZXdheS11c2UtbGFtYmRhLWF1dGhvcml6ZXIuaHRtbFxuICAgKiBAcGFyYW0gcHJvcGVydHkga2V5IG9mIHRoZSBjb250ZXh0IG1hcC5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY29udGV4dEF1dGhvcml6ZXIocHJvcGVydHk6IHN0cmluZykge1xuICAgIHJldHVybiBgJGNvbnRleHQuYXV0aG9yaXplci4ke3Byb3BlcnR5fWA7XG4gIH1cblxuICAvKipcbiAgICogVGhlIEFXUyBlbmRwb2ludCdzIHJlcXVlc3QgSUQuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGNvbnRleHRBd3NFbmRwb2ludFJlcXVlc3RJZCgpIHtcbiAgICByZXR1cm4gJyRjb250ZXh0LmF3c0VuZHBvaW50UmVxdWVzdElkJztcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgZnVsbCBkb21haW4gbmFtZSB1c2VkIHRvIGludm9rZSB0aGUgQVBJLiBUaGlzIHNob3VsZCBiZSB0aGUgc2FtZSBhcyB0aGUgaW5jb21pbmcgYEhvc3RgIGhlYWRlci5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY29udGV4dERvbWFpbk5hbWUoKSB7XG4gICAgcmV0dXJuICckY29udGV4dC5kb21haW5OYW1lJztcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgZmlyc3QgbGFiZWwgb2YgdGhlIGAkY29udGV4dC5kb21haW5OYW1lYC4gVGhpcyBpcyBvZnRlbiB1c2VkIGFzIGEgY2FsbGVyL2N1c3RvbWVyIGlkZW50aWZpZXIuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGNvbnRleHREb21haW5QcmVmaXgoKSB7XG4gICAgcmV0dXJuICckY29udGV4dC5kb21haW5QcmVmaXgnO1xuICB9XG5cbiAgLyoqXG4gICAqIEEgc3RyaW5nIGNvbnRhaW5pbmcgYW4gQVBJIEdhdGV3YXkgZXJyb3IgbWVzc2FnZS5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY29udGV4dEVycm9yTWVzc2FnZSgpIHtcbiAgICByZXR1cm4gJyRjb250ZXh0LmVycm9yLm1lc3NhZ2UnO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBxdW90ZWQgdmFsdWUgb2YgJGNvbnRleHQuZXJyb3IubWVzc2FnZSwgbmFtZWx5IFwiJGNvbnRleHQuZXJyb3IubWVzc2FnZVwiLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBjb250ZXh0RXJyb3JNZXNzYWdlU3RyaW5nKCkge1xuICAgIHJldHVybiAnJGNvbnRleHQuZXJyb3IubWVzc2FnZVN0cmluZyc7XG4gIH1cblxuICAvKipcbiAgICogQSB0eXBlIG9mIEdhdGV3YXlSZXNwb25zZS4gVGhpcyB2YXJpYWJsZSBjYW4gb25seSBiZSB1c2VkIGZvciBzaW1wbGUgdmFyaWFibGUgc3Vic3RpdHV0aW9uIGluIGEgR2F0ZXdheVJlc3BvbnNlIGJvZHktbWFwcGluZyB0ZW1wbGF0ZSxcbiAgICogd2hpY2ggaXMgbm90IHByb2Nlc3NlZCBieSB0aGUgVmVsb2NpdHkgVGVtcGxhdGUgTGFuZ3VhZ2UgZW5naW5lLCBhbmQgaW4gYWNjZXNzIGxvZ2dpbmcuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2FwaWdhdGV3YXkvbGF0ZXN0L2RldmVsb3Blcmd1aWRlL2FwaWdhdGV3YXktd2Vic29ja2V0LWFwaS1sb2dnaW5nLmh0bWxcbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vYXBpZ2F0ZXdheS9sYXRlc3QvZGV2ZWxvcGVyZ3VpZGUvY3VzdG9taXplLWdhdGV3YXktcmVzcG9uc2VzLmh0bWxcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY29udGV4dEVycm9yUmVzcG9uc2VUeXBlKCkge1xuICAgIHJldHVybiAnJGNvbnRleHQuZXJyb3IucmVzcG9uc2VUeXBlJztcbiAgfVxuXG4gIC8qKlxuICAgKiBBIHN0cmluZyBjb250YWluaW5nIGEgZGV0YWlsZWQgdmFsaWRhdGlvbiBlcnJvciBtZXNzYWdlLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBjb250ZXh0RXJyb3JWYWxpZGF0aW9uRXJyb3JTdHJpbmcoKSB7XG4gICAgcmV0dXJuICckY29udGV4dC5lcnJvci52YWxpZGF0aW9uRXJyb3JTdHJpbmcnO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBleHRlbmRlZCBJRCB0aGF0IEFQSSBHYXRld2F5IGFzc2lnbnMgdG8gdGhlIEFQSSByZXF1ZXN0LCB3aGljaCBjb250YWlucyBtb3JlIHVzZWZ1bCBpbmZvcm1hdGlvbiBmb3IgZGVidWdnaW5nL3Ryb3VibGVzaG9vdGluZy5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY29udGV4dEV4dGVuZGVkUmVxdWVzdElkKCkge1xuICAgIHJldHVybiAnJGNvbnRleHQuZXh0ZW5kZWRSZXF1ZXN0SWQnO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBIVFRQIG1ldGhvZCB1c2VkLiBWYWxpZCB2YWx1ZXMgaW5jbHVkZTogYERFTEVURWAsIGBHRVRgLCBgSEVBRGAsIGBPUFRJT05TYCwgYFBBVENIYCwgYFBPU1RgLCBhbmQgYFBVVGAuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGNvbnRleHRIdHRwTWV0aG9kKCkge1xuICAgIHJldHVybiAnJGNvbnRleHQuaHR0cE1ldGhvZCc7XG4gIH1cblxuICAvKipcbiAgICogVGhlIEFXUyBhY2NvdW50IElEIGFzc29jaWF0ZWQgd2l0aCB0aGUgcmVxdWVzdC5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY29udGV4dElkZW50aXR5QWNjb3VudElkKCkge1xuICAgIHJldHVybiAnJGNvbnRleHQuaWRlbnRpdHkuYWNjb3VudElkJztcbiAgfVxuXG4gIC8qKlxuICAgKiBGb3IgQVBJIG1ldGhvZHMgdGhhdCByZXF1aXJlIGFuIEFQSSBrZXksIHRoaXMgdmFyaWFibGUgaXMgdGhlIEFQSSBrZXkgYXNzb2NpYXRlZCB3aXRoIHRoZSBtZXRob2QgcmVxdWVzdC5cbiAgICogRm9yIG1ldGhvZHMgdGhhdCBkb24ndCByZXF1aXJlIGFuIEFQSSBrZXksIHRoaXMgdmFyaWFibGUgaXNcbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vYXBpZ2F0ZXdheS9sYXRlc3QvZGV2ZWxvcGVyZ3VpZGUvYXBpLWdhdGV3YXktYXBpLXVzYWdlLXBsYW5zLmh0bWxcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY29udGV4dElkZW50aXR5QXBpS2V5KCkge1xuICAgIHJldHVybiAnJGNvbnRleHQuaWRlbnRpdHkuYXBpS2V5JztcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgQVBJIGtleSBJRCBhc3NvY2lhdGVkIHdpdGggYW4gQVBJIHJlcXVlc3QgdGhhdCByZXF1aXJlcyBhbiBBUEkga2V5LlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBjb250ZXh0SWRlbnRpdHlBcGlLZXlJZCgpIHtcbiAgICByZXR1cm4gJyRjb250ZXh0LmlkZW50aXR5LmFwaUtleUlkJztcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgcHJpbmNpcGFsIGlkZW50aWZpZXIgb2YgdGhlIGNhbGxlciBtYWtpbmcgdGhlIHJlcXVlc3QuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGNvbnRleHRJZGVudGl0eUNhbGxlcigpIHtcbiAgICByZXR1cm4gJyRjb250ZXh0LmlkZW50aXR5LmNhbGxlcic7XG4gIH1cblxuICAvKipcbiAgICogVGhlIEFtYXpvbiBDb2duaXRvIGF1dGhlbnRpY2F0aW9uIHByb3ZpZGVyIHVzZWQgYnkgdGhlIGNhbGxlciBtYWtpbmcgdGhlIHJlcXVlc3QuXG4gICAqIEF2YWlsYWJsZSBvbmx5IGlmIHRoZSByZXF1ZXN0IHdhcyBzaWduZWQgd2l0aCBBbWF6b24gQ29nbml0byBjcmVkZW50aWFscy5cbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vY29nbml0by9sYXRlc3QvZGV2ZWxvcGVyZ3VpZGUvY29nbml0by1pZGVudGl0eS5odG1sXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGNvbnRleHRJZGVudGl0eUNvZ25pdG9BdXRoZW50aWNhdGlvblByb3ZpZGVyKCkge1xuICAgIHJldHVybiAnJGNvbnRleHQuaWRlbnRpdHkuY29nbml0b0F1dGhlbnRpY2F0aW9uUHJvdmlkZXInO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBBbWF6b24gQ29nbml0byBhdXRoZW50aWNhdGlvbiB0eXBlIG9mIHRoZSBjYWxsZXIgbWFraW5nIHRoZSByZXF1ZXN0LlxuICAgKiBBdmFpbGFibGUgb25seSBpZiB0aGUgcmVxdWVzdCB3YXMgc2lnbmVkIHdpdGggQW1hem9uIENvZ25pdG8gY3JlZGVudGlhbHMuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGNvbnRleHRJZGVudGl0eUNvZ25pdG9BdXRoZW50aWNhdGlvblR5cGUoKSB7XG4gICAgcmV0dXJuICckY29udGV4dC5pZGVudGl0eS5jb2duaXRvQXV0aGVudGljYXRpb25UeXBlJztcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgQW1hem9uIENvZ25pdG8gaWRlbnRpdHkgSUQgb2YgdGhlIGNhbGxlciBtYWtpbmcgdGhlIHJlcXVlc3QuIEF2YWlsYWJsZSBvbmx5IGlmIHRoZSByZXF1ZXN0IHdhcyBzaWduZWQgd2l0aCBBbWF6b24gQ29nbml0byBjcmVkZW50aWFscy5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY29udGV4dElkZW50aXR5Q29nbml0b0lkZW50aXR5SWQoKSB7XG4gICAgcmV0dXJuICckY29udGV4dC5pZGVudGl0eS5jb2duaXRvSWRlbnRpdHlJZCc7XG4gIH1cblxuICAvKipcbiAgICogVGhlIEFtYXpvbiBDb2duaXRvIGlkZW50aXR5IHBvb2wgSUQgb2YgdGhlIGNhbGxlciBtYWtpbmcgdGhlIHJlcXVlc3QuXG4gICAqIEF2YWlsYWJsZSBvbmx5IGlmIHRoZSByZXF1ZXN0IHdhcyBzaWduZWQgd2l0aCBBbWF6b24gQ29nbml0byBjcmVkZW50aWFscy5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY29udGV4dElkZW50aXR5Q29nbml0b0lkZW50aXR5UG9vbElkKCkge1xuICAgIHJldHVybiAnJGNvbnRleHQuaWRlbnRpdHkuY29nbml0b0lkZW50aXR5UG9vbElkJztcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgQVdTIG9yZ2FuaXphdGlvbiBJRC5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY29udGV4dElkZW50aXR5UHJpbmNpcGFsT3JnSWQoKSB7XG4gICAgcmV0dXJuICckY29udGV4dC5pZGVudGl0eS5wcmluY2lwYWxPcmdJZCc7XG4gIH1cblxuICAvKipcbiAgICogVGhlIHNvdXJjZSBJUCBhZGRyZXNzIG9mIHRoZSBUQ1AgY29ubmVjdGlvbiBtYWtpbmcgdGhlIHJlcXVlc3QgdG8gQVBJIEdhdGV3YXkuXG4gICAqIFdhcm5pbmc6IFlvdSBzaG91bGQgbm90IHRydXN0IHRoaXMgdmFsdWUgaWYgdGhlcmUgaXMgYW55IGNoYW5jZSB0aGF0IHRoZSBgWC1Gb3J3YXJkZWQtRm9yYCBoZWFkZXIgY291bGQgYmUgZm9yZ2VkLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBjb250ZXh0SWRlbnRpdHlTb3VyY2VJcCgpIHtcbiAgICByZXR1cm4gJyRjb250ZXh0LmlkZW50aXR5LnNvdXJjZUlwJztcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgcHJpbmNpcGFsIGlkZW50aWZpZXIgb2YgdGhlIHVzZXIgbWFraW5nIHRoZSByZXF1ZXN0LiBVc2VkIGluIExhbWJkYSBhdXRob3JpemVycy5cbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vYXBpZ2F0ZXdheS9sYXRlc3QvZGV2ZWxvcGVyZ3VpZGUvYXBpLWdhdGV3YXktbGFtYmRhLWF1dGhvcml6ZXItb3V0cHV0Lmh0bWxcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY29udGV4dElkZW50aXR5VXNlcigpIHtcbiAgICByZXR1cm4gJyRjb250ZXh0LmlkZW50aXR5LnVzZXInO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBVc2VyLUFnZW50IGhlYWRlciBvZiB0aGUgQVBJIGNhbGxlci5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY29udGV4dElkZW50aXR5VXNlckFnZW50KCkge1xuICAgIHJldHVybiAnJGNvbnRleHQuaWRlbnRpdHkudXNlckFnZW50JztcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgQW1hem9uIFJlc291cmNlIE5hbWUgKEFSTikgb2YgdGhlIGVmZmVjdGl2ZSB1c2VyIGlkZW50aWZpZWQgYWZ0ZXIgYXV0aGVudGljYXRpb24uXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0lBTS9sYXRlc3QvVXNlckd1aWRlL2lkX3VzZXJzLmh0bWxcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY29udGV4dElkZW50aXR5VXNlckFybigpIHtcbiAgICByZXR1cm4gJyRjb250ZXh0LmlkZW50aXR5LnVzZXJBcm4nO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSByZXF1ZXN0IHBhdGguXG4gICAqIEZvciBleGFtcGxlLCBmb3IgYSBub24tcHJveHkgcmVxdWVzdCBVUkwgb2YgaHR0cHM6Ly97cmVzdC1hcGktaWQuZXhlY3V0ZS1hcGkue3JlZ2lvbn0uYW1hem9uYXdzLmNvbS97c3RhZ2V9L3Jvb3QvY2hpbGQsXG4gICAqIHRoaXMgdmFsdWUgaXMgL3tzdGFnZX0vcm9vdC9jaGlsZC5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY29udGV4dFBhdGgoKSB7XG4gICAgcmV0dXJuICckY29udGV4dC5wYXRoJztcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgcmVxdWVzdCBwcm90b2NvbCwgZm9yIGV4YW1wbGUsIEhUVFAvMS4xLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBjb250ZXh0UHJvdG9jb2woKSB7XG4gICAgcmV0dXJuICckY29udGV4dC5wcm90b2NvbCc7XG4gIH1cblxuICAvKipcbiAgICogVGhlIElEIHRoYXQgQVBJIEdhdGV3YXkgYXNzaWducyB0byB0aGUgQVBJIHJlcXVlc3QuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGNvbnRleHRSZXF1ZXN0SWQoKSB7XG4gICAgcmV0dXJuICckY29udGV4dC5yZXF1ZXN0SWQnO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSByZXF1ZXN0IGhlYWRlciBvdmVycmlkZS5cbiAgICogSWYgdGhpcyBwYXJhbWV0ZXIgaXMgZGVmaW5lZCwgaXQgY29udGFpbnMgdGhlIGhlYWRlcnMgdG8gYmUgdXNlZCBpbnN0ZWFkIG9mIHRoZSBIVFRQIEhlYWRlcnMgdGhhdCBhcmUgZGVmaW5lZCBpbiB0aGUgSW50ZWdyYXRpb24gUmVxdWVzdCBwYW5lLlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9hcGlnYXRld2F5L2xhdGVzdC9kZXZlbG9wZXJndWlkZS9hcGlnYXRld2F5LW92ZXJyaWRlLXJlcXVlc3QtcmVzcG9uc2UtcGFyYW1ldGVycy5odG1sXG4gICAqXG4gICAqIEBwYXJhbSBoZWFkZXJOYW1lXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGNvbnRleHRSZXF1ZXN0T3ZlcnJpZGVIZWFkZXIoaGVhZGVyTmFtZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIGAkY29udGV4dC5yZXF1ZXN0T3ZlcnJpZGUuaGVhZGVyLiR7aGVhZGVyTmFtZX1gO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSByZXF1ZXN0IHBhdGggb3ZlcnJpZGUuIElmIHRoaXMgcGFyYW1ldGVyIGlzIGRlZmluZWQsXG4gICAqIGl0IGNvbnRhaW5zIHRoZSByZXF1ZXN0IHBhdGggdG8gYmUgdXNlZCBpbnN0ZWFkIG9mIHRoZSBVUkwgUGF0aCBQYXJhbWV0ZXJzIHRoYXQgYXJlIGRlZmluZWQgaW4gdGhlIEludGVncmF0aW9uIFJlcXVlc3QgcGFuZS5cbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vYXBpZ2F0ZXdheS9sYXRlc3QvZGV2ZWxvcGVyZ3VpZGUvYXBpZ2F0ZXdheS1vdmVycmlkZS1yZXF1ZXN0LXJlc3BvbnNlLXBhcmFtZXRlcnMuaHRtbFxuICAgKlxuICAgKiBAcGFyYW0gcGF0aE5hbWVcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY29udGV4dFJlcXVlc3RPdmVycmlkZVBhdGgocGF0aE5hbWU6IHN0cmluZykge1xuICAgIHJldHVybiBgJGNvbnRleHQucmVxdWVzdE92ZXJyaWRlLnBhdGguJHtwYXRoTmFtZX1gO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSByZXF1ZXN0IHF1ZXJ5IHN0cmluZyBvdmVycmlkZS5cbiAgICogSWYgdGhpcyBwYXJhbWV0ZXIgaXMgZGVmaW5lZCwgaXQgY29udGFpbnMgdGhlIHJlcXVlc3QgcXVlcnkgc3RyaW5ncyB0byBiZSB1c2VkIGluc3RlYWRcbiAgICogb2YgdGhlIFVSTCBRdWVyeSBTdHJpbmcgUGFyYW1ldGVycyB0aGF0IGFyZSBkZWZpbmVkIGluIHRoZSBJbnRlZ3JhdGlvbiBSZXF1ZXN0IHBhbmUuXG4gICAqXG4gICAqIEBwYXJhbSBxdWVyeXN0cmluZ05hbWVcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY29udGV4dFJlcXVlc3RPdmVycmlkZVF1ZXJ5c3RyaW5nKHF1ZXJ5c3RyaW5nTmFtZTogc3RyaW5nKSB7XG4gICAgcmV0dXJuIGAkY29udGV4dC5yZXF1ZXN0T3ZlcnJpZGUucXVlcnlzdHJpbmcuJHtxdWVyeXN0cmluZ05hbWV9YDtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgcmVzcG9uc2UgaGVhZGVyIG92ZXJyaWRlLlxuICAgKiBJZiB0aGlzIHBhcmFtZXRlciBpcyBkZWZpbmVkLCBpdCBjb250YWlucyB0aGUgaGVhZGVyIHRvIGJlIHJldHVybmVkIGluc3RlYWQgb2YgdGhlIFJlc3BvbnNlIGhlYWRlclxuICAgKiB0aGF0IGlzIGRlZmluZWQgYXMgdGhlIERlZmF1bHQgbWFwcGluZyBpbiB0aGUgSW50ZWdyYXRpb24gUmVzcG9uc2UgcGFuZS5cbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vYXBpZ2F0ZXdheS9sYXRlc3QvZGV2ZWxvcGVyZ3VpZGUvYXBpZ2F0ZXdheS1vdmVycmlkZS1yZXF1ZXN0LXJlc3BvbnNlLXBhcmFtZXRlcnMuaHRtbFxuICAgKlxuICAgKiBAcGFyYW0gaGVhZGVyTmFtZVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBjb250ZXh0UmVzcG9uc2VPdmVycmlkZUhlYWRlcihoZWFkZXJOYW1lOiBzdHJpbmcpIHtcbiAgICByZXR1cm4gYCRjb250ZXh0LnJlc3BvbnNlT3ZlcnJpZGUuaGVhZGVyLiR7aGVhZGVyTmFtZX1gO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSByZXNwb25zZSBzdGF0dXMgY29kZSBvdmVycmlkZS5cbiAgICogSWYgdGhpcyBwYXJhbWV0ZXIgaXMgZGVmaW5lZCwgaXQgY29udGFpbnMgdGhlIHN0YXR1cyBjb2RlIHRvIGJlIHJldHVybmVkIGluc3RlYWQgb2YgdGhlIE1ldGhvZCByZXNwb25zZSBzdGF0dXNcbiAgICogdGhhdCBpcyBkZWZpbmVkIGFzIHRoZSBEZWZhdWx0IG1hcHBpbmcgaW4gdGhlIEludGVncmF0aW9uIFJlc3BvbnNlIHBhbmUuXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2FwaWdhdGV3YXkvbGF0ZXN0L2RldmVsb3Blcmd1aWRlL2FwaWdhdGV3YXktb3ZlcnJpZGUtcmVxdWVzdC1yZXNwb25zZS1wYXJhbWV0ZXJzLmh0bWxcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY29udGV4dFJlc3BvbnNlT3ZlcnJpZGVTdGF0dXMoKSB7XG4gICAgcmV0dXJuICckY29udGV4dC5yZXNwb25zZU92ZXJyaWRlLnN0YXR1cyc7XG4gIH1cblxuICAvKipcbiAgICogVGhlIENMRi1mb3JtYXR0ZWQgcmVxdWVzdCB0aW1lIChkZC9NTU0veXl5eTpISDptbTpzcyArLWhobW0pLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBjb250ZXh0UmVxdWVzdFRpbWUoKSB7XG4gICAgcmV0dXJuICckY29udGV4dC5yZXF1ZXN0VGltZSc7XG4gIH1cblxuICAvKipcbiAgICogVGhlIEVwb2NoLWZvcm1hdHRlZCByZXF1ZXN0IHRpbWUuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGNvbnRleHRSZXF1ZXN0VGltZUVwb2NoKCkge1xuICAgIHJldHVybiAnJGNvbnRleHQucmVxdWVzdFRpbWVFcG9jaCc7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGlkZW50aWZpZXIgdGhhdCBBUEkgR2F0ZXdheSBhc3NpZ25zIHRvIHlvdXIgcmVzb3VyY2UuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGNvbnRleHRSZXNvdXJjZUlkKCkge1xuICAgIHJldHVybiAnJGNvbnRleHQucmVzb3VyY2VJZCc7XG4gIH1cblxuICAvKipcbiAgICogVGhlIHBhdGggdG8geW91ciByZXNvdXJjZS5cbiAgICogRm9yIGV4YW1wbGUsIGZvciB0aGUgbm9uLXByb3h5IHJlcXVlc3QgVVJJIG9mIGBodHRwczovL3tyZXN0LWFwaS1pZC5leGVjdXRlLWFwaS57cmVnaW9ufS5hbWF6b25hd3MuY29tL3tzdGFnZX0vcm9vdC9jaGlsZGAsXG4gICAqIFRoZSAkY29udGV4dC5yZXNvdXJjZVBhdGggdmFsdWUgaXMgYC9yb290L2NoaWxkYC5cbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vYXBpZ2F0ZXdheS9sYXRlc3QvZGV2ZWxvcGVyZ3VpZGUvYXBpLWdhdGV3YXktY3JlYXRlLWFwaS1zdGVwLWJ5LXN0ZXAuaHRtbFxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBjb250ZXh0UmVzb3VyY2VQYXRoKCkge1xuICAgIHJldHVybiAnJGNvbnRleHQucmVzb3VyY2VQYXRoJztcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgZGVwbG95bWVudCBzdGFnZSBvZiB0aGUgQVBJIHJlcXVlc3QgKGZvciBleGFtcGxlLCBgQmV0YWAgb3IgYFByb2RgKS5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY29udGV4dFN0YWdlKCkge1xuICAgIHJldHVybiAnJGNvbnRleHQuc3RhZ2UnO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSByZXNwb25zZSByZWNlaXZlZCBmcm9tIEFXUyBXQUY6IGBXQUZfQUxMT1dgIG9yIGBXQUZfQkxPQ0tgLiBXaWxsIG5vdCBiZSBzZXQgaWYgdGhlIHN0YWdlIGlzIG5vdCBhc3NvY2lhdGVkIHdpdGggYSB3ZWIgQUNMLlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9hcGlnYXRld2F5L2xhdGVzdC9kZXZlbG9wZXJndWlkZS9hcGlnYXRld2F5LWNvbnRyb2wtYWNjZXNzLWF3cy13YWYuaHRtbFxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBjb250ZXh0V2FmUmVzcG9uc2VDb2RlKCkge1xuICAgIHJldHVybiAnJGNvbnRleHQud2FmUmVzcG9uc2VDb2RlJztcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgY29tcGxldGUgQVJOIG9mIHRoZSB3ZWIgQUNMIHRoYXQgaXMgdXNlZCB0byBkZWNpZGUgd2hldGhlciB0byBhbGxvdyBvciBibG9jayB0aGUgcmVxdWVzdC5cbiAgICogV2lsbCBub3QgYmUgc2V0IGlmIHRoZSBzdGFnZSBpcyBub3QgYXNzb2NpYXRlZCB3aXRoIGEgd2ViIEFDTC5cbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vYXBpZ2F0ZXdheS9sYXRlc3QvZGV2ZWxvcGVyZ3VpZGUvYXBpZ2F0ZXdheS1jb250cm9sLWFjY2Vzcy1hd3Mtd2FmLmh0bWxcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY29udGV4dFdlYmFjbEFybigpIHtcbiAgICByZXR1cm4gJyRjb250ZXh0LndlYmFjbEFybic7XG4gIH1cblxuICAvKipcbiAgICogVGhlIHRyYWNlIElEIGZvciB0aGUgWC1SYXkgdHJhY2UuXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2FwaWdhdGV3YXkvbGF0ZXN0L2RldmVsb3Blcmd1aWRlL2FwaWdhdGV3YXktZW5hYmxpbmcteHJheS5odG1sXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGNvbnRleHRYcmF5VHJhY2VJZCgpIHtcbiAgICByZXR1cm4gJyRjb250ZXh0LnhyYXlUcmFjZUlkJztcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgYXV0aG9yaXplciBsYXRlbmN5IGluIG1zLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBjb250ZXh0QXV0aG9yaXplckludGVncmF0aW9uTGF0ZW5jeSgpIHtcbiAgICByZXR1cm4gJyRjb250ZXh0LmF1dGhvcml6ZXIuaW50ZWdyYXRpb25MYXRlbmN5JztcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgaW50ZWdyYXRpb24gbGF0ZW5jeSBpbiBtcy5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY29udGV4dEludGVncmF0aW9uTGF0ZW5jeSgpIHtcbiAgICByZXR1cm4gJyRjb250ZXh0LmludGVncmF0aW9uTGF0ZW5jeSc7XG4gIH1cblxuICAvKipcbiAgICogRm9yIExhbWJkYSBwcm94eSBpbnRlZ3JhdGlvbiwgdGhpcyBwYXJhbWV0ZXIgcmVwcmVzZW50cyB0aGUgc3RhdHVzIGNvZGUgcmV0dXJuZWQgZnJvbSBBV1MgTGFtYmRhLFxuICAgKiBub3QgZnJvbSB0aGUgYmFja2VuZCBMYW1iZGEgZnVuY3Rpb24uXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGNvbnRleHRJbnRlZ3JhdGlvblN0YXR1cygpIHtcbiAgICByZXR1cm4gJyRjb250ZXh0LmludGVncmF0aW9uU3RhdHVzJztcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgcmVzcG9uc2UgbGF0ZW5jeSBpbiBtcy5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY29udGV4dFJlc3BvbnNlTGF0ZW5jeSgpIHtcbiAgICByZXR1cm4gJyRjb250ZXh0LnJlc3BvbnNlTGF0ZW5jeSc7XG4gIH1cblxuICAvKipcbiAgICogVGhlIHJlc3BvbnNlIHBheWxvYWQgbGVuZ3RoLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBjb250ZXh0UmVzcG9uc2VMZW5ndGgoKSB7XG4gICAgcmV0dXJuICckY29udGV4dC5yZXNwb25zZUxlbmd0aCc7XG4gIH1cblxuICAvKipcbiAgICogVGhlIG1ldGhvZCByZXNwb25zZSBzdGF0dXMuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGNvbnRleHRTdGF0dXMoKSB7XG4gICAgcmV0dXJuICckY29udGV4dC5zdGF0dXMnO1xuICB9XG59XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgY29udHJvbGxpbmcgaXRlbXMgb3V0cHV0IGluIEpTT04gc3RhbmRhcmQgZm9ybWF0XG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSnNvbldpdGhTdGFuZGFyZEZpZWxkUHJvcHMge1xuICAvKipcbiAgICogSWYgdGhpcyBmbGFnIGlzIGVuYWJsZWQsIHRoZSBzb3VyY2UgSVAgb2YgcmVxdWVzdCB3aWxsIGJlIG91dHB1dCB0byB0aGUgbG9nXG4gICAqL1xuICByZWFkb25seSBpcDogYm9vbGVhbixcbiAgLyoqXG4gICAqIElmIHRoaXMgZmxhZyBpcyBlbmFibGVkLCB0aGUgcHJpbmNpcGFsIGlkZW50aWZpZXIgb2YgdGhlIGNhbGxlciB3aWxsIGJlIG91dHB1dCB0byB0aGUgbG9nXG4gICAqL1xuICByZWFkb25seSBjYWxsZXI6IGJvb2xlYW4sXG4gIC8qKlxuICAgKiBJZiB0aGlzIGZsYWcgaXMgZW5hYmxlZCwgdGhlIHByaW5jaXBhbCBpZGVudGlmaWVyIG9mIHRoZSB1c2VyIHdpbGwgYmUgb3V0cHV0IHRvIHRoZSBsb2dcbiAgICovXG4gIHJlYWRvbmx5IHVzZXI6IGJvb2xlYW4sXG4gIC8qKlxuICAgKiBJZiB0aGlzIGZsYWcgaXMgZW5hYmxlZCwgdGhlIENMRi1mb3JtYXR0ZWQgcmVxdWVzdCB0aW1lKChkZC9NTU0veXl5eTpISDptbTpzcyArLWhobW0pIHdpbGwgYmUgb3V0cHV0IHRvIHRoZSBsb2dcbiAgICovXG4gIHJlYWRvbmx5IHJlcXVlc3RUaW1lOiBib29sZWFuLFxuICAvKipcbiAgICogSWYgdGhpcyBmbGFnIGlzIGVuYWJsZWQsIHRoZSBodHRwIG1ldGhvZCB3aWxsIGJlIG91dHB1dCB0byB0aGUgbG9nXG4gICAqL1xuICByZWFkb25seSBodHRwTWV0aG9kOiBib29sZWFuLFxuICAvKipcbiAgICogSWYgdGhpcyBmbGFnIGlzIGVuYWJsZWQsIHRoZSBwYXRoIHRvIHlvdXIgcmVzb3VyY2Ugd2lsbCBiZSBvdXRwdXQgdG8gdGhlIGxvZ1xuICAgKi9cbiAgcmVhZG9ubHkgcmVzb3VyY2VQYXRoOiBib29sZWFuLFxuICAvKipcbiAgICogSWYgdGhpcyBmbGFnIGlzIGVuYWJsZWQsIHRoZSBtZXRob2QgcmVzcG9uc2Ugc3RhdHVzIHdpbGwgYmUgb3V0cHV0IHRvIHRoZSBsb2dcbiAgICovXG4gIHJlYWRvbmx5IHN0YXR1czogYm9vbGVhbixcbiAgLyoqXG4gICAqIElmIHRoaXMgZmxhZyBpcyBlbmFibGVkLCB0aGUgcmVxdWVzdCBwcm90b2NvbCB3aWxsIGJlIG91dHB1dCB0byB0aGUgbG9nXG4gICAqL1xuICByZWFkb25seSBwcm90b2NvbDogYm9vbGVhbixcbiAgLyoqXG4gICAqIElmIHRoaXMgZmxhZyBpcyBlbmFibGVkLCB0aGUgcmVzcG9uc2UgcGF5bG9hZCBsZW5ndGggd2lsbCBiZSBvdXRwdXQgdG8gdGhlIGxvZ1xuICAgKi9cbiAgcmVhZG9ubHkgcmVzcG9uc2VMZW5ndGg6IGJvb2xlYW5cbn1cblxuLyoqXG4gKiBmYWN0b3J5IG1ldGhvZHMgZm9yIGFjY2VzcyBsb2cgZm9ybWF0LlxuICovXG5leHBvcnQgY2xhc3MgQWNjZXNzTG9nRm9ybWF0IHtcbiAgLyoqXG4gICAqIEN1c3RvbSBsb2cgZm9ybWF0LlxuICAgKiBZb3UgY2FuIGNyZWF0ZSBhbnkgbG9nIGZvcm1hdCBzdHJpbmcuIFlvdSBjYW4gZWFzaWx5IGdldCB0aGUgJCBjb250ZXh0IHZhcmlhYmxlIGJ5IHVzaW5nIHRoZSBtZXRob2RzIG9mIEFjY2Vzc0xvZ0ZpZWxkLlxuICAgKiBAcGFyYW0gZm9ybWF0XG4gICAqIEBleGFtcGxlXG4gICAqXG4gICAqICBhcGlnYXRld2F5LkFjY2Vzc0xvZ0Zvcm1hdC5jdXN0b20oSlNPTi5zdHJpbmdpZnkoe1xuICAgKiAgICAgIHJlcXVlc3RJZDogYXBpZ2F0ZXdheS5BY2Nlc3NMb2dGaWVsZC5jb250ZXh0UmVxdWVzdElkKCksXG4gICAqICAgICAgc291cmNlSXA6IGFwaWdhdGV3YXkuQWNjZXNzTG9nRmllbGQuY29udGV4dElkZW50aXR5U291cmNlSXAoKSxcbiAgICogICAgICBtZXRob2Q6IGFwaWdhdGV3YXkuQWNjZXNzTG9nRmllbGQuY29udGV4dEh0dHBNZXRob2QoKSxcbiAgICogICAgICB1c2VyQ29udGV4dDoge1xuICAgKiAgICAgICAgc3ViOiBhcGlnYXRld2F5LkFjY2Vzc0xvZ0ZpZWxkLmNvbnRleHRBdXRob3JpemVyQ2xhaW1zKCdzdWInKSxcbiAgICogICAgICAgIGVtYWlsOiBhcGlnYXRld2F5LkFjY2Vzc0xvZ0ZpZWxkLmNvbnRleHRBdXRob3JpemVyQ2xhaW1zKCdlbWFpbCcpXG4gICAqICAgICAgfVxuICAgKiAgIH0pKVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBjdXN0b20oZm9ybWF0OiBzdHJpbmcpOiBBY2Nlc3NMb2dGb3JtYXQge1xuICAgIHJldHVybiBuZXcgQWNjZXNzTG9nRm9ybWF0KGZvcm1hdCk7XG4gIH1cblxuICAvKipcbiAgICogR2VuZXJhdGUgQ29tbW9uIExvZyBGb3JtYXQuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGNsZigpOiBBY2Nlc3NMb2dGb3JtYXQge1xuICAgIGNvbnN0IHJlcXVlc3RlciA9IFtBY2Nlc3NMb2dGaWVsZC5jb250ZXh0SWRlbnRpdHlTb3VyY2VJcCgpLCBBY2Nlc3NMb2dGaWVsZC5jb250ZXh0SWRlbnRpdHlDYWxsZXIoKSwgQWNjZXNzTG9nRmllbGQuY29udGV4dElkZW50aXR5VXNlcigpXS5qb2luKCcgJyk7XG4gICAgY29uc3QgcmVxdWVzdFRpbWUgPSBBY2Nlc3NMb2dGaWVsZC5jb250ZXh0UmVxdWVzdFRpbWUoKTtcbiAgICBjb25zdCByZXF1ZXN0ID0gW0FjY2Vzc0xvZ0ZpZWxkLmNvbnRleHRIdHRwTWV0aG9kKCksIEFjY2Vzc0xvZ0ZpZWxkLmNvbnRleHRSZXNvdXJjZVBhdGgoKSwgQWNjZXNzTG9nRmllbGQuY29udGV4dFByb3RvY29sKCldLmpvaW4oJyAnKTtcbiAgICBjb25zdCBzdGF0dXMgPSBbQWNjZXNzTG9nRmllbGQuY29udGV4dFN0YXR1cygpLCBBY2Nlc3NMb2dGaWVsZC5jb250ZXh0UmVzcG9uc2VMZW5ndGgoKSwgQWNjZXNzTG9nRmllbGQuY29udGV4dFJlcXVlc3RJZCgpXS5qb2luKCcgJyk7XG5cbiAgICByZXR1cm4gbmV3IEFjY2Vzc0xvZ0Zvcm1hdChgJHtyZXF1ZXN0ZXJ9IFske3JlcXVlc3RUaW1lfV0gXCIke3JlcXVlc3R9XCIgJHtzdGF0dXN9YCk7XG4gIH1cblxuICAvKipcbiAgICogQWNjZXNzIGxvZyB3aWxsIGJlIHByb2R1Y2VkIGluIHRoZSBKU09OIGZvcm1hdCB3aXRoIGEgc2V0IG9mIGZpZWxkcyBtb3N0IHVzZWZ1bCBpbiB0aGUgYWNjZXNzIGxvZy4gQWxsIGZpZWxkcyBhcmUgdHVybmVkIG9uIGJ5IGRlZmF1bHQgd2l0aCB0aGVcbiAgICogb3B0aW9uIHRvIHR1cm4gb2ZmIHNwZWNpZmljIGZpZWxkcy5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMganNvbldpdGhTdGFuZGFyZEZpZWxkcyhcbiAgICBmaWVsZHM6IEpzb25XaXRoU3RhbmRhcmRGaWVsZFByb3BzID0ge1xuICAgICAgaXA6IHRydWUsXG4gICAgICB1c2VyOiB0cnVlLFxuICAgICAgY2FsbGVyOiB0cnVlLFxuICAgICAgcmVxdWVzdFRpbWU6IHRydWUsXG4gICAgICBodHRwTWV0aG9kOiB0cnVlLFxuICAgICAgcmVzb3VyY2VQYXRoOiB0cnVlLFxuICAgICAgc3RhdHVzOiB0cnVlLFxuICAgICAgcHJvdG9jb2w6IHRydWUsXG4gICAgICByZXNwb25zZUxlbmd0aDogdHJ1ZSxcbiAgICB9KTogQWNjZXNzTG9nRm9ybWF0IHtcbiAgICByZXR1cm4gdGhpcy5jdXN0b20oSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgcmVxdWVzdElkOiBBY2Nlc3NMb2dGaWVsZC5jb250ZXh0UmVxdWVzdElkKCksXG4gICAgICBpcDogZmllbGRzLmlwID8gQWNjZXNzTG9nRmllbGQuY29udGV4dElkZW50aXR5U291cmNlSXAoKSA6IHVuZGVmaW5lZCxcbiAgICAgIHVzZXI6IGZpZWxkcy51c2VyID8gQWNjZXNzTG9nRmllbGQuY29udGV4dElkZW50aXR5VXNlcigpIDogdW5kZWZpbmVkLFxuICAgICAgY2FsbGVyOiBmaWVsZHMuY2FsbGVyID8gQWNjZXNzTG9nRmllbGQuY29udGV4dElkZW50aXR5Q2FsbGVyKCkgOiB1bmRlZmluZWQsXG4gICAgICByZXF1ZXN0VGltZTogZmllbGRzLnJlcXVlc3RUaW1lID8gQWNjZXNzTG9nRmllbGQuY29udGV4dFJlcXVlc3RUaW1lKCkgOiB1bmRlZmluZWQsXG4gICAgICBodHRwTWV0aG9kOiBmaWVsZHMuaHR0cE1ldGhvZCA/IEFjY2Vzc0xvZ0ZpZWxkLmNvbnRleHRIdHRwTWV0aG9kKCkgOiB1bmRlZmluZWQsXG4gICAgICByZXNvdXJjZVBhdGg6IGZpZWxkcy5yZXNvdXJjZVBhdGggPyBBY2Nlc3NMb2dGaWVsZC5jb250ZXh0UmVzb3VyY2VQYXRoKCkgOiB1bmRlZmluZWQsXG4gICAgICBzdGF0dXM6IGZpZWxkcy5zdGF0dXMgPyBBY2Nlc3NMb2dGaWVsZC5jb250ZXh0U3RhdHVzKCkgOiB1bmRlZmluZWQsXG4gICAgICBwcm90b2NvbDogZmllbGRzLnByb3RvY29sID8gQWNjZXNzTG9nRmllbGQuY29udGV4dFByb3RvY29sKCkgOiB1bmRlZmluZWQsXG4gICAgICByZXNwb25zZUxlbmd0aDogZmllbGRzLnJlc3BvbnNlTGVuZ3RoID8gQWNjZXNzTG9nRmllbGQuY29udGV4dFJlc3BvbnNlTGVuZ3RoKCkgOiB1bmR