iam-floyd
Version:
AWS IAM policy statement generator with fluent interface
493 lines • 46.7 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Appflow = void 0;
const shared_1 = require("../../shared");
/**
* Statement provider for service [appflow](https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazonappflow.html).
*
* @param sid [SID](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_sid.html) of the statement
*/
class Appflow extends shared_1.PolicyStatement {
/**
* Statement provider for service [appflow](https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazonappflow.html).
*
* @param sid [SID](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_sid.html) of the statement
*/
constructor(sid) {
super(sid);
this.servicePrefix = 'appflow';
this.accessLevelList = {
Write: [
'CancelFlowExecutions',
'CreateConnectorProfile',
'CreateFlow',
'DeleteConnectorProfile',
'DeleteFlow',
'RegisterConnector',
'ResetConnectorMetadataCache',
'RunFlow',
'StartFlow',
'StopFlow',
'UnRegisterConnector',
'UpdateConnectorProfile',
'UpdateConnectorRegistration',
'UpdateFlow',
'UseConnectorProfile'
],
Read: [
'DescribeConnector',
'DescribeConnectorEntity',
'DescribeConnectorFields',
'DescribeConnectorProfiles',
'DescribeConnectors',
'DescribeFlow',
'DescribeFlowExecution',
'DescribeFlowExecutionRecords',
'DescribeFlows',
'ListConnectorFields',
'ListTagsForResource'
],
List: [
'ListConnectorEntities',
'ListConnectors',
'ListFlows'
],
Tagging: [
'TagResource',
'UntagResource'
]
};
}
/**
* Grants permission to cancel in-progress executions of an Amazon AppFlow flow
*
* Access Level: Write
*
* https://docs.aws.amazon.com/appflow/1.0/APIReference/API_CancelFlowExecutions.html
*/
toCancelFlowExecutions() {
return this.to('CancelFlowExecutions');
}
/**
* Grants permission to create a login profile to be used with Amazon AppFlow flows
*
* Access Level: Write
*
* https://docs.aws.amazon.com/appflow/1.0/APIReference/API_CreateConnectorProfile.html
*/
toCreateConnectorProfile() {
return this.to('CreateConnectorProfile');
}
/**
* Grants permission to create an Amazon AppFlow flow
*
* Access Level: Write
*
* Possible conditions:
* - .ifAwsRequestTag()
* - .ifAwsTagKeys()
*
* https://docs.aws.amazon.com/appflow/1.0/APIReference/API_CreateFlow.html
*/
toCreateFlow() {
return this.to('CreateFlow');
}
/**
* Grants permission to delete a login profile configured in Amazon AppFlow
*
* Access Level: Write
*
* https://docs.aws.amazon.com/appflow/1.0/APIReference/API_DescribeConnectorProfiles.html
*/
toDeleteConnectorProfile() {
return this.to('DeleteConnectorProfile');
}
/**
* Grants permission to delete an Amazon AppFlow flow
*
* Access Level: Write
*
* Possible conditions:
* - .ifAwsRequestTag()
* - .ifAwsTagKeys()
*
* https://docs.aws.amazon.com/appflow/1.0/APIReference/API_DeleteFlow.html
*/
toDeleteFlow() {
return this.to('DeleteFlow');
}
/**
* Grants permission to describe a connector registered in Amazon AppFlow
*
* Access Level: Read
*
* https://docs.aws.amazon.com/appflow/1.0/APIReference/API_DescribeConnector.html
*/
toDescribeConnector() {
return this.to('DescribeConnector');
}
/**
* Grants permission to describe all fields for an object in a login profile configured in Amazon AppFlow
*
* Access Level: Read
*
* https://docs.aws.amazon.com/appflow/1.0/APIReference/API_DescribeConnectorEntity.html
*/
toDescribeConnectorEntity() {
return this.to('DescribeConnectorEntity');
}
/**
* Grants permission to describe all fields for an object in a login profile configured in Amazon AppFlow (Console Only)
*
* Access Level: Read
*
* https://docs.aws.amazon.com/appflow/latest/userguide/identity-access-management.html#appflow-api-actions
*/
toDescribeConnectorFields() {
return this.to('DescribeConnectorFields');
}
/**
* Grants permission to describe all login profiles configured in Amazon AppFlow
*
* Access Level: Read
*
* https://docs.aws.amazon.com/appflow/1.0/APIReference/API_DescribeConnectorProfiles.html
*/
toDescribeConnectorProfiles() {
return this.to('DescribeConnectorProfiles');
}
/**
* Grants permission to describe all connectors supported by Amazon AppFlow
*
* Access Level: Read
*
* https://docs.aws.amazon.com/appflow/1.0/APIReference/API_DescribeConnectors.html
*/
toDescribeConnectors() {
return this.to('DescribeConnectors');
}
/**
* Grants permission to describe a specific flow configured in Amazon AppFlow
*
* Access Level: Read
*
* https://docs.aws.amazon.com/appflow/1.0/APIReference/API_DescribeFlow.html
*/
toDescribeFlow() {
return this.to('DescribeFlow');
}
/**
* Grants permission to describe all flow executions for a flow configured in Amazon AppFlow (Console Only)
*
* Access Level: Read
*
* https://docs.aws.amazon.com/appflow/latest/userguide/identity-access-management.html#appflow-api-actions
*/
toDescribeFlowExecution() {
return this.to('DescribeFlowExecution');
}
/**
* Grants permission to describe all flow executions for a flow configured in Amazon AppFlow
*
* Access Level: Read
*
* https://docs.aws.amazon.com/appflow/1.0/APIReference/API_DescribeFlowExecutionRecords.html
*/
toDescribeFlowExecutionRecords() {
return this.to('DescribeFlowExecutionRecords');
}
/**
* Grants permission to describe all flows configured in Amazon AppFlow (Console Only)
*
* Access Level: Read
*
* https://docs.aws.amazon.com/appflow/latest/userguide/identity-access-management.html#appflow-api-actions
*/
toDescribeFlows() {
return this.to('DescribeFlows');
}
/**
* Grants permission to list all objects for a login profile configured in Amazon AppFlow
*
* Access Level: List
*
* https://docs.aws.amazon.com/appflow/1.0/APIReference/API_ListConnectorEntities.html
*/
toListConnectorEntities() {
return this.to('ListConnectorEntities');
}
/**
* Grants permission to list all objects for a login profile configured in Amazon AppFlow (Console Only)
*
* Access Level: Read
*
* https://docs.aws.amazon.com/appflow/latest/userguide/identity-access-management.html#appflow-api-actions
*/
toListConnectorFields() {
return this.to('ListConnectorFields');
}
/**
* Grants permission to list all connectors supported in Amazon AppFlow
*
* Access Level: List
*
* https://docs.aws.amazon.com/appflow/1.0/APIReference/API_ListConnectors.html
*/
toListConnectors() {
return this.to('ListConnectors');
}
/**
* Grants permission to list all flows configured in Amazon AppFlow
*
* Access Level: List
*
* https://docs.aws.amazon.com/appflow/1.0/APIReference/API_ListFlows.html
*/
toListFlows() {
return this.to('ListFlows');
}
/**
* Grants permission to list tags for a flow
*
* Access Level: Read
*
* https://docs.aws.amazon.com/appflow/1.0/APIReference/API_ListTagsForResource.html
*/
toListTagsForResource() {
return this.to('ListTagsForResource');
}
/**
* Grants permission to register an Amazon AppFlow connector
*
* Access Level: Write
*
* Possible conditions:
* - .ifAwsRequestTag()
* - .ifAwsTagKeys()
*
* https://docs.aws.amazon.com/appflow/1.0/APIReference/API_RegisterConnector.html
*/
toRegisterConnector() {
return this.to('RegisterConnector');
}
/**
* Grants permission to resets metadata of connector entities that Amazon AppFlow stored in its cache
*
* Access Level: Write
*
* https://docs.aws.amazon.com/appflow/1.0/APIReference/API_ResetConnectorMetadataCache.html
*/
toResetConnectorMetadataCache() {
return this.to('ResetConnectorMetadataCache');
}
/**
* Grants permission to run a flow configured in Amazon AppFlow (Console Only)
*
* Access Level: Write
*
* https://docs.aws.amazon.com/appflow/latest/userguide/identity-access-management.html#appflow-api-actions
*/
toRunFlow() {
return this.to('RunFlow');
}
/**
* Grants permission to activate (for scheduled and event-triggered flows) or run (for on-demand flows) a flow configured in Amazon AppFlow
*
* Access Level: Write
*
* https://docs.aws.amazon.com/appflow/1.0/APIReference/API_StartFlow.html
*/
toStartFlow() {
return this.to('StartFlow');
}
/**
* Grants permission to deactivate a scheduled or event-triggered flow configured in Amazon AppFlow
*
* Access Level: Write
*
* https://docs.aws.amazon.com/appflow/1.0/APIReference/API_StopFlow.html
*/
toStopFlow() {
return this.to('StopFlow');
}
/**
* Grants permission to tag a flow or a connector
*
* Access Level: Tagging
*
* Possible conditions:
* - .ifAwsTagKeys()
* - .ifAwsRequestTag()
*
* https://docs.aws.amazon.com/appflow/1.0/APIReference/API_TagResource.html
*/
toTagResource() {
return this.to('TagResource');
}
/**
* Grants permission to un-register a connector in Amazon AppFlow
*
* Access Level: Write
*
* Possible conditions:
* - .ifAwsRequestTag()
* - .ifAwsTagKeys()
*
* https://docs.aws.amazon.com/appflow/1.0/APIReference/API_UnregisterConnector.html
*/
toUnRegisterConnector() {
return this.to('UnRegisterConnector');
}
/**
* Grants permission to untag a flow or a connector
*
* Access Level: Tagging
*
* Possible conditions:
* - .ifAwsTagKeys()
*
* https://docs.aws.amazon.com/appflow/1.0/APIReference/API_UntagResource.html
*/
toUntagResource() {
return this.to('UntagResource');
}
/**
* Grants permission to update a login profile configured in Amazon AppFlow
*
* Access Level: Write
*
* https://docs.aws.amazon.com/appflow/1.0/APIReference/API_UpdateConnectorProfile.html
*/
toUpdateConnectorProfile() {
return this.to('UpdateConnectorProfile');
}
/**
* Grants permission to update a registered connector configured in Amazon AppFlow
*
* Access Level: Write
*
* https://docs.aws.amazon.com/appflow/1.0/APIReference/API_UpdateConnectorRegistration.html
*/
toUpdateConnectorRegistration() {
return this.to('UpdateConnectorRegistration');
}
/**
* Grants permission to update a flow configured in Amazon AppFlow
*
* Access Level: Write
*
* https://docs.aws.amazon.com/appflow/1.0/APIReference/API_UpdateFlow.html
*/
toUpdateFlow() {
return this.to('UpdateFlow');
}
/**
* Grants permission to use a connector profile while creating a flow in Amazon AppFlow
*
* Access Level: Write
*/
toUseConnectorProfile() {
return this.to('UseConnectorProfile');
}
/**
* Adds a resource of type connectorprofile to the statement
*
* https://docs.aws.amazon.com/appflow/1.0/APIReference/API_ConnectorProfile.html
*
* @param profileName - Identifier for the profileName.
* @param account - Account of the resource; defaults to `*`, unless using the CDK, where the default is the current Stack's account.
* @param region - Region of the resource; defaults to `*`, unless using the CDK, where the default is the current Stack's region.
* @param partition - Partition of the AWS account [aws, aws-cn, aws-us-gov]; defaults to `aws`, unless using the CDK, where the default is the current Stack's partition.
*/
onConnectorprofile(profileName, account, region, partition) {
return this.on(`arn:${partition ?? this.defaultPartition}:appflow:${region ?? this.defaultRegion}:${account ?? this.defaultAccount}:connectorprofile/${profileName}`);
}
/**
* Adds a resource of type flow to the statement
*
* https://docs.aws.amazon.com/appflow/1.0/APIReference/API_FlowDefinition.html
*
* @param flowName - Identifier for the flowName.
* @param account - Account of the resource; defaults to `*`, unless using the CDK, where the default is the current Stack's account.
* @param region - Region of the resource; defaults to `*`, unless using the CDK, where the default is the current Stack's region.
* @param partition - Partition of the AWS account [aws, aws-cn, aws-us-gov]; defaults to `aws`, unless using the CDK, where the default is the current Stack's partition.
*
* Possible conditions:
* - .ifAwsResourceTag()
*/
onFlow(flowName, account, region, partition) {
return this.on(`arn:${partition ?? this.defaultPartition}:appflow:${region ?? this.defaultRegion}:${account ?? this.defaultAccount}:flow/${flowName}`);
}
/**
* Adds a resource of type connector to the statement
*
* https://docs.aws.amazon.com/appflow/1.0/APIReference/API_ConnectorDetail.html
*
* @param connectorLabel - Identifier for the connectorLabel.
* @param account - Account of the resource; defaults to `*`, unless using the CDK, where the default is the current Stack's account.
* @param region - Region of the resource; defaults to `*`, unless using the CDK, where the default is the current Stack's region.
* @param partition - Partition of the AWS account [aws, aws-cn, aws-us-gov]; defaults to `aws`, unless using the CDK, where the default is the current Stack's partition.
*
* Possible conditions:
* - .ifAwsResourceTag()
*/
onConnector(connectorLabel, account, region, partition) {
return this.on(`arn:${partition ?? this.defaultPartition}:appflow:${region ?? this.defaultRegion}:${account ?? this.defaultAccount}:connector/${connectorLabel}`);
}
/**
* Filters access by allowed set of values for each of the tags
*
* https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-requesttag
*
* Applies to actions:
* - .toCreateFlow()
* - .toDeleteFlow()
* - .toRegisterConnector()
* - .toTagResource()
* - .toUnRegisterConnector()
*
* @param tagKey The tag key to check
* @param value The value(s) to check
* @param operator Works with [string operators](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition_operators.html#Conditions_String). **Default:** `StringLike`
*/
ifAwsRequestTag(tagKey, value, operator) {
return this.if(`aws:RequestTag/${tagKey}`, value, operator ?? 'StringLike');
}
/**
* Filters access by tag-value associated with the resource
*
* https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-resourcetag
*
* Applies to resource types:
* - flow
* - connector
*
* @param tagKey The tag key to check
* @param value The value(s) to check
* @param operator Works with [string operators](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition_operators.html#Conditions_String). **Default:** `StringLike`
*/
ifAwsResourceTag(tagKey, value, operator) {
return this.if(`aws:ResourceTag/${tagKey}`, value, operator ?? 'StringLike');
}
/**
* Filters access by presence of mandatory tags in the request
*
* https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-tagkeys
*
* Applies to actions:
* - .toCreateFlow()
* - .toDeleteFlow()
* - .toRegisterConnector()
* - .toTagResource()
* - .toUnRegisterConnector()
* - .toUntagResource()
*
* @param value The value(s) to check
* @param operator Works with [string operators](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition_operators.html#Conditions_String). **Default:** `StringLike`
*/
ifAwsTagKeys(value, operator) {
return this.if(`aws:TagKeys`, value, operator ?? 'StringLike');
}
}
exports.Appflow = Appflow;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwZmxvdy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImFwcGZsb3cudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQ0EseUNBQXlEO0FBRXpEOzs7O0dBSUc7QUFDSCxNQUFhLE9BQVEsU0FBUSx3QkFBZTtJQUcxQzs7OztPQUlHO0lBQ0gsWUFBWSxHQUFZO1FBQ3RCLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztRQVJOLGtCQUFhLEdBQUcsU0FBUyxDQUFDO1FBcVh2QixvQkFBZSxHQUFvQjtZQUMzQyxLQUFLLEVBQUU7Z0JBQ0wsc0JBQXNCO2dCQUN0Qix3QkFBd0I7Z0JBQ3hCLFlBQVk7Z0JBQ1osd0JBQXdCO2dCQUN4QixZQUFZO2dCQUNaLG1CQUFtQjtnQkFDbkIsNkJBQTZCO2dCQUM3QixTQUFTO2dCQUNULFdBQVc7Z0JBQ1gsVUFBVTtnQkFDVixxQkFBcUI7Z0JBQ3JCLHdCQUF3QjtnQkFDeEIsNkJBQTZCO2dCQUM3QixZQUFZO2dCQUNaLHFCQUFxQjthQUN0QjtZQUNELElBQUksRUFBRTtnQkFDSixtQkFBbUI7Z0JBQ25CLHlCQUF5QjtnQkFDekIseUJBQXlCO2dCQUN6QiwyQkFBMkI7Z0JBQzNCLG9CQUFvQjtnQkFDcEIsY0FBYztnQkFDZCx1QkFBdUI7Z0JBQ3ZCLDhCQUE4QjtnQkFDOUIsZUFBZTtnQkFDZixxQkFBcUI7Z0JBQ3JCLHFCQUFxQjthQUN0QjtZQUNELElBQUksRUFBRTtnQkFDSix1QkFBdUI7Z0JBQ3ZCLGdCQUFnQjtnQkFDaEIsV0FBVzthQUNaO1lBQ0QsT0FBTyxFQUFFO2dCQUNQLGFBQWE7Z0JBQ2IsZUFBZTthQUNoQjtTQUNGLENBQUM7SUFwWkYsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNJLHNCQUFzQjtRQUMzQixPQUFPLElBQUksQ0FBQyxFQUFFLENBQUMsc0JBQXNCLENBQUMsQ0FBQztJQUN6QyxDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0ksd0JBQXdCO1FBQzdCLE9BQU8sSUFBSSxDQUFDLEVBQUUs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QUFJLENBQUMsRUFBRSxDQUFDLGFBQWEsRUFBRSxLQUFLLEVBQUUsUUFBUSxJQUFJLFlBQVksQ0FBQyxDQUFDO0lBQ2pFLENBQUM7Q0FDRjtBQXhnQkQsMEJBd2dCQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFjY2Vzc0xldmVsTGlzdCB9IGZyb20gJy4uLy4uL3NoYXJlZC9hY2Nlc3MtbGV2ZWwnO1xuaW1wb3J0IHsgUG9saWN5U3RhdGVtZW50LCBPcGVyYXRvciB9IGZyb20gJy4uLy4uL3NoYXJlZCc7XG5cbi8qKlxuICogU3RhdGVtZW50IHByb3ZpZGVyIGZvciBzZXJ2aWNlIFthcHBmbG93XShodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vc2VydmljZS1hdXRob3JpemF0aW9uL2xhdGVzdC9yZWZlcmVuY2UvbGlzdF9hbWF6b25hcHBmbG93Lmh0bWwpLlxuICpcbiAqIEBwYXJhbSBzaWQgW1NJRF0oaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0lBTS9sYXRlc3QvVXNlckd1aWRlL3JlZmVyZW5jZV9wb2xpY2llc19lbGVtZW50c19zaWQuaHRtbCkgb2YgdGhlIHN0YXRlbWVudFxuICovXG5leHBvcnQgY2xhc3MgQXBwZmxvdyBleHRlbmRzIFBvbGljeVN0YXRlbWVudCB7XG4gIHB1YmxpYyBzZXJ2aWNlUHJlZml4ID0gJ2FwcGZsb3cnO1xuXG4gIC8qKlxuICAgKiBTdGF0ZW1lbnQgcHJvdmlkZXIgZm9yIHNlcnZpY2UgW2FwcGZsb3ddKGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9zZXJ2aWNlLWF1dGhvcml6YXRpb24vbGF0ZXN0L3JlZmVyZW5jZS9saXN0X2FtYXpvbmFwcGZsb3cuaHRtbCkuXG4gICAqXG4gICAqIEBwYXJhbSBzaWQgW1NJRF0oaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0lBTS9sYXRlc3QvVXNlckd1aWRlL3JlZmVyZW5jZV9wb2xpY2llc19lbGVtZW50c19zaWQuaHRtbCkgb2YgdGhlIHN0YXRlbWVudFxuICAgKi9cbiAgY29uc3RydWN0b3Ioc2lkPzogc3RyaW5nKSB7XG4gICAgc3VwZXIoc2lkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHcmFudHMgcGVybWlzc2lvbiB0byBjYW5jZWwgaW4tcHJvZ3Jlc3MgZXhlY3V0aW9ucyBvZiBhbiBBbWF6b24gQXBwRmxvdyBmbG93XG4gICAqXG4gICAqIEFjY2VzcyBMZXZlbDogV3JpdGVcbiAgICpcbiAgICogaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2FwcGZsb3cvMS4wL0FQSVJlZmVyZW5jZS9BUElfQ2FuY2VsRmxvd0V4ZWN1dGlvbnMuaHRtbFxuICAgKi9cbiAgcHVibGljIHRvQ2FuY2VsRmxvd0V4ZWN1dGlvbnMoKSB7XG4gICAgcmV0dXJuIHRoaXMudG8oJ0NhbmNlbEZsb3dFeGVjdXRpb25zJyk7XG4gIH1cblxuICAvKipcbiAgICogR3JhbnRzIHBlcm1pc3Npb24gdG8gY3JlYXRlIGEgbG9naW4gcHJvZmlsZSB0byBiZSB1c2VkIHdpdGggQW1hem9uIEFwcEZsb3cgZmxvd3NcbiAgICpcbiAgICogQWNjZXNzIExldmVsOiBXcml0ZVxuICAgKlxuICAgKiBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vYXBwZmxvdy8xLjAvQVBJUmVmZXJlbmNlL0FQSV9DcmVhdGVDb25uZWN0b3JQcm9maWxlLmh0bWxcbiAgICovXG4gIHB1YmxpYyB0b0NyZWF0ZUNvbm5lY3RvclByb2ZpbGUoKSB7XG4gICAgcmV0dXJuIHRoaXMudG8oJ0NyZWF0ZUNvbm5lY3RvclByb2ZpbGUnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHcmFudHMgcGVybWlzc2lvbiB0byBjcmVhdGUgYW4gQW1hem9uIEFwcEZsb3cgZmxvd1xuICAgKlxuICAgKiBBY2Nlc3MgTGV2ZWw6IFdyaXRlXG4gICAqXG4gICAqIFBvc3NpYmxlIGNvbmRpdGlvbnM6XG4gICAqIC0gLmlmQXdzUmVxdWVzdFRhZygpXG4gICAqIC0gLmlmQXdzVGFnS2V5cygpXG4gICAqXG4gICAqIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9hcHBmbG93LzEuMC9BUElSZWZlcmVuY2UvQVBJX0NyZWF0ZUZsb3cuaHRtbFxuICAgKi9cbiAgcHVibGljIHRvQ3JlYXRlRmxvdygpIHtcbiAgICByZXR1cm4gdGhpcy50bygnQ3JlYXRlRmxvdycpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdyYW50cyBwZXJtaXNzaW9uIHRvIGRlbGV0ZSBhIGxvZ2luIHByb2ZpbGUgY29uZmlndXJlZCBpbiBBbWF6b24gQXBwRmxvd1xuICAgKlxuICAgKiBBY2Nlc3MgTGV2ZWw6IFdyaXRlXG4gICAqXG4gICAqIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9hcHBmbG93LzEuMC9BUElSZWZlcmVuY2UvQVBJX0Rlc2NyaWJlQ29ubmVjdG9yUHJvZmlsZXMuaHRtbFxuICAgKi9cbiAgcHVibGljIHRvRGVsZXRlQ29ubmVjdG9yUHJvZmlsZSgpIHtcbiAgICByZXR1cm4gdGhpcy50bygnRGVsZXRlQ29ubmVjdG9yUHJvZmlsZScpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdyYW50cyBwZXJtaXNzaW9uIHRvIGRlbGV0ZSBhbiBBbWF6b24gQXBwRmxvdyBmbG93XG4gICAqXG4gICAqIEFjY2VzcyBMZXZlbDogV3JpdGVcbiAgICpcbiAgICogUG9zc2libGUgY29uZGl0aW9uczpcbiAgICogLSAuaWZBd3NSZXF1ZXN0VGFnKClcbiAgICogLSAuaWZBd3NUYWdLZXlzKClcbiAgICpcbiAgICogaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2FwcGZsb3cvMS4wL0FQSVJlZmVyZW5jZS9BUElfRGVsZXRlRmxvdy5odG1sXG4gICAqL1xuICBwdWJsaWMgdG9EZWxldGVGbG93KCkge1xuICAgIHJldHVybiB0aGlzLnRvKCdEZWxldGVGbG93Jyk7XG4gIH1cblxuICAvKipcbiAgICogR3JhbnRzIHBlcm1pc3Npb24gdG8gZGVzY3JpYmUgYSBjb25uZWN0b3IgcmVnaXN0ZXJlZCBpbiBBbWF6b24gQXBwRmxvd1xuICAgKlxuICAgKiBBY2Nlc3MgTGV2ZWw6IFJlYWRcbiAgICpcbiAgICogaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2FwcGZsb3cvMS4wL0FQSVJlZmVyZW5jZS9BUElfRGVzY3JpYmVDb25uZWN0b3IuaHRtbFxuICAgKi9cbiAgcHVibGljIHRvRGVzY3JpYmVDb25uZWN0b3IoKSB7XG4gICAgcmV0dXJuIHRoaXMudG8oJ0Rlc2NyaWJlQ29ubmVjdG9yJyk7XG4gIH1cblxuICAvKipcbiAgICogR3JhbnRzIHBlcm1pc3Npb24gdG8gZGVzY3JpYmUgYWxsIGZpZWxkcyBmb3IgYW4gb2JqZWN0IGluIGEgbG9naW4gcHJvZmlsZSBjb25maWd1cmVkIGluIEFtYXpvbiBBcHBGbG93XG4gICAqXG4gICAqIEFjY2VzcyBMZXZlbDogUmVhZFxuICAgKlxuICAgKiBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vYXBwZmxvdy8xLjAvQVBJUmVmZXJlbmNlL0FQSV9EZXNjcmliZUNvbm5lY3RvckVudGl0eS5odG1sXG4gICAqL1xuICBwdWJsaWMgdG9EZXNjcmliZUNvbm5lY3RvckVudGl0eSgpIHtcbiAgICByZXR1cm4gdGhpcy50bygnRGVzY3JpYmVDb25uZWN0b3JFbnRpdHknKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHcmFudHMgcGVybWlzc2lvbiB0byBkZXNjcmliZSBhbGwgZmllbGRzIGZvciBhbiBvYmplY3QgaW4gYSBsb2dpbiBwcm9maWxlIGNvbmZpZ3VyZWQgaW4gQW1hem9uIEFwcEZsb3cgKENvbnNvbGUgT25seSlcbiAgICpcbiAgICogQWNjZXNzIExldmVsOiBSZWFkXG4gICAqXG4gICAqIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9hcHBmbG93L2xhdGVzdC91c2VyZ3VpZGUvaWRlbnRpdHktYWNjZXNzLW1hbmFnZW1lbnQuaHRtbCNhcHBmbG93LWFwaS1hY3Rpb25zXG4gICAqL1xuICBwdWJsaWMgdG9EZXNjcmliZUNvbm5lY3RvckZpZWxkcygpIHtcbiAgICByZXR1cm4gdGhpcy50bygnRGVzY3JpYmVDb25uZWN0b3JGaWVsZHMnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHcmFudHMgcGVybWlzc2lvbiB0byBkZXNjcmliZSBhbGwgbG9naW4gcHJvZmlsZXMgY29uZmlndXJlZCBpbiBBbWF6b24gQXBwRmxvd1xuICAgKlxuICAgKiBBY2Nlc3MgTGV2ZWw6IFJlYWRcbiAgICpcbiAgICogaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2FwcGZsb3cvMS4wL0FQSVJlZmVyZW5jZS9BUElfRGVzY3JpYmVDb25uZWN0b3JQcm9maWxlcy5odG1sXG4gICAqL1xuICBwdWJsaWMgdG9EZXNjcmliZUNvbm5lY3RvclByb2ZpbGVzKCkge1xuICAgIHJldHVybiB0aGlzLnRvKCdEZXNjcmliZUNvbm5lY3RvclByb2ZpbGVzJyk7XG4gIH1cblxuICAvKipcbiAgICogR3JhbnRzIHBlcm1pc3Npb24gdG8gZGVzY3JpYmUgYWxsIGNvbm5lY3RvcnMgc3VwcG9ydGVkIGJ5IEFtYXpvbiBBcHBGbG93XG4gICAqXG4gICAqIEFjY2VzcyBMZXZlbDogUmVhZFxuICAgKlxuICAgKiBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vYXBwZmxvdy8xLjAvQVBJUmVmZXJlbmNlL0FQSV9EZXNjcmliZUNvbm5lY3RvcnMuaHRtbFxuICAgKi9cbiAgcHVibGljIHRvRGVzY3JpYmVDb25uZWN0b3JzKCkge1xuICAgIHJldHVybiB0aGlzLnRvKCdEZXNjcmliZUNvbm5lY3RvcnMnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHcmFudHMgcGVybWlzc2lvbiB0byBkZXNjcmliZSBhIHNwZWNpZmljIGZsb3cgY29uZmlndXJlZCBpbiBBbWF6b24gQXBwRmxvd1xuICAgKlxuICAgKiBBY2Nlc3MgTGV2ZWw6IFJlYWRcbiAgICpcbiAgICogaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2FwcGZsb3cvMS4wL0FQSVJlZmVyZW5jZS9BUElfRGVzY3JpYmVGbG93Lmh0bWxcbiAgICovXG4gIHB1YmxpYyB0b0Rlc2NyaWJlRmxvdygpIHtcbiAgICByZXR1cm4gdGhpcy50bygnRGVzY3JpYmVGbG93Jyk7XG4gIH1cblxuICAvKipcbiAgICogR3JhbnRzIHBlcm1pc3Npb24gdG8gZGVzY3JpYmUgYWxsIGZsb3cgZXhlY3V0aW9ucyBmb3IgYSBmbG93IGNvbmZpZ3VyZWQgaW4gQW1hem9uIEFwcEZsb3cgKENvbnNvbGUgT25seSlcbiAgICpcbiAgICogQWNjZXNzIExldmVsOiBSZWFkXG4gICAqXG4gICAqIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9hcHBmbG93L2xhdGVzdC91c2VyZ3VpZGUvaWRlbnRpdHktYWNjZXNzLW1hbmFnZW1lbnQuaHRtbCNhcHBmbG93LWFwaS1hY3Rpb25zXG4gICAqL1xuICBwdWJsaWMgdG9EZXNjcmliZUZsb3dFeGVjdXRpb24oKSB7XG4gICAgcmV0dXJuIHRoaXMudG8oJ0Rlc2NyaWJlRmxvd0V4ZWN1dGlvbicpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdyYW50cyBwZXJtaXNzaW9uIHRvIGRlc2NyaWJlIGFsbCBmbG93IGV4ZWN1dGlvbnMgZm9yIGEgZmxvdyBjb25maWd1cmVkIGluIEFtYXpvbiBBcHBGbG93XG4gICAqXG4gICAqIEFjY2VzcyBMZXZlbDogUmVhZFxuICAgKlxuICAgKiBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vYXBwZmxvdy8xLjAvQVBJUmVmZXJlbmNlL0FQSV9EZXNjcmliZUZsb3dFeGVjdXRpb25SZWNvcmRzLmh0bWxcbiAgICovXG4gIHB1YmxpYyB0b0Rlc2NyaWJlRmxvd0V4ZWN1dGlvblJlY29yZHMoKSB7XG4gICAgcmV0dXJuIHRoaXMudG8oJ0Rlc2NyaWJlRmxvd0V4ZWN1dGlvblJlY29yZHMnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHcmFudHMgcGVybWlzc2lvbiB0byBkZXNjcmliZSBhbGwgZmxvd3MgY29uZmlndXJlZCBpbiBBbWF6b24gQXBwRmxvdyAoQ29uc29sZSBPbmx5KVxuICAgKlxuICAgKiBBY2Nlc3MgTGV2ZWw6IFJlYWRcbiAgICpcbiAgICogaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2FwcGZsb3cvbGF0ZXN0L3VzZXJndWlkZS9pZGVudGl0eS1hY2Nlc3MtbWFuYWdlbWVudC5odG1sI2FwcGZsb3ctYXBpLWFjdGlvbnNcbiAgICovXG4gIHB1YmxpYyB0b0Rlc2NyaWJlRmxvd3MoKSB7XG4gICAgcmV0dXJuIHRoaXMudG8oJ0Rlc2NyaWJlRmxvd3MnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHcmFudHMgcGVybWlzc2lvbiB0byBsaXN0IGFsbCBvYmplY3RzIGZvciBhIGxvZ2luIHByb2ZpbGUgY29uZmlndXJlZCBpbiBBbWF6b24gQXBwRmxvd1xuICAgKlxuICAgKiBBY2Nlc3MgTGV2ZWw6IExpc3RcbiAgICpcbiAgICogaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2FwcGZsb3cvMS4wL0FQSVJlZmVyZW5jZS9BUElfTGlzdENvbm5lY3RvckVudGl0aWVzLmh0bWxcbiAgICovXG4gIHB1YmxpYyB0b0xpc3RDb25uZWN0b3JFbnRpdGllcygpIHtcbiAgICByZXR1cm4gdGhpcy50bygnTGlzdENvbm5lY3RvckVudGl0aWVzJyk7XG4gIH1cblxuICAvKipcbiAgICogR3JhbnRzIHBlcm1pc3Npb24gdG8gbGlzdCBhbGwgb2JqZWN0cyBmb3IgYSBsb2dpbiBwcm9maWxlIGNvbmZpZ3VyZWQgaW4gQW1hem9uIEFwcEZsb3cgKENvbnNvbGUgT25seSlcbiAgICpcbiAgICogQWNjZXNzIExldmVsOiBSZWFkXG4gICAqXG4gICAqIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9hcHBmbG93L2xhdGVzdC91c2VyZ3VpZGUvaWRlbnRpdHktYWNjZXNzLW1hbmFnZW1lbnQuaHRtbCNhcHBmbG93LWFwaS1hY3Rpb25zXG4gICAqL1xuICBwdWJsaWMgdG9MaXN0Q29ubmVjdG9yRmllbGRzKCkge1xuICAgIHJldHVybiB0aGlzLnRvKCdMaXN0Q29ubmVjdG9yRmllbGRzJyk7XG4gIH1cblxuICAvKipcbiAgICogR3JhbnRzIHBlcm1pc3Npb24gdG8gbGlzdCBhbGwgY29ubmVjdG9ycyBzdXBwb3J0ZWQgaW4gQW1hem9uIEFwcEZsb3dcbiAgICpcbiAgICogQWNjZXNzIExldmVsOiBMaXN0XG4gICAqXG4gICAqIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9hcHBmbG93LzEuMC9BUElSZWZlcmVuY2UvQVBJX0xpc3RDb25uZWN0b3JzLmh0bWxcbiAgICovXG4gIHB1YmxpYyB0b0xpc3RDb25uZWN0b3JzKCkge1xuICAgIHJldHVybiB0aGlzLnRvKCdMaXN0Q29ubmVjdG9ycycpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdyYW50cyBwZXJtaXNzaW9uIHRvIGxpc3QgYWxsIGZsb3dzIGNvbmZpZ3VyZWQgaW4gQW1hem9uIEFwcEZsb3dcbiAgICpcbiAgICogQWNjZXNzIExldmVsOiBMaXN0XG4gICAqXG4gICAqIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9hcHBmbG93LzEuMC9BUElSZWZlcmVuY2UvQVBJX0xpc3RGbG93cy5odG1sXG4gICAqL1xuICBwdWJsaWMgdG9MaXN0Rmxvd3MoKSB7XG4gICAgcmV0dXJuIHRoaXMudG8oJ0xpc3RGbG93cycpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdyYW50cyBwZXJtaXNzaW9uIHRvIGxpc3QgdGFncyBmb3IgYSBmbG93XG4gICAqXG4gICAqIEFjY2VzcyBMZXZlbDogUmVhZFxuICAgKlxuICAgKiBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vYXBwZmxvdy8xLjAvQVBJUmVmZXJlbmNlL0FQSV9MaXN0VGFnc0ZvclJlc291cmNlLmh0bWxcbiAgICovXG4gIHB1YmxpYyB0b0xpc3RUYWdzRm9yUmVzb3VyY2UoKSB7XG4gICAgcmV0dXJuIHRoaXMudG8oJ0xpc3RUYWdzRm9yUmVzb3VyY2UnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHcmFudHMgcGVybWlzc2lvbiB0byByZWdpc3RlciBhbiBBbWF6b24gQXBwRmxvdyBjb25uZWN0b3JcbiAgICpcbiAgICogQWNjZXNzIExldmVsOiBXcml0ZVxuICAgKlxuICAgKiBQb3NzaWJsZSBjb25kaXRpb25zOlxuICAgKiAtIC5pZkF3c1JlcXVlc3RUYWcoKVxuICAgKiAtIC5pZkF3c1RhZ0tleXMoKVxuICAgKlxuICAgKiBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vYXBwZmxvdy8xLjAvQVBJUmVmZXJlbmNlL0FQSV9SZWdpc3RlckNvbm5lY3Rvci5odG1sXG4gICAqL1xuICBwdWJsaWMgdG9SZWdpc3RlckNvbm5lY3RvcigpIHtcbiAgICByZXR1cm4gdGhpcy50bygnUmVnaXN0ZXJDb25uZWN0b3InKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHcmFudHMgcGVybWlzc2lvbiB0byByZXNldHMgbWV0YWRhdGEgb2YgY29ubmVjdG9yIGVudGl0aWVzIHRoYXQgQW1hem9uIEFwcEZsb3cgc3RvcmVkIGluIGl0cyBjYWNoZVxuICAgKlxuICAgKiBBY2Nlc3MgTGV2ZWw6IFdyaXRlXG4gICAqXG4gICAqIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9hcHBmbG93LzEuMC9BUElSZWZlcmVuY2UvQVBJX1Jlc2V0Q29ubmVjdG9yTWV0YWRhdGFDYWNoZS5odG1sXG4gICAqL1xuICBwdWJsaWMgdG9SZXNldENvbm5lY3Rvck1ldGFkYXRhQ2FjaGUoKSB7XG4gICAgcmV0dXJuIHRoaXMudG8oJ1Jlc2V0Q29ubmVjdG9yTWV0YWRhdGFDYWNoZScpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdyYW50cyBwZXJtaXNzaW9uIHRvIHJ1biBhIGZsb3cgY29uZmlndXJlZCBpbiBBbWF6b24gQXBwRmxvdyAoQ29uc29sZSBPbmx5KVxuICAgKlxuICAgKiBBY2Nlc3MgTGV2ZWw6IFdyaXRlXG4gICAqXG4gICAqIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9hcHBmbG93L2xhdGVzdC91c2VyZ3VpZGUvaWRlbnRpdHktYWNjZXNzLW1hbmFnZW1lbnQuaHRtbCNhcHBmbG93LWFwaS1hY3Rpb25zXG4gICAqL1xuICBwdWJsaWMgdG9SdW5GbG93KCkge1xuICAgIHJldHVybiB0aGlzLnRvKCdSdW5GbG93Jyk7XG4gIH1cblxuICAvKipcbiAgICogR3JhbnRzIHBlcm1pc3Npb24gdG8gYWN0aXZhdGUgKGZvciBzY2hlZHVsZWQgYW5kIGV2ZW50LXRyaWdnZXJlZCBmbG93cykgb3IgcnVuIChmb3Igb24tZGVtYW5kIGZsb3dzKSBhIGZsb3cgY29uZmlndXJlZCBpbiBBbWF6b24gQXBwRmxvd1xuICAgKlxuICAgKiBBY2Nlc3MgTGV2ZWw6IFdyaXRlXG4gICAqXG4gICAqIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9hcHBmbG93LzEuMC9BUElSZWZlcmVuY2UvQVBJX1N0YXJ0Rmxvdy5odG1sXG4gICAqL1xuICBwdWJsaWMgdG9TdGFydEZsb3coKSB7XG4gICAgcmV0dXJuIHRoaXMudG8oJ1N0YXJ0RmxvdycpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdyYW50cyBwZXJtaXNzaW9uIHRvIGRlYWN0aXZhdGUgYSBzY2hlZHVsZWQgb3IgZXZlbnQtdHJpZ2dlcmVkIGZsb3cgY29uZmlndXJlZCBpbiBBbWF6b24gQXBwRmxvd1xuICAgKlxuICAgKiBBY2Nlc3MgTGV2ZWw6IFdyaXRlXG4gICAqXG4gICAqIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9hcHBmbG93LzEuMC9BUElSZWZlcmVuY2UvQVBJX1N0b3BGbG93Lmh0bWxcbiAgICovXG4gIHB1YmxpYyB0b1N0b3BGbG93KCkge1xuICAgIHJldHVybiB0aGlzLnRvKCdTdG9wRmxvdycpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdyYW50cyBwZXJtaXNzaW9uIHRvIHRhZyBhIGZsb3cgb3IgYSBjb25uZWN0b3JcbiAgICpcbiAgICogQWNjZXNzIExldmVsOiBUYWdnaW5nXG4gICAqXG4gICAqIFBvc3NpYmxlIGNvbmRpdGlvbnM6XG4gICAqIC0gLmlmQXdzVGFnS2V5cygpXG4gICAqIC0gLmlmQXdzUmVxdWVzdFRhZygpXG4gICAqXG4gICAqIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9hcHBmbG93LzEuMC9BUElSZWZlcmVuY2UvQVBJX1RhZ1Jlc291cmNlLmh0bWxcbiAgICovXG4gIHB1YmxpYyB0b1RhZ1Jlc291cmNlKCkge1xuICAgIHJldHVybiB0aGlzLnRvKCdUYWdSZXNvdXJjZScpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdyYW50cyBwZXJtaXNzaW9uIHRvIHVuLXJlZ2lzdGVyIGEgY29ubmVjdG9yIGluIEFtYXpvbiBBcHBGbG93XG4gICAqXG4gICAqIEFjY2VzcyBMZXZlbDogV3JpdGVcbiAgICpcbiAgICogUG9zc2libGUgY29uZGl0aW9uczpcbiAgICogLSAuaWZBd3NSZXF1ZXN0VGFnKClcbiAgICogLSAuaWZBd3NUYWdLZXlzKClcbiAgICpcbiAgICogaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2FwcGZsb3cvMS4wL0FQSVJlZmVyZW5jZS9BUElfVW5yZWdpc3RlckNvbm5lY3Rvci5odG1sXG4gICAqL1xuICBwdWJsaWMgdG9VblJlZ2lzdGVyQ29ubmVjdG9yKCkge1xuICAgIHJldHVybiB0aGlzLnRvKCdVblJlZ2lzdGVyQ29ubmVjdG9yJyk7XG4gIH1cblxuICAvKipcbiAgICogR3JhbnRzIHBlcm1pc3Npb24gdG8gdW50YWcgYSBmbG93IG9yIGEgY29ubmVjdG9yXG4gICAqXG4gICAqIEFjY2VzcyBMZXZlbDogVGFnZ2luZ1xuICAgKlxuICAgKiBQb3NzaWJsZSBjb25kaXRpb25zOlxuICAgKiAtIC5pZkF3c1RhZ0tleXMoKVxuICAgKlxuICAgKiBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vYXBwZmxvdy8xLjAvQVBJUmVmZXJlbmNlL0FQSV9VbnRhZ1Jlc291cmNlLmh0bWxcbiAgICovXG4gIHB1YmxpYyB0b1VudGFnUmVzb3VyY2UoKSB7XG4gICAgcmV0dXJuIHRoaXMudG8oJ1VudGFnUmVzb3VyY2UnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHcmFudHMgcGVybWlzc2lvbiB0byB1cGRhdGUgYSBsb2dpbiBwcm9maWxlIGNvbmZpZ3VyZWQgaW4gQW1hem9uIEFwcEZsb3dcbiAgICpcbiAgICogQWNjZXNzIExldmVsOiBXcml0ZVxuICAgKlxuICAgKiBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vYXBwZmxvdy8xLjAvQVBJUmVmZXJlbmNlL0FQSV9VcGRhdGVDb25uZWN0b3JQcm9maWxlLmh0bWxcbiAgICovXG4gIHB1YmxpYyB0b1VwZGF0ZUNvbm5lY3RvclByb2ZpbGUoKSB7XG4gICAgcmV0dXJuIHRoaXMudG8oJ1VwZGF0ZUNvbm5lY3RvclByb2ZpbGUnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHcmFudHMgcGVybWlzc2lvbiB0byB1cGRhdGUgYSByZWdpc3RlcmVkIGNvbm5lY3RvciBjb25maWd1cmVkIGluIEFtYXpvbiBBcHBGbG93XG4gICAqXG4gICAqIEFjY2VzcyBMZXZlbDogV3JpdGVcbiAgICpcbiAgICogaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2FwcGZsb3cvMS4wL0FQSVJlZmVyZW5jZS9BUElfVXBkYXRlQ29ubmVjdG9yUmVnaXN0cmF0aW9uLmh0bWxcbiAgICovXG4gIHB1YmxpYyB0b1VwZGF0ZUNvbm5lY3RvclJlZ2lzdHJhdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy50bygnVXBkYXRlQ29ubmVjdG9yUmVnaXN0cmF0aW9uJyk7XG4gIH1cblxuICAvKipcbiAgICogR3JhbnRzIHBlcm1pc3Npb24gdG8gdXBkYXRlIGEgZmxvdyBjb25maWd1cmVkIGluIEFtYXpvbiBBcHBGbG93XG4gICAqXG4gICAqIEFjY2VzcyBMZXZlbDogV3JpdGVcbiAgICpcbiAgICogaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2FwcGZsb3cvMS4wL0FQSVJlZmVyZW5jZS9BUElfVXBkYXRlRmxvdy5odG1sXG4gICAqL1xuICBwdWJsaWMgdG9VcGRhdGVGbG93KCkge1xuICAgIHJldHVybiB0aGlzLnRvKCdVcGRhdGVGbG93Jyk7XG4gIH1cblxuICAvKipcbiAgICogR3JhbnRzIHBlcm1pc3Npb24gdG8gdXNlIGEgY29ubmVjdG9yIHByb2ZpbGUgd2hpbGUgY3JlYXRpbmcgYSBmbG93IGluIEFtYXpvbiBBcHBGbG93XG4gICAqXG4gICAqIEFjY2VzcyBMZXZlbDogV3JpdGVcbiAgICovXG4gIHB1YmxpYyB0b1VzZUNvbm5lY3RvclByb2ZpbGUoKSB7XG4gICAgcmV0dXJuIHRoaXMudG8oJ1VzZUNvbm5lY3RvclByb2ZpbGUnKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhY2Nlc3NMZXZlbExpc3Q6IEFjY2Vzc0xldmVsTGlzdCA9IHtcbiAgICBXcml0ZTogW1xuICAgICAgJ0NhbmNlbEZsb3dFeGVjdXRpb25zJyxcbiAgICAgICdDcmVhdGVDb25uZWN0b3JQcm9maWxlJyxcbiAgICAgICdDcmVhdGVGbG93JyxcbiAgICAgICdEZWxldGVDb25uZWN0b3JQcm9maWxlJyxcbiAgICAgICdEZWxldGVGbG93JyxcbiAgICAgICdSZWdpc3RlckNvbm5lY3RvcicsXG4gICAgICAnUmVzZXRDb25uZWN0b3JNZXRhZGF0YUNhY2hlJyxcbiAgICAgICdSdW5GbG93JyxcbiAgICAgICdTdGFydEZsb3cnLFxuICAgICAgJ1N0b3BGbG93JyxcbiAgICAgICdVblJlZ2lzdGVyQ29ubmVjdG9yJyxcbiAgICAgICdVcGRhdGVDb25uZWN0b3JQcm9maWxlJyxcbiAgICAgICdVcGRhdGVDb25uZWN0b3JSZWdpc3RyYXRpb24nLFxuICAgICAgJ1VwZGF0ZUZsb3cnLFxuICAgICAgJ1VzZUNvbm5lY3RvclByb2ZpbGUnXG4gICAgXSxcbiAgICBSZWFkOiBbXG4gICAgICAnRGVzY3JpYmVDb25uZWN0b3InLFxuICAgICAgJ0Rlc2NyaWJlQ29ubmVjdG9yRW50aXR5JyxcbiAgICAgICdEZXNjcmliZUNvbm5lY3RvckZpZWxkcycsXG4gICAgICAnRGVzY3JpYmVDb25uZWN0b3JQcm9maWxlcycsXG4gICAgICAnRGVzY3JpYmVDb25uZWN0b3JzJyxcbiAgICAgICdEZXNjcmliZUZsb3cnLFxuICAgICAgJ0Rlc2NyaWJlRmxvd0V4ZWN1dGlvbicsXG4gICAgICAnRGVzY3JpYmVGbG93RXhlY3V0aW9uUmVjb3JkcycsXG4gICAgICAnRGVzY3JpYmVGbG93cycsXG4gICAgICAnTGlzdENvbm5lY3RvckZpZWxkcycsXG4gICAgICAnTGlzdFRhZ3NGb3JSZXNvdXJjZSdcbiAgICBdLFxuICAgIExpc3Q6IFtcbiAgICAgICdMaXN0Q29ubmVjdG9yRW50aXRpZXMnLFxuICAgICAgJ0xpc3RDb25uZWN0b3JzJyxcbiAgICAgICdMaXN0Rmxvd3MnXG4gICAgXSxcbiAgICBUYWdnaW5nOiBbXG4gICAgICAnVGFnUmVzb3VyY2UnLFxuICAgICAgJ1VudGFnUmVzb3VyY2UnXG4gICAgXVxuICB9O1xuXG4gIC8qKlxuICAgKiBBZGRzIGEgcmVzb3VyY2Ugb2YgdHlwZSBjb25uZWN0b3Jwcm9maWxlIHRvIHRoZSBzdGF0ZW1lbnRcbiAgICpcbiAgICogaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2FwcGZsb3cvMS4wL0FQSVJlZmVyZW5jZS9BUElfQ29ubmVjdG9yUHJvZmlsZS5odG1sXG4gICAqXG4gICAqIEBwYXJhbSBwcm9maWxlTmFtZSAtIElkZW50aWZpZXIgZm9yIHRoZSBwcm9maWxlTmFtZS5cbiAgICogQHBhcmFtIGFjY291bnQgLSBBY2NvdW50IG9mIHRoZSByZXNvdXJjZTsgZGVmYXVsdHMgdG8gYCpgLCB1bmxlc3MgdXNpbmcgdGhlIENESywgd2hlcmUgdGhlIGRlZmF1bHQgaXMgdGhlIGN1cnJlbnQgU3RhY2sncyBhY2NvdW50LlxuICAgKiBAcGFyYW0gcmVnaW9uIC0gUmVnaW9uIG9mIHRoZSByZXNvdXJjZTsgZGVmYXVsdHMgdG8gYCpgLCB1bmxlc3MgdXNpbmcgdGhlIENESywgd2hlcmUgdGhlIGRlZmF1bHQgaXMgdGhlIGN1cnJlbnQgU3RhY2sncyByZWdpb24uXG4gICAqIEBwYXJhbSBwYXJ0aXRpb24gLSBQYXJ0aXRpb24gb2YgdGhlIEFXUyBhY2NvdW50IFthd3MsIGF3cy1jbiwgYXdzLXVzLWdvdl07IGRlZmF1bHRzIHRvIGBhd3NgLCB1bmxlc3MgdXNpbmcgdGhlIENESywgd2hlcmUgdGhlIGRlZmF1bHQgaXMgdGhlIGN1cnJlbnQgU3RhY2sncyBwYXJ0aXRpb24uXG4gICAqL1xuICBwdWJsaWMgb25Db25uZWN0b3Jwcm9maWxlKHByb2ZpbGVOYW1lOiBzdHJpbmcsIGFjY291bnQ/OiBzdHJpbmcsIHJlZ2lvbj86IHN0cmluZywgcGFydGl0aW9uPzogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMub24oYGFybjokeyBwYXJ0aXRpb24gPz8gdGhpcy5kZWZhdWx0UGFydGl0aW9uIH06YXBwZmxvdzokeyByZWdpb24gPz8gdGhpcy5kZWZhdWx0UmVnaW9uIH06JHsgYWNjb3VudCA/PyB0aGlzLmRlZmF1bHRBY2NvdW50IH06Y29ubmVjdG9ycHJvZmlsZS8keyBwcm9maWxlTmFtZSB9YCk7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhIHJlc291cmNlIG9mIHR5cGUgZmxvdyB0byB0aGUgc3RhdGVtZW50XG4gICAqXG4gICAqIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9hcHBmbG93LzEuMC9BUElSZWZlcmVuY2UvQVBJX0Zsb3dEZWZpbml0aW9uLmh0bWxcbiAgICpcbiAgICogQHBhcmFtIGZsb3dOYW1lIC0gSWRlbnRpZmllciBmb3IgdGhlIGZsb3dOYW1lLlxuICAgKiBAcGFyYW0gYWNjb3VudCAtIEFjY291bnQgb2YgdGhlIHJlc291cmNlOyBkZWZhdWx0cyB0byBgKmAsIHVubGVzcyB1c2luZyB0aGUgQ0RLLCB3aGVyZSB0aGUgZGVmYXVsdCBpcyB0aGUgY3VycmVudCBTdGFjaydzIGFjY291bnQuXG4gICAqIEBwYXJhbSByZWdpb24gLSBSZWdpb24gb2YgdGhlIHJlc291cmNlOyBkZWZhdWx0cyB0byBgKmAsIHVubGVzcyB1c2luZyB0aGUgQ0RLLCB3aGVyZSB0aGUgZGVmYXVsdCBpcyB0aGUgY3VycmVudCBTdGFjaydzIHJlZ2lvbi5cbiAgICogQHBhcmFtIHBhcnRpdGlvbiAtIFBhcnRpdGlvbiBvZiB0aGUgQVdTIGFjY291bnQgW2F3cywgYXdzLWNuLCBhd3MtdXMtZ292XTsgZGVmYXVsdHMgdG8gYGF3c2AsIHVubGVzcyB1c2luZyB0aGUgQ0RLLCB3aGVyZSB0aGUgZGVmYXVsdCBpcyB0aGUgY3VycmVudCBTdGFjaydzIHBhcnRpdGlvbi5cbiAgICpcbiAgICogUG9zc2libGUgY29uZGl0aW9uczpcbiAgICogLSAuaWZBd3NSZXNvdXJjZVRhZygpXG4gICAqL1xuICBwdWJsaWMgb25GbG93KGZsb3dOYW1lOiBzdHJpbmcsIGFjY291bnQ/OiBzdHJpbmcsIHJlZ2lvbj86IHN0cmluZywgcGFydGl0aW9uPzogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHRoaXMub24oYGFybjokeyBwYXJ0aXRpb24gPz8gdGhpcy5kZWZhdWx0UGFydGl0aW9uIH06YXBwZmxvdzokeyByZWdpb24gPz8gdGhpcy5kZWZhdWx0UmVnaW9uIH06JHsgYWNjb3VudCA/PyB0aGlzLmRlZmF1bHRBY2NvdW50IH06Zmxvdy8keyBmbG93TmFtZSB9YCk7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhIHJlc291cmNlIG9mIHR5cGUgY29ubmVjdG9yIHRvIHRoZSBzdGF0ZW1lbnRcbiAgICpcbiAgICogaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL2FwcGZsb3cvMS4wL0FQSVJlZmVyZW5jZS9BUElfQ29ubmVjdG9yRGV0YWlsLmh0bWxcbiAgICpcbiAgICogQHBhcmFtIGNvbm5lY3RvckxhYmVsIC0gSWRlbnRpZmllciBmb3IgdGhlIGNvbm5lY3RvckxhYmVsLlxuICAgKiBAcGFyYW0gYWNjb3VudCAtIEFjY291bnQgb2YgdGhlIHJlc291cmNlOyBkZWZhdWx0cyB0byBgKmAsIHVubGVzcyB1c2luZyB0aGUgQ0RLLCB3aGVyZSB0aGUgZGVmYXVsdCBpcyB0aGUgY3VycmVudCBTdGFjaydzIGFjY291bnQuXG4gICAqIEBwYXJhbSByZWdpb24gLSBSZWdpb24gb2YgdGhlIHJlc291cmNlOyBkZWZhdWx0cyB0byBgKmAsIHVubGVzcyB1c2luZyB0aGUgQ0RLLCB3aGVyZSB0aGUgZGVmYXVsdCBpcyB0aGUgY3VycmVudCBTdGFjaydzIHJlZ2lvbi5cbiAgICogQHBhcmFtIHBhcnRpdGlvbiAtIFBhcnRpdGlvbiBvZiB0aGUgQVdTIGFjY291bnQgW2F3cywgYXdzLWNuLCBhd3MtdXMtZ292XTsgZGVmYXVsdHMgdG8gYGF3c2AsIHVubGVzcyB1c2luZyB0aGUgQ0RLLCB3aGVyZSB0aGUgZGVmYXVsdCBpcyB0aGUgY3VycmVudCBTdGFjaydzIHBhcnRpdGlvbi5cbiAgICpcbiAgICogUG9zc2libGUgY29uZGl0aW9uczpcbiAgICogLSAuaWZBd3NSZXNvdXJjZVRhZygpXG4gICAqL1xuICBwdWJsaWMgb25Db25uZWN0b3IoY29ubmVjdG9yTGFiZWw6IHN0cmluZywgYWNjb3VudD86IHN0cmluZywgcmVnaW9uPzogc3RyaW5nLCBwYXJ0aXRpb24/OiBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5vbihgYXJuOiR7IHBhcnRpdGlvbiA/PyB0aGlzLmRlZmF1bHRQYXJ0aXRpb24gfTphcHBmbG93OiR7IHJlZ2lvbiA/PyB0aGlzLmRlZmF1bHRSZWdpb24gfTokeyBhY2NvdW50ID8/IHRoaXMuZGVmYXVsdEFjY291bnQgfTpjb25uZWN0b3IvJHsgY29ubmVjdG9yTGFiZWwgfWApO1xuICB9XG5cbiAgLyoqXG4gICAqIEZpbHRlcnMgYWNjZXNzIGJ5IGFsbG93ZWQgc2V0IG9mIHZhbHVlcyBmb3IgZWFjaCBvZiB0aGUgdGFnc1xuICAgKlxuICAgKiBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vSUFNL2xhdGVzdC9Vc2VyR3VpZGUvcmVmZXJlbmNlX3BvbGljaWVzX2NvbmRpdGlvbi1rZXlzLmh0bWwjY29uZGl0aW9uLWtleXMtcmVxdWVzdHRhZ1xuICAgKlxuICAgKiBBcHBsaWVzIHRvIGFjdGlvbnM6XG4gICAqIC0gLnRvQ3JlYXRlRmxvdygpXG4gICAqIC0gLnRvRGVsZXRlRmxvdygpXG4gICAqIC0gLnRvUmVnaXN0ZXJDb25uZWN0b3IoKVxuICAgKiAtIC50b1RhZ1Jlc291cmNlKClcbiAgICogLSAudG9VblJlZ2lzdGVyQ29ubmVjdG9yKClcbiAgICpcbiAgICogQHBhcmFtIHRhZ0tleSBUaGUgdGFnIGtleSB0byBjaGVja1xuICAgKiBAcGFyYW0gdmFsdWUgVGhlIHZhbHVlKHMpIHRvIGNoZWNrXG4gICAqIEBwYXJhbSBvcGVyYXRvciBXb3JrcyB3aXRoIFtzdHJpbmcgb3BlcmF0b3JzXShodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vSUFNL2xhdGVzdC9Vc2VyR3VpZGUvcmVmZXJlbmNlX3BvbGljaWVzX2VsZW1lbnRzX2NvbmRpdGlvbl9vcGVyYXRvcnMuaHRtbCNDb25kaXRpb25zX1N0cmluZykuICoqRGVmYXVsdDoqKiBgU3RyaW5nTGlrZWBcbiAgICovXG4gIHB1YmxpYyBpZkF3c1JlcXVlc3RUYWcodGFnS2V5OiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcgfCBzdHJpbmdbXSwgb3BlcmF0b3I/OiBPcGVyYXRvciB8IHN0cmluZykge1xuICAgIHJldHVybiB0aGlzLmlmKGBhd3M6UmVxdWVzdFRhZy8keyB0YWdLZXkgfWAsIHZhbHVlLCBvcGVyYXRvciA/PyAnU3RyaW5nTGlrZScpO1xuICB9XG5cbiAgLyoqXG4gICAqIEZpbHRlcnMgYWNjZXNzIGJ5IHRhZy12YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIHJlc291cmNlXG4gICAqXG4gICAqIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9JQU0vbGF0ZXN0L1VzZXJHdWlkZS9yZWZlcmVuY2VfcG9saWNpZXNfY29uZGl0aW9uLWtleXMuaHRtbCNjb25kaXRpb24ta2V5cy1yZXNvdXJjZXRhZ1xuICAgKlxuICAgKiBBcHBsaWVzIHRvIHJlc291cmNlIHR5cGVzOlxuICAgKiAtIGZsb3dcbiAgICogLSBjb25uZWN0b3JcbiAgICpcbiAgICogQHBhcmFtIHRhZ0tleSBUaGUgdGFnIGtleSB0byBjaGVja1xuICAgKiBAcGFyYW0gdmFsdWUgVGhlIHZhbHVlKHMpIHRvIGNoZWNrXG4gICAqIEBwYXJhbSBvcGVyYXRvciBXb3JrcyB3aXRoIFtzdHJpbmcgb3BlcmF0b3JzXShodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vSUFNL2xhdGVzdC9Vc2VyR3VpZGUvcmVmZXJlbmNlX3BvbGljaWVzX2VsZW1lbnRzX2NvbmRpdGlvbl9vcGVyYXRvcnMuaHRtbCNDb25kaXRpb25zX1N0cmluZykuICoqRGVmYXVsdDoqKiBgU3RyaW5nTGlrZWBcbiAgICovXG4gIHB1YmxpYyBpZkF3c1Jlc291cmNlVGFnKHRhZ0tleTogc3RyaW5nLCB2YWx1ZTogc3RyaW5nIHwgc3RyaW5nW10sIG9wZXJhdG9yPzogT3BlcmF0b3IgfCBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5pZihgYXdzOlJlc291cmNlVGFnLyR7IHRhZ0tleSB9YCwgdmFsdWUsIG9wZXJhdG9yID8/ICdTdHJpbmdMaWtlJyk7XG4gIH1cblxuICAvKipcbiAgICogRmlsdGVycyBhY2Nlc3MgYnkgcHJlc2VuY2Ugb2YgbWFuZGF0b3J5IHRhZ3MgaW4gdGhlIHJlcXVlc3RcbiAgICpcbiAgICogaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0lBTS9sYXRlc3QvVXNlckd1aWRlL3JlZmVyZW5jZV9wb2xpY2llc19jb25kaXRpb24ta2V5cy5odG1sI2NvbmRpdGlvbi1rZXlzLXRhZ2tleXNcbiAgICpcbiAgICogQXBwbGllcyB0byBhY3Rpb25zOlxuICAgKiAtIC50b0NyZWF0ZUZsb3coKVxuICAgKiAtIC50b0RlbGV0ZUZsb3coKVxuICAgKiAtIC50b1JlZ2lzdGVyQ29ubmVjdG9yKClcbiAgICogLSAudG9UYWdSZXNvdXJjZSgpXG4gICAqIC0gLnRvVW5SZWdpc3RlckNvbm5lY3RvcigpXG4gICAqIC0gLnRvVW50YWdSZXNvdXJjZSgpXG4gICAqXG4gICAqIEBwYXJhbSB2YWx1ZSBUaGUgdmFsdWUocykgdG8gY2hlY2tcbiAgICogQHBhcmFtIG9wZXJhdG9yIFdvcmtzIHdpdGggW3N0cmluZyBvcGVyYXRvcnNdKGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9JQU0vbGF0ZXN0L1VzZXJHdWlkZS9yZWZlcmVuY2VfcG9saWNpZXNfZWxlbWVudHNfY29uZGl0aW9uX29wZXJhdG9ycy5odG1sI0NvbmRpdGlvbnNfU3RyaW5nKS4gKipEZWZhdWx0OioqIGBTdHJpbmdMaWtlYFxuICAgKi9cbiAgcHVibGljIGlmQXdzVGFnS2V5cyh2YWx1ZTogc3RyaW5nIHwgc3RyaW5nW10sIG9wZXJhdG9yPzogT3BlcmF0b3IgfCBzdHJpbmcpIHtcbiAgICByZXR1cm4gdGhpcy5pZihgYXdzOlRhZ0tleXNgLCB2YWx1ZSwgb3BlcmF0b3IgPz8gJ1N0cmluZ0xpa2UnKTtcbiAgfVxufVxuIl19