terraconstructs 0.0.23 → 0.0.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (266) hide show
  1. package/.jsii +61226 -46941
  2. package/go.mod +10 -7
  3. package/go.sum +20 -14
  4. package/lib/aws/arn.js +1 -1
  5. package/lib/aws/aws-construct.js +1 -1
  6. package/lib/aws/aws-stack.js +1 -1
  7. package/lib/aws/aws-tags.js +2 -2
  8. package/lib/aws/cloudwatch/actions/ec2.js +1 -1
  9. package/lib/aws/cloudwatch/actions/lambda.js +1 -1
  10. package/lib/aws/cloudwatch/alarm-base.js +1 -1
  11. package/lib/aws/cloudwatch/alarm-rule.js +1 -1
  12. package/lib/aws/cloudwatch/alarm-status-widget.js +1 -1
  13. package/lib/aws/cloudwatch/alarm.js +4 -5
  14. package/lib/aws/cloudwatch/composite-alarm.js +1 -1
  15. package/lib/aws/cloudwatch/dashboard.js +1 -1
  16. package/lib/aws/cloudwatch/data-protection-policy.js +5 -5
  17. package/lib/aws/cloudwatch/graph.js +8 -8
  18. package/lib/aws/cloudwatch/layout.js +3 -3
  19. package/lib/aws/cloudwatch/log-destinations/kinesis.js +1 -1
  20. package/lib/aws/cloudwatch/log-destinations/lambda.js +1 -1
  21. package/lib/aws/cloudwatch/log-group.js +3 -3
  22. package/lib/aws/cloudwatch/log-query.js +1 -1
  23. package/lib/aws/cloudwatch/log-stream.js +1 -1
  24. package/lib/aws/cloudwatch/metric-filter.js +1 -1
  25. package/lib/aws/cloudwatch/metric.js +4 -4
  26. package/lib/aws/cloudwatch/pattern.js +3 -3
  27. package/lib/aws/cloudwatch/policy.js +1 -1
  28. package/lib/aws/cloudwatch/private/metric-util.js +1 -2
  29. package/lib/aws/cloudwatch/query-definition.js +2 -2
  30. package/lib/aws/cloudwatch/stats.js +1 -1
  31. package/lib/aws/cloudwatch/subscription-filter.js +1 -1
  32. package/lib/aws/cloudwatch/text.js +1 -1
  33. package/lib/aws/cloudwatch/variable.js +3 -3
  34. package/lib/aws/cloudwatch/widget.js +1 -1
  35. package/lib/aws/compute/activity.js +1 -1
  36. package/lib/aws/compute/alb/application-listener-action.js +1 -1
  37. package/lib/aws/compute/alb/application-listener-certificate.js +1 -1
  38. package/lib/aws/compute/alb/application-listener-rule.js +1 -1
  39. package/lib/aws/compute/alb/application-listener.js +2 -4
  40. package/lib/aws/compute/alb/application-load-balancer.js +2 -4
  41. package/lib/aws/compute/alb/application-target-group.js +1 -1
  42. package/lib/aws/compute/alb/conditions.js +1 -1
  43. package/lib/aws/compute/alb/trust-store-revocation.js +1 -1
  44. package/lib/aws/compute/alb/trust-store.js +1 -1
  45. package/lib/aws/compute/architecture.js +1 -1
  46. package/lib/aws/compute/aspects/require-imdsv2-aspect.js +2 -2
  47. package/lib/aws/compute/autoscaling-common/index.d.ts +3 -0
  48. package/lib/aws/compute/autoscaling-common/index.js +21 -0
  49. package/lib/aws/compute/autoscaling-common/interval-utils.d.ts +21 -0
  50. package/lib/aws/compute/autoscaling-common/interval-utils.js +213 -0
  51. package/lib/aws/compute/autoscaling-common/test-utils.d.ts +21 -0
  52. package/lib/aws/compute/autoscaling-common/test-utils.js +94 -0
  53. package/lib/aws/compute/autoscaling-common/types.d.ts +34 -0
  54. package/lib/aws/compute/autoscaling-common/types.js +3 -0
  55. package/lib/aws/compute/base-scalable-attribute.d.ts +74 -0
  56. package/lib/aws/compute/base-scalable-attribute.js +58 -0
  57. package/lib/aws/compute/bastion-host.js +1 -1
  58. package/lib/aws/compute/chain.js +1 -1
  59. package/lib/aws/compute/client-vpn-authorization-rule.js +1 -1
  60. package/lib/aws/compute/client-vpn-endpoint.js +2 -2
  61. package/lib/aws/compute/client-vpn-route.js +2 -2
  62. package/lib/aws/compute/condition.js +1 -1
  63. package/lib/aws/compute/connections.js +1 -1
  64. package/lib/aws/compute/ec2-util.js +1 -4
  65. package/lib/aws/compute/event-invoke-config.js +1 -1
  66. package/lib/aws/compute/event-source-filter.js +2 -2
  67. package/lib/aws/compute/event-source-mapping.js +3 -3
  68. package/lib/aws/compute/event-sources/s3-onfailure-destination.js +1 -1
  69. package/lib/aws/compute/event-sources/s3.js +1 -1
  70. package/lib/aws/compute/event-sources/sqs-dlq.js +1 -1
  71. package/lib/aws/compute/event-sources/sqs.js +1 -1
  72. package/lib/aws/compute/fields.js +4 -4
  73. package/lib/aws/compute/function-alias.js +1 -1
  74. package/lib/aws/compute/function-base.js +7 -8
  75. package/lib/aws/compute/function-destinations/event-bridge.js +3 -3
  76. package/lib/aws/compute/function-destinations/function.js +1 -1
  77. package/lib/aws/compute/function-destinations/sqs.js +1 -1
  78. package/lib/aws/compute/function-nodejs.js +1 -1
  79. package/lib/aws/compute/function-url.js +1 -1
  80. package/lib/aws/compute/function.js +1 -1
  81. package/lib/aws/compute/index.d.ts +7 -0
  82. package/lib/aws/compute/index.js +11 -2
  83. package/lib/aws/compute/instance-types.js +1 -1
  84. package/lib/aws/compute/instance.js +1 -1
  85. package/lib/aws/compute/ip-addresses.js +2 -2
  86. package/lib/aws/compute/ipam.js +1 -1
  87. package/lib/aws/compute/key-pair.js +1 -1
  88. package/lib/aws/compute/launch-template.js +2 -2
  89. package/lib/aws/compute/lb-shared/base-listener.js +1 -1
  90. package/lib/aws/compute/lb-shared/base-load-balancer.js +2 -2
  91. package/lib/aws/compute/lb-shared/base-target-group.js +1 -1
  92. package/lib/aws/compute/lb-shared/listener-certificate.js +1 -1
  93. package/lib/aws/compute/lb-shared/load-balancer-targets.js +2 -2
  94. package/lib/aws/compute/lb-shared/util.js +1 -2
  95. package/lib/aws/compute/lb-targets/alb-target.js +3 -3
  96. package/lib/aws/compute/lb-targets/instance-target.js +2 -2
  97. package/lib/aws/compute/lb-targets/ip-target.js +1 -1
  98. package/lib/aws/compute/lb-targets/lambda-target.js +1 -1
  99. package/lib/aws/compute/load-balancer.js +3 -3
  100. package/lib/aws/compute/machine-image/amazon-linux-2022.js +2 -2
  101. package/lib/aws/compute/machine-image/amazon-linux-2023.js +2 -2
  102. package/lib/aws/compute/machine-image/amazon-linux2.js +2 -2
  103. package/lib/aws/compute/machine-image/common.js +1 -1
  104. package/lib/aws/compute/machine-image/machine-image.js +8 -8
  105. package/lib/aws/compute/machine-image/utils.js +6 -6
  106. package/lib/aws/compute/nat.js +5 -5
  107. package/lib/aws/compute/network-acl-types.js +2 -2
  108. package/lib/aws/compute/network-acl.js +3 -3
  109. package/lib/aws/compute/nlb/network-listener-action.js +1 -1
  110. package/lib/aws/compute/nlb/network-listener.js +2 -3
  111. package/lib/aws/compute/nlb/network-load-balancer.js +1 -1
  112. package/lib/aws/compute/nlb/network-target-group.js +1 -1
  113. package/lib/aws/compute/peer.js +1 -1
  114. package/lib/aws/compute/placement-group.js +1 -1
  115. package/lib/aws/compute/port.js +1 -1
  116. package/lib/aws/compute/prefix-list.js +1 -1
  117. package/lib/aws/compute/private/context-stub.js +2 -2
  118. package/lib/aws/compute/route.js +11 -11
  119. package/lib/aws/compute/scalable-target.d.ts +197 -0
  120. package/lib/aws/compute/scalable-target.js +168 -0
  121. package/lib/aws/compute/schedule.d.ts +81 -0
  122. package/lib/aws/compute/schedule.js +145 -0
  123. package/lib/aws/compute/security-group.js +4 -4
  124. package/lib/aws/compute/state-graph.js +1 -1
  125. package/lib/aws/compute/state-machine-fragment.js +1 -1
  126. package/lib/aws/compute/state-machine.js +4 -4
  127. package/lib/aws/compute/states/choice.js +1 -1
  128. package/lib/aws/compute/states/custom-state.js +1 -1
  129. package/lib/aws/compute/states/distributed-map/item-batcher.js +1 -1
  130. package/lib/aws/compute/states/distributed-map/item-reader.js +7 -7
  131. package/lib/aws/compute/states/distributed-map/result-writer.js +1 -1
  132. package/lib/aws/compute/states/distributed-map.js +4 -4
  133. package/lib/aws/compute/states/fail.js +1 -1
  134. package/lib/aws/compute/states/map-base.js +1 -1
  135. package/lib/aws/compute/states/map.js +1 -1
  136. package/lib/aws/compute/states/parallel.js +1 -1
  137. package/lib/aws/compute/states/pass.js +2 -2
  138. package/lib/aws/compute/states/state.js +1 -1
  139. package/lib/aws/compute/states/succeed.js +1 -1
  140. package/lib/aws/compute/states/task-base.js +2 -2
  141. package/lib/aws/compute/states/task.js +1 -1
  142. package/lib/aws/compute/states/wait.js +2 -2
  143. package/lib/aws/compute/step-scaling-action.d.ts +148 -0
  144. package/lib/aws/compute/step-scaling-action.js +109 -0
  145. package/lib/aws/compute/step-scaling-policy.d.ts +132 -0
  146. package/lib/aws/compute/step-scaling-policy.js +153 -0
  147. package/lib/aws/compute/subnet-v2.js +2 -2
  148. package/lib/aws/compute/subnet.js +1 -1
  149. package/lib/aws/compute/target-tracking-scaling-policy.d.ts +262 -0
  150. package/lib/aws/compute/target-tracking-scaling-policy.js +234 -0
  151. package/lib/aws/compute/task-credentials.js +1 -1
  152. package/lib/aws/compute/task-input.js +1 -1
  153. package/lib/aws/compute/tasks/aws-sdk/call-aws-service.js +1 -1
  154. package/lib/aws/compute/tasks/eventbridge/put-events.js +1 -1
  155. package/lib/aws/compute/tasks/http/invoke.js +1 -1
  156. package/lib/aws/compute/tasks/lambda/invoke.js +1 -1
  157. package/lib/aws/compute/tasks/sqs/send-message.js +1 -1
  158. package/lib/aws/compute/tasks/stepfunctions/invoke-activity.js +1 -1
  159. package/lib/aws/compute/tasks/stepfunctions/start-execution.js +1 -1
  160. package/lib/aws/compute/types.js +1 -1
  161. package/lib/aws/compute/user-data.js +3 -3
  162. package/lib/aws/compute/volume.js +2 -2
  163. package/lib/aws/compute/vpc-endpoint-service.js +1 -1
  164. package/lib/aws/compute/vpc-endpoint.js +6 -6
  165. package/lib/aws/compute/vpc-flow-logs.js +4 -4
  166. package/lib/aws/compute/vpc-v2-base.js +1 -1
  167. package/lib/aws/compute/vpc-v2.js +2 -2
  168. package/lib/aws/compute/vpc.d.ts +1 -1
  169. package/lib/aws/compute/vpc.js +10 -16
  170. package/lib/aws/compute/vpn.js +4 -7
  171. package/lib/aws/compute/windows-versions.js +1 -2
  172. package/lib/aws/edge/certificate.js +1 -1
  173. package/lib/aws/edge/distribution.js +4 -5
  174. package/lib/aws/edge/dns-alias-record-targets.js +3 -3
  175. package/lib/aws/edge/dns-record.js +13 -13
  176. package/lib/aws/edge/dns-zone.js +1 -1
  177. package/lib/aws/edge/function.js +2 -2
  178. package/lib/aws/edge/key-value-store.js +4 -4
  179. package/lib/aws/edge/origin.js +3 -3
  180. package/lib/aws/edge/response-headers-policy.js +1 -1
  181. package/lib/aws/encryption/alias.js +1 -1
  182. package/lib/aws/encryption/key.js +1 -1
  183. package/lib/aws/encryption/via-service-principal.js +1 -1
  184. package/lib/aws/iam/grant.js +3 -4
  185. package/lib/aws/iam/group.js +1 -1
  186. package/lib/aws/iam/instance-profile.js +1 -1
  187. package/lib/aws/iam/managed-policy.js +1 -1
  188. package/lib/aws/iam/oidc-provider.js +3 -3
  189. package/lib/aws/iam/policy-document.js +1 -1
  190. package/lib/aws/iam/policy-statement.js +1 -1
  191. package/lib/aws/iam/policy.js +1 -1
  192. package/lib/aws/iam/principals.js +20 -20
  193. package/lib/aws/iam/role.js +1 -1
  194. package/lib/aws/iam/saml-provider.js +2 -2
  195. package/lib/aws/iam/unknown-principal.js +1 -1
  196. package/lib/aws/iam/user.js +1 -1
  197. package/lib/aws/network/simple-ipv4-vpc.js +1 -1
  198. package/lib/aws/network/subnet-group.js +3 -3
  199. package/lib/aws/network/subnet.js +4 -4
  200. package/lib/aws/notify/archive.js +1 -1
  201. package/lib/aws/notify/connection.js +7 -7
  202. package/lib/aws/notify/event-bus.js +3 -3
  203. package/lib/aws/notify/event-pattern.js +1 -1
  204. package/lib/aws/notify/input.js +2 -2
  205. package/lib/aws/notify/kinesis-stream.js +1 -1
  206. package/lib/aws/notify/notification-rule.js +1 -1
  207. package/lib/aws/notify/policy.js +1 -1
  208. package/lib/aws/notify/queue-policy.js +1 -1
  209. package/lib/aws/notify/queue.js +1 -1
  210. package/lib/aws/notify/resource-policy.js +1 -1
  211. package/lib/aws/notify/rule.js +1 -1
  212. package/lib/aws/notify/schedule.js +1 -1
  213. package/lib/aws/notify/subscription-filter.js +1 -1
  214. package/lib/aws/notify/subscription.js +4 -4
  215. package/lib/aws/notify/subscriptions/email.js +1 -1
  216. package/lib/aws/notify/subscriptions/lambda.js +1 -1
  217. package/lib/aws/notify/subscriptions/sms.js +1 -1
  218. package/lib/aws/notify/subscriptions/sqs.js +1 -1
  219. package/lib/aws/notify/subscriptions/url.js +1 -1
  220. package/lib/aws/notify/targets/event-bus.js +1 -1
  221. package/lib/aws/notify/targets/function.js +1 -1
  222. package/lib/aws/notify/targets/log-group.js +2 -2
  223. package/lib/aws/notify/targets/sqs.js +3 -3
  224. package/lib/aws/notify/targets/state-machine.js +1 -1
  225. package/lib/aws/notify/targets/util.js +2 -2
  226. package/lib/aws/notify/topic-base.js +1 -1
  227. package/lib/aws/notify/topic.js +1 -1
  228. package/lib/aws/storage/billing.d.ts +62 -0
  229. package/lib/aws/storage/billing.js +49 -0
  230. package/lib/aws/storage/bucket-notifications.js +1 -1
  231. package/lib/aws/storage/bucket-policy.js +1 -1
  232. package/lib/aws/storage/bucket-source.js +3 -3
  233. package/lib/aws/storage/bucket.js +2 -2
  234. package/lib/aws/storage/capacity.d.ts +96 -0
  235. package/lib/aws/storage/capacity.js +103 -0
  236. package/lib/aws/storage/dynamodb-canned-metrics.generated.d.ts +493 -0
  237. package/lib/aws/storage/dynamodb-canned-metrics.generated.js +263 -0
  238. package/lib/aws/storage/dynamodb-perms.d.ts +8 -0
  239. package/lib/aws/storage/dynamodb-perms.js +45 -0
  240. package/lib/aws/storage/encryption.d.ts +54 -0
  241. package/lib/aws/storage/encryption.js +116 -0
  242. package/lib/aws/storage/index.d.ts +6 -0
  243. package/lib/aws/storage/index.js +10 -1
  244. package/lib/aws/storage/notification-targets/function.js +1 -1
  245. package/lib/aws/storage/notification-targets/queue.js +1 -1
  246. package/lib/aws/storage/origin-access-identity.js +1 -1
  247. package/lib/aws/storage/parameter.js +2 -2
  248. package/lib/aws/storage/scalable-attribute-api.d.ts +36 -0
  249. package/lib/aws/storage/scalable-attribute-api.js +3 -0
  250. package/lib/aws/storage/scalable-table-attribute.d.ts +32 -0
  251. package/lib/aws/storage/scalable-table-attribute.js +48 -0
  252. package/lib/aws/storage/shared.d.ts +419 -0
  253. package/lib/aws/storage/shared.js +161 -0
  254. package/lib/aws/storage/table.d.ts +536 -0
  255. package/lib/aws/storage/table.js +1054 -0
  256. package/lib/construct-base.js +2 -2
  257. package/lib/duration.js +1 -1
  258. package/lib/expiration.js +1 -1
  259. package/lib/index.d.ts +1 -0
  260. package/lib/index.js +2 -1
  261. package/lib/size.js +1 -1
  262. package/lib/stack-base.js +1 -1
  263. package/lib/terra-func.js +1 -1
  264. package/lib/time-zone.d.ts +724 -0
  265. package/lib/time-zone.js +737 -0
  266. package/package.json +2 -1
@@ -0,0 +1,1054 @@
1
+ "use strict";
2
+ var _a, _b, _c;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.Table = exports.TableBase = exports.ApproximateCreationDateTimePrecision = exports.InputFormat = exports.InputCompressionType = void 0;
5
+ const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
6
+ // https://github.com/aws/aws-cdk/blob/v2.186.0/packages/aws-cdk-lib/aws-dynamodb/lib/table.ts
7
+ const provider_aws_1 = require("@cdktf/provider-aws");
8
+ const cdktf_1 = require("cdktf");
9
+ const __1 = require("..");
10
+ const dynamodb_canned_metrics_generated_1 = require("./dynamodb-canned-metrics.generated");
11
+ const perms = require("./dynamodb-perms");
12
+ const scalable_table_attribute_1 = require("./scalable-table-attribute");
13
+ const shared_1 = require("./shared");
14
+ const cloudwatch = require("../cloudwatch");
15
+ const appscaling = require("../compute");
16
+ const kms = require("../encryption");
17
+ const iam = require("../iam");
18
+ // Missing in Terraform DynamoDb Replica Configuration block
19
+ // https://registry.terraform.io/providers/hashicorp/aws/5.88.0/docs/resources/dynamodb_table#replica
20
+ // import { Duration } from "../../duration";
21
+ // TODO Adopt UnscopedValidationError, ValidationError when available:
22
+ // - https://github.com/aws/aws-cdk/pull/33382/
23
+ // - https://github.com/aws/aws-cdk/pull/33045
24
+ // import {
25
+ // UnscopedValidationError,
26
+ // ValidationError,
27
+ // } from "../../core/lib/errors";
28
+ const HASH_KEY_TYPE = "HASH";
29
+ const RANGE_KEY_TYPE = "RANGE";
30
+ const MAX_LOCAL_SECONDARY_INDEX_COUNT = 5;
31
+ /**
32
+ * Type of compression to use for imported data.
33
+ */
34
+ var InputCompressionType;
35
+ (function (InputCompressionType) {
36
+ /**
37
+ * GZIP compression.
38
+ */
39
+ InputCompressionType["GZIP"] = "GZIP";
40
+ /**
41
+ * ZSTD compression.
42
+ */
43
+ InputCompressionType["ZSTD"] = "ZSTD";
44
+ /**
45
+ * No compression.
46
+ */
47
+ InputCompressionType["NONE"] = "NONE";
48
+ })(InputCompressionType || (exports.InputCompressionType = InputCompressionType = {}));
49
+ /**
50
+ * The format of the source data.
51
+ */
52
+ class InputFormat {
53
+ /**
54
+ * DynamoDB JSON format.
55
+ */
56
+ static dynamoDBJson() {
57
+ return new (class extends InputFormat {
58
+ _render() {
59
+ return {
60
+ inputFormat: "DYNAMODB_JSON",
61
+ };
62
+ }
63
+ })();
64
+ }
65
+ /**
66
+ * Amazon Ion format.
67
+ */
68
+ static ion() {
69
+ return new (class extends InputFormat {
70
+ _render() {
71
+ return {
72
+ inputFormat: "ION",
73
+ };
74
+ }
75
+ })();
76
+ }
77
+ /**
78
+ * CSV format.
79
+ */
80
+ static csv(options) {
81
+ if (options?.delimiter &&
82
+ (!this.validCsvDelimiters.includes(options.delimiter) ||
83
+ options.delimiter.length !== 1)) {
84
+ // throw new UnscopedValidationError(
85
+ throw new Error([
86
+ "Delimiter must be a single character and one of the following:",
87
+ `${this.readableValidCsvDelimiters.join(", ")},`,
88
+ `got '${options.delimiter}'`,
89
+ ].join(" "));
90
+ }
91
+ return new (class extends InputFormat {
92
+ _render() {
93
+ return {
94
+ inputFormat: "CSV",
95
+ inputFormatOptions: options
96
+ ? {
97
+ csv: {
98
+ delimiter: options?.delimiter,
99
+ headerList: options?.headerList,
100
+ },
101
+ }
102
+ : undefined,
103
+ };
104
+ }
105
+ })();
106
+ }
107
+ }
108
+ exports.InputFormat = InputFormat;
109
+ _a = JSII_RTTI_SYMBOL_1;
110
+ InputFormat[_a] = { fqn: "terraconstructs.aws.storage.InputFormat", version: "0.0.25" };
111
+ InputFormat.validCsvDelimiters = [",", "\t", ":", ";", "|", " "];
112
+ InputFormat.readableValidCsvDelimiters = [
113
+ "comma (,)",
114
+ "tab (\\t)",
115
+ "colon (:)",
116
+ "semicolon (;)",
117
+ "pipe (|)",
118
+ "space ( )",
119
+ ];
120
+ /**
121
+ * The precision associated with the DynamoDB write timestamps that will be replicated to Kinesis.
122
+ * The default setting for record timestamp precision is microseconds. You can change this setting at any time.
123
+ * @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-kinesisstreamspecification.html#aws-properties-dynamodb-table-kinesisstreamspecification-properties
124
+ */
125
+ var ApproximateCreationDateTimePrecision;
126
+ (function (ApproximateCreationDateTimePrecision) {
127
+ /**
128
+ * Millisecond precision
129
+ */
130
+ ApproximateCreationDateTimePrecision["MILLISECOND"] = "MILLISECOND";
131
+ /**
132
+ * Microsecond precision
133
+ */
134
+ ApproximateCreationDateTimePrecision["MICROSECOND"] = "MICROSECOND";
135
+ })(ApproximateCreationDateTimePrecision || (exports.ApproximateCreationDateTimePrecision = ApproximateCreationDateTimePrecision = {}));
136
+ class TableBase extends __1.AwsConstructBase {
137
+ constructor() {
138
+ super(...arguments);
139
+ this.regionalArns = new Array();
140
+ }
141
+ get outputs() {
142
+ return {
143
+ tableArn: this.tableArn,
144
+ tableName: this.tableName,
145
+ tableStreamArn: this.tableStreamArn,
146
+ };
147
+ }
148
+ grant(grantee, ...actions) {
149
+ const resources = [
150
+ this.tableArn,
151
+ cdktf_1.Lazy.stringValue({
152
+ produce: () => (this.hasIndex ? `${this.tableArn}/index/*` : undefined),
153
+ }),
154
+ ...this.regionalArns,
155
+ ...this.regionalArns.map((arn) => cdktf_1.Lazy.stringValue({
156
+ produce: () => (this.hasIndex ? `${arn}/index/*` : undefined),
157
+ })),
158
+ ];
159
+ return iam.Grant.addToPrincipalOrResource({
160
+ grantee,
161
+ actions,
162
+ resourceArns: resources.filter((r) => r !== undefined),
163
+ resource: this, // Grant will take the principal from the grantee
164
+ });
165
+ }
166
+ grantStream(grantee, ...actions) {
167
+ if (!this.tableStreamArn) {
168
+ // throw new ValidationError(
169
+ throw new Error(`DynamoDB Streams must be enabled on the table ${this.node.path}`);
170
+ }
171
+ return iam.Grant.addToPrincipal({
172
+ grantee,
173
+ actions,
174
+ resourceArns: [this.tableStreamArn],
175
+ scope: this,
176
+ });
177
+ }
178
+ grantReadData(grantee) {
179
+ const tableActions = perms.READ_DATA_ACTIONS_TABLE_SAFE.concat(perms.DESCRIBE_TABLE);
180
+ // If streams are available, also grant stream-specific actions
181
+ if (this.tableStreamArn) {
182
+ return this.combinedGrant(grantee, {
183
+ keyActions: perms.KEY_READ_ACTIONS,
184
+ tableActions,
185
+ streamActions: perms.READ_DATA_ACTIONS_STREAM_ONLY,
186
+ });
187
+ }
188
+ return this.combinedGrant(grantee, {
189
+ keyActions: perms.KEY_READ_ACTIONS,
190
+ tableActions,
191
+ });
192
+ }
193
+ grantTableListStreams(grantee) {
194
+ if (!this.tableStreamArn) {
195
+ // throw new ValidationError(
196
+ throw new Error(`DynamoDB Streams must be enabled on the table ${this.node.path}`);
197
+ }
198
+ return iam.Grant.addToPrincipal({
199
+ grantee,
200
+ actions: ["dynamodb:ListStreams"],
201
+ resourceArns: ["*"],
202
+ });
203
+ }
204
+ grantStreamRead(grantee) {
205
+ this.grantTableListStreams(grantee);
206
+ return this.combinedGrant(grantee, {
207
+ keyActions: perms.KEY_READ_ACTIONS,
208
+ streamActions: perms.READ_STREAM_DATA_ACTIONS,
209
+ });
210
+ }
211
+ grantWriteData(grantee) {
212
+ const tableActions = perms.WRITE_DATA_ACTIONS.concat(perms.DESCRIBE_TABLE);
213
+ const keyActions = perms.KEY_READ_ACTIONS.concat(perms.KEY_WRITE_ACTIONS);
214
+ return this.combinedGrant(grantee, { keyActions, tableActions });
215
+ }
216
+ grantReadWriteData(grantee) {
217
+ const tableActions = perms.READ_DATA_ACTIONS.concat(perms.WRITE_DATA_ACTIONS).concat(perms.DESCRIBE_TABLE);
218
+ const keyActions = perms.KEY_READ_ACTIONS.concat(perms.KEY_WRITE_ACTIONS);
219
+ return this.combinedGrant(grantee, { keyActions, tableActions });
220
+ }
221
+ grantFullAccess(grantee) {
222
+ const keyActions = perms.KEY_READ_ACTIONS.concat(perms.KEY_WRITE_ACTIONS);
223
+ return this.combinedGrant(grantee, {
224
+ keyActions,
225
+ tableActions: ["dynamodb:*"],
226
+ });
227
+ }
228
+ addToResourcePolicy(statement) {
229
+ if (!this.resourcePolicy) {
230
+ // ensure a policy exists and is associated with the table
231
+ this.resourcePolicy = new iam.PolicyDocument(this, "Policy", {
232
+ statement: [],
233
+ });
234
+ new provider_aws_1.dynamodbResourcePolicy.DynamodbResourcePolicy(this, "PolicyAttachment", {
235
+ policy: this.resourcePolicy.json,
236
+ resourceArn: this.tableArn,
237
+ });
238
+ }
239
+ this.resourcePolicy.addStatements(statement);
240
+ return {
241
+ statementAdded: true,
242
+ policyDependable: this,
243
+ };
244
+ }
245
+ metric(metricName, props) {
246
+ return new cloudwatch.Metric({
247
+ namespace: "AWS/DynamoDB",
248
+ metricName,
249
+ dimensionsMap: {
250
+ TableName: this.tableName,
251
+ },
252
+ ...props,
253
+ }).attachTo(this);
254
+ }
255
+ metricConsumedReadCapacityUnits(props) {
256
+ return this.cannedMetric(dynamodb_canned_metrics_generated_1.DynamoDBMetrics.consumedReadCapacityUnitsSum, props);
257
+ }
258
+ metricConsumedWriteCapacityUnits(props) {
259
+ return this.cannedMetric(dynamodb_canned_metrics_generated_1.DynamoDBMetrics.consumedWriteCapacityUnitsSum, props);
260
+ }
261
+ /** @deprecated use `metricSystemErrorsForOperations`. */
262
+ metricSystemErrors(props) {
263
+ if (!props?.dimensionsMap?.Operation) {
264
+ // 'Operation' must be passed because its an operational metric.
265
+ // throw new ValidationError(
266
+ throw new Error("'Operation' dimension must be passed for the 'SystemErrors' metric.");
267
+ }
268
+ const dimensionsMap = {
269
+ TableName: this.tableName,
270
+ ...props?.dimensionsMap,
271
+ };
272
+ return this.metric("SystemErrors", {
273
+ statistic: "sum",
274
+ ...props,
275
+ dimensionsMap,
276
+ });
277
+ }
278
+ metricUserErrors(props) {
279
+ if (props?.dimensionsMap) {
280
+ // throw new ValidationError(
281
+ throw new Error("'dimensionsMap' is not supported for the 'UserErrors' metric");
282
+ }
283
+ return this.metric("UserErrors", {
284
+ statistic: "sum",
285
+ ...props,
286
+ dimensionsMap: {},
287
+ });
288
+ }
289
+ metricConditionalCheckFailedRequests(props) {
290
+ return this.metric("ConditionalCheckFailedRequests", {
291
+ statistic: "sum",
292
+ ...props,
293
+ });
294
+ }
295
+ /** @deprecated Do not use this function. It returns an invalid metric. Use `metricThrottledRequestsForOperation` instead. */
296
+ metricThrottledRequests(props) {
297
+ return this.metric("ThrottledRequests", { statistic: "sum", ...props });
298
+ }
299
+ metricSuccessfulRequestLatency(props) {
300
+ if (!props?.dimensionsMap?.Operation) {
301
+ // throw new ValidationError(
302
+ throw new Error("'Operation' dimension must be passed for the 'SuccessfulRequestLatency' metric.");
303
+ }
304
+ const dimensionsMap = {
305
+ TableName: this.tableName,
306
+ Operation: props.dimensionsMap.Operation,
307
+ };
308
+ return new cloudwatch.Metric({
309
+ ...dynamodb_canned_metrics_generated_1.DynamoDBMetrics.successfulRequestLatencyAverage(dimensionsMap),
310
+ ...props,
311
+ dimensionsMap,
312
+ }).attachTo(this);
313
+ }
314
+ metricThrottledRequestsForOperation(operation, props) {
315
+ return new cloudwatch.Metric({
316
+ ...dynamodb_canned_metrics_generated_1.DynamoDBMetrics.throttledRequestsSum({
317
+ Operation: operation,
318
+ TableName: this.tableName,
319
+ }),
320
+ ...props,
321
+ }).attachTo(this);
322
+ }
323
+ metricThrottledRequestsForOperations(props) {
324
+ return this.sumMetricsForOperations("ThrottledRequests", "Sum of throttled requests across all operations", props);
325
+ }
326
+ metricSystemErrorsForOperations(props) {
327
+ return this.sumMetricsForOperations("SystemErrors", "Sum of errors across all operations", props);
328
+ }
329
+ sumMetricsForOperations(metricName, expressionLabel, props) {
330
+ if (props?.dimensionsMap?.Operation) {
331
+ // throw new ValidationError(
332
+ throw new Error("The Operation dimension is not supported. Use the 'operations' property.");
333
+ }
334
+ const operations = props?.operations ?? Object.values(shared_1.Operation);
335
+ const values = this.createMetricsForOperations(metricName, operations, {
336
+ statistic: "sum",
337
+ ...props,
338
+ });
339
+ return new cloudwatch.MathExpression({
340
+ expression: `${Object.keys(values).join(" + ")}`,
341
+ usingMetrics: { ...values },
342
+ color: props?.color,
343
+ label: expressionLabel,
344
+ period: props?.period,
345
+ });
346
+ }
347
+ createMetricsForOperations(metricName, operations, props, metricNameMapper) {
348
+ const metrics = {};
349
+ const mapper = metricNameMapper ?? ((op) => op.toLowerCase());
350
+ if (props?.dimensionsMap?.Operation) {
351
+ // throw new ValidationError(
352
+ throw new Error("Invalid properties. Operation dimension is not supported when calculating operational metrics");
353
+ }
354
+ for (const operation of operations) {
355
+ const metric = this.metric(metricName, {
356
+ ...props,
357
+ dimensionsMap: {
358
+ TableName: this.tableName,
359
+ Operation: operation,
360
+ ...props?.dimensionsMap,
361
+ },
362
+ });
363
+ const operationMetricName = mapper(operation);
364
+ const firstChar = operationMetricName.charAt(0);
365
+ if (firstChar === firstChar.toUpperCase()) {
366
+ // https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/using-metric-math.html#metric-math-syntax
367
+ // throw new ValidationError(
368
+ throw new Error(`Mapper generated an illegal operation metric name: ${operationMetricName}. Must start with a lowercase letter`);
369
+ }
370
+ metrics[operationMetricName] = metric;
371
+ }
372
+ return metrics;
373
+ }
374
+ combinedGrant(grantee, opts) {
375
+ if (this.encryptionKey && opts.keyActions) {
376
+ this.encryptionKey.grant(grantee, ...opts.keyActions);
377
+ }
378
+ if (opts.tableActions) {
379
+ const resources = [
380
+ this.tableArn,
381
+ cdktf_1.Lazy.stringValue({
382
+ produce: () => this.hasIndex ? `${this.tableArn}/index/*` : undefined,
383
+ }),
384
+ ...this.regionalArns,
385
+ ...this.regionalArns.map((arn) => cdktf_1.Lazy.stringValue({
386
+ produce: () => (this.hasIndex ? `${arn}/index/*` : undefined),
387
+ })),
388
+ ];
389
+ const ret = iam.Grant.addToPrincipalOrResource({
390
+ grantee,
391
+ actions: opts.tableActions,
392
+ resourceArns: resources.filter((r) => r !== undefined),
393
+ resource: this,
394
+ });
395
+ return ret;
396
+ }
397
+ if (opts.streamActions) {
398
+ if (!this.tableStreamArn) {
399
+ // throw new ValidationError(
400
+ throw new Error(`DynamoDB Streams must be enabled on the table ${this.node.path}`);
401
+ }
402
+ const ret = iam.Grant.addToPrincipalOrResource({
403
+ grantee,
404
+ actions: opts.streamActions,
405
+ resourceArns: [this.tableStreamArn],
406
+ resource: this,
407
+ });
408
+ return ret;
409
+ }
410
+ // throw new ValidationError(
411
+ throw new Error(`Unexpected grant combination, actions must be provided for table or stream.`);
412
+ }
413
+ cannedMetric(fn, props) {
414
+ return new cloudwatch.Metric({
415
+ ...fn({ TableName: this.tableName }),
416
+ ...props,
417
+ }).attachTo(this);
418
+ }
419
+ }
420
+ exports.TableBase = TableBase;
421
+ _b = JSII_RTTI_SYMBOL_1;
422
+ TableBase[_b] = { fqn: "terraconstructs.aws.storage.TableBase", version: "0.0.25" };
423
+ /**
424
+ * Provides a DynamoDB table.
425
+ */
426
+ class Table extends TableBase {
427
+ /**
428
+ * Permits an IAM Principal to list all DynamoDB Streams.
429
+ * @deprecated Use `#grantTableListStreams` for more granular permission
430
+ * @param grantee The principal (no-op if undefined)
431
+ */
432
+ static grantListStreams(grantee) {
433
+ return iam.Grant.addToPrincipal({
434
+ grantee,
435
+ actions: ["dynamodb:ListStreams"],
436
+ resourceArns: ["*"],
437
+ });
438
+ }
439
+ /**
440
+ * Creates a Table construct that represents an external table via table name.
441
+ *
442
+ * @param scope The parent creating construct (usually `this`).
443
+ * @param id The construct's name.
444
+ * @param tableName The table's name.
445
+ */
446
+ static fromTableName(scope, id, tableName) {
447
+ return Table.fromTableAttributes(scope, id, { tableName });
448
+ }
449
+ /**
450
+ * Creates a Table construct that represents an external table via table arn.
451
+ *
452
+ * @param scope The parent creating construct (usually `this`).
453
+ * @param id The construct's name.
454
+ * @param tableArn The table's ARN.
455
+ */
456
+ static fromTableArn(scope, id, tableArn) {
457
+ return Table.fromTableAttributes(scope, id, { tableArn });
458
+ }
459
+ /**
460
+ * Creates a Table construct that represents an external table.
461
+ *
462
+ * @param scope The parent creating construct (usually `this`).
463
+ * @param id The construct's name.
464
+ * @param attrs A `TableAttributes` object.
465
+ */
466
+ static fromTableAttributes(scope, id, attrs) {
467
+ class Import extends TableBase {
468
+ constructor(props, _tableArn, tableName, tableStreamArn) {
469
+ super(scope, id, props);
470
+ this.hasIndex = (attrs.grantIndexPermissions ?? false) ||
471
+ (attrs.globalIndexes ?? []).length > 0 ||
472
+ (attrs.localIndexes ?? []).length > 0;
473
+ this.tableArn = _tableArn;
474
+ this.tableName = tableName;
475
+ this.tableStreamArn = tableStreamArn;
476
+ this.encryptionKey = attrs.encryptionKey;
477
+ }
478
+ }
479
+ let name;
480
+ let arn;
481
+ const stack = __1.AwsStack.ofAwsConstruct(scope);
482
+ if (!attrs.tableName) {
483
+ if (!attrs.tableArn) {
484
+ // throw new ValidationError(
485
+ throw new Error("One of tableName or tableArn is required!");
486
+ }
487
+ arn = attrs.tableArn;
488
+ const maybeTableName = stack.splitArn(attrs.tableArn, __1.ArnFormat.SLASH_RESOURCE_NAME).resourceName;
489
+ if (!maybeTableName) {
490
+ // throw new ValidationError(
491
+ throw new Error("ARN for DynamoDB table must be in the form: arn:<partition>:dynamodb:<region>:<account>:table/<table-name>");
492
+ }
493
+ name = maybeTableName;
494
+ }
495
+ else {
496
+ if (attrs.tableArn) {
497
+ // throw new ValidationError(
498
+ throw new Error("Only one of tableArn or tableName can be provided");
499
+ }
500
+ name = attrs.tableName;
501
+ arn = stack.formatArn({
502
+ service: "dynamodb",
503
+ resource: "table",
504
+ resourceName: attrs.tableName,
505
+ });
506
+ }
507
+ return new Import({ environmentFromArn: arn }, arn, name, attrs.tableStreamArn);
508
+ }
509
+ constructor(scope, id, props) {
510
+ super(scope, id, props);
511
+ this.attributeDefinitionsInternal = new Array();
512
+ this.globalSecondaryIndexesInternal = new Array();
513
+ this.localSecondaryIndexesInternal = new Array();
514
+ this.secondaryIndexSchemas = new Map();
515
+ this.nonKeyAttributes = new Set();
516
+ this.tableScaling = {};
517
+ this.indexScaling = new Map();
518
+ const physicalTableName = props.tableName ?? this.stack.uniqueResourceName(this);
519
+ const { sseSpecification, encryptionKey } = this.parseEncryption(props);
520
+ this.encryptionKey = encryptionKey;
521
+ const pointInTimeRecovery = this.renderPointInTimeRecovery(props);
522
+ // error if both replicationRegions and replicaSpecification are specified
523
+ if (props.replicationRegions && props.replicaSpecification) {
524
+ // throw new ValidationError(
525
+ throw new Error("You cannot specify both `replicationRegions` and `replicaSpecification`");
526
+ }
527
+ let streamSpecification;
528
+ if ((props.replicationRegions && props.replicationRegions.length > 0) ||
529
+ (props.replicaSpecification && props.replicaSpecification.length > 0)) {
530
+ if (props.stream && props.stream !== shared_1.StreamViewType.NEW_AND_OLD_IMAGES) {
531
+ // throw new ValidationError(
532
+ throw new Error("`stream` must be set to `NEW_AND_OLD_IMAGES` when specifying `replicationRegions`");
533
+ }
534
+ this.billingMode = props.billingMode ?? shared_1.BillingMode.PAY_PER_REQUEST;
535
+ streamSpecification = {
536
+ streamEnabled: true,
537
+ streamViewType: shared_1.StreamViewType.NEW_AND_OLD_IMAGES,
538
+ };
539
+ }
540
+ else {
541
+ this.billingMode = props.billingMode ?? shared_1.BillingMode.PROVISIONED;
542
+ if (props.stream) {
543
+ streamSpecification = {
544
+ streamEnabled: true,
545
+ streamViewType: props.stream,
546
+ };
547
+ }
548
+ }
549
+ this.validateProvisioning(props);
550
+ this.addKey(props.partitionKey, HASH_KEY_TYPE);
551
+ this.tablePartitionKey = props.partitionKey;
552
+ if (props.sortKey) {
553
+ this.addKey(props.sortKey, RANGE_KEY_TYPE);
554
+ this.tableSortKey = props.sortKey;
555
+ }
556
+ this._replicas = this.renderReplicas(props.replicationRegions, props.replicaSpecification);
557
+ if (this._replicas && this._replicas.length > 0) {
558
+ this._replicas.forEach((r) =>
559
+ // Save regional arns for grantXxx() methods
560
+ this.regionalArns.push(this.stack.formatArn({
561
+ region: r.regionName,
562
+ service: "dynamodb",
563
+ resource: "table",
564
+ resourceName: physicalTableName,
565
+ })));
566
+ }
567
+ this._resource = new provider_aws_1.dynamodbTable.DynamodbTable(this, "Resource", {
568
+ name: physicalTableName,
569
+ hashKey: this.tablePartitionKey.name,
570
+ rangeKey: this.tableSortKey?.name,
571
+ attribute: this.attributeDefinitionsInternal,
572
+ globalSecondaryIndex: cdktf_1.Lazy.anyValue({
573
+ produce: () => this.globalSecondaryIndexesInternal.map(provider_aws_1.dynamodbTable.dynamodbTableGlobalSecondaryIndexToTerraform),
574
+ }, { omitEmptyArray: true }),
575
+ localSecondaryIndex: cdktf_1.Lazy.anyValue({
576
+ produce: () => this.localSecondaryIndexesInternal.map(provider_aws_1.dynamodbTable.dynamodbTableLocalSecondaryIndexToTerraform),
577
+ }, { omitEmptyArray: true }),
578
+ pointInTimeRecovery,
579
+ billingMode: this.billingMode,
580
+ readCapacity: this.billingMode === shared_1.BillingMode.PROVISIONED
581
+ ? (props.readCapacity ?? 5)
582
+ : undefined,
583
+ writeCapacity: this.billingMode === shared_1.BillingMode.PROVISIONED
584
+ ? (props.writeCapacity ?? 5)
585
+ : undefined,
586
+ onDemandThroughput: this.billingMode === shared_1.BillingMode.PAY_PER_REQUEST &&
587
+ (props.maxReadRequestUnits || props.maxWriteRequestUnits)
588
+ ? {
589
+ maxReadRequestUnits: props.maxReadRequestUnits,
590
+ maxWriteRequestUnits: props.maxWriteRequestUnits,
591
+ }
592
+ : undefined,
593
+ serverSideEncryption: sseSpecification,
594
+ streamEnabled: streamSpecification?.streamEnabled,
595
+ streamViewType: streamSpecification?.streamViewType,
596
+ tableClass: props.tableClass,
597
+ ttl: props.timeToLiveAttribute
598
+ ? { attributeName: props.timeToLiveAttribute, enabled: true }
599
+ : undefined,
600
+ deletionProtectionEnabled: props.deletionProtection,
601
+ importTable: this.renderImportSourceSpecification(props.importSource),
602
+ replica: this._replicas,
603
+ // resourcePolicy: props.resourcePolicy ? { policyDocument: this.stack.toJsonString(props.resourcePolicy.toJSON()) } : undefined, // Not in TF resource
604
+ // TODO: https://github.com/hashicorp/terraform-provider-aws/issues/43142
605
+ // warmThroughput: props.warmThroughput ?? undefined, // Not in TF resource
606
+ });
607
+ this.tableArn = this._resource.arn;
608
+ this.tableName = this._resource.name;
609
+ this.tableStreamArn = streamSpecification?.streamEnabled
610
+ ? this._resource.streamArn
611
+ : undefined;
612
+ this.resourcePolicy = props.resourcePolicy;
613
+ if (this.resourcePolicy) {
614
+ new provider_aws_1.dynamodbResourcePolicy.DynamodbResourcePolicy(this, "ResourcePolicy", {
615
+ policy: this.resourcePolicy.json,
616
+ resourceArn: this.tableArn,
617
+ });
618
+ }
619
+ if (props.kinesisStream) {
620
+ new provider_aws_1.dynamodbKinesisStreamingDestination.DynamodbKinesisStreamingDestination(this, "KinesisStreamingDestination", {
621
+ tableName: this.tableName,
622
+ streamArn: props.kinesisStream.streamArn,
623
+ ...(props.kinesisPrecisionTimestamp && {
624
+ approximateCreationDateTimePrecision: props.kinesisPrecisionTimestamp,
625
+ }),
626
+ });
627
+ }
628
+ if (props.contributorInsightsEnabled) {
629
+ // TODO: Generate conntributor insights per Global Secondary Index
630
+ // this.globalSecondaryIndexesInternal
631
+ new provider_aws_1.dynamodbContributorInsights.DynamodbContributorInsights(this, "ContributorInsights", {
632
+ tableName: this.tableName,
633
+ // TODO: use for each on gli iterator
634
+ // indexName: iterator.value,
635
+ });
636
+ }
637
+ // Commenting out scalingRole initialization - let Terraform auto-create service-linked role
638
+ // this.scalingRole = this.makeScalingRole();
639
+ this.node.addValidation({ validate: () => this.validateTable() });
640
+ }
641
+ addGlobalSecondaryIndex(props) {
642
+ this.validateProvisioningGSI(props);
643
+ this.validateIndexName(props.indexName);
644
+ const gsiProjection = this.buildIndexProjection(props);
645
+ this.registerAttribute(props.partitionKey);
646
+ if (props.sortKey) {
647
+ this.registerAttribute(props.sortKey);
648
+ }
649
+ this.globalSecondaryIndexesInternal.push({
650
+ name: props.indexName,
651
+ hashKey: props.partitionKey.name,
652
+ rangeKey: props.sortKey?.name,
653
+ projectionType: gsiProjection.projectionType,
654
+ nonKeyAttributes: gsiProjection.nonKeyAttributes,
655
+ readCapacity: this.billingMode === shared_1.BillingMode.PROVISIONED
656
+ ? (props.readCapacity ?? 5)
657
+ : undefined,
658
+ writeCapacity: this.billingMode === shared_1.BillingMode.PROVISIONED
659
+ ? (props.writeCapacity ?? 5)
660
+ : undefined,
661
+ onDemandThroughput: this.billingMode === shared_1.BillingMode.PAY_PER_REQUEST &&
662
+ (props.maxReadRequestUnits || props.maxWriteRequestUnits)
663
+ ? {
664
+ maxReadRequestUnits: props.maxReadRequestUnits,
665
+ maxWriteRequestUnits: props.maxWriteRequestUnits,
666
+ }
667
+ : undefined,
668
+ // contributorInsightsEnabled: props.contributorInsightsEnabled, // Not in TF GSI block
669
+ // warmThroughput: props.warmThroughput, // Not in TF GSI block
670
+ });
671
+ this.secondaryIndexSchemas.set(props.indexName, {
672
+ partitionKey: props.partitionKey,
673
+ sortKey: props.sortKey,
674
+ });
675
+ this.indexScaling.set(props.indexName, {});
676
+ }
677
+ addLocalSecondaryIndex(props) {
678
+ if (this.localSecondaryIndexesInternal.length >=
679
+ MAX_LOCAL_SECONDARY_INDEX_COUNT) {
680
+ throw new RangeError(`A maximum number of local secondary index per table is ${MAX_LOCAL_SECONDARY_INDEX_COUNT}`);
681
+ }
682
+ this.validateIndexName(props.indexName);
683
+ if (!this.tablePartitionKey) {
684
+ // throw new ValidationError(
685
+ throw new Error("Table partition key must be defined before adding local secondary index");
686
+ }
687
+ this.registerAttribute(this.tablePartitionKey);
688
+ this.registerAttribute(props.sortKey);
689
+ const lsiProjection = this.buildIndexProjection(props);
690
+ this.localSecondaryIndexesInternal.push({
691
+ name: props.indexName,
692
+ rangeKey: props.sortKey.name,
693
+ projectionType: lsiProjection.projectionType,
694
+ nonKeyAttributes: lsiProjection.nonKeyAttributes,
695
+ });
696
+ this.secondaryIndexSchemas.set(props.indexName, {
697
+ partitionKey: this.tablePartitionKey,
698
+ sortKey: props.sortKey,
699
+ });
700
+ }
701
+ autoScaleReadCapacity(props) {
702
+ if (this.tableScaling.scalableReadAttribute) {
703
+ // throw new ValidationError(
704
+ throw new Error("Read AutoScaling already enabled for this table");
705
+ }
706
+ if (this.billingMode === shared_1.BillingMode.PAY_PER_REQUEST) {
707
+ // throw new ValidationError(
708
+ throw new Error("AutoScaling is not available for tables with PAY_PER_REQUEST billing mode");
709
+ }
710
+ return (this.tableScaling.scalableReadAttribute =
711
+ new scalable_table_attribute_1.ScalableTableAttribute(this, "ReadScaling", {
712
+ serviceNamespace: appscaling.ServiceNamespace.DYNAMODB,
713
+ resourceId: `table/${this.tableName}`,
714
+ dimension: "dynamodb:table:ReadCapacityUnits",
715
+ // role: this.scalingRole, // Commenting out - let Terraform use service-linked role
716
+ ...props,
717
+ }));
718
+ }
719
+ autoScaleWriteCapacity(props) {
720
+ if (this.tableScaling.scalableWriteAttribute) {
721
+ // throw new ValidationError(
722
+ throw new Error("Write AutoScaling already enabled for this table");
723
+ }
724
+ if (this.billingMode === shared_1.BillingMode.PAY_PER_REQUEST) {
725
+ // throw new ValidationError(
726
+ throw new Error("AutoScaling is not available for tables with PAY_PER_REQUEST billing mode");
727
+ }
728
+ this.tableScaling.scalableWriteAttribute = new scalable_table_attribute_1.ScalableTableAttribute(this, "WriteScaling", {
729
+ serviceNamespace: appscaling.ServiceNamespace.DYNAMODB,
730
+ resourceId: `table/${this.tableName}`,
731
+ dimension: "dynamodb:table:WriteCapacityUnits",
732
+ // role: this.scalingRole, // Commenting out - let Terraform use service-linked role
733
+ ...props,
734
+ });
735
+ // If there are replicas, they depend on the write scaling policy of the main table.
736
+ // This is not explicitly modeled in TF but was handled by CustomResource dependencies in CDK.
737
+ // For TF, this dependency is implicit if the provider handles it, or might need explicit dependsOn if issues arise.
738
+ return this.tableScaling.scalableWriteAttribute;
739
+ }
740
+ autoScaleGlobalSecondaryIndexReadCapacity(indexName, props) {
741
+ if (this.billingMode === shared_1.BillingMode.PAY_PER_REQUEST) {
742
+ // throw new ValidationError(
743
+ throw new Error("AutoScaling is not available for tables with PAY_PER_REQUEST billing mode");
744
+ }
745
+ const attributePair = this.indexScaling.get(indexName);
746
+ if (!attributePair) {
747
+ // throw new ValidationError(
748
+ throw new Error(`No global secondary index with name ${indexName}`);
749
+ }
750
+ if (attributePair.scalableReadAttribute) {
751
+ // throw new ValidationError(
752
+ throw new Error("Read AutoScaling already enabled for this index");
753
+ }
754
+ return (attributePair.scalableReadAttribute = new scalable_table_attribute_1.ScalableTableAttribute(this, `${indexName}ReadScaling`, {
755
+ serviceNamespace: appscaling.ServiceNamespace.DYNAMODB,
756
+ resourceId: `table/${this.tableName}/index/${indexName}`,
757
+ dimension: "dynamodb:index:ReadCapacityUnits",
758
+ // role: this.scalingRole, // Commenting out - let Terraform use service-linked role
759
+ ...props,
760
+ }));
761
+ }
762
+ autoScaleGlobalSecondaryIndexWriteCapacity(indexName, props) {
763
+ if (this.billingMode === shared_1.BillingMode.PAY_PER_REQUEST) {
764
+ // throw new ValidationError(
765
+ throw new Error("AutoScaling is not available for tables with PAY_PER_REQUEST billing mode");
766
+ }
767
+ const attributePair = this.indexScaling.get(indexName);
768
+ if (!attributePair) {
769
+ // throw new ValidationError(
770
+ throw new Error(`No global secondary index with name ${indexName}`);
771
+ }
772
+ if (attributePair.scalableWriteAttribute) {
773
+ // throw new ValidationError(
774
+ throw new Error("Write AutoScaling already enabled for this index");
775
+ }
776
+ return (attributePair.scalableWriteAttribute = new scalable_table_attribute_1.ScalableTableAttribute(this, `${indexName}WriteScaling`, {
777
+ serviceNamespace: appscaling.ServiceNamespace.DYNAMODB,
778
+ resourceId: `table/${this.tableName}/index/${indexName}`,
779
+ dimension: "dynamodb:index:WriteCapacityUnits",
780
+ // role: this.scalingRole, // Commenting out - let Terraform use service-linked role
781
+ ...props,
782
+ }));
783
+ }
784
+ schema(indexName) {
785
+ if (!indexName) {
786
+ return {
787
+ partitionKey: this.tablePartitionKey,
788
+ sortKey: this.tableSortKey,
789
+ };
790
+ }
791
+ const schema = this.secondaryIndexSchemas.get(indexName);
792
+ if (!schema) {
793
+ // throw new ValidationError(
794
+ throw new Error(`Cannot find schema for index: ${indexName}. Use 'addGlobalSecondaryIndex' or 'addLocalSecondaryIndex' to add index`);
795
+ }
796
+ return schema;
797
+ }
798
+ validateTable() {
799
+ const errors = new Array();
800
+ if (!this.tablePartitionKey) {
801
+ errors.push("A partition key must be specified");
802
+ }
803
+ if (this.localSecondaryIndexesInternal.length > 0 && !this.tableSortKey) {
804
+ errors.push("A sort key of the table must be specified to add local secondary indexes");
805
+ }
806
+ if (this._replicas &&
807
+ this._replicas.length > 0 &&
808
+ this.billingMode === shared_1.BillingMode.PROVISIONED) {
809
+ const writeAutoScaleAttribute = this.tableScaling.scalableWriteAttribute;
810
+ if (!writeAutoScaleAttribute) {
811
+ errors.push("A global Table that uses PROVISIONED as the billing mode needs auto-scaled write capacity. " +
812
+ "Use the autoScaleWriteCapacity() method to enable it.");
813
+ }
814
+ else if (!writeAutoScaleAttribute._scalingPolicyCreated) {
815
+ errors.push("A global Table that uses PROVISIONED as the billing mode needs auto-scaled write capacity with a policy. " +
816
+ "Call one of the scaleOn*() methods of the object returned from autoScaleWriteCapacity()");
817
+ }
818
+ }
819
+ return errors;
820
+ }
821
+ validateProvisioning(props) {
822
+ if (this.billingMode === shared_1.BillingMode.PAY_PER_REQUEST) {
823
+ if (props.readCapacity !== undefined ||
824
+ props.writeCapacity !== undefined) {
825
+ // throw new ValidationError(
826
+ throw new Error("You cannot provision read and write capacity for a table with PAY_PER_REQUEST billing mode");
827
+ }
828
+ }
829
+ }
830
+ validateProvisioningGSI(props) {
831
+ if (this.billingMode === shared_1.BillingMode.PAY_PER_REQUEST) {
832
+ if (props.readCapacity !== undefined ||
833
+ props.writeCapacity !== undefined) {
834
+ // throw new ValidationError(
835
+ throw new Error("You cannot provision read and write capacity for a GSI with PAY_PER_REQUEST billing mode on the table");
836
+ }
837
+ }
838
+ }
839
+ validateIndexName(indexName) {
840
+ if (this.secondaryIndexSchemas.has(indexName)) {
841
+ // throw new ValidationError(
842
+ throw new Error(`A duplicate index name, ${indexName}, is not allowed`);
843
+ }
844
+ }
845
+ validateNonKeyAttributes(nonKeyAttributes) {
846
+ if (this.nonKeyAttributes.size + nonKeyAttributes.length > 100) {
847
+ throw new RangeError("A maximum number of nonKeyAttributes across all of secondary indexes is 100");
848
+ }
849
+ nonKeyAttributes.forEach((att) => this.nonKeyAttributes.add(att));
850
+ }
851
+ renderPointInTimeRecovery(props) {
852
+ if (props.pointInTimeRecoverySpecification !== undefined &&
853
+ props.pointInTimeRecovery !== undefined) {
854
+ // throw new ValidationError(
855
+ throw new Error("`pointInTimeRecoverySpecification` and `pointInTimeRecovery` are set. Use `pointInTimeRecoverySpecification` only.");
856
+ }
857
+ const spec = props.pointInTimeRecoverySpecification;
858
+ if (spec?.recoveryPeriodInDays) {
859
+ // TODO: Upgrade provider to 5.98.0 to support recoveryPeriodInDays
860
+ cdktf_1.Annotations.of(this).addWarning("Warning: recoveryPeriodInDays is not supported until provider aws is upgraded to 5.98.0 and will be ignored.");
861
+ }
862
+ const enabled = spec?.pointInTimeRecoveryEnabled ?? props.pointInTimeRecovery;
863
+ if (enabled === undefined)
864
+ return undefined;
865
+ return { enabled };
866
+ }
867
+ buildIndexProjection(props) {
868
+ if (props.projectionType === shared_1.ProjectionType.INCLUDE &&
869
+ !props.nonKeyAttributes) {
870
+ // throw new ValidationError(
871
+ throw new Error(`Non-key attributes should be specified when using ${shared_1.ProjectionType.INCLUDE} projection type`);
872
+ }
873
+ if (props.projectionType !== shared_1.ProjectionType.INCLUDE &&
874
+ props.nonKeyAttributes) {
875
+ // throw new ValidationError(
876
+ throw new Error(`Non-key attributes should not be specified when not using ${shared_1.ProjectionType.INCLUDE} projection type`);
877
+ }
878
+ if (props.nonKeyAttributes) {
879
+ this.validateNonKeyAttributes(props.nonKeyAttributes);
880
+ }
881
+ return {
882
+ projectionType: props.projectionType ?? shared_1.ProjectionType.ALL,
883
+ nonKeyAttributes: props.nonKeyAttributes,
884
+ };
885
+ }
886
+ // TODO: keyType is unused
887
+ addKey(attribute, _keyType) {
888
+ const existingAttr = this.attributeDefinitionsInternal.find((def) => def.name === attribute.name);
889
+ if (existingAttr && existingAttr.type !== attribute.type) {
890
+ // throw new ValidationError(
891
+ throw new Error(`Unable to specify ${attribute.name} as ${attribute.type} because it was already defined as ${existingAttr.type}`);
892
+ }
893
+ if (!existingAttr) {
894
+ this.attributeDefinitionsInternal.push({
895
+ name: attribute.name,
896
+ type: attribute.type,
897
+ });
898
+ }
899
+ // For the main table, hashKey and rangeKey are set directly on the resource.
900
+ // For GSIs/LSIs, they are part of their respective blocks.
901
+ }
902
+ registerAttribute(attribute) {
903
+ const existingDef = this.attributeDefinitionsInternal.find((def) => def.name === attribute.name);
904
+ if (existingDef && existingDef.type !== attribute.type) {
905
+ // throw new ValidationError(
906
+ throw new Error(`Unable to specify ${attribute.name} as ${attribute.type} because it was already defined as ${existingDef.type}`);
907
+ }
908
+ if (!existingDef) {
909
+ this.attributeDefinitionsInternal.push({
910
+ name: attribute.name,
911
+ type: attribute.type,
912
+ });
913
+ }
914
+ }
915
+ // Commenting out makeScalingRole method - Terraform handles service-linked roles automatically
916
+ // Unlike AWS CDK CloudFormation implementation, Terraform AWS provider creates appropriate
917
+ // service-linked roles when roleArn is omitted from aws_appautoscaling_target resource
918
+ // private makeScalingRole(): iam.IRole {
919
+ // // Use a Service Linked Role.
920
+ // // https://docs.aws.amazon.com/autoscaling/application/userguide/application-auto-scaling-service-linked-roles.html
921
+ // return iam.Role.fromRoleArn(
922
+ // this,
923
+ // "ScalingRole",
924
+ // this.stack.formatArn({
925
+ // service: "iam",
926
+ // region: "", // SLRs are global
927
+ // resource:
928
+ // "role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com",
929
+ // resourceName: "AWSServiceRoleForApplicationAutoScaling_DynamoDBTable",
930
+ // // TODO: Is this needed?
931
+ // // arnFormat: ArnFormat.SLASH_RESOURCE_SLASH_RESOURCE_NAME, // Special format for SLRs
932
+ // }),
933
+ // );
934
+ // }
935
+ /**
936
+ * Creates replica tables
937
+ *
938
+ * @param regions regions where to create tables
939
+ */
940
+ renderReplicas(regions, replicaSpecification) {
941
+ if (replicaSpecification && replicaSpecification.length > 0) {
942
+ if (!cdktf_1.Token.isUnresolved(this.stack.region) &&
943
+ replicaSpecification.some((replica) => replica.regionName === this.stack.region)) {
944
+ // throw new ValidationError(
945
+ throw new Error("`replicaSpecification` cannot include the region where this stack is deployed.");
946
+ }
947
+ return replicaSpecification.map((replica) => ({
948
+ regionName: replica.regionName,
949
+ kmsKeyArn: replica.encryptionKey?.keyArn,
950
+ pointInTimeRecovery: replica.pointInTimeRecovery,
951
+ propagateTags: replica.propagateTags,
952
+ }));
953
+ }
954
+ if (!regions || regions.length === 0)
955
+ return undefined;
956
+ if (!cdktf_1.Token.isUnresolved(this.stack.region) &&
957
+ regions.includes(this.stack.region)) {
958
+ // throw new ValidationError(
959
+ throw new Error("`replicationRegions` cannot include the region where this stack is deployed.");
960
+ }
961
+ return [...new Set(regions)].map((region) => ({
962
+ regionName: region,
963
+ }));
964
+ }
965
+ get hasIndex() {
966
+ return (this.globalSecondaryIndexesInternal.length +
967
+ this.localSecondaryIndexesInternal.length >
968
+ 0);
969
+ }
970
+ parseEncryption(props) {
971
+ let encryptionType = props.encryption;
972
+ if (encryptionType != null && props.serverSideEncryption != null) {
973
+ // throw new ValidationError(
974
+ throw new Error("Only one of encryption and serverSideEncryption can be specified, but both were provided");
975
+ }
976
+ if (props.serverSideEncryption && props.encryptionKey) {
977
+ // throw new ValidationError(
978
+ throw new Error("encryptionKey cannot be specified when serverSideEncryption is specified. Use encryption instead");
979
+ }
980
+ if (encryptionType === undefined) {
981
+ encryptionType =
982
+ props.encryptionKey != null
983
+ ? shared_1.TableEncryption.CUSTOMER_MANAGED
984
+ : props.serverSideEncryption
985
+ ? shared_1.TableEncryption.AWS_MANAGED
986
+ : undefined;
987
+ }
988
+ if (encryptionType !== shared_1.TableEncryption.CUSTOMER_MANAGED &&
989
+ props.encryptionKey) {
990
+ // throw new ValidationError(
991
+ throw new Error(`encryptionKey cannot be specified unless encryption is set to TableEncryption.CUSTOMER_MANAGED (it was set to ${encryptionType})`);
992
+ }
993
+ // in this case, each replica should specify a Customer KMS key.
994
+ if (encryptionType === shared_1.TableEncryption.CUSTOMER_MANAGED &&
995
+ props.replicationRegions) {
996
+ // throw new ValidationError(
997
+ throw new Error("TableEncryption.CUSTOMER_MANAGED is not supported by DynamoDB Global Tables (where replicationRegions was set)");
998
+ }
999
+ if (props.replicaSpecification &&
1000
+ props.replicaSpecification.length > 0 &&
1001
+ encryptionType === shared_1.TableEncryption.CUSTOMER_MANAGED) {
1002
+ if (props.replicaSpecification.some((replica) => !replica.encryptionKey)) {
1003
+ // throw new ValidationError(
1004
+ throw new Error("When using replicaSpecification, each replica must specify an encryptionKey if TableEncryption.CUSTOMER_MANAGED is used");
1005
+ }
1006
+ //Validate that the keys belong to the correct regions
1007
+ if (props.replicaSpecification.some((replica) => replica.encryptionKey &&
1008
+ replica.encryptionKey.env.region !== replica.regionName)) {
1009
+ // throw new ValidationError(
1010
+ throw new Error("When using replicaSpecification, each replica's encryptionKey must be in the same region as its replica");
1011
+ }
1012
+ }
1013
+ switch (encryptionType) {
1014
+ case shared_1.TableEncryption.CUSTOMER_MANAGED:
1015
+ const key = props.encryptionKey ??
1016
+ new kms.Key(this, "Key", {
1017
+ description: `Customer-managed key auto-created for encrypting DynamoDB table at ${this.node.path}`,
1018
+ enableKeyRotation: true,
1019
+ });
1020
+ return {
1021
+ sseSpecification: { enabled: true, kmsKeyArn: key.keyArn },
1022
+ encryptionKey: key,
1023
+ };
1024
+ case shared_1.TableEncryption.AWS_MANAGED:
1025
+ return { sseSpecification: { enabled: true } }; // Uses alias/aws/dynamodb by default
1026
+ case shared_1.TableEncryption.DEFAULT:
1027
+ return { sseSpecification: { enabled: false } }; // AWS-owned key
1028
+ case undefined:
1029
+ return { sseSpecification: undefined }; // Defaults to AWS-owned key
1030
+ default:
1031
+ // throw new ValidationError(
1032
+ throw new Error(`Unexpected 'encryptionType': ${encryptionType}`);
1033
+ }
1034
+ }
1035
+ renderImportSourceSpecification(importSource) {
1036
+ if (!importSource)
1037
+ return undefined;
1038
+ const renderedInputFormat = importSource.inputFormat._render();
1039
+ return {
1040
+ inputFormat: renderedInputFormat.inputFormat,
1041
+ inputFormatOptions: renderedInputFormat.inputFormatOptions,
1042
+ inputCompressionType: importSource.compressionType,
1043
+ s3BucketSource: {
1044
+ bucket: importSource.bucket.bucketName,
1045
+ bucketOwner: importSource.bucketOwner,
1046
+ keyPrefix: importSource.keyPrefix,
1047
+ },
1048
+ };
1049
+ }
1050
+ }
1051
+ exports.Table = Table;
1052
+ _c = JSII_RTTI_SYMBOL_1;
1053
+ Table[_c] = { fqn: "terraconstructs.aws.storage.Table", version: "0.0.25" };
1054
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFibGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYXdzL3N0b3JhZ2UvdGFibGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSw4RkFBOEY7QUFFOUYsc0RBSzZCO0FBQzdCLGlDQUFpRDtBQUdqRCwwQkFBOEU7QUFDOUUsMkZBQXNFO0FBQ3RFLDBDQUEwQztBQUsxQyx5RUFBb0U7QUFDcEUscUNBY2tCO0FBQ2xCLDRDQUE0QztBQUM1Qyx5Q0FBeUM7QUFDekMscUNBQXFDO0FBQ3JDLDhCQUE4QjtBQUU5Qiw0REFBNEQ7QUFDNUQscUdBQXFHO0FBQ3JHLDZDQUE2QztBQUU3QyxzRUFBc0U7QUFDdEUsK0NBQStDO0FBQy9DLDhDQUE4QztBQUM5QyxXQUFXO0FBQ1gsNkJBQTZCO0FBQzdCLHFCQUFxQjtBQUNyQixrQ0FBa0M7QUFFbEMsTUFBTSxhQUFhLEdBQUcsTUFBTSxDQUFDO0FBQzdCLE1BQU0sY0FBYyxHQUFHLE9BQU8sQ0FBQztBQUUvQixNQUFNLCtCQUErQixHQUFHLENBQUMsQ0FBQztBQW1CMUM7O0dBRUc7QUFDSCxJQUFZLG9CQWVYO0FBZkQsV0FBWSxvQkFBb0I7SUFDOUI7O09BRUc7SUFDSCxxQ0FBYSxDQUFBO0lBRWI7O09BRUc7SUFDSCxxQ0FBYSxDQUFBO0lBRWI7O09BRUc7SUFDSCxxQ0FBYSxDQUFBO0FBQ2YsQ0FBQyxFQWZXLG9CQUFvQixvQ0FBcEIsb0JBQW9CLFFBZS9CO0FBZ0NEOztHQUVHO0FBQ0gsTUFBc0IsV0FBVztJQUMvQjs7T0FFRztJQUNJLE1BQU0sQ0FBQyxZQUFZO1FBQ3hCLE9BQU8sSUFBSSxDQUFDLEtBQU0sU0FBUSxXQUFXO1lBQzVCLE9BQU87Z0JBSVosT0FBTztvQkFDTCxXQUFXLEVBQUUsZUFBZTtpQkFDN0IsQ0FBQztZQUNKLENBQUM7U0FDRixDQUFDLEVBQUUsQ0FBQztJQUNQLENBQUM7SUFFRDs7T0FFRztJQUNJLE1BQU0sQ0FBQyxHQUFHO1FBQ2YsT0FB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RSxPQUFPLFNBQVMsQ0FBQztRQUNwQyxNQUFNLG1CQUFtQixHQUFHLFlBQVksQ0FBQyxXQUFXLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDL0QsT0FBTztZQUNMLFdBQVcsRUFBRSxtQkFBbUIsQ0FBQyxXQUFXO1lBQzVDLGtCQUFrQixFQUFFLG1CQUFtQixDQUFDLGtCQUFrQjtZQUMxRCxvQkFBb0IsRUFBRSxZQUFZLENBQUMsZUFBZTtZQUNsRCxjQUFjLEVBQUU7Z0JBQ2QsTUFBTSxFQUFFLFlBQVksQ0FBQyxNQUFNLENBQUMsVUFBVTtnQkFDdEMsV0FBVyxFQUFFLFlBQVksQ0FBQyxXQUFXO2dCQUNyQyxTQUFTLEVBQUUsWUFBWSxDQUFDLFNBQVM7YUFDbEM7U0FDRixDQUFDO0lBQ0osQ0FBQzs7QUFwOUJILHNCQXE5QkMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBodHRwczovL2dpdGh1Yi5jb20vYXdzL2F3cy1jZGsvYmxvYi92Mi4xODYuMC9wYWNrYWdlcy9hd3MtY2RrLWxpYi9hd3MtZHluYW1vZGIvbGliL3RhYmxlLnRzXG5cbmltcG9ydCB7XG4gIGR5bmFtb2RiQ29udHJpYnV0b3JJbnNpZ2h0cyxcbiAgZHluYW1vZGJLaW5lc2lzU3RyZWFtaW5nRGVzdGluYXRpb24sXG4gIGR5bmFtb2RiUmVzb3VyY2VQb2xpY3ksXG4gIGR5bmFtb2RiVGFibGUsXG59IGZyb20gXCJAY2RrdGYvcHJvdmlkZXItYXdzXCI7XG5pbXBvcnQgeyBUb2tlbiwgTGF6eSwgQW5ub3RhdGlvbnMgfSBmcm9tIFwiY2RrdGZcIjtcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gXCJjb25zdHJ1Y3RzXCI7XG5pbXBvcnQgKiBhcyBzdG9yYWdlIGZyb20gXCIuXCI7XG5pbXBvcnQgeyBBcm5Gb3JtYXQsIEF3c0NvbnN0cnVjdEJhc2UsIEF3c0NvbnN0cnVjdFByb3BzLCBBd3NTdGFjayB9IGZyb20gXCIuLlwiO1xuaW1wb3J0IHsgRHluYW1vREJNZXRyaWNzIH0gZnJvbSBcIi4vZHluYW1vZGItY2FubmVkLW1ldHJpY3MuZ2VuZXJhdGVkXCI7XG5pbXBvcnQgKiBhcyBwZXJtcyBmcm9tIFwiLi9keW5hbW9kYi1wZXJtc1wiO1xuaW1wb3J0IHtcbiAgRW5hYmxlU2NhbGluZ1Byb3BzLFxuICBJU2NhbGFibGVUYWJsZUF0dHJpYnV0ZSxcbn0gZnJvbSBcIi4vc2NhbGFibGUtYXR0cmlidXRlLWFwaVwiO1xuaW1wb3J0IHsgU2NhbGFibGVUYWJsZUF0dHJpYnV0ZSB9IGZyb20gXCIuL3NjYWxhYmxlLXRhYmxlLWF0dHJpYnV0ZVwiO1xuaW1wb3J0IHtcbiAgT3BlcmF0aW9uLFxuICBPcGVyYXRpb25zTWV0cmljT3B0aW9ucyxcbiAgU3lzdGVtRXJyb3JzRm9yT3BlcmF0aW9uc01ldHJpY09wdGlvbnMsXG4gIEF0dHJpYnV0ZSxcbiAgQmlsbGluZ01vZGUsXG4gIFByb2plY3Rpb25UeXBlLFxuICBJVGFibGUsXG4gIFNlY29uZGFyeUluZGV4UHJvcHMsXG4gIFRhYmxlQ2xhc3MsXG4gIExvY2FsU2Vjb25kYXJ5SW5kZXhQcm9wcyxcbiAgVGFibGVFbmNyeXB0aW9uLFxuICBTdHJlYW1WaWV3VHlwZSxcbiAgUG9pbnRJblRpbWVSZWNvdmVyeVNwZWNpZmljYXRpb24sXG59IGZyb20gXCIuL3NoYXJlZFwiO1xuaW1wb3J0ICogYXMgY2xvdWR3YXRjaCBmcm9tIFwiLi4vY2xvdWR3YXRjaFwiO1xuaW1wb3J0ICogYXMgYXBwc2NhbGluZyBmcm9tIFwiLi4vY29tcHV0ZVwiO1xuaW1wb3J0ICogYXMga21zIGZyb20gXCIuLi9lbmNyeXB0aW9uXCI7XG5pbXBvcnQgKiBhcyBpYW0gZnJvbSBcIi4uL2lhbVwiO1xuaW1wb3J0ICogYXMga2luZXNpcyBmcm9tIFwiLi4vbm90aWZ5XCI7XG4vLyBNaXNzaW5nIGluIFRlcnJhZm9ybSBEeW5hbW9EYiBSZXBsaWNhIENvbmZpZ3VyYXRpb24gYmxvY2tcbi8vIGh0dHBzOi8vcmVnaXN0cnkudGVycmFmb3JtLmlvL3Byb3ZpZGVycy9oYXNoaWNvcnAvYXdzLzUuODguMC9kb2NzL3Jlc291cmNlcy9keW5hbW9kYl90YWJsZSNyZXBsaWNhXG4vLyBpbXBvcnQgeyBEdXJhdGlvbiB9IGZyb20gXCIuLi8uLi9kdXJhdGlvblwiO1xuXG4vLyBUT0RPIEFkb3B0IFVuc2NvcGVkVmFsaWRhdGlvbkVycm9yLCBWYWxpZGF0aW9uRXJyb3Igd2hlbiBhdmFpbGFibGU6XG4vLyAtIGh0dHBzOi8vZ2l0aHViLmNvbS9hd3MvYXdzLWNkay9wdWxsLzMzMzgyL1xuLy8gLSBodHRwczovL2dpdGh1Yi5jb20vYXdzL2F3cy1jZGsvcHVsbC8zMzA0NVxuLy8gaW1wb3J0IHtcbi8vICAgVW5zY29wZWRWYWxpZGF0aW9uRXJyb3IsXG4vLyAgIFZhbGlkYXRpb25FcnJvcixcbi8vIH0gZnJvbSBcIi4uLy4uL2NvcmUvbGliL2Vycm9yc1wiO1xuXG5jb25zdCBIQVNIX0tFWV9UWVBFID0gXCJIQVNIXCI7XG5jb25zdCBSQU5HRV9LRVlfVFlQRSA9IFwiUkFOR0VcIjtcblxuY29uc3QgTUFYX0xPQ0FMX1NFQ09OREFSWV9JTkRFWF9DT1VOVCA9IDU7XG5cbi8qKlxuICogUmVwcmVzZW50cyB0aGUgdGFibGUgc2NoZW1hIGF0dHJpYnV0ZXMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2NoZW1hT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBQYXJ0aXRpb24ga2V5IGF0dHJpYnV0ZSBkZWZpbml0aW9uLlxuICAgKi9cbiAgcmVhZG9ubHkgcGFydGl0aW9uS2V5OiBBdHRyaWJ1dGU7XG5cbiAgLyoqXG4gICAqIFNvcnQga2V5IGF0dHJpYnV0ZSBkZWZpbml0aW9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCBubyBzb3J0IGtleVxuICAgKi9cbiAgcmVhZG9ubHkgc29ydEtleT86IEF0dHJpYnV0ZTtcbn1cblxuLyoqXG4gKiBUeXBlIG9mIGNvbXByZXNzaW9uIHRvIHVzZSBmb3IgaW1wb3J0ZWQgZGF0YS5cbiAqL1xuZXhwb3J0IGVudW0gSW5wdXRDb21wcmVzc2lvblR5cGUge1xuICAvKipcbiAgICogR1pJUCBjb21wcmVzc2lvbi5cbiAgICovXG4gIEdaSVAgPSBcIkdaSVBcIixcblxuICAvKipcbiAgICogWlNURCBjb21wcmVzc2lvbi5cbiAgICovXG4gIFpTVEQgPSBcIlpTVERcIixcblxuICAvKipcbiAgICogTm8gY29tcHJlc3Npb24uXG4gICAqL1xuICBOT05FID0gXCJOT05FXCIsXG59XG5cbi8qKlxuICogVGhlIG9wdGlvbnMgZm9yIGltcG9ydGVkIHNvdXJjZSBmaWxlcyBpbiBDU1YgZm9ybWF0LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIENzdk9wdGlvbnMge1xuICAvKipcbiAgICogVGhlIGRlbGltaXRlciB1c2VkIGZvciBzZXBhcmF0aW5nIGl0ZW1zIGluIHRoZSBDU1YgZmlsZSBiZWluZyBpbXBvcnRlZC5cbiAgICpcbiAgICogVmFsaWQgZGVsaW1pdGVycyBhcmUgYXMgZm9sbG93czpcbiAgICogLSBjb21tYSAoYCxgKVxuICAgKiAtIHRhYiAoYFxcdGApXG4gICAqIC0gY29sb24gKGA6YClcbiAgICogLSBzZW1pY29sb24gKGA7YClcbiAgICogLSBwaXBlIChgfGApXG4gICAqIC0gc3BhY2UgKGAgYClcbiAgICpcbiAgICogQGRlZmF1bHQgLSB1c2UgY29tbWEgYXMgYSBkZWxpbWl0ZXIuXG4gICAqL1xuICByZWFkb25seSBkZWxpbWl0ZXI/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIExpc3Qgb2YgdGhlIGhlYWRlcnMgdXNlZCB0byBzcGVjaWZ5IGEgY29tbW9uIGhlYWRlciBmb3IgYWxsIHNvdXJjZSBDU1YgZmlsZXMgYmVpbmcgaW1wb3J0ZWQuXG4gICAqXG4gICAqICoqTk9URSoqOiBJZiB0aGlzIGZpZWxkIGlzIHNwZWNpZmllZCB0aGVuIHRoZSBmaXJzdCBsaW5lIG9mIGVhY2ggQ1NWIGZpbGUgaXMgdHJlYXRlZCBhcyBkYXRhIGluc3RlYWQgb2YgdGhlIGhlYWRlci5cbiAgICogSWYgdGhpcyBmaWVsZCBpcyBub3Qgc3BlY2lmaWVkIHRoZSB0aGUgZmlyc3QgbGluZSBvZiBlYWNoIENTViBmaWxlIGlzIHRyZWF0ZWQgYXMgdGhlIGhlYWRlci5cbiAgICpcbiAgICogQGRlZmF1bHQgLSB0aGUgZmlyc3QgbGluZSBvZiB0aGUgQ1NWIGZpbGUgaXMgdHJlYXRlZCBhcyB0aGUgaGVhZGVyXG4gICAqL1xuICByZWFkb25seSBoZWFkZXJMaXN0Pzogc3RyaW5nW107XG59XG5cbi8qKlxuICogVGhlIGZvcm1hdCBvZiB0aGUgc291cmNlIGRhdGEuXG4gKi9cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBJbnB1dEZvcm1hdCB7XG4gIC8qKlxuICAgKiBEeW5hbW9EQiBKU09OIGZvcm1hdC5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZHluYW1vREJKc29uKCk6IElucHV0Rm9ybWF0IHtcbiAgICByZXR1cm4gbmV3IChjbGFzcyBleHRlbmRzIElucHV0Rm9ybWF0IHtcbiAgICAgIHB1YmxpYyBfcmVuZGVyKCk6IFBpY2s8XG4gICAgICAgIGR5bmFtb2RiVGFibGUuRHluYW1vZGJUYWJsZUltcG9ydFRhYmxlLFxuICAgICAgICBcImlucHV0Rm9ybWF0XCIgfCBcImlucHV0Rm9ybWF0T3B0aW9uc1wiXG4gICAgICA+IHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBpbnB1dEZvcm1hdDogXCJEWU5BTU9EQl9KU09OXCIsXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfSkoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBbWF6b24gSW9uIGZvcm1hdC5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgaW9uKCk6IElucHV0Rm9ybWF0IHtcbiAgICByZXR1cm4gbmV3IChjbGFzcyBleHRlbmRzIElucHV0Rm9ybWF0IHtcbiAgICAgIHB1YmxpYyBfcmVuZGVyKCk6IFBpY2s8XG4gICAgICAgIGR5bmFtb2RiVGFibGUuRHluYW1vZGJUYWJsZUltcG9ydFRhYmxlLFxuICAgICAgICBcImlucHV0Rm9ybWF0XCIgfCBcImlucHV0Rm9ybWF0T3B0aW9uc1wiXG4gICAgICA+IHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBpbnB1dEZvcm1hdDogXCJJT05cIixcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9KSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIENTViBmb3JtYXQuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGNzdihvcHRpb25zPzogQ3N2T3B0aW9ucyk6IElucHV0Rm9ybWF0IHtcbiAgICBpZiAoXG4gICAgICBvcHRpb25zPy5kZWxpbWl0ZXIgJiZcbiAgICAgICghdGhpcy52YWxpZENzdkRlbGltaXRlcnMuaW5jbHVkZXMob3B0aW9ucy5kZWxpbWl0ZXIpIHx8XG4gICAgICAgIG9wdGlvbnMuZGVsaW1pdGVyLmxlbmd0aCAhPT0gMSlcbiAgICApIHtcbiAgICAgIC8vIHRocm93IG5ldyBVbnNjb3BlZFZhbGlkYXRpb25FcnJvcihcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgW1xuICAgICAgICAgIFwiRGVsaW1pdGVyIG11c3QgYmUgYSBzaW5nbGUgY2hhcmFjdGVyIGFuZCBvbmUgb2YgdGhlIGZvbGxvd2luZzpcIixcbiAgICAgICAgICBgJHt0aGlzLnJlYWRhYmxlVmFsaWRDc3ZEZWxpbWl0ZXJzLmpvaW4oXCIsIFwiKX0sYCxcbiAgICAgICAgICBgZ290ICcke29wdGlvbnMuZGVsaW1pdGVyfSdgLFxuICAgICAgICBdLmpvaW4oXCIgXCIpLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IChjbGFzcyBleHRlbmRzIElucHV0Rm9ybWF0IHtcbiAgICAgIHB1YmxpYyBfcmVuZGVyKCk6IFBpY2s8XG4gICAgICAgIGR5bmFtb2RiVGFibGUuRHluYW1vZGJUYWJsZUltcG9ydFRhYmxlLFxuICAgICAgICBcImlucHV0Rm9ybWF0XCIgfCBcImlucHV0Rm9ybWF0T3B0aW9uc1wiXG4gICAgICA+IHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBpbnB1dEZvcm1hdDogXCJDU1ZcIixcbiAgICAgICAgICBpbnB1dEZvcm1hdE9wdGlvbnM6IG9wdGlvbnNcbiAgICAgICAgICAgID8ge1xuICAgICAgICAgICAgICAgIGNzdjoge1xuICAgICAgICAgICAgICAgICAgZGVsaW1pdGVyOiBvcHRpb25zPy5kZWxpbWl0ZXIsXG4gICAgICAgICAgICAgICAgICBoZWFkZXJMaXN0OiBvcHRpb25zPy5oZWFkZXJMaXN0LFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDogdW5kZWZpbmVkLFxuICAgICAgICB9O1xuICAgICAgfVxuICAgIH0pKCk7XG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyB2YWxpZENzdkRlbGltaXRlcnMgPSBbXCIsXCIsIFwiXFx0XCIsIFwiOlwiLCBcIjtcIiwgXCJ8XCIsIFwiIFwiXTtcbiAgcHJpdmF0ZSBzdGF0aWMgcmVhZGFibGVWYWxpZENzdkRlbGltaXRlcnMgPSBbXG4gICAgXCJjb21tYSAoLClcIixcbiAgICBcInRhYiAoXFxcXHQpXCIsXG4gICAgXCJjb2xvbiAoOilcIixcbiAgICBcInNlbWljb2xvbiAoOylcIixcbiAgICBcInBpcGUgKHwpXCIsXG4gICAgXCJzcGFjZSAoIClcIixcbiAgXTtcblxuICAvKipcbiAgICogQGludGVybmFsXG4gICAqL1xuICBwdWJsaWMgYWJzdHJhY3QgX3JlbmRlcigpOiBQaWNrPFxuICAgIGR5bmFtb2RiVGFibGUuRHluYW1vZGJUYWJsZUltcG9ydFRhYmxlLFxuICAgIFwiaW5wdXRGb3JtYXRcIiB8IFwiaW5wdXRGb3JtYXRPcHRpb25zXCJcbiAgPjtcbn1cblxuLyoqXG4gKiAgUHJvcGVydGllcyBmb3IgaW1wb3J0aW5nIGRhdGEgZnJvbSB0aGUgUzMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSW1wb3J0U291cmNlU3BlY2lmaWNhdGlvbiB7XG4gIC8qKlxuICAgKiBUaGUgY29tcHJlc3Npb24gdHlwZSBvZiB0aGUgaW1wb3J0ZWQgZGF0YS5cbiAgICpcbiAgICogQGRlZmF1bHQgSW5wdXRDb21wcmVzc2lvblR5cGUuTk9ORVxuICAgKi9cbiAgcmVhZG9ubHkgY29tcHJlc3Npb25UeXBlPzogSW5wdXRDb21wcmVzc2lvblR5cGU7XG5cbiAgLyoqXG4gICAqIFRoZSBmb3JtYXQgb2YgdGhlIGltcG9ydGVkIGRhdGEuXG4gICAqL1xuICByZWFkb25seSBpbnB1dEZvcm1hdDogSW5wdXRGb3JtYXQ7XG5cbiAgLyoqXG4gICAqIFRoZSBTMyBidWNrZXQgdGhhdCBpcyBiZWluZyBpbXBvcnRlZCBmcm9tLlxuICAgKi9cbiAgcmVhZG9ubHkgYnVja2V0OiBzdG9yYWdlLklCdWNrZXQ7XG5cbiAgLyoqXG4gICAqIFRoZSBhY2NvdW50IG51bWJlciBvZiB0aGUgUzMgYnVja2V0IHRoYXQgaXMgYmVpbmcgaW1wb3J0ZWQgZnJvbS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyB2YWx1ZVxuICAgKi9cbiAgcmVhZG9ubHkgYnVja2V0T3duZXI/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBrZXkgcHJlZml4IHNoYXJlZCBieSBhbGwgUzMgT2JqZWN0cyB0aGF0IGFyZSBiZWluZyBpbXBvcnRlZC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyB2YWx1ZVxuICAgKi9cbiAgcmVhZG9ubHkga2V5UHJlZml4Pzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRoZSBwcmVjaXNpb24gYXNzb2NpYXRlZCB3aXRoIHRoZSBEeW5hbW9EQiB3cml0ZSB0aW1lc3RhbXBzIHRoYXQgd2lsbCBiZSByZXBsaWNhdGVkIHRvIEtpbmVzaXMuXG4gKiBUaGUgZGVmYXVsdCBzZXR0aW5nIGZvciByZWNvcmQgdGltZXN0YW1wIHByZWNpc2lvbiBpcyBtaWNyb3NlY29uZHMuIFlvdSBjYW4gY2hhbmdlIHRoaXMgc2V0dGluZyBhdCBhbnkgdGltZS5cbiAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0Nsb3VkRm9ybWF0aW9uL2xhdGVzdC9Vc2VyR3VpZGUvYXdzLXByb3BlcnRpZXMtZHluYW1vZGItdGFibGUta2luZXNpc3N0cmVhbXNwZWNpZmljYXRpb24uaHRtbCNhd3MtcHJvcGVydGllcy1keW5hbW9kYi10YWJsZS1raW5lc2lzc3RyZWFtc3BlY2lmaWNhdGlvbi1wcm9wZXJ0aWVzXG4gKi9cbmV4cG9ydCBlbnVtIEFwcHJveGltYXRlQ3JlYXRpb25EYXRlVGltZVByZWNpc2lvbiB7XG4gIC8qKlxuICAgKiBNaWxsaXNlY29uZCBwcmVjaXNpb25cbiAgICovXG4gIE1JTExJU0VDT05EID0gXCJNSUxMSVNFQ09ORFwiLFxuXG4gIC8qKlxuICAgKiBNaWNyb3NlY29uZCBwcmVjaXNpb25cbiAgICovXG4gIE1JQ1JPU0VDT05EID0gXCJNSUNST1NFQ09ORFwiLFxufVxuXG5leHBvcnQgaW50ZXJmYWNlIER5bmFtb2RiVGFibGVSZXBsaWNhIHtcbiAgLyoqIChPcHRpb25hbCkgQVJOIG9mIHRoZSBDTUsgdGhhdCBzaG91bGQgYmUgdXNlZCBmb3IgdGhlIEFXUyBLTVMgZW5jcnlwdGlvbi4gVGhpcyBhcmd1bWVudCBzaG91bGQgb25seSBiZSB1c2VkIGlmIHRoZSBrZXkgaXMgZGlmZmVyZW50IGZyb20gdGhlIGRlZmF1bHQgS01TLW1hbmFnZWQgRHluYW1vREIga2V5LCBgYWxpYXMvYXdzL2R5bmFtb2RiYC4gKipOb3RlOioqIFRoaXMgYXR0cmlidXRlIHdpbGwgX25vdF8gYmUgcG9wdWxhdGVkIHdpdGggdGhlIEFSTiBvZiBfZGVmYXVsdF8ga2V5cy4gKi9cbiAgcmVhZG9ubHkgZW5jcnlwdGlvbktleT86IGttcy5JS2V5O1xuICAvKiogKE9wdGlvbmFsKSBXaGV0aGVyIHRvIGVuYWJsZSBQb2ludCBJbiBUaW1lIFJlY292ZXJ5IGZvciB0aGUgcmVwbGljYS4gRGVmYXVsdCBpcyBgZmFsc2VgLiAqL1xuICByZWFkb25seSBwb2ludEluVGltZVJlY292ZXJ5PzogYm9vbGVhbjtcbiAgLyoqIChPcHRpb25hbCkgV2hldGhlciB0byBwcm9wYWdhdGUgdGhlIGdsb2JhbCB0YWJsZSdzIHRhZ3MgdG8gYSByZXBsaWNhLiBEZWZhdWx0IGlzIGBmYWxzZWAuIENoYW5nZXMgdG8gdGFncyBvbmx5IG1vdmUgaW4gb25lIGRpcmVjdGlvbjogZnJvbSBnbG9iYWwgKHNvdXJjZSkgdG8gcmVwbGljYS4gSW4gb3RoZXIgd29yZHMsIHRhZyBkcmlmdCBvbiBhIHJlcGxpY2Egd2lsbCBub3QgdHJpZ2dlciBhbiB1cGRhdGUuIFRhZyBvciByZXBsaWNhIGNoYW5nZXMgb24gdGhlIGdsb2JhbCB0YWJsZSwgd2hldGhlciBmcm9tIGRyaWZ0IG9yIGNvbmZpZ3VyYXRpb24gY2hhbmdlcywgYXJlIHByb3BhZ2F0ZWQgdG8gcmVwbGljYXMuIENoYW5naW5nIGZyb20gYHRydWVgIHRvIGBmYWxzZWAgb24gYSBzdWJzZXF1ZW50IGBhcHBseWAgbWVhbnMgcmVwbGljYSB0YWdzIGFyZSBsZWZ0IGFzIHRoZXkgd2VyZSwgdW5tYW5hZ2VkLCBub3QgZGVsZXRlZC4gKi9cbiAgcmVhZG9ubHkgcHJvcGFnYXRlVGFncz86IGJvb2xlYW47XG4gIC8qKiAoUmVxdWlyZWQpIFJlZ2lvbiBuYW1lIG9mIHRoZSByZXBsaWNhLiAqL1xuICByZWFkb25seSByZWdpb25OYW1lOiBzdHJpbmc7XG59XG5cbi8qKlxuICogUHJvcGVydGllcyBvZiBhIER5bmFtb0RCIFRhYmxlXG4gKlxuICogVXNlIGBUYWJsZVByb3BzYCBmb3IgYWxsIHRhYmxlIHByb3BlcnRpZXNcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBUYWJsZU9wdGlvbnMgZXh0ZW5kcyBTY2hlbWFPcHRpb25zIHtcbiAgLyoqXG4gICAqIFRoZSByZWFkIGNhcGFjaXR5IGZvciB0aGUgdGFibGUuIENhcmVmdWwgaWYgeW91IGFkZCBHbG9iYWwgU2Vjb25kYXJ5IEluZGV4ZXMsIGFzXG4gICAqIHRob3NlIHdpbGwgc2hhcmUgdGhlIHRhYmxlJ3MgcHJvdmlzaW9uZWQgdGhyb3VnaHB1dC5cbiAgICpcbiAgICogQ2FuIG9ubHkgYmUgcHJvdmlkZWQgaWYgYmlsbGluZ01vZGUgaXMgUHJvdmlzaW9uZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IDVcbiAgICovXG4gIHJlYWRvbmx5IHJlYWRDYXBhY2l0eT86IG51bWJlcjtcbiAgLyoqXG4gICAqIFRoZSB3cml0ZSBjYXBhY2l0eSBmb3IgdGhlIHRhYmxlLiBDYXJlZnVsIGlmIHlvdSBhZGQgR2xvYmFsIFNlY29uZGFyeSBJbmRleGVzLCBhc1xuICAgKiB0aG9zZSB3aWxsIHNoYXJlIHRoZSB0YWJsZSdzIHByb3Zpc2lvbmVkIHRocm91Z2hwdXQuXG4gICAqXG4gICAqIENhbiBvbmx5IGJlIHByb3ZpZGVkIGlmIGJpbGxpbmdNb2RlIGlzIFByb3Zpc2lvbmVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCA1XG4gICAqL1xuICByZWFkb25seSB3cml0ZUNhcGFjaXR5PzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBUaGUgbWF4aW11bSByZWFkIHJlcXVlc3QgdW5pdHMgZm9yIHRoZSB0YWJsZS4gQ2FyZWZ1bCBpZiB5b3UgYWRkIEdsb2JhbCBTZWNvbmRhcnkgSW5kZXhlcywgYXNcbiAgICogdGhvc2Ugd2lsbCBzaGFyZSB0aGUgdGFibGUncyBtYXhpbXVtIG9uLWRlbWFuZCB0aHJvdWdocHV0LlxuICAgKlxuICAgKiBDYW4gb25seSBiZSBwcm92aWRlZCBpZiBiaWxsaW5nTW9kZSBpcyBQQVlfUEVSX1JFUVVFU1QuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gb24tZGVtYW5kIHRocm91Z2hwdXQgaXMgZGlzYWJsZWRcbiAgICovXG4gIHJlYWRvbmx5IG1heFJlYWRSZXF1ZXN0VW5pdHM/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBUaGUgd3JpdGUgcmVxdWVzdCB1bml0cyBmb3IgdGhlIHRhYmxlLiBDYXJlZnVsIGlmIHlvdSBhZGQgR2xvYmFsIFNlY29uZGFyeSBJbmRleGVzLCBhc1xuICAgKiB0aG9zZSB3aWxsIHNoYXJlIHRoZSB0YWJsZSdzIG1heGltdW0gb24tZGVtYW5kIHRocm91Z2hwdXQuXG4gICAqXG4gICAqIENhbiBvbmx5IGJlIHByb3ZpZGVkIGlmIGJpbGxpbmdNb2RlIGlzIFBBWV9QRVJfUkVRVUVTVC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBvbi1kZW1hbmQgdGhyb3VnaHB1dCBpcyBkaXNhYmxlZFxuICAgKi9cbiAgcmVhZG9ubHkgbWF4V3JpdGVSZXF1ZXN0VW5pdHM/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFNwZWNpZnkgaG93IHlvdSBhcmUgY2hhcmdlZCBmb3IgcmVhZCBhbmQgd3JpdGUgdGhyb3VnaHB1dCBhbmQgaG93IHlvdSBtYW5hZ2UgY2FwYWNpdHkuXG4gICAqXG4gICAqIEBkZWZhdWx0IFBST1ZJU0lPTkVEIGlmIGByZXBsaWNhdGlvblJlZ2lvbnNgIGlzIG5vdCBzcGVjaWZpZWQsIFBBWV9QRVJfUkVRVUVTVCBvdGhlcndpc2VcbiAgICovXG4gIHJlYWRvbmx5IGJpbGxpbmdNb2RlPzogQmlsbGluZ01vZGU7XG5cbiAgLy8gVE9ETzogaHR0cHM6Ly9naXRodWIuY29tL2hhc2hpY29ycC90ZXJyYWZvcm0tcHJvdmlkZXItYXdzL2lzc3Vlcy80MzE0MlxuICAvLyByZWFkb25seSB3YXJtVGhyb3VnaHB1dD86IFdhcm1UaHJvdWdocHV0O1xuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHBvaW50LWluLXRpbWUgcmVjb3ZlcnkgaXMgZW5hYmxlZC5cbiAgICogQGRlcHJlY2F0ZWQgdXNlIGBwb2ludEluVGltZVJlY292ZXJ5U3BlY2lmaWNhdGlvbmAgaW5zdGVhZFxuICAgKiBAZGVmYXVsdCBmYWxzZSAtIHBvaW50IGluIHRpbWUgcmVjb3ZlcnkgaXMgbm90IGVuYWJsZWQuXG4gICAqL1xuICByZWFkb25seSBwb2ludEluVGltZVJlY292ZXJ5PzogYm9vbGVhbjtcblxuICAvKipcbiAgICogV2hldGhlciBwb2ludC1pbi10aW1lIHJlY292ZXJ5IGlzIGVuYWJsZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gcG9pbnQgaW4gdGltZSByZWNvdmVyeSBpcyBub3QgZW5hYmxlZC5cbiAgICovXG4gIHJlYWRvbmx5IHBvaW50SW5UaW1lUmVjb3ZlcnlTcGVjaWZpY2F0aW9uPzogUG9pbnRJblRpbWVSZWNvdmVyeVNwZWNpZmljYXRpb247XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgc2VydmVyLXNpZGUgZW5jcnlwdGlvbiB3aXRoIGFuIEFXUyBtYW5hZ2VkIGN1c3RvbWVyIG1hc3RlciBrZXkgaXMgZW5hYmxlZC5cbiAgICpcbiAgICogVGhpcyBwcm9wZXJ0eSBjYW5ub3QgYmUgc2V0IGlmIGBlbmNyeXB0aW9uYCBhbmQvb3IgYGVuY3J5cHRpb25LZXlgIGlzIHNldC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBUaGUgdGFibGUgaXMgZW5jcnlwdGVkIHdpdGggYW4gZW5jcnlwdGlvbiBrZXkgbWFuYWdlZCBieSBEeW5hbW9EQiwgYW5kIHlvdSBhcmUgbm90IGNoYXJnZWQgYW55IGZlZSBmb3IgdXNpbmcgaXQuXG4gICAqXG4gICAqIEBkZXByZWNhdGVkIFRoaXMgcHJvcGVydHkgaXMgZGVwcmVjYXRlZC4gSW4gb3JkZXIgdG8gb2J0YWluIHRoZSBzYW1lIGJlaGF2aW9yIGFzXG4gICAqIGVuYWJsaW5nIHRoaXMsIHNldCB0aGUgYGVuY3J5cHRpb25gIHByb3BlcnR5IHRvIGBUYWJsZUVuY3J5cHRpb24uQVdTX01BTkFHRURgIGluc3RlYWQuXG4gICAqL1xuICByZWFkb25seSBzZXJ2ZXJTaWRlRW5jcnlwdGlvbj86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFNwZWNpZnkgdGhlIHRhYmxlIGNsYXNzLlxuICAgKiBAZGVmYXVsdCBTVEFOREFSRFxuICAgKi9cbiAgcmVhZG9ubHkgdGFibGVDbGFzcz86IFRhYmxlQ2xhc3M7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgc2VydmVyLXNpZGUgZW5jcnlwdGlvbiB3aXRoIGFuIEFXUyBtYW5hZ2VkIGN1c3RvbWVyIG1hc3RlciBrZXkgaXMgZW5hYmxlZC5cbiAgICpcbiAgICogVGhpcyBwcm9wZXJ0eSBjYW5ub3QgYmUgc2V0IGlmIGBzZXJ2ZXJTaWRlRW5jcnlwdGlvbmAgaXMgc2V0LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIFRoZSB0YWJsZSBpcyBlbmNyeXB0ZWQgd2l0aCBhbiBlbmNyeXB0aW9uIGtleSBtYW5hZ2VkIGJ5IER5bmFtb0RCLCBhbmQgeW91IGFyZSBub3QgY2hhcmdlZCBhbnkgZmVlIGZvciB1c2luZyBpdC5cbiAgICovXG4gIHJlYWRvbmx5IGVuY3J5cHRpb24/OiBUYWJsZUVuY3J5cHRpb247XG5cbiAgLyoqXG4gICAqIEV4dGVybmFsIEtNUyBrZXkgdG8gdXNlIGZvciB0YWJsZSBlbmNyeXB0aW9uLlxuICAgKlxuICAgKiBUaGlzIHByb3BlcnR5IGNhbiBvbmx5IGJlIHNldCBpZiBgZW5jcnlwdGlvbmAgaXMgc2V0IHRvIGBUYWJsZUVuY3J5cHRpb24uQ1VTVE9NRVJfTUFOQUdFRGAuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gSWYgYGVuY3J5cHRpb25gIGlzIHNldCB0byBgVGFibGVFbmNyeXB0aW9uLkNVU1RPTUVSX01BTkFHRURgIGFuZCB0aGlzXG4gICAqIHByb3BlcnR5IGlzIHVuZGVmaW5lZCwgYSBuZXcgS01TIGtleSB3aWxsIGJlIGNyZWF0ZWQgYW5kIGFzc29jaWF0ZWQgd2l0aCB0aGlzIHRhYmxlLlxuICAgKiBJZiBgZW5jcnlwdGlvbmAgYW5kIHRoaXMgcHJvcGVydHkgYXJlIGJvdGggdW5kZWZpbmVkLCB0aGVuIHRoZSB0YWJsZSBpcyBlbmNyeXB0ZWQgd2l0aFxuICAgKiBhbiBlbmNyeXB0aW9uIGtleSBtYW5hZ2VkIGJ5IER5bmFtb0RCLCBhbmQgeW91IGFyZSBub3QgY2hhcmdlZCBhbnkgZmVlIGZvciB1c2luZyBpdC5cbiAgICovXG4gIHJlYWRvbmx5IGVuY3J5cHRpb25LZXk/OiBrbXMuSUtleTtcblxuICAvKipcbiAgICogVGhlIG5hbWUgb2YgVFRMIGF0dHJpYnV0ZS5cbiAgICogQGRlZmF1bHQgLSBUVEwgaXMgZGlzYWJsZWRcbiAgICovXG4gIHJlYWRvbmx5IHRpbWVUb0xpdmVBdHRyaWJ1dGU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFdoZW4gYW4gaXRlbSBpbiB0aGUgdGFibGUgaXMgbW9kaWZpZWQsIFN0cmVhbVZpZXdUeXBlIGRldGVybWluZXMgd2hhdCBpbmZvcm1hdGlvblxuICAgKiBpcyB3cml0dGVuIHRvIHRoZSBzdHJlYW0gZm9yIHRoaXMgdGFibGUuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gc3RyZWFtcyBhcmUgZGlzYWJsZWQgdW5sZXNzIGByZXBsaWNhdGlvblJlZ2lvbnNgIGlzIHNwZWNpZmllZFxuICAgKi9cbiAgcmVhZG9ubHkgc3RyZWFtPzogU3RyZWFtVmlld1R5cGU7XG5cbiAgLyoqXG4gICAqIFJlZ2lvbnMgd2hlcmUgcmVwbGljYSB0YWJsZXMgd2lsbCBiZSBjcmVhdGVkXG4gICAqXG4gICAqIEBkZXByZWNhdGVkIHVzZSByZXBsaWNhU3BlY2lmaWNhdGlvbiBpbnN0ZWFkXG4gICAqIEBkZWZhdWx0IC0gbm8gcmVwbGljYSB0YWJsZXMgYXJlIGNyZWF0ZWRcbiAgICovXG4gIHJlYWRvbmx5IHJlcGxpY2F0aW9uUmVnaW9ucz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBUaGUgc3BlY2lmaWNhdGlvbiBmb3IgcmVwbGljYSB0YWJsZXMuXG4gICAqL1xuICByZWFkb25seSByZXBsaWNhU3BlY2lmaWNhdGlvbj86IER5bmFtb2RiVGFibGVSZXBsaWNhW107XG5cbiAgLy8gcmVhZG9ubHkgcmVwbGljYXRpb25UaW1lb3V0PzogRHVyYXRpb247IC8vIE5vdCBkaXJlY3RseSBhcHBsaWNhYmxlIHRvIFRGJ3MgcmVwbGljYSBibG9jayBjb25maWd1cmF0aW9uXG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgQ2xvdWRXYXRjaCBjb250cmlidXRvciBpbnNpZ2h0cyBpcyBlbmFibGVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgY29udHJpYnV0b3JJbnNpZ2h0c0VuYWJsZWQ/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBFbmFibGVzIGRlbGV0aW9uIHByb3RlY3Rpb24gZm9yIHRoZSB0YWJsZS5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGRlbGV0aW9uUHJvdGVjdGlvbj86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFRoZSBwcm9wZXJ0aWVzIG9mIGRhdGEgYmVpbmcgaW1wb3J0ZWQgZnJvbSB0aGUgUzMgYnVja2V0IHNvdXJjZSB0byB0aGUgdGFibGUuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm8gZGF0YSBpbXBvcnQgZnJvbSB0aGUgUzMgYnVja2V0XG4gICAqL1xuICByZWFkb25seSBpbXBvcnRTb3VyY2U/OiBJbXBvcnRTb3VyY2VTcGVjaWZpY2F0aW9uO1xuXG4gIC8qKlxuICAgKiBSZXNvdXJjZSBwb2xpY3kgdG8gYXNzaWduIHRvIHRhYmxlLlxuICAgKiBOb3RlOiBgYXdzX2R5bmFtb2RiX3RhYmxlYCBkb2VzIG5vdCBkaXJlY3RseSBzdXBwb3J0IGEgcmVzb3VyY2UgcG9saWN5IHByb3BlcnR5LlxuICAgKiBUaGlzIHBvbGljeSB3b3VsZCBuZWVkIHRvIGJlIG1hbmFnZWQgYW5kIGFwcGxpZWQgc2VwYXJhdGVseSwgZS5nLiwgdmlhIGBhd3NfaWFtX3BvbGljeWAgYXR0YWNoZWQgdG8gcHJpbmNpcGFscy5cbiAgICogQGRlZmF1bHQgLSBObyByZXNvdXJjZSBwb2xpY3kgc3RhdGVtZW50XG4gICAqL1xuICByZWFkb25seSByZXNvdXJjZVBvbGljeT86IGlhbS5Qb2xpY3lEb2N1bWVudDtcbn1cblxuLyoqXG4gKiBQcm9wZXJ0aWVzIGZvciBhIER5bmFtb0RCIFRhYmxlXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVGFibGVQcm9wcyBleHRlbmRzIFRhYmxlT3B0aW9ucywgQXdzQ29uc3RydWN0UHJvcHMge1xuICAvKipcbiAgICogRW5mb3JjZXMgYSBwYXJ0aWN1bGFyIHBoeXNpY2FsIHRhYmxlIG5hbWUuXG4gICAqIEBkZWZhdWx0IDxnZW5lcmF0ZWQ+XG4gICAqL1xuICByZWFkb25seSB0YWJsZU5hbWU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEtpbmVzaXMgRGF0YSBTdHJlYW0gdG8gY2FwdHVyZSBpdGVtLWxldmVsIGNoYW5nZXMgZm9yIHRoZSB0YWJsZS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBLaW5lc2lzIERhdGEgU3RyZWFtXG4gICAqL1xuICByZWFkb25seSBraW5lc2lzU3RyZWFtPzoga2luZXNpcy5JU3RyZWFtO1xuXG4gIC8qKlxuICAgKiBLaW5lc2lzIERhdGEgU3RyZWFtIGFwcHJveGltYXRlIGNyZWF0aW9uIHRpbWVzdGFtcCBwcmVjaXNpb25cbiAgICpcbiAgICogQGRlZmF1bHQgQXBwcm94aW1hdGVDcmVhdGlvbkRhdGVUaW1lUHJlY2lzaW9uLk1JQ1JPU0VDT05EXG4gICAqL1xuICByZWFkb25seSBraW5lc2lzUHJlY2lzaW9uVGltZXN0YW1wPzogQXBwcm94aW1hdGVDcmVhdGlvbkRhdGVUaW1lUHJlY2lzaW9uO1xufVxuXG4vKipcbiAqIFByb3BlcnRpZXMgZm9yIGEgZ2xvYmFsIHNlY29uZGFyeSBpbmRleFxuICovXG5leHBvcnQgaW50ZXJmYWNlIEdsb2JhbFNlY29uZGFyeUluZGV4UHJvcHNcbiAgZXh0ZW5kcyBTZWNvbmRhcnlJbmRleFByb3BzLFxuICAgIFNjaGVtYU9wdGlvbnMge1xuICAvKipcbiAgICogVGhlIHJlYWQgY2FwYWNpdHkgZm9yIHRoZSBnbG9iYWwgc2Vjb25kYXJ5IGluZGV4LlxuICAgKlxuICAgKiBDYW4gb25seSBiZSBwcm92aWRlZCBpZiB0YWJsZSBiaWxsaW5nTW9kZSBpcyBQcm92aXNpb25lZCBvciB1bmRlZmluZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IDVcbiAgICovXG4gIHJlYWRvbmx5IHJlYWRDYXBhY2l0eT86IG51bWJlcjtcblxuICAvKipcbiAgICogVGhlIHdyaXRlIGNhcGFjaXR5IGZvciB0aGUgZ2xvYmFsIHNlY29uZGFyeSBpbmRleC5cbiAgICpcbiAgICogQ2FuIG9ubHkgYmUgcHJvdmlkZWQgaWYgdGFibGUgYmlsbGluZ01vZGUgaXMgUHJvdmlzaW9uZWQgb3IgdW5kZWZpbmVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCA1XG4gICAqL1xuICByZWFkb25seSB3cml0ZUNhcGFjaXR5PzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBUaGUgbWF4aW11bSByZWFkIHJlcXVlc3QgdW5pdHMgZm9yIHRoZSBnbG9iYWwgc2Vjb25kYXJ5IGluZGV4LlxuICAgKlxuICAgKiBDYW4gb25seSBiZSBwcm92aWRlZCBpZiB0YWJsZSBiaWxsaW5nTW9kZSBpcyBQQVlfUEVSX1JFUVVFU1QuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gb24tZGVtYW5kIHRocm91Z2hwdXQgaXMgZGlzYWJsZWRcbiAgICovXG4gIHJlYWRvbmx5IG1heFJlYWRSZXF1ZXN0VW5pdHM/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFRoZSBtYXhpbXVtIHdyaXRlIHJlcXVlc3QgdW5pdHMgZm9yIHRoZSBnbG9iYWwgc2Vjb25kYXJ5IGluZGV4LlxuICAgKlxuICAgKiBDYW4gb25seSBiZSBwcm92aWRlZCBpZiB0YWJsZSBiaWxsaW5nTW9kZSBpcyBQQVlfUEVSX1JFUVVFU1QuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gb24tZGVtYW5kIHRocm91Z2hwdXQgaXMgZGlzYWJsZWRcbiAgICovXG4gIHJlYWRvbmx5IG1heFdyaXRlUmVxdWVzdFVuaXRzPzogbnVtYmVyO1xuXG4gIC8vIFRPRE86IGh0dHBzOi8vZ2l0aHViLmNvbS9oYXNoaWNvcnAvdGVycmFmb3JtLXByb3ZpZGVyLWF3cy9pc3N1ZXMvNDMxNDJcbiAgLy8gcmVhZG9ubHkgd2FybVRocm91Z2hwdXQ/OiBXYXJtVGhyb3VnaHB1dDtcblxuICAvKipcbiAgICogV2hldGhlciBDbG91ZFdhdGNoIGNvbnRyaWJ1dG9yIGluc2lnaHRzIGlzIGVuYWJsZWQgZm9yIHRoZSBzcGVjaWZpZWQgZ2xvYmFsIHNlY29uZGFyeSBpbmRleC5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGNvbnRyaWJ1dG9ySW5zaWdodHNFbmFibGVkPzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBSZWZlcmVuY2UgdG8gYSBkeW5hbW9kYiB0YWJsZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBUYWJsZUF0dHJpYnV0ZXMge1xuICAvKipcbiAgICogVGhlIEFSTiBvZiB0aGUgZHluYW1vZGIgdGFibGUuXG4gICAqIE9uZSBvZiB0aGlzLCBvciBgdGFibGVOYW1lYCwgaXMgcmVxdWlyZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm8gdGFibGUgYXJuXG4gICAqL1xuICByZWFkb25seSB0YWJsZUFybj86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIHRhYmxlIG5hbWUgb2YgdGhlIGR5bmFtb2RiIHRhYmxlLlxuICAgKiBPbmUgb2YgdGhpcywgb3IgYHRhYmxlQXJuYCwgaXMgcmVxdWlyZWQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm8gdGFibGUgbmFtZVxuICAgKi9cbiAgcmVhZG9ubHkgdGFibGVOYW1lPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgQVJOIG9mIHRoZSB0YWJsZSdzIHN0cmVhbS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyB0YWJsZSBzdHJlYW1cbiAgICovXG4gIHJlYWRvbmx5IHRhYmxlU3RyZWFtQXJuPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBLTVMgZW5jcnlwdGlvbiBrZXksIGlmIHRoaXMgdGFibGUgdXNlcyBhIGN1c3RvbWVyLW1hbmFnZWQgZW5jcnlwdGlvbiBrZXkuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm8ga2V5XG4gICAqL1xuICByZWFkb25seSBlbmNyeXB0aW9uS2V5Pzoga21zLklLZXk7XG5cbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIHRoZSBnbG9iYWwgaW5kZXhlcyBzZXQgZm9yIHRoaXMgVGFibGUuXG4gICAqIE5vdGUgdGhhdCB5b3UgbmVlZCB0byBzZXQgZWl0aGVyIHRoaXMgcHJvcGVydHksXG4gICAqIG9yIGBsb2NhbEluZGV4ZXNgLFxuICAgKiBpZiB5b3Ugd2FudCBtZXRob2RzIGxpa2UgZ3JhbnRSZWFkRGF0YSgpXG4gICAqIHRvIGdyYW50IHBlcm1pc3Npb25zIGZvciBpbmRleGVzIGFzIHdlbGwgYXMgdGhlIHRhYmxlIGl0c2VsZi5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBubyBnbG9iYWwgaW5kZXhlc1xuICAgKi9cbiAgcmVhZG9ubHkgZ2xvYmFsSW5kZXhlcz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgbG9jYWwgaW5kZXhlcyBzZXQgZm9yIHRoaXMgVGFibGUuXG4gICAqIE5vdGUgdGhhdCB5b3UgbmVlZCB0byBzZXQgZWl0aGVyIHRoaXMgcHJvcGVydHksXG4gICAqIG9yIGBnbG9iYWxJbmRleGVzYCxcbiAgICogaWYgeW91IHdhbnQgbWV0aG9kcyBsaWtlIGdyYW50UmVhZERhdGEoKVxuICAgKiB0byBncmFudCBwZXJtaXNzaW9ucyBmb3IgaW5kZXhlcyBhcyB3ZWxsIGFzIHRoZSB0YWJsZSBpdHNlbGYuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gbm8gbG9jYWwgaW5kZXhlc1xuICAgKi9cbiAgcmVhZG9ubHkgbG9jYWxJbmRleGVzPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIElmIHNldCB0byB0cnVlLCBncmFudCBtZXRob2RzIGFsd2F5cyBncmFudCBwZXJtaXNzaW9ucyBmb3IgYWxsIGluZGV4ZXMuXG4gICAqIElmIGZhbHNlIGlzIHByb3ZpZGVkLCBncmFudCBtZXRob2RzIGdyYW50IHRoZSBwZXJtaXNzaW9uc1xuICAgKiBvbmx5IHdoZW4gYGdsb2JhbEluZGV4ZXNgIG9yIGBsb2NhbEluZGV4ZXNgIGlzIHNwZWNpZmllZC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgZ3JhbnRJbmRleFBlcm1pc3Npb25zPzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIFRhYmxlQmFzZVxuICBleHRlbmRzIEF3c0NvbnN0cnVjdEJhc2VcbiAgaW1wbGVtZW50cyBJVGFibGUsIGlhbS5JQXdzQ29uc3RydWN0V2l0aFBvbGljeVxue1xuICBwdWJsaWMgYWJzdHJhY3QgcmVhZG9ubHkgdGFibGVBcm46IHN0cmluZztcbiAgcHVibGljIGFic3RyYWN0IHJlYWRvbmx5IHRhYmxlTmFtZTogc3RyaW5nO1xuICBwdWJsaWMgYWJzdHJhY3QgcmVhZG9ubHkgdGFibGVTdHJlYW1Bcm4/OiBzdHJpbmc7XG4gIHB1YmxpYyBhYnN0cmFjdCByZWFkb25seSBlbmNyeXB0aW9uS2V5Pzoga21zLklLZXk7XG4gIHB1YmxpYyBhYnN0cmFjdCByZXNvdXJjZVBvbGljeT86IGlhbS5Qb2xpY3lEb2N1bWVudDtcblxuICBwcm90ZWN0ZWQgcmVhZG9ubHkgcmVnaW9uYWxBcm5zID0gbmV3IEFycmF5PHN0cmluZz4oKTtcblxuICBwdWJsaWMgZ2V0IG91dHB1dHMoKTogUmVjb3JkPHN0cmluZywgYW55PiB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHRhYmxlQXJuOiB0aGlzLnRhYmxlQXJuLFxuICAgICAgdGFibGVOYW1lOiB0aGlzLnRhYmxlTmFtZSxcbiAgICAgIHRhYmxlU3RyZWFtQXJuOiB0aGlzLnRhYmxlU3RyZWFtQXJuLFxuICAgIH07XG4gIH1cblxuICBwdWJsaWMgZ3JhbnQoZ3JhbnRlZTogaWFtLklHcmFudGFibGUsIC4uLmFjdGlvbnM6IHN0cmluZ1tdKTogaWFtLkdyYW50IHtcbiAgICBjb25zdCByZXNvdXJjZXMgPSBbXG4gICAgICB0aGlzLnRhYmxlQXJuLFxuICAgICAgTGF6eS5zdHJpbmdWYWx1ZSh7XG4gICAgICAgIHByb2R1Y2U6ICgpID0+ICh0aGlzLmhhc0luZGV4ID8gYCR7dGhpcy50YWJsZUFybn0vaW5kZXgvKmAgOiB1bmRlZmluZWQpLFxuICAgICAgfSksXG4gICAgICAuLi50aGlzLnJlZ2lvbmFsQXJucyxcbiAgICAgIC4uLnRoaXMucmVnaW9uYWxBcm5zLm1hcCgoYXJuKSA9PlxuICAgICAgICBMYXp5LnN0cmluZ1ZhbHVlKHtcbiAgICAgICAgICBwcm9kdWNlOiAoKSA9PiAodGhpcy5oYXNJbmRleCA/IGAke2Fybn0vaW5kZXgvKmAgOiB1bmRlZmluZWQpLFxuICAgICAgICB9KSxcbiAgICAgICksXG4gICAgXTtcblxuICAgIHJldHVybiBpYW0uR3JhbnQuYWRkVG9QcmluY2lwYWxPclJlc291cmNlKHtcbiAgICAgIGdyYW50ZWUsXG4gICAgICBhY3Rpb25zLFxuICAgICAgcmVzb3VyY2VBcm5zOiByZXNvdXJjZXMuZmlsdGVyKChyKSA9PiByICE9PSB1bmRlZmluZWQpLFxuICAgICAgcmVzb3VyY2U6IHRoaXMsIC8vIEdyYW50IHdpbGwgdGFrZSB0aGUgcHJpbmNpcGFsIGZyb20gdGhlIGdyYW50ZWVcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBncmFudFN0cmVhbShncmFudGVlOiBpYW0uSUdyYW50YWJsZSwgLi4uYWN0aW9uczogc3RyaW5nW10pOiBpYW0uR3JhbnQge1xuICAgIGlmICghdGhpcy50YWJsZVN0cmVhbUFybikge1xuICAgICAgLy8gdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYER5bmFtb0RCIFN0cmVhbXMgbXVzdCBiZSBlbmFibGVkIG9uIHRoZSB0YWJsZSAke3RoaXMubm9kZS5wYXRofWAsXG4gICAgICAgIC8vIHRoaXMsXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiBpYW0uR3JhbnQuYWRkVG9QcmluY2lwYWwoe1xuICAgICAgZ3JhbnRlZSxcbiAgICAgIGFjdGlvbnMsXG4gICAgICByZXNvdXJjZUFybnM6IFt0aGlzLnRhYmxlU3RyZWFtQXJuXSxcbiAgICAgIHNjb3BlOiB0aGlzLFxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIGdyYW50UmVhZERhdGEoZ3JhbnRlZTogaWFtLklHcmFudGFibGUpOiBpYW0uR3JhbnQge1xuICAgIGNvbnN0IHRhYmxlQWN0aW9ucyA9IHBlcm1zLlJFQURfREFUQV9BQ1RJT05TX1RBQkxFX1NBRkUuY29uY2F0KFxuICAgICAgcGVybXMuREVTQ1JJQkVfVEFCTEUsXG4gICAgKTtcblxuICAgIC8vIElmIHN0cmVhbXMgYXJlIGF2YWlsYWJsZSwgYWxzbyBncmFudCBzdHJlYW0tc3BlY2lmaWMgYWN0aW9uc1xuICAgIGlmICh0aGlzLnRhYmxlU3RyZWFtQXJuKSB7XG4gICAgICByZXR1cm4gdGhpcy5jb21iaW5lZEdyYW50KGdyYW50ZWUsIHtcbiAgICAgICAga2V5QWN0aW9uczogcGVybXMuS0VZX1JFQURfQUNUSU9OUyxcbiAgICAgICAgdGFibGVBY3Rpb25zLFxuICAgICAgICBzdHJlYW1BY3Rpb25zOiBwZXJtcy5SRUFEX0RBVEFfQUNUSU9OU19TVFJFQU1fT05MWSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmNvbWJpbmVkR3JhbnQoZ3JhbnRlZSwge1xuICAgICAga2V5QWN0aW9uczogcGVybXMuS0VZX1JFQURfQUNUSU9OUyxcbiAgICAgIHRhYmxlQWN0aW9ucyxcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBncmFudFRhYmxlTGlzdFN0cmVhbXMoZ3JhbnRlZTogaWFtLklHcmFudGFibGUpOiBpYW0uR3JhbnQge1xuICAgIGlmICghdGhpcy50YWJsZVN0cmVhbUFybikge1xuICAgICAgLy8gdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYER5bmFtb0RCIFN0cmVhbXMgbXVzdCBiZSBlbmFibGVkIG9uIHRoZSB0YWJsZSAke3RoaXMubm9kZS5wYXRofWAsXG4gICAgICAgIC8vIHRoaXMsXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiBpYW0uR3JhbnQuYWRkVG9QcmluY2lwYWwoe1xuICAgICAgZ3JhbnRlZSxcbiAgICAgIGFjdGlvbnM6IFtcImR5bmFtb2RiOkxpc3RTdHJlYW1zXCJdLFxuICAgICAgcmVzb3VyY2VBcm5zOiBbXCIqXCJdLFxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIGdyYW50U3RyZWFtUmVhZChncmFudGVlOiBpYW0uSUdyYW50YWJsZSk6IGlhbS5HcmFudCB7XG4gICAgdGhpcy5ncmFudFRhYmxlTGlzdFN0cmVhbXMoZ3JhbnRlZSk7XG4gICAgcmV0dXJuIHRoaXMuY29tYmluZWRHcmFudChncmFudGVlLCB7XG4gICAgICBrZXlBY3Rpb25zOiBwZXJtcy5LRVlfUkVBRF9BQ1RJT05TLFxuICAgICAgc3RyZWFtQWN0aW9uczogcGVybXMuUkVBRF9TVFJFQU1fREFUQV9BQ1RJT05TLFxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIGdyYW50V3JpdGVEYXRhKGdyYW50ZWU6IGlhbS5JR3JhbnRhYmxlKTogaWFtLkdyYW50IHtcbiAgICBjb25zdCB0YWJsZUFjdGlvbnMgPSBwZXJtcy5XUklURV9EQVRBX0FDVElPTlMuY29uY2F0KHBlcm1zLkRFU0NSSUJFX1RBQkxFKTtcbiAgICBjb25zdCBrZXlBY3Rpb25zID0gcGVybXMuS0VZX1JFQURfQUNUSU9OUy5jb25jYXQocGVybXMuS0VZX1dSSVRFX0FDVElPTlMpO1xuICAgIHJldHVybiB0aGlzLmNvbWJpbmVkR3JhbnQoZ3JhbnRlZSwgeyBrZXlBY3Rpb25zLCB0YWJsZUFjdGlvbnMgfSk7XG4gIH1cblxuICBwdWJsaWMgZ3JhbnRSZWFkV3JpdGVEYXRhKGdyYW50ZWU6IGlhbS5JR3JhbnRhYmxlKTogaWFtLkdyYW50IHtcbiAgICBjb25zdCB0YWJsZUFjdGlvbnMgPSBwZXJtcy5SRUFEX0RBVEFfQUNUSU9OUy5jb25jYXQoXG4gICAgICBwZXJtcy5XUklURV9EQVRBX0FDVElPTlMsXG4gICAgKS5jb25jYXQocGVybXMuREVTQ1JJQkVfVEFCTEUpO1xuICAgIGNvbnN0IGtleUFjdGlvbnMgPSBwZXJtcy5LRVlfUkVBRF9BQ1RJT05TLmNvbmNhdChwZXJtcy5LRVlfV1JJVEVfQUNUSU9OUyk7XG4gICAgcmV0dXJuIHRoaXMuY29tYmluZWRHcmFudChncmFudGVlLCB7IGtleUFjdGlvbnMsIHRhYmxlQWN0aW9ucyB9KTtcbiAgfVxuXG4gIHB1YmxpYyBncmFudEZ1bGxBY2Nlc3MoZ3JhbnRlZTogaWFtLklHcmFudGFibGUpIHtcbiAgICBjb25zdCBrZXlBY3Rpb25zID0gcGVybXMuS0VZX1JFQURfQUNUSU9OUy5jb25jYXQocGVybXMuS0VZX1dSSVRFX0FDVElPTlMpO1xuICAgIHJldHVybiB0aGlzLmNvbWJpbmVkR3JhbnQoZ3JhbnRlZSwge1xuICAgICAga2V5QWN0aW9ucyxcbiAgICAgIHRhYmxlQWN0aW9uczogW1wiZHluYW1vZGI6KlwiXSxcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBhZGRUb1Jlc291cmNlUG9saWN5KFxuICAgIHN0YXRlbWVudDogaWFtLlBvbGljeVN0YXRlbWVudCxcbiAgKTogaWFtLkFkZFRvUmVzb3VyY2VQb2xpY3lSZXN1bHQge1xuICAgIGlmICghdGhpcy5yZXNvdXJjZVBvbGljeSkge1xuICAgICAgLy8gZW5zdXJlIGEgcG9saWN5IGV4aXN0cyBhbmQgaXMgYXNzb2NpYXRlZCB3aXRoIHRoZSB0YWJsZVxuICAgICAgdGhpcy5yZXNvdXJjZVBvbGljeSA9IG5ldyBpYW0uUG9saWN5RG9jdW1lbnQodGhpcywgXCJQb2xpY3lcIiwge1xuICAgICAgICBzdGF0ZW1lbnQ6IFtdLFxuICAgICAgfSk7XG4gICAgICBuZXcgZHluYW1vZGJSZXNvdXJjZVBvbGljeS5EeW5hbW9kYlJlc291cmNlUG9saWN5KFxuICAgICAgICB0aGlzLFxuICAgICAgICBcIlBvbGljeUF0dGFjaG1lbnRcIixcbiAgICAgICAge1xuICAgICAgICAgIHBvbGljeTogdGhpcy5yZXNvdXJjZVBvbGljeS5qc29uLFxuICAgICAgICAgIHJlc291cmNlQXJuOiB0aGlzLnRhYmxlQXJuLFxuICAgICAgICB9LFxuICAgICAgKTtcbiAgICB9XG4gICAgdGhpcy5yZXNvdXJjZVBvbGljeS5hZGRTdGF0ZW1lbnRzKHN0YXRlbWVudCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIHN0YXRlbWVudEFkZGVkOiB0cnVlLFxuICAgICAgcG9saWN5RGVwZW5kYWJsZTogdGhpcyxcbiAgICB9O1xuICB9XG5cbiAgcHVibGljIG1ldHJpYyhcbiAgICBtZXRyaWNOYW1lOiBzdHJpbmcsXG4gICAgcHJvcHM/OiBjbG91ZHdhdGNoLk1ldHJpY09wdGlvbnMsXG4gICk6IGNsb3Vkd2F0Y2guTWV0cmljIHtcbiAgICByZXR1cm4gbmV3IGNsb3Vkd2F0Y2guTWV0cmljKHtcbiAgICAgIG5hbWVzcGFjZTogXCJBV1MvRHluYW1vREJcIixcbiAgICAgIG1ldHJpY05hbWUsXG4gICAgICBkaW1lbnNpb25zTWFwOiB7XG4gICAgICAgIFRhYmxlTmFtZTogdGhpcy50YWJsZU5hbWUsXG4gICAgICB9LFxuICAgICAgLi4ucHJvcHMsXG4gICAgfSkuYXR0YWNoVG8odGhpcyk7XG4gIH1cblxuICBwdWJsaWMgbWV0cmljQ29uc3VtZWRSZWFkQ2FwYWNpdHlVbml0cyhcbiAgICBwcm9wcz86IGNsb3Vkd2F0Y2guTWV0cmljT3B0aW9ucyxcbiAgKTogY2xvdWR3YXRjaC5NZXRyaWMge1xuICAgIHJldHVybiB0aGlzLmNhbm5lZE1ldHJpYyhcbiAgICAgIER5bmFtb0RCTWV0cmljcy5jb25zdW1lZFJlYWRDYXBhY2l0eVVuaXRzU3VtLFxuICAgICAgcHJvcHMsXG4gICAgKTtcbiAgfVxuXG4gIHB1YmxpYyBtZXRyaWNDb25zdW1lZFdyaXRlQ2FwYWNpdHlVbml0cyhcbiAgICBwcm9wcz86IGNsb3Vkd2F0Y2guTWV0cmljT3B0aW9ucyxcbiAgKTogY2xvdWR3YXRjaC5NZXRyaWMge1xuICAgIHJldHVybiB0aGlzLmNhbm5lZE1ldHJpYyhcbiAgICAgIER5bmFtb0RCTWV0cmljcy5jb25zdW1lZFdyaXRlQ2FwYWNpdHlVbml0c1N1bSxcbiAgICAgIHByb3BzLFxuICAgICk7XG4gIH1cblxuICAvKiogQGRlcHJlY2F0ZWQgdXNlIGBtZXRyaWNTeXN0ZW1FcnJvcnNGb3JPcGVyYXRpb25zYC4gKi9cbiAgcHVibGljIG1ldHJpY1N5c3RlbUVycm9ycyhcbiAgICBwcm9wcz86IGNsb3Vkd2F0Y2guTWV0cmljT3B0aW9ucyxcbiAgKTogY2xvdWR3YXRjaC5NZXRyaWMge1xuICAgIGlmICghcHJvcHM/LmRpbWVuc2lvbnNNYXA/Lk9wZXJhdGlvbikge1xuICAgICAgLy8gJ09wZXJhdGlvbicgbXVzdCBiZSBwYXNzZWQgYmVjYXVzZSBpdHMgYW4gb3BlcmF0aW9uYWwgbWV0cmljLlxuICAgICAgLy8gdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgXCInT3BlcmF0aW9uJyBkaW1lbnNpb24gbXVzdCBiZSBwYXNzZWQgZm9yIHRoZSAnU3lzdGVtRXJyb3JzJyBtZXRyaWMuXCIsXG4gICAgICAgIC8vIHRoaXMsXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IGRpbWVuc2lvbnNNYXAgPSB7XG4gICAgICBUYWJsZU5hbWU6IHRoaXMudGFibGVOYW1lLFxuICAgICAgLi4ucHJvcHM/LmRpbWVuc2lvbnNNYXAsXG4gICAgfTtcblxuICAgIHJldHVybiB0aGlzLm1ldHJpYyhcIlN5c3RlbUVycm9yc1wiLCB7XG4gICAgICBzdGF0aXN0aWM6IFwic3VtXCIsXG4gICAgICAuLi5wcm9wcyxcbiAgICAgIGRpbWVuc2lvbnNNYXAsXG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgbWV0cmljVXNlckVycm9ycyhwcm9wcz86IGNsb3Vkd2F0Y2guTWV0cmljT3B0aW9ucyk6IGNsb3Vkd2F0Y2guTWV0cmljIHtcbiAgICBpZiAocHJvcHM/LmRpbWVuc2lvbnNNYXApIHtcbiAgICAgIC8vIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIFwiJ2RpbWVuc2lvbnNNYXAnIGlzIG5vdCBzdXBwb3J0ZWQgZm9yIHRoZSAnVXNlckVycm9ycycgbWV0cmljXCIsXG4gICAgICAgIC8vIHRoaXMsXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5tZXRyaWMoXCJVc2VyRXJyb3JzXCIsIHtcbiAgICAgIHN0YXRpc3RpYzogXCJzdW1cIixcbiAgICAgIC4uLnByb3BzLFxuICAgICAgZGltZW5zaW9uc01hcDoge30sXG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgbWV0cmljQ29uZGl0aW9uYWxDaGVja0ZhaWxlZFJlcXVlc3RzKFxuICAgIHByb3BzPzogY2xvdWR3YXRjaC5NZXRyaWNPcHRpb25zLFxuICApOiBjbG91ZHdhdGNoLk1ldHJpYyB7XG4gICAgcmV0dXJuIHRoaXMubWV0cmljKFwiQ29uZGl0aW9uYWxDaGVja0ZhaWxlZFJlcXVlc3RzXCIsIHtcbiAgICAgIHN0YXRpc3RpYzogXCJzdW1cIixcbiAgICAgIC4uLnByb3BzLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqIEBkZXByZWNhdGVkIERvIG5vdCB1c2UgdGhpcyBmdW5jdGlvbi4gSXQgcmV0dXJucyBhbiBpbnZhbGlkIG1ldHJpYy4gVXNlIGBtZXRyaWNUaHJvdHRsZWRSZXF1ZXN0c0Zvck9wZXJhdGlvbmAgaW5zdGVhZC4gKi9cbiAgcHVibGljIG1ldHJpY1Rocm90dGxlZFJlcXVlc3RzKFxuICAgIHByb3BzPzogY2xvdWR3YXRjaC5NZXRyaWNPcHRpb25zLFxuICApOiBjbG91ZHdhdGNoLk1ldHJpYyB7XG4gICAgcmV0dXJuIHRoaXMubWV0cmljKFwiVGhyb3R0bGVkUmVxdWVzdHNcIiwgeyBzdGF0aXN0aWM6IFwic3VtXCIsIC4uLnByb3BzIH0pO1xuICB9XG5cbiAgcHVibGljIG1ldHJpY1N1Y2Nlc3NmdWxSZXF1ZXN0TGF0ZW5jeShcbiAgICBwcm9wcz86IGNsb3Vkd2F0Y2guTWV0cmljT3B0aW9ucyxcbiAgKTogY2xvdWR3YXRjaC5NZXRyaWMge1xuICAgIGlmICghcHJvcHM/LmRpbWVuc2lvbnNNYXA/Lk9wZXJhdGlvbikge1xuICAgICAgLy8gdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgXCInT3BlcmF0aW9uJyBkaW1lbnNpb24gbXVzdCBiZSBwYXNzZWQgZm9yIHRoZSAnU3VjY2Vzc2Z1bFJlcXVlc3RMYXRlbmN5JyBtZXRyaWMuXCIsXG4gICAgICAgIC8vIHRoaXMsXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IGRpbWVuc2lvbnNNYXAgPSB7XG4gICAgICBUYWJsZU5hbWU6IHRoaXMudGFibGVOYW1lLFxuICAgICAgT3BlcmF0aW9uOiBwcm9wcy5kaW1lbnNpb25zTWFwLk9wZXJhdGlvbixcbiAgICB9O1xuXG4gICAgcmV0dXJuIG5ldyBjbG91ZHdhdGNoLk1ldHJpYyh7XG4gICAgICAuLi5EeW5hbW9EQk1ldHJpY3Muc3VjY2Vzc2Z1bFJlcXVlc3RMYXRlbmN5QXZlcmFnZShkaW1lbnNpb25zTWFwKSxcbiAgICAgIC4uLnByb3BzLFxuICAgICAgZGltZW5zaW9uc01hcCxcbiAgICB9KS5hdHRhY2hUbyh0aGlzKTtcbiAgfVxuXG4gIHB1YmxpYyBtZXRyaWNUaHJvdHRsZWRSZXF1ZXN0c0Zvck9wZXJhdGlvbihcbiAgICBvcGVyYXRpb246IHN0cmluZyxcbiAgICBwcm9wcz86IGNsb3Vkd2F0Y2guTWV0cmljT3B0aW9ucyxcbiAgKTogY2xvdWR3YXRjaC5NZXRyaWMge1xuICAgIHJldHVybiBuZXcgY2xvdWR3YXRjaC5NZXRyaWMoe1xuICAgICAgLi4uRHluYW1vREJNZXRyaWNzLnRocm90dGxlZFJlcXVlc3RzU3VtKHtcbiAgICAgICAgT3BlcmF0aW9uOiBvcGVyYXRpb24sXG4gICAgICAgIFRhYmxlTmFtZTogdGhpcy50YWJsZU5hbWUsXG4gICAgICB9KSxcbiAgICAgIC4uLnByb3BzLFxuICAgIH0pLmF0dGFjaFRvKHRoaXMpO1xuICB9XG5cbiAgcHVibGljIG1ldHJpY1Rocm90dGxlZFJlcXVlc3RzRm9yT3BlcmF0aW9ucyhcbiAgICBwcm9wcz86IE9wZXJhdGlvbnNNZXRyaWNPcHRpb25zLFxuICApOiBjbG91ZHdhdGNoLklNZXRyaWMge1xuICAgIHJldHVybiB0aGlzLnN1bU1ldHJpY3NGb3JPcGVyYXRpb25zKFxuICAgICAgXCJUaHJvdHRsZWRSZXF1ZXN0c1wiLFxuICAgICAgXCJTdW0gb2YgdGhyb3R0bGVkIHJlcXVlc3RzIGFjcm9zcyBhbGwgb3BlcmF0aW9uc1wiLFxuICAgICAgcHJvcHMsXG4gICAgKTtcbiAgfVxuXG4gIHB1YmxpYyBtZXRyaWNTeXN0ZW1FcnJvcnNGb3JPcGVyYXRpb25zKFxuICAgIHByb3BzPzogU3lzdGVtRXJyb3JzRm9yT3BlcmF0aW9uc01ldHJpY09wdGlvbnMsXG4gICk6IGNsb3Vkd2F0Y2guSU1ldHJpYyB7XG4gICAgcmV0dXJuIHRoaXMuc3VtTWV0cmljc0Zvck9wZXJhdGlvbnMoXG4gICAgICBcIlN5c3RlbUVycm9yc1wiLFxuICAgICAgXCJTdW0gb2YgZXJyb3JzIGFjcm9zcyBhbGwgb3BlcmF0aW9uc1wiLFxuICAgICAgcHJvcHMsXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgc3VtTWV0cmljc0Zvck9wZXJhdGlvbnMoXG4gICAgbWV0cmljTmFtZTogc3RyaW5nLFxuICAgIGV4cHJlc3Npb25MYWJlbDogc3RyaW5nLFxuICAgIHByb3BzPzogT3BlcmF0aW9uc01ldHJpY09wdGlvbnMsXG4gICk6IGNsb3Vkd2F0Y2guSU1ldHJpYyB7XG4gICAgaWYgKHByb3BzPy5kaW1lbnNpb25zTWFwPy5PcGVyYXRpb24pIHtcbiAgICAgIC8vIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIFwiVGhlIE9wZXJhdGlvbiBkaW1lbnNpb24gaXMgbm90IHN1cHBvcnRlZC4gVXNlIHRoZSAnb3BlcmF0aW9ucycgcHJvcGVydHkuXCIsXG4gICAgICAgIC8vIHRoaXMsXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IG9wZXJhdGlvbnMgPSBwcm9wcz8ub3BlcmF0aW9ucyA/PyBPYmplY3QudmFsdWVzKE9wZXJhdGlvbik7XG4gICAgY29uc3QgdmFsdWVzID0gdGhpcy5jcmVhdGVNZXRyaWNzRm9yT3BlcmF0aW9ucyhtZXRyaWNOYW1lLCBvcGVyYXRpb25zLCB7XG4gICAgICBzdGF0aXN0aWM6IFwic3VtXCIsXG4gICAgICAuLi5wcm9wcyxcbiAgICB9KTtcblxuICAgIHJldHVybiBuZXcgY2xvdWR3YXRjaC5NYXRoRXhwcmVzc2lvbih7XG4gICAgICBleHByZXNzaW9uOiBgJHtPYmplY3Qua2V5cyh2YWx1ZXMpLmpvaW4oXCIgKyBcIil9YCxcbiAgICAgIHVzaW5nTWV0cmljczogeyAuLi52YWx1ZXMgfSxcbiAgICAgIGNvbG9yOiBwcm9wcz8uY29sb3IsXG4gICAgICBsYWJlbDogZXhwcmVzc2lvbkxhYmVsLFxuICAgICAgcGVyaW9kOiBwcm9wcz8ucGVyaW9kLFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVNZXRyaWNzRm9yT3BlcmF0aW9ucyhcbiAgICBtZXRyaWNOYW1lOiBzdHJpbmcsXG4gICAgb3BlcmF0aW9uczogT3BlcmF0aW9uW10sXG4gICAgcHJvcHM/OiBjbG91ZHdhdGNoLk1ldHJpY09wdGlvbnMsXG4gICAgbWV0cmljTmFtZU1hcHBlcj86IChvcDogT3BlcmF0aW9uKSA9PiBzdHJpbmcsXG4gICk6IFJlY29yZDxzdHJpbmcsIGNsb3Vkd2F0Y2guSU1ldHJpYz4ge1xuICAgIGNvbnN0IG1ldHJpY3M6IFJlY29yZDxzdHJpbmcsIGNsb3Vkd2F0Y2guSU1ldHJpYz4gPSB7fTtcbiAgICBjb25zdCBtYXBwZXIgPSBtZXRyaWNOYW1lTWFwcGVyID8/ICgob3ApID0+IG9wLnRvTG93ZXJDYXNlKCkpO1xuXG4gICAgaWYgKHByb3BzPy5kaW1lbnNpb25zTWFwPy5PcGVyYXRpb24pIHtcbiAgICAgIC8vIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIFwiSW52YWxpZCBwcm9wZXJ0aWVzLiBPcGVyYXRpb24gZGltZW5zaW9uIGlzIG5vdCBzdXBwb3J0ZWQgd2hlbiBjYWxjdWxhdGluZyBvcGVyYXRpb25hbCBtZXRyaWNzXCIsXG4gICAgICAgIC8vIHRoaXMsXG4gICAgICApO1xuICAgIH1cblxuICAgIGZvciAoY29uc3Qgb3BlcmF0aW9uIG9mIG9wZXJhdGlvbnMpIHtcbiAgICAgIGNvbnN0IG1ldHJpYyA9IHRoaXMubWV0cmljKG1ldHJpY05hbWUsIHtcbiAgICAgICAgLi4ucHJvcHMsXG4gICAgICAgIGRpbWVuc2lvbnNNYXA6IHtcbiAgICAgICAgICBUYWJsZU5hbWU6IHRoaXMudGFibGVOYW1lLFxuICAgICAgICAgIE9wZXJhdGlvbjogb3BlcmF0aW9uLFxuICAgICAgICAgIC4uLnByb3BzPy5kaW1lbnNpb25zTWFwLFxuICAgICAgICB9LFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IG9wZXJhdGlvbk1ldHJpY05hbWUgPSBtYXBwZXIob3BlcmF0aW9uKTtcbiAgICAgIGNvbnN0IGZpcnN0Q2hhciA9IG9wZXJhdGlvbk1ldHJpY05hbWUuY2hhckF0KDApO1xuXG4gICAgICBpZiAoZmlyc3RDaGFyID09PSBmaXJzdENoYXIudG9VcHBlckNhc2UoKSkge1xuICAgICAgICAvLyBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQW1hem9uQ2xvdWRXYXRjaC9sYXRlc3QvbW9uaXRvcmluZy91c2luZy1tZXRyaWMtbWF0aC5odG1sI21ldHJpYy1tYXRoLXN5bnRheFxuICAgICAgICAvLyB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKFxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgYE1hcHBlciBnZW5lcmF0ZWQgYW4gaWxsZWdhbCBvcGVyYXRpb24gbWV0cmljIG5hbWU6ICR7b3BlcmF0aW9uTWV0cmljTmFtZX0uIE11c3Qgc3RhcnQgd2l0aCBhIGxvd2VyY2FzZSBsZXR0ZXJgLFxuICAgICAgICAgIC8vIHRoaXMsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICBtZXRyaWNzW29wZXJhdGlvbk1ldHJpY05hbWVdID0gbWV0cmljO1xuICAgIH1cbiAgICByZXR1cm4gbWV0cmljcztcbiAgfVxuXG4gIHByb3RlY3RlZCBhYnN0cmFjdCBnZXQgaGFzSW5kZXgoKTogYm9vbGVhbjtcblxuICBwcml2YXRlIGNvbWJpbmVkR3JhbnQoXG4gICAgZ3JhbnRlZTogaWFtLklHcmFudGFibGUsXG4gICAgb3B0czoge1xuICAgICAga2V5QWN0aW9ucz86IHN0cmluZ1tdO1xuICAgICAgdGFibGVBY3Rpb25zPzogc3RyaW5nW107XG4gICAgICBzdHJlYW1BY3Rpb25zPzogc3RyaW5nW107XG4gICAgfSxcbiAgKTogaWFtLkdyYW50IHtcbiAgICBpZiAodGhpcy5lbmNyeXB0aW9uS2V5ICYmIG9wdHMua2V5QWN0aW9ucykge1xuICAgICAgdGhpcy5lbmNyeXB0aW9uS2V5LmdyYW50KGdyYW50ZWUsIC4uLm9wdHMua2V5QWN0aW9ucyk7XG4gICAgfVxuICAgIGlmIChvcHRzLnRhYmxlQWN0aW9ucykge1xuICAgICAgY29uc3QgcmVzb3VyY2VzID0gW1xuICAgICAgICB0aGlzLnRhYmxlQXJuLFxuICAgICAgICBMYXp5LnN0cmluZ1ZhbHVlKHtcbiAgICAgICAgICBwcm9kdWNlOiAoKSA9PlxuICAgICAgICAgICAgdGhpcy5oYXNJbmRleCA/IGAke3RoaXMudGFibGVBcm59L2luZGV4LypgIDogdW5kZWZpbmVkLFxuICAgICAgICB9KSxcbiAgICAgICAgLi4udGhpcy5yZWdpb25hbEFybnMsXG4gICAgICAgIC4uLnRoaXMucmVnaW9uYWxBcm5zLm1hcCgoYXJuKSA9PlxuICAgICAgICAgIExhenkuc3RyaW5nVmFsdWUoe1xuICAgICAgICAgICAgcHJvZHVjZTogKCkgPT4gKHRoaXMuaGFzSW5kZXggPyBgJHthcm59L2luZGV4LypgIDogdW5kZWZpbmVkKSxcbiAgICAgICAgICB9KSxcbiAgICAgICAgKSxcbiAgICAgIF07XG4gICAgICBjb25zdCByZXQgPSBpYW0uR3JhbnQuYWRkVG9QcmluY2lwYWxPclJlc291cmNlKHtcbiAgICAgICAgZ3JhbnRlZSxcbiAgICAgICAgYWN0aW9uczogb3B0cy50YWJsZUFjdGlvbnMsXG4gICAgICAgIHJlc291cmNlQXJuczogcmVzb3VyY2VzLmZpbHRlcigocikgPT4gciAhPT0gdW5kZWZpbmVkKSxcbiAgICAgICAgcmVzb3VyY2U6IHRoaXMsXG4gICAgICB9KTtcbiAgICAgIHJldHVybiByZXQ7XG4gICAgfVxuXG4gICAgaWYgKG9wdHMuc3RyZWFtQWN0aW9ucykge1xuICAgICAgaWYgKCF0aGlzLnRhYmxlU3RyZWFtQXJuKSB7XG4gICAgICAgIC8vIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICBgRHluYW1vREIgU3RyZWFtcyBtdXN0IGJlIGVuYWJsZWQgb24gdGhlIHRhYmxlICR7dGhpcy5ub2RlLnBhdGh9YCxcbiAgICAgICAgICAvLyB0aGlzLFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgY29uc3QgcmV0ID0gaWFtLkdyYW50LmFkZFRvUHJpbmNpcGFsT3JSZXNvdXJjZSh7XG4gICAgICAgIGdyYW50ZWUsXG4gICAgICAgIGFjdGlvbnM6IG9wdHMuc3RyZWFtQWN0aW9ucyxcbiAgICAgICAgcmVzb3VyY2VBcm5zOiBbdGhpcy50YWJsZVN0cmVhbUFybl0sXG4gICAgICAgIHJlc291cmNlOiB0aGlzLFxuICAgICAgfSk7XG4gICAgICByZXR1cm4gcmV0O1xuICAgIH1cbiAgICAvLyB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKFxuICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgIGBVbmV4cGVjdGVkIGdyYW50IGNvbWJpbmF0aW9uLCBhY3Rpb25zIG11c3QgYmUgcHJvdmlkZWQgZm9yIHRhYmxlIG9yIHN0cmVhbS5gLFxuICAgICAgLy8gdGhpcyxcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBjYW5uZWRNZXRyaWMoXG4gICAgZm46IChkaW1zOiB7IFRhYmxlTmFtZTogc3RyaW5nIH0pID0+IGNsb3Vkd2F0Y2guTWV0cmljUHJvcHMsXG4gICAgcHJvcHM/OiBjbG91ZHdhdGNoLk1ldHJpY09wdGlvbnMsXG4gICk6IGNsb3Vkd2F0Y2guTWV0cmljIHtcbiAgICByZXR1cm4gbmV3IGNsb3Vkd2F0Y2guTWV0cmljKHtcbiAgICAgIC4uLmZuKHsgVGFibGVOYW1lOiB0aGlzLnRhYmxlTmFtZSB9KSxcbiAgICAgIC4uLnByb3BzLFxuICAgIH0pLmF0dGFjaFRvKHRoaXMpO1xuICB9XG59XG5cbi8qKlxuICogUHJvdmlkZXMgYSBEeW5hbW9EQiB0YWJsZS5cbiAqL1xuZXhwb3J0IGNsYXNzIFRhYmxlIGV4dGVuZHMgVGFibGVCYXNlIHtcbiAgLyoqXG4gICAqIFBlcm1pdHMgYW4gSUFNIFByaW5jaXBhbCB0byBsaXN0IGFsbCBEeW5hbW9EQiBTdHJlYW1zLlxuICAgKiBAZGVwcmVjYXRlZCBVc2UgYCNncmFudFRhYmxlTGlzdFN0cmVhbXNgIGZvciBtb3JlIGdyYW51bGFyIHBlcm1pc3Npb25cbiAgICogQHBhcmFtIGdyYW50ZWUgVGhlIHByaW5jaXBhbCAobm8tb3AgaWYgdW5kZWZpbmVkKVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBncmFudExpc3RTdHJlYW1zKGdyYW50ZWU6IGlhbS5JR3JhbnRhYmxlKTogaWFtLkdyYW50IHtcbiAgICByZXR1cm4gaWFtLkdyYW50LmFkZFRvUHJpbmNpcGFsKHtcbiAgICAgIGdyYW50ZWUsXG4gICAgICBhY3Rpb25zOiBbXCJkeW5hbW9kYjpMaXN0U3RyZWFtc1wiXSxcbiAgICAgIHJlc291cmNlQXJuczogW1wiKlwiXSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgVGFibGUgY29uc3RydWN0IHRoYXQgcmVwcmVzZW50cyBhbiBleHRlcm5hbCB0YWJsZSB2aWEgdGFibGUgbmFtZS5cbiAgICpcbiAgICogQHBhcmFtIHNjb3BlIFRoZSBwYXJlbnQgY3JlYXRpbmcgY29uc3RydWN0ICh1c3VhbGx5IGB0aGlzYCkuXG4gICAqIEBwYXJhbSBpZCBUaGUgY29uc3RydWN0J3MgbmFtZS5cbiAgICogQHBhcmFtIHRhYmxlTmFtZSBUaGUgdGFibGUncyBuYW1lLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBmcm9tVGFibGVOYW1lKFxuICAgIHNjb3BlOiBDb25zdHJ1Y3QsXG4gICAgaWQ6IHN0cmluZyxcbiAgICB0YWJsZU5hbWU6IHN0cmluZyxcbiAgKTogSVRhYmxlIHtcbiAgICByZXR1cm4gVGFibGUuZnJvbVRhYmxlQXR0cmlidXRlcyhzY29wZSwgaWQsIHsgdGFibGVOYW1lIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBUYWJsZSBjb25zdHJ1Y3QgdGhhdCByZXByZXNlbnRzIGFuIGV4dGVybmFsIHRhYmxlIHZpYSB0YWJsZSBhcm4uXG4gICAqXG4gICAqIEBwYXJhbSBzY29wZSBUaGUgcGFyZW50IGNyZWF0aW5nIGNvbnN0cnVjdCAodXN1YWxseSBgdGhpc2ApLlxuICAgKiBAcGFyYW0gaWQgVGhlIGNvbnN0cnVjdCdzIG5hbWUuXG4gICAqIEBwYXJhbSB0YWJsZUFybiBUaGUgdGFibGUncyBBUk4uXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGZyb21UYWJsZUFybihcbiAgICBzY29wZTogQ29uc3RydWN0LFxuICAgIGlkOiBzdHJpbmcsXG4gICAgdGFibGVBcm46IHN0cmluZyxcbiAgKTogSVRhYmxlIHtcbiAgICByZXR1cm4gVGFibGUuZnJvbVRhYmxlQXR0cmlidXRlcyhzY29wZSwgaWQsIHsgdGFibGVBcm4gfSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIFRhYmxlIGNvbnN0cnVjdCB0aGF0IHJlcHJlc2VudHMgYW4gZXh0ZXJuYWwgdGFibGUuXG4gICAqXG4gICAqIEBwYXJhbSBzY29wZSBUaGUgcGFyZW50IGNyZWF0aW5nIGNvbnN0cnVjdCAodXN1YWxseSBgdGhpc2ApLlxuICAgKiBAcGFyYW0gaWQgVGhlIGNvbnN0cnVjdCdzIG5hbWUuXG4gICAqIEBwYXJhbSBhdHRycyBBIGBUYWJsZUF0dHJpYnV0ZXNgIG9iamVjdC5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZnJvbVRhYmxlQXR0cmlidXRlcyhcbiAgICBzY29wZTogQ29uc3RydWN0LFxuICAgIGlkOiBzdHJpbmcsXG4gICAgYXR0cnM6IFRhYmxlQXR0cmlidXRlcyxcbiAgKTogSVRhYmxlIHtcbiAgICBjbGFzcyBJbXBvcnQgZXh0ZW5kcyBUYWJsZUJhc2Uge1xuICAgICAgcHVibGljIHJlYWRvbmx5IHRhYmxlTmFtZTogc3RyaW5nO1xuICAgICAgcHVibGljIHJlYWRvbmx5IHRhYmxlQXJuOiBzdHJpbmc7XG4gICAgICBwdWJsaWMgcmVhZG9ubHkgdGFibGVTdHJlYW1Bcm4/OiBzdHJpbmc7XG4gICAgICBwdWJsaWMgcmVhZG9ubHkgZW5jcnlwdGlvbktleT86IGttcy5JS2V5O1xuICAgICAgcHVibGljIHJlc291cmNlUG9saWN5PzogaWFtLlBvbGljeURvY3VtZW50O1xuICAgICAgcHJvdGVjdGVkIHJlYWRvbmx5IGhhc0luZGV4ID1cbiAgICAgICAgKGF0dHJzLmdyYW50SW5kZXhQZXJtaXNzaW9ucyA/PyBmYWxzZSkgfHxcbiAgICAgICAgKGF0dHJzLmdsb2JhbEluZGV4ZXMgPz8gW10pLmxlbmd0aCA+IDAgfHxcbiAgICAgICAgKGF0dHJzLmxvY2FsSW5kZXhlcyA/PyBbXSkubGVuZ3RoID4gMDtcblxuICAgICAgY29uc3RydWN0b3IoXG4gICAgICAgIHByb3BzOiBBd3NDb25zdHJ1Y3RQcm9wcyxcbiAgICAgICAgX3RhYmxlQXJuOiBzdHJpbmcsXG4gICAgICAgIHRhYmxlTmFtZTogc3RyaW5nLFxuICAgICAgICB0YWJsZVN0cmVhbUFybj86IHN0cmluZyxcbiAgICAgICkge1xuICAgICAgICBzdXBlcihzY29wZSwgaWQsIHByb3BzKTtcbiAgICAgICAgdGhpcy50YWJsZUFybiA9IF90YWJsZUFybjtcbiAgICAgICAgdGhpcy50YWJsZU5hbWUgPSB0YWJsZU5hbWU7XG4gICAgICAgIHRoaXMudGFibGVTdHJlYW1Bcm4gPSB0YWJsZVN0cmVhbUFybjtcbiAgICAgICAgdGhpcy5lbmNyeXB0aW9uS2V5ID0gYXR0cnMuZW5jcnlwdGlvbktleTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBsZXQgbmFtZTogc3RyaW5nO1xuICAgIGxldCBhcm46IHN0cmluZztcbiAgICBjb25zdCBzdGFjayA9IEF3c1N0YWNrLm9mQXdzQ29uc3RydWN0KHNjb3BlKTtcbiAgICBpZiAoIWF0dHJzLnRhYmxlTmFtZSkge1xuICAgICAgaWYgKCFhdHRycy50YWJsZUFybikge1xuICAgICAgICAvLyB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKFxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgXCJPbmUgb2YgdGFibGVOYW1lIG9yIHRhYmxlQXJuIGlzIHJlcXVpcmVkIVwiLFxuICAgICAgICAgIC8vIHNjb3BlLFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgYXJuID0gYXR0cnMudGFibGVBcm47XG4gICAgICBjb25zdCBtYXliZVRhYmxlTmFtZSA9IHN0YWNrLnNwbGl0QXJuKFxuICAgICAgICBhdHRycy50YWJsZUFybixcbiAgICAgICAgQXJuRm9ybWF0LlNMQVNIX1JFU09VUkNFX05BTUUsXG4gICAgICApLnJlc291cmNlTmFtZTtcbiAgICAgIGlmICghbWF5YmVUYWJsZU5hbWUpIHtcbiAgICAgICAgLy8gdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIFwiQVJOIGZvciBEeW5hbW9EQiB0YWJsZSBtdXN0IGJlIGluIHRoZSBmb3JtOiBhcm46PHBhcnRpdGlvbj46ZHluYW1vZGI6PHJlZ2lvbj46PGFjY291bnQ+OnRhYmxlLzx0YWJsZS1uYW1lPlwiLFxuICAgICAgICAgIC8vIHNjb3BlLFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgbmFtZSA9IG1heWJlVGFibGVOYW1lO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoYXR0cnMudGFibGVBcm4pIHtcbiAgICAgICAgLy8gdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIFwiT25seSBvbmUgb2YgdGFibGVBcm4gb3IgdGFibGVOYW1lIGNhbiBiZSBwcm92aWRlZFwiLFxuICAgICAgICAgIC8vIHNjb3BlLFxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgbmFtZSA9IGF0dHJzLnRhYmxlTmFtZTtcbiAgICAgIGFybiA9IHN0YWNrLmZvcm1hdEFybih7XG4gICAgICAgIHNlcnZpY2U6IFwiZHluYW1vZGJcIixcbiAgICAgICAgcmVzb3VyY2U6IFwidGFibGVcIixcbiAgICAgICAgcmVzb3VyY2VOYW1lOiBhdHRycy50YWJsZU5hbWUsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IEltcG9ydChcbiAgICAgIHsgZW52aXJvbm1lbnRGcm9tQXJuOiBhcm4gfSxcbiAgICAgIGFybixcbiAgICAgIG5hbWUsXG4gICAgICBhdHRycy50YWJsZVN0cmVhbUFybixcbiAgICApO1xuICB9XG5cbiAgcHVibGljIHJlYWRvbmx5IGVuY3J5cHRpb25LZXk/OiBrbXMuSUtleTtcblxuICAvKipcbiAgICogUmVzb3VyY2UgcG9saWN5IHRvIGFzc2lnbiB0byBEeW5hbW9EQiBUYWJsZS5cbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1keW5hbW9kYi10YWJsZS1yZXNvdXJjZXBvbGljeS5odG1sXG4gICAqIEBkZWZhdWx0IC0gTm8gcmVzb3VyY2UgcG9saWN5IHN0YXRlbWVudHMgYXJlIGFkZGVkIHRvIHRoZSBjcmVhdGVkIHRhYmxlLlxuICAgKi9cbiAgcHVibGljIHJlc291cmNlUG9saWN5PzogaWFtLlBvbGljeURvY3VtZW50O1xuICBwdWJsaWMgcmVhZG9ubHkgdGFibGVBcm46IHN0cmluZztcbiAgcHVibGljIHJlYWRvbmx5IHRhYmxlTmFtZTogc3RyaW5nO1xuICBwdWJsaWMgcmVhZG9ubHkgdGFibGVTdHJlYW1Bcm46IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICBwcml2YXRlIHJlYWRvbmx5IGF0dHJpYnV0ZURlZmluaXRpb25zSW50ZXJuYWwgPVxuICAgIG5ldyBBcnJheTxkeW5hbW9kYlRhYmxlLkR5bmFtb2RiVGFibGVBdHRyaWJ1dGU+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgZ2xvYmFsU2Vjb25kYXJ5SW5kZXhlc0ludGVybmFsID1cbiAgICBuZXcgQXJyYXk8ZHluYW1vZGJUYWJsZS5EeW5hbW9kYlRhYmxlR2xvYmFsU2Vjb25kYXJ5SW5kZXg+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgbG9jYWxTZWNvbmRhcnlJbmRleGVzSW50ZXJuYWwgPVxuICAgIG5ldyBBcnJheTxkeW5hbW9kYlRhYmxlLkR5bmFtb2RiVGFibGVMb2NhbFNlY29uZGFyeUluZGV4PigpO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgc2Vjb25kYXJ5SW5kZXhTY2hlbWFzID0gbmV3IE1hcDxzdHJpbmcsIFNjaGVtYU9wdGlvbnM+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgbm9uS2V5QXR0cmlidXRlcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgdGFibGVQYXJ0aXRpb25LZXk6IEF0dHJpYnV0ZTtcbiAgcHJpdmF0ZSByZWFkb25seSB0YWJsZVNvcnRLZXk/OiBBdHRyaWJ1dGU7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBiaWxsaW5nTW9kZTogQmlsbGluZ01vZGU7XG4gIHByaXZhdGUgcmVhZG9ubHkgdGFibGVTY2FsaW5nOiBTY2FsYWJsZUF0dHJpYnV0ZVBhaXIgPSB7fTtcbiAgcHJpdmF0ZSByZWFkb25seSBpbmRleFNjYWxpbmcgPSBuZXcgTWFwPHN0cmluZywgU2NhbGFibGVBdHRyaWJ1dGVQYWlyPigpO1xuICAvLyBDb21tZW50aW5nIG91dCBzY2FsaW5nUm9sZSBhcyBUZXJyYWZvcm0gYXV0by1jcmVhdGVzIHNlcnZpY2UtbGlua2VkIHJvbGVzXG4gIC8vIFVubGlrZSBBV1MgQ0RLIENsb3VkRm9ybWF0aW9uLCBUZXJyYWZvcm0gQVdTIHByb3ZpZGVyJ3Mgcm9sZUFybiBpcyBvcHRpb25hbFxuICAvLyBhbmQgZGVmYXVsdHMgdG8gYXBwcm9wcmlhdGUgc2VydmljZS1saW5rZWQgcm9sZXMgd2hlbiBvbWl0dGVkXG4gIC8vIHByaXZhdGUgcmVhZG9ubHkgc2NhbGluZ1JvbGU6IGlhbS5JUm9sZTtcblxuICBwcml2YXRlIHJlYWRvbmx5IF9yZXNvdXJjZTogZHluYW1vZGJUYWJsZS5EeW5hbW9kYlRhYmxlO1xuICBwcml2YXRlIHJlYWRvbmx5IF9yZXBsaWNhczogZHluYW1vZGJUYWJsZS5EeW5hbW9kYlRhYmxlUmVwbGljYVtdIHwgdW5kZWZpbmVkO1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBUYWJsZVByb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkLCBwcm9wcyk7XG5cbiAgICBjb25zdCBwaHlzaWNhbFRhYmxlTmFtZSA9XG4gICAgICBwcm9wcy50YWJsZU5hbWUgPz8gdGhpcy5zdGFjay51bmlxdWVSZXNvdXJjZU5hbWUodGhpcyk7XG5cbiAgICBjb25zdCB7IHNzZVNwZWNpZmljYXRpb24sIGVuY3J5cHRpb25LZXkgfSA9IHRoaXMucGFyc2VFbmNyeXB0aW9uKHByb3BzKTtcbiAgICB0aGlzLmVuY3J5cHRpb25LZXkgPSBlbmNyeXB0aW9uS2V5O1xuXG4gICAgY29uc3QgcG9pbnRJblRpbWVSZWNvdmVyeSA9IHRoaXMucmVuZGVyUG9pbnRJblRpbWVSZWNvdmVyeShwcm9wcyk7XG5cbiAgICAvLyBlcnJvciBpZiBib3RoIHJlcGxpY2F0aW9uUmVnaW9ucyBhbmQgcmVwbGljYVNwZWNpZmljYXRpb24gYXJlIHNwZWNpZmllZFxuICAgIGlmIChwcm9wcy5yZXBsaWNhdGlvblJlZ2lvbnMgJiYgcHJvcHMucmVwbGljYVNwZWNpZmljYXRpb24pIHtcbiAgICAgIC8vIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIFwiWW91IGNhbm5vdCBzcGVjaWZ5IGJvdGggYHJlcGxpY2F0aW9uUmVnaW9uc2AgYW5kIGByZXBsaWNhU3BlY2lmaWNhdGlvbmBcIixcbiAgICAgICAgLy8gdGhpcyxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgbGV0IHN0cmVhbVNwZWNpZmljYXRpb246XG4gICAgICB8IHtcbiAgICAgICAgICBzdHJlYW1FbmFibGVkOiBib29sZWFuO1xuICAgICAgICAgIHN0cmVhbVZpZXdUeXBlPzogU3RyZWFtVmlld1R5cGU7XG4gICAgICAgIH1cbiAgICAgIHwgdW5kZWZpbmVkO1xuICAgIGlmIChcbiAgICAgIChwcm9wcy5yZXBsaWNhdGlvblJlZ2lvbnMgJiYgcHJvcHMucmVwbGljYXRpb25SZWdpb25zLmxlbmd0aCA+IDApIHx8XG4gICAgICAocHJvcHMucmVwbGljYVNwZWNpZmljYXRpb24gJiYgcHJvcHMucmVwbGljYVNwZWNpZmljYXRpb24ubGVuZ3RoID4gMClcbiAgICApIHtcbiAgICAgIGlmIChwcm9wcy5zdHJlYW0gJiYgcHJvcHMuc3RyZWFtICE9PSBTdHJlYW1WaWV3VHlwZS5ORVdfQU5EX09MRF9JTUFHRVMpIHtcbiAgICAgICAgLy8gdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIFwiYHN0cmVhbWAgbXVzdCBiZSBzZXQgdG8gYE5FV19BTkRfT0xEX0lNQUdFU2Agd2hlbiBzcGVjaWZ5aW5nIGByZXBsaWNhdGlvblJlZ2lvbnNgXCIsXG4gICAgICAgICAgLy8gdGhpcyxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuYmlsbGluZ01vZGUgPSBwcm9wcy5iaWxsaW5nTW9kZSA/PyBCaWxsaW5nTW9kZS5QQVlfUEVSX1JFUVVFU1Q7XG4gICAgICBzdHJlYW1TcGVjaWZpY2F0aW9uID0ge1xuICAgICAgICBzdHJlYW1FbmFibGVkOiB0cnVlLFxuICAgICAgICBzdHJlYW1WaWV3VHlwZTogU3RyZWFtVmlld1R5cGUuTkVXX0FORF9PTERfSU1BR0VTLFxuICAgICAgfTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5iaWxsaW5nTW9kZSA9IHByb3BzLmJpbGxpbmdNb2RlID8/IEJpbGxpbmdNb2RlLlBST1ZJU0lPTkVEO1xuICAgICAgaWYgKHByb3BzLnN0cmVhbSkge1xuICAgICAgICBzdHJlYW1TcGVjaWZpY2F0aW9uID0ge1xuICAgICAgICAgIHN0cmVhbUVuYWJsZWQ6IHRydWUsXG4gICAgICAgICAgc3RyZWFtVmlld1R5cGU6IHByb3BzLnN0cmVhbSxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9XG4gICAgdGhpcy52YWxpZGF0ZVByb3Zpc2lvbmluZyhwcm9wcyk7XG4gICAgdGhpcy5hZGRLZXkocHJvcHMucGFydGl0aW9uS2V5LCBIQVNIX0tFWV9UWVBFKTtcbiAgICB0aGlzLnRhYmxlUGFydGl0aW9uS2V5ID0gcHJvcHMucGFydGl0aW9uS2V5O1xuICAgIGlmIChwcm9wcy5zb3J0S2V5KSB7XG4gICAgICB0aGlzLmFkZEtleShwcm9wcy5zb3J0S2V5LCBSQU5HRV9LRVlfVFlQRSk7XG4gICAgICB0aGlzLnRhYmxlU29ydEtleSA9IHByb3BzLnNvcnRLZXk7XG4gICAgfVxuXG4gICAgdGhpcy5fcmVwbGljYXMgPSB0aGlzLnJlbmRlclJlcGxpY2FzKFxuICAgICAgcHJvcHMucmVwbGljYXRpb25SZWdpb25zLFxuICAgICAgcHJvcHMucmVwbGljYVNwZWNpZmljYXRpb24sXG4gICAgKTtcbiAgICBpZiAodGhpcy5fcmVwbGljYXMgJiYgdGhpcy5fcmVwbGljYXMubGVuZ3RoID4gMCkge1xuICAgICAgdGhpcy5fcmVwbGljYXMuZm9yRWFjaCgocikgPT5cbiAgICAgICAgLy8gU2F2ZSByZWdpb25hbCBhcm5zIGZvciBncmFudFh4eCgpIG1ldGhvZHNcbiAgICAgICAgdGhpcy5yZWdpb25hbEFybnMucHVzaChcbiAgICAgICAgICB0aGlzLnN0YWNrLmZvcm1hdEFybih7XG4gICAgICAgICAgICByZWdpb246IHIucmVnaW9uTmFtZSxcbiAgICAgICAgICAgIHNlcnZpY2U6IFwiZHluYW1vZGJcIixcbiAgICAgICAgICAgIHJlc291cmNlOiBcInRhYmxlXCIsXG4gICAgICAgICAgICByZXNvdXJjZU5hbWU6IHBoeXNpY2FsVGFibGVOYW1lLFxuICAgICAgICAgIH0pLFxuICAgICAgICApLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICB0aGlzLl9yZXNvdXJjZSA9IG5ldyBkeW5hbW9kYlRhYmxlLkR5bmFtb2RiVGFibGUodGhpcywgXCJSZXNvdXJjZVwiLCB7XG4gICAgICBuYW1lOiBwaHlzaWNhbFRhYmxlTmFtZSxcbiAgICAgIGhhc2hLZXk6IHRoaXMudGFibGVQYXJ0aXRpb25LZXkubmFtZSxcbiAgICAgIHJhbmdlS2V5OiB0aGlzLnRhYmxlU29ydEtleT8ubmFtZSxcbiAgICAgIGF0dHJpYnV0ZTogdGhpcy5hdHRyaWJ1dGVEZWZpbml0aW9uc0ludGVybmFsLFxuICAgICAgZ2xvYmFsU2Vjb25kYXJ5SW5kZXg6IExhenkuYW55VmFsdWUoXG4gICAgICAgIHtcbiAgICAgICAgICBwcm9kdWNlOiAoKSA9PlxuICAgICAgICAgICAgdGhpcy5nbG9iYWxTZWNvbmRhcnlJbmRleGVzSW50ZXJuYWwubWFwKFxuICAgICAgICAgICAgICBkeW5hbW9kYlRhYmxlLmR5bmFtb2RiVGFibGVHbG9iYWxTZWNvbmRhcnlJbmRleFRvVGVycmFmb3JtLFxuICAgICAgICAgICAgKSxcbiAgICAgICAgfSxcbiAgICAgICAgeyBvbWl0RW1wdHlBcnJheTogdHJ1ZSB9LFxuICAgICAgKSxcbiAgICAgIGxvY2FsU2Vjb25kYXJ5SW5kZXg6IExhenkuYW55VmFsdWUoXG4gICAgICAgIHtcbiAgICAgICAgICBwcm9kdWNlOiAoKSA9PlxuICAgICAgICAgICAgdGhpcy5sb2NhbFNlY29uZGFyeUluZGV4ZXNJbnRlcm5hbC5tYXAoXG4gICAgICAgICAgICAgIGR5bmFtb2RiVGFibGUuZHluYW1vZGJUYWJsZUxvY2FsU2Vjb25kYXJ5SW5kZXhUb1RlcnJhZm9ybSxcbiAgICAgICAgICAgICksXG4gICAgICAgIH0sXG4gICAgICAgIHsgb21pdEVtcHR5QXJyYXk6IHRydWUgfSxcbiAgICAgICksXG4gICAgICBwb2ludEluVGltZVJlY292ZXJ5LFxuICAgICAgYmlsbGluZ01vZGU6IHRoaXMuYmlsbGluZ01vZGUsXG4gICAgICByZWFkQ2FwYWNpdHk6XG4gICAgICAgIHRoaXMuYmlsbGluZ01vZGUgPT09IEJpbGxpbmdNb2RlLlBST1ZJU0lPTkVEXG4gICAgICAgICAgPyAocHJvcHMucmVhZENhcGFjaXR5ID8/IDUpXG4gICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICB3cml0ZUNhcGFjaXR5OlxuICAgICAgICB0aGlzLmJpbGxpbmdNb2RlID09PSBCaWxsaW5nTW9kZS5QUk9WSVNJT05FRFxuICAgICAgICAgID8gKHByb3BzLndyaXRlQ2FwYWNpdHkgPz8gNSlcbiAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgIG9uRGVtYW5kVGhyb3VnaHB1dDpcbiAgICAgICAgdGhpcy5iaWxsaW5nTW9kZSA9PT0gQmlsbGluZ01vZGUuUEFZX1BFUl9SRVFVRVNUICYmXG4gICAgICAgIChwcm9wcy5tYXhSZWFkUmVxdWVzdFVuaXRzIHx8IHByb3BzLm1heFdyaXRlUmVxdWVzdFVuaXRzKVxuICAgICAgICAgID8ge1xuICAgICAgICAgICAgICBtYXhSZWFkUmVxdWVzdFVuaXRzOiBwcm9wcy5tYXhSZWFkUmVxdWVzdFVuaXRzLFxuICAgICAgICAgICAgICBtYXhXcml0ZVJlcXVlc3RVbml0czogcHJvcHMubWF4V3JpdGVSZXF1ZXN0VW5pdHMsXG4gICAgICAgICAgICB9XG4gICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICBzZXJ2ZXJTaWRlRW5jcnlwdGlvbjogc3NlU3BlY2lmaWNhdGlvbixcbiAgICAgIHN0cmVhbUVuYWJsZWQ6IHN0cmVhbVNwZWNpZmljYXRpb24/LnN0cmVhbUVuYWJsZWQsXG4gICAgICBzdHJlYW1WaWV3VHlwZTogc3RyZWFtU3BlY2lmaWNhdGlvbj8uc3RyZWFtVmlld1R5cGUsXG4gICAgICB0YWJsZUNsYXNzOiBwcm9wcy50YWJsZUNsYXNzLFxuICAgICAgdHRsOiBwcm9wcy50aW1lVG9MaXZlQXR0cmlidXRlXG4gICAgICAgID8geyBhdHRyaWJ1dGVOYW1lOiBwcm9wcy50aW1lVG9MaXZlQXR0cmlidXRlLCBlbmFibGVkOiB0cnVlIH1cbiAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICBkZWxldGlvblByb3RlY3Rpb25FbmFibGVkOiBwcm9wcy5kZWxldGlvblByb3RlY3Rpb24sXG4gICAgICBpbXBvcnRUYWJsZTogdGhpcy5yZW5kZXJJbXBvcnRTb3VyY2VTcGVjaWZpY2F0aW9uKHByb3BzLmltcG9ydFNvdXJjZSksXG4gICAgICByZXBsaWNhOiB0aGlzLl9yZXBsaWNhcyxcbiAgICAgIC8vIHJlc291cmNlUG9saWN5OiBwcm9wcy5yZXNvdXJjZVBvbGljeSA/IHsgcG9saWN5RG9jdW1lbnQ6IHRoaXMuc3RhY2sudG9Kc29uU3RyaW5nKHByb3BzLnJlc291cmNlUG9saWN5LnRvSlNPTigpKSB9IDogdW5kZWZpbmVkLCAvLyBOb3QgaW4gVEYgcmVzb3VyY2VcbiAgICAgIC8vIFRPRE86IGh0dHBzOi8vZ2l0aHViLmNvbS9oYXNoaWNvcnAvdGVycmFmb3JtLXByb3ZpZGVyLWF3cy9pc3N1ZXMvNDMxNDJcbiAgICAgIC8vIHdhcm1UaHJvdWdocHV0OiBwcm9wcy53YXJtVGhyb3VnaHB1dCA/PyB1bmRlZmluZWQsIC8vIE5vdCBpbiBURiByZXNvdXJjZVxuICAgIH0pO1xuXG4gICAgdGhpcy50YWJsZUFybiA9IHRoaXMuX3Jlc291cmNlLmFybjtcbiAgICB0aGlzLnRhYmxlTmFtZSA9IHRoaXMuX3Jlc291cmNlLm5hbWU7XG4gICAgdGhpcy50YWJsZVN0cmVhbUFybiA9IHN0cmVhbVNwZWNpZmljYXRpb24/LnN0cmVhbUVuYWJsZWRcbiAgICAgID8gdGhpcy5fcmVzb3VyY2Uuc3RyZWFtQXJuXG4gICAgICA6IHVuZGVmaW5lZDtcbiAgICB0aGlzLnJlc291cmNlUG9saWN5ID0gcHJvcHMucmVzb3VyY2VQb2xpY3k7XG4gICAgaWYgKHRoaXMucmVzb3VyY2VQb2xpY3kpIHtcbiAgICAgIG5ldyBkeW5hbW9kYlJlc291cmNlUG9saWN5LkR5bmFtb2RiUmVzb3VyY2VQb2xpY3koXG4gICAgICAgIHRoaXMsXG4gICAgICAgIFwiUmVzb3VyY2VQb2xpY3lcIixcbiAgICAgICAge1xuICAgICAgICAgIHBvbGljeTogdGhpcy5yZXNvdXJjZVBvbGljeS5qc29uLFxuICAgICAgICAgIHJlc291cmNlQXJuOiB0aGlzLnRhYmxlQXJuLFxuICAgICAgICB9LFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAocHJvcHMua2luZXNpc1N0cmVhbSkge1xuICAgICAgbmV3IGR5bmFtb2RiS2luZXNpc1N0cmVhbWluZ0Rlc3RpbmF0aW9uLkR5bmFtb2RiS2luZXNpc1N0cmVhbWluZ0Rlc3RpbmF0aW9uKFxuICAgICAgICB0aGlzLFxuICAgICAgICBcIktpbmVzaXNTdHJlYW1pbmdEZXN0aW5hdGlvblwiLFxuICAgICAgICB7XG4gICAgICAgICAgdGFibGVOYW1lOiB0aGlzLnRhYmxlTmFtZSxcbiAgICAgICAgICBzdHJlYW1Bcm46IHByb3BzLmtpbmVzaXNTdHJlYW0uc3RyZWFtQXJuLFxuICAgICAgICAgIC4uLihwcm9wcy5raW5lc2lzUHJlY2lzaW9uVGltZXN0YW1wICYmIHtcbiAgICAgICAgICAgIGFwcHJveGltYXRlQ3JlYXRpb25EYXRlVGltZVByZWNpc2lvbjpcbiAgICAgICAgICAgICAgcHJvcHMua2luZXNpc1ByZWNpc2lvblRpbWVzdGFtcCxcbiAgICAgICAgICB9KSxcbiAgICAgICAgfSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgaWYgKHByb3BzLmNvbnRyaWJ1dG9ySW5zaWdodHNFbmFibGVkKSB7XG4gICAgICAvLyBUT0RPOiBHZW5lcmF0ZSBjb25udHJpYnV0b3IgaW5zaWdodHMgcGVyIEdsb2JhbCBTZWNvbmRhcnkgSW5kZXhcbiAgICAgIC8vIHRoaXMuZ2xvYmFsU2Vjb25kYXJ5SW5kZXhlc0ludGVybmFsXG4gICAgICBuZXcgZHluYW1vZGJDb250cmlidXRvckluc2lnaHRzLkR5bmFtb2RiQ29udHJpYnV0b3JJbnNpZ2h0cyhcbiAgICAgICAgdGhpcyxcbiAgICAgICAgXCJDb250cmlidXRvckluc2lnaHRzXCIsXG4gICAgICAgIHtcbiAgICAgICAgICB0YWJsZU5hbWU6IHRoaXMudGFibGVOYW1lLFxuICAgICAgICAgIC8vIFRPRE86IHVzZSBmb3IgZWFjaCBvbiBnbGkgaXRlcmF0b3JcbiAgICAgICAgICAvLyBpbmRleE5hbWU6IGl0ZXJhdG9yLnZhbHVlLFxuICAgICAgICB9LFxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBDb21tZW50aW5nIG91dCBzY2FsaW5nUm9sZSBpbml0aWFsaXphdGlvbiAtIGxldCBUZXJyYWZvcm0gYXV0by1jcmVhdGUgc2VydmljZS1saW5rZWQgcm9sZVxuICAgIC8vIHRoaXMuc2NhbGluZ1JvbGUgPSB0aGlzLm1ha2VTY2FsaW5nUm9sZSgpO1xuXG4gICAgdGhpcy5ub2RlLmFkZFZhbGlkYXRpb24oeyB2YWxpZGF0ZTogKCkgPT4gdGhpcy52YWxpZGF0ZVRhYmxlKCkgfSk7XG4gIH1cblxuICBwdWJsaWMgYWRkR2xvYmFsU2Vjb25kYXJ5SW5kZXgocHJvcHM6IEdsb2JhbFNlY29uZGFyeUluZGV4UHJvcHMpIHtcbiAgICB0aGlzLnZhbGlkYXRlUHJvdmlzaW9uaW5nR1NJKHByb3BzKTtcbiAgICB0aGlzLnZhbGlkYXRlSW5kZXhOYW1lKHByb3BzLmluZGV4TmFtZSk7XG5cbiAgICBjb25zdCBnc2lQcm9qZWN0aW9uID0gdGhpcy5idWlsZEluZGV4UHJvamVjdGlvbihwcm9wcyk7XG4gICAgdGhpcy5yZWdpc3RlckF0dHJpYnV0ZShwcm9wcy5wYXJ0aXRpb25LZXkpO1xuICAgIGlmIChwcm9wcy5zb3J0S2V5KSB7XG4gICAgICB0aGlzLnJlZ2lzdGVyQXR0cmlidXRlKHByb3BzLnNvcnRLZXkpO1xuICAgIH1cblxuICAgIHRoaXMuZ2xvYmFsU2Vjb25kYXJ5SW5kZXhlc0ludGVybmFsLnB1c2goe1xuICAgICAgbmFtZTogcHJvcHMuaW5kZXhOYW1lLFxuICAgICAgaGFzaEtleTogcHJvcHMucGFydGl0aW9uS2V5Lm5hbWUsXG4gICAgICByYW5nZUtleTogcHJvcHMuc29ydEtleT8ubmFtZSxcbiAgICAgIHByb2plY3Rpb25UeXBlOiBnc2lQcm9qZWN0aW9uLnByb2plY3Rpb25UeXBlLFxuICAgICAgbm9uS2V5QXR0cmlidXRlczogZ3NpUHJvamVjdGlvbi5ub25LZXlBdHRyaWJ1dGVzLFxuICAgICAgcmVhZENhcGFjaXR5OlxuICAgICAgICB0aGlzLmJpbGxpbmdNb2RlID09PSBCaWxsaW5nTW9kZS5QUk9WSVNJT05FRFxuICAgICAgICAgID8gKHByb3BzLnJlYWRDYXBhY2l0eSA/PyA1KVxuICAgICAgICAgIDogdW5kZWZpbmVkLFxuICAgICAgd3JpdGVDYXBhY2l0eTpcbiAgICAgICAgdGhpcy5iaWxsaW5nTW9kZSA9PT0gQmlsbGluZ01vZGUuUFJPVklTSU9ORURcbiAgICAgICAgICA/IChwcm9wcy53cml0ZUNhcGFjaXR5ID8/IDUpXG4gICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICBvbkRlbWFuZFRocm91Z2hwdXQ6XG4gICAgICAgIHRoaXMuYmlsbGluZ01vZGUgPT09IEJpbGxpbmdNb2RlLlBBWV9QRVJfUkVRVUVTVCAmJlxuICAgICAgICAocHJvcHMubWF4UmVhZFJlcXVlc3RVbml0cyB8fCBwcm9wcy5tYXhXcml0ZVJlcXVlc3RVbml0cylcbiAgICAgICAgICA/IHtcbiAgICAgICAgICAgICAgbWF4UmVhZFJlcXVlc3RVbml0czogcHJvcHMubWF4UmVhZFJlcXVlc3RVbml0cyxcbiAgICAgICAgICAgICAgbWF4V3JpdGVSZXF1ZXN0VW5pdHM6IHByb3BzLm1heFdyaXRlUmVxdWVzdFVuaXRzLFxuICAgICAgICAgICAgfVxuICAgICAgICAgIDogdW5kZWZpbmVkLFxuICAgICAgLy8gY29udHJpYnV0b3JJbnNpZ2h0c0VuYWJsZWQ6IHByb3BzLmNvbnRyaWJ1dG9ySW5zaWdodHNFbmFibGVkLCAvLyBOb3QgaW4gVEYgR1NJIGJsb2NrXG4gICAgICAvLyB3YXJtVGhyb3VnaHB1dDogcHJvcHMud2FybVRocm91Z2hwdXQsIC8vIE5vdCBpbiBURiBHU0kgYmxvY2tcbiAgICB9KTtcblxuICAgIHRoaXMuc2Vjb25kYXJ5SW5kZXhTY2hlbWFzLnNldChwcm9wcy5pbmRleE5hbWUsIHtcbiAgICAgIHBhcnRpdGlvbktleTogcHJvcHMucGFydGl0aW9uS2V5LFxuICAgICAgc29ydEtleTogcHJvcHMuc29ydEtleSxcbiAgICB9KTtcbiAgICB0aGlzLmluZGV4U2NhbGluZy5zZXQocHJvcHMuaW5kZXhOYW1lLCB7fSk7XG4gIH1cblxuICBwdWJsaWMgYWRkTG9jYWxTZWNvbmRhcnlJbmRleChwcm9wczogTG9jYWxTZWNvbmRhcnlJbmRleFByb3BzKSB7XG4gICAgaWYgKFxuICAgICAgdGhpcy5sb2NhbFNlY29uZGFyeUluZGV4ZXNJbnRlcm5hbC5sZW5ndGggPj1cbiAgICAgIE1BWF9MT0NBTF9TRUNPTkRBUllfSU5ERVhfQ09VTlRcbiAgICApIHtcbiAgICAgIHRocm93IG5ldyBSYW5nZUVycm9yKFxuICAgICAgICBgQSBtYXhpbXVtIG51bWJlciBvZiBsb2NhbCBzZWNvbmRhcnkgaW5kZXggcGVyIHRhYmxlIGlzICR7TUFYX0xPQ0FMX1NFQ09OREFSWV9JTkRFWF9DT1VOVH1gLFxuICAgICAgKTtcbiAgICB9XG4gICAgdGhpcy52YWxpZGF0ZUluZGV4TmFtZShwcm9wcy5pbmRleE5hbWUpO1xuXG4gICAgaWYgKCF0aGlzLnRhYmxlUGFydGl0aW9uS2V5KSB7XG4gICAgICAvLyB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKFxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBcIlRhYmxlIHBhcnRpdGlvbiBrZXkgbXVzdCBiZSBkZWZpbmVkIGJlZm9yZSBhZGRpbmcgbG9jYWwgc2Vjb25kYXJ5IGluZGV4XCIsXG4gICAgICAgIC8vIHRoaXMsXG4gICAgICApO1xuICAgIH1cbiAgICB0aGlzLnJlZ2lzdGVyQXR0cmlidXRlKHRoaXMudGFibGVQYXJ0aXRpb25LZXkpO1xuICAgIHRoaXMucmVnaXN0ZXJBdHRyaWJ1dGUocHJvcHMuc29ydEtleSk7XG5cbiAgICBjb25zdCBsc2lQcm9qZWN0aW9uID0gdGhpcy5idWlsZEluZGV4UHJvamVjdGlvbihwcm9wcyk7XG5cbiAgICB0aGlzLmxvY2FsU2Vjb25kYXJ5SW5kZXhlc0ludGVybmFsLnB1c2goe1xuICAgICAgbmFtZTogcHJvcHMuaW5kZXhOYW1lLFxuICAgICAgcmFuZ2VLZXk6IHByb3BzLnNvcnRLZXkubmFtZSxcbiAgICAgIHByb2plY3Rpb25UeXBlOiBsc2lQcm9qZWN0aW9uLnByb2plY3Rpb25UeXBlLFxuICAgICAgbm9uS2V5QXR0cmlidXRlczogbHNpUHJvamVjdGlvbi5ub25LZXlBdHRyaWJ1dGVzLFxuICAgIH0pO1xuXG4gICAgdGhpcy5zZWNvbmRhcnlJbmRleFNjaGVtYXMuc2V0KHByb3BzLmluZGV4TmFtZSwge1xuICAgICAgcGFydGl0aW9uS2V5OiB0aGlzLnRhYmxlUGFydGl0aW9uS2V5LFxuICAgICAgc29ydEtleTogcHJvcHMuc29ydEtleSxcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBhdXRvU2NhbGVSZWFkQ2FwYWNpdHkoXG4gICAgcHJvcHM6IEVuYWJsZVNjYWxpbmdQcm9wcyxcbiAgKTogSVNjYWxhYmxlVGFibGVBdHRyaWJ1dGUge1xuICAgIGlmICh0aGlzLnRhYmxlU2NhbGluZy5zY2FsYWJsZVJlYWRBdHRyaWJ1dGUpIHtcbiAgICAgIC8vIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIFwiUmVhZCBBdXRvU2NhbGluZyBhbHJlYWR5IGVuYWJsZWQgZm9yIHRoaXMgdGFibGVcIixcbiAgICAgICAgLy8gdGhpcyxcbiAgICAgICk7XG4gICAgfVxuICAgIGlmICh0aGlzLmJpbGxpbmdNb2RlID09PSBCaWxsaW5nTW9kZS5QQVlfUEVSX1JFUVVFU1QpIHtcbiAgICAgIC8vIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIFwiQXV0b1NjYWxpbmcgaXMgbm90IGF2YWlsYWJsZSBmb3IgdGFibGVzIHdpdGggUEFZX1BFUl9SRVFVRVNUIGJpbGxpbmcgbW9kZVwiLFxuICAgICAgICAvLyB0aGlzLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gKHRoaXMudGFibGVTY2FsaW5nLnNjYWxhYmxlUmVhZEF0dHJpYnV0ZSA9XG4gICAgICBuZXcgU2NhbGFibGVUYWJsZUF0dHJpYnV0ZSh0aGlzLCBcIlJlYWRTY2FsaW5nXCIsIHtcbiAgICAgICAgc2VydmljZU5hbWVzcGFjZTogYXBwc2NhbGluZy5TZXJ2aWNlTmFtZXNwYWNlLkRZTkFNT0RCLFxuICAgICAgICByZXNvdXJjZUlkOiBgdGFibGUvJHt0aGlzLnRhYmxlTmFtZX1gLFxuICAgICAgICBkaW1lbnNpb246IFwiZHluYW1vZGI6dGFibGU6UmVhZENhcGFjaXR5VW5pdHNcIixcbiAgICAgICAgLy8gcm9sZTogdGhpcy5zY2FsaW5nUm9sZSwgLy8gQ29tbWVudGluZyBvdXQgLSBsZXQgVGVycmFmb3JtIHVzZSBzZXJ2aWNlLWxpbmtlZCByb2xlXG4gICAgICAgIC4uLnByb3BzLFxuICAgICAgfSkpO1xuICB9XG5cbiAgcHVibGljIGF1dG9TY2FsZVdyaXRlQ2FwYWNpdHkoXG4gICAgcHJvcHM6IEVuYWJsZVNjYWxpbmdQcm9wcyxcbiAgKTogSVNjYWxhYmxlVGFibGVBdHRyaWJ1dGUge1xuICAgIGlmICh0aGlzLnRhYmxlU2NhbGluZy5zY2FsYWJsZVdyaXRlQXR0cmlidXRlKSB7XG4gICAgICAvLyB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKFxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBcIldyaXRlIEF1dG9TY2FsaW5nIGFscmVhZHkgZW5hYmxlZCBmb3IgdGhpcyB0YWJsZVwiLFxuICAgICAgICAvLyB0aGlzLFxuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuYmlsbGluZ01vZGUgPT09IEJpbGxpbmdNb2RlLlBBWV9QRVJfUkVRVUVTVCkge1xuICAgICAgLy8gdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgXCJBdXRvU2NhbGluZyBpcyBub3QgYXZhaWxhYmxlIGZvciB0YWJsZXMgd2l0aCBQQVlfUEVSX1JFUVVFU1QgYmlsbGluZyBtb2RlXCIsXG4gICAgICAgIC8vIHRoaXMsXG4gICAgICApO1xuICAgIH1cblxuICAgIHRoaXMudGFibGVTY2FsaW5nLnNjYWxhYmxlV3JpdGVBdHRyaWJ1dGUgPSBuZXcgU2NhbGFibGVUYWJsZUF0dHJpYnV0ZShcbiAgICAgIHRoaXMsXG4gICAgICBcIldyaXRlU2NhbGluZ1wiLFxuICAgICAge1xuICAgICAgICBzZXJ2aWNlTmFtZXNwYWNlOiBhcHBzY2FsaW5nLlNlcnZpY2VOYW1lc3BhY2UuRFlOQU1PREIsXG4gICAgICAgIHJlc291cmNlSWQ6IGB0YWJsZS8ke3RoaXMudGFibGVOYW1lfWAsXG4gICAgICAgIGRpbWVuc2lvbjogXCJkeW5hbW9kYjp0YWJsZTpXcml0ZUNhcGFjaXR5VW5pdHNcIixcbiAgICAgICAgLy8gcm9sZTogdGhpcy5zY2FsaW5nUm9sZSwgLy8gQ29tbWVudGluZyBvdXQgLSBsZXQgVGVycmFmb3JtIHVzZSBzZXJ2aWNlLWxpbmtlZCByb2xlXG4gICAgICAgIC4uLnByb3BzLFxuICAgICAgfSxcbiAgICApO1xuICAgIC8vIElmIHRoZXJlIGFyZSByZXBsaWNhcywgdGhleSBkZXBlbmQgb24gdGhlIHdyaXRlIHNjYWxpbmcgcG9saWN5IG9mIHRoZSBtYWluIHRhYmxlLlxuICAgIC8vIFRoaXMgaXMgbm90IGV4cGxpY2l0bHkgbW9kZWxlZCBpbiBURiBidXQgd2FzIGhhbmRsZWQgYnkgQ3VzdG9tUmVzb3VyY2UgZGVwZW5kZW5jaWVzIGluIENESy5cbiAgICAvLyBGb3IgVEYsIHRoaXMgZGVwZW5kZW5jeSBpcyBpbXBsaWNpdCBpZiB0aGUgcHJvdmlkZXIgaGFuZGxlcyBpdCwgb3IgbWlnaHQgbmVlZCBleHBsaWNpdCBkZXBlbmRzT24gaWYgaXNzdWVzIGFyaXNlLlxuICAgIHJldHVybiB0aGlzLnRhYmxlU2NhbGluZy5zY2FsYWJsZVdyaXRlQXR0cmlidXRlO1xuICB9XG5cbiAgcHVibGljIGF1dG9TY2FsZUdsb2JhbFNlY29uZGFyeUluZGV4UmVhZENhcGFjaXR5KFxuICAgIGluZGV4TmFtZTogc3RyaW5nLFxuICAgIHByb3BzOiBFbmFibGVTY2FsaW5nUHJvcHMsXG4gICk6IElTY2FsYWJsZVRhYmxlQXR0cmlidXRlIHtcbiAgICBpZiAodGhpcy5iaWxsaW5nTW9kZSA9PT0gQmlsbGluZ01vZGUuUEFZX1BFUl9SRVFVRVNUKSB7XG4gICAgICAvLyB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKFxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBcIkF1dG9TY2FsaW5nIGlzIG5vdCBhdmFpbGFibGUgZm9yIHRhYmxlcyB3aXRoIFBBWV9QRVJfUkVRVUVTVCBiaWxsaW5nIG1vZGVcIixcbiAgICAgICAgLy8gdGhpcyxcbiAgICAgICk7XG4gICAgfVxuICAgIGNvbnN0IGF0dHJpYnV0ZVBhaXIgPSB0aGlzLmluZGV4U2NhbGluZy5nZXQoaW5kZXhOYW1lKTtcbiAgICBpZiAoIWF0dHJpYnV0ZVBhaXIpIHtcbiAgICAgIC8vIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBObyBnbG9iYWwgc2Vjb25kYXJ5IGluZGV4IHdpdGggbmFtZSAke2luZGV4TmFtZX1gLFxuICAgICAgICAvLyB0aGlzLFxuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKGF0dHJpYnV0ZVBhaXIuc2NhbGFibGVSZWFkQXR0cmlidXRlKSB7XG4gICAgICAvLyB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKFxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBcIlJlYWQgQXV0b1NjYWxpbmcgYWxyZWFkeSBlbmFibGVkIGZvciB0aGlzIGluZGV4XCIsXG4gICAgICAgIC8vIHRoaXMsXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiAoYXR0cmlidXRlUGFpci5zY2FsYWJsZVJlYWRBdHRyaWJ1dGUgPSBuZXcgU2NhbGFibGVUYWJsZUF0dHJpYnV0ZShcbiAgICAgIHRoaXMsXG4gICAgICBgJHtpbmRleE5hbWV9UmVhZFNjYWxpbmdgLFxuICAgICAge1xuICAgICAgICBzZXJ2aWNlTmFtZXNwYWNlOiBhcHBzY2FsaW5nLlNlcnZpY2VOYW1lc3BhY2UuRFlOQU1PREIsXG4gICAgICAgIHJlc291cmNlSWQ6IGB0YWJsZS8ke3RoaXMudGFibGVOYW1lfS9pbmRleC8ke2luZGV4TmFtZX1gLFxuICAgICAgICBkaW1lbnNpb246IFwiZHluYW1vZGI6aW5kZXg6UmVhZENhcGFjaXR5VW5pdHNcIixcbiAgICAgICAgLy8gcm9sZTogdGhpcy5zY2FsaW5nUm9sZSwgLy8gQ29tbWVudGluZyBvdXQgLSBsZXQgVGVycmFmb3JtIHVzZSBzZXJ2aWNlLWxpbmtlZCByb2xlXG4gICAgICAgIC4uLnByb3BzLFxuICAgICAgfSxcbiAgICApKTtcbiAgfVxuXG4gIHB1YmxpYyBhdXRvU2NhbGVHbG9iYWxTZWNvbmRhcnlJbmRleFdyaXRlQ2FwYWNpdHkoXG4gICAgaW5kZXhOYW1lOiBzdHJpbmcsXG4gICAgcHJvcHM6IEVuYWJsZVNjYWxpbmdQcm9wcyxcbiAgKTogSVNjYWxhYmxlVGFibGVBdHRyaWJ1dGUge1xuICAgIGlmICh0aGlzLmJpbGxpbmdNb2RlID09PSBCaWxsaW5nTW9kZS5QQVlfUEVSX1JFUVVFU1QpIHtcbiAgICAgIC8vIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIFwiQXV0b1NjYWxpbmcgaXMgbm90IGF2YWlsYWJsZSBmb3IgdGFibGVzIHdpdGggUEFZX1BFUl9SRVFVRVNUIGJpbGxpbmcgbW9kZVwiLFxuICAgICAgICAvLyB0aGlzLFxuICAgICAgKTtcbiAgICB9XG4gICAgY29uc3QgYXR0cmlidXRlUGFpciA9IHRoaXMuaW5kZXhTY2FsaW5nLmdldChpbmRleE5hbWUpO1xuICAgIGlmICghYXR0cmlidXRlUGFpcikge1xuICAgICAgLy8gdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYE5vIGdsb2JhbCBzZWNvbmRhcnkgaW5kZXggd2l0aCBuYW1lICR7aW5kZXhOYW1lfWAsXG4gICAgICAgIC8vIHRoaXMsXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAoYXR0cmlidXRlUGFpci5zY2FsYWJsZVdyaXRlQXR0cmlidXRlKSB7XG4gICAgICAvLyB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKFxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBcIldyaXRlIEF1dG9TY2FsaW5nIGFscmVhZHkgZW5hYmxlZCBmb3IgdGhpcyBpbmRleFwiLFxuICAgICAgICAvLyB0aGlzLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gKGF0dHJpYnV0ZVBhaXIuc2NhbGFibGVXcml0ZUF0dHJpYnV0ZSA9IG5ldyBTY2FsYWJsZVRhYmxlQXR0cmlidXRlKFxuICAgICAgdGhpcyxcbiAgICAgIGAke2luZGV4TmFtZX1Xcml0ZVNjYWxpbmdgLFxuICAgICAge1xuICAgICAgICBzZXJ2aWNlTmFtZXNwYWNlOiBhcHBzY2FsaW5nLlNlcnZpY2VOYW1lc3BhY2UuRFlOQU1PREIsXG4gICAgICAgIHJlc291cmNlSWQ6IGB0YWJsZS8ke3RoaXMudGFibGVOYW1lfS9pbmRleC8ke2luZGV4TmFtZX1gLFxuICAgICAgICBkaW1lbnNpb246IFwiZHluYW1vZGI6aW5kZXg6V3JpdGVDYXBhY2l0eVVuaXRzXCIsXG4gICAgICAgIC8vIHJvbGU6IHRoaXMuc2NhbGluZ1JvbGUsIC8vIENvbW1lbnRpbmcgb3V0IC0gbGV0IFRlcnJhZm9ybSB1c2Ugc2VydmljZS1saW5rZWQgcm9sZVxuICAgICAgICAuLi5wcm9wcyxcbiAgICAgIH0sXG4gICAgKSk7XG4gIH1cblxuICBwdWJsaWMgc2NoZW1hKGluZGV4TmFtZT86IHN0cmluZyk6IFNjaGVtYU9wdGlvbnMge1xuICAgIGlmICghaW5kZXhOYW1lKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBwYXJ0aXRpb25LZXk6IHRoaXMudGFibGVQYXJ0aXRpb25LZXksXG4gICAgICAgIHNvcnRLZXk6IHRoaXMudGFibGVTb3J0S2V5LFxuICAgICAgfTtcbiAgICB9XG4gICAgY29uc3Qgc2NoZW1hID0gdGhpcy5zZWNvbmRhcnlJbmRleFNjaGVtYXMuZ2V0KGluZGV4TmFtZSk7XG4gICAgaWYgKCFzY2hlbWEpIHtcbiAgICAgIC8vIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBDYW5ub3QgZmluZCBzY2hlbWEgZm9yIGluZGV4OiAke2luZGV4TmFtZX0uIFVzZSAnYWRkR2xvYmFsU2Vjb25kYXJ5SW5kZXgnIG9yICdhZGRMb2NhbFNlY29uZGFyeUluZGV4JyB0byBhZGQgaW5kZXhgLFxuICAgICAgICAvLyB0aGlzLFxuICAgICAgKTtcbiAgICB9XG4gICAgcmV0dXJuIHNjaGVtYTtcbiAgfVxuXG4gIHByaXZhdGUgdmFsaWRhdGVUYWJsZSgpOiBzdHJpbmdbXSB7XG4gICAgY29uc3QgZXJyb3JzID0gbmV3IEFycmF5PHN0cmluZz4oKTtcbiAgICBpZiAoIXRoaXMudGFibGVQYXJ0aXRpb25LZXkpIHtcbiAgICAgIGVycm9ycy5wdXNoKFwiQSBwYXJ0aXRpb24ga2V5IG11c3QgYmUgc3BlY2lmaWVkXCIpO1xuICAgIH1cbiAgICBpZiAodGhpcy5sb2NhbFNlY29uZGFyeUluZGV4ZXNJbnRlcm5hbC5sZW5ndGggPiAwICYmICF0aGlzLnRhYmxlU29ydEtleSkge1xuICAgICAgZXJyb3JzLnB1c2goXG4gICAgICAgIFwiQSBzb3J0IGtleSBvZiB0aGUgdGFibGUgbXVzdCBiZSBzcGVjaWZpZWQgdG8gYWRkIGxvY2FsIHNlY29uZGFyeSBpbmRleGVzXCIsXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAoXG4gICAgICB0aGlzLl9yZXBsaWNhcyAmJlxuICAgICAgdGhpcy5fcmVwbGljYXMubGVuZ3RoID4gMCAmJlxuICAgICAgdGhpcy5iaWxsaW5nTW9kZSA9PT0gQmlsbGluZ01vZGUuUFJPVklTSU9ORURcbiAgICApIHtcbiAgICAgIGNvbnN0IHdyaXRlQXV0b1NjYWxlQXR0cmlidXRlID0gdGhpcy50YWJsZVNjYWxpbmcuc2NhbGFibGVXcml0ZUF0dHJpYnV0ZTtcbiAgICAgIGlmICghd3JpdGVBdXRvU2NhbGVBdHRyaWJ1dGUpIHtcbiAgICAgICAgZXJyb3JzLnB1c2goXG4gICAgICAgICAgXCJBIGdsb2JhbCBUYWJsZSB0aGF0IHVzZXMgUFJPVklTSU9ORUQgYXMgdGhlIGJpbGxpbmcgbW9kZSBuZWVkcyBhdXRvLXNjYWxlZCB3cml0ZSBjYXBhY2l0eS4gXCIgK1xuICAgICAgICAgICAgXCJVc2UgdGhlIGF1dG9TY2FsZVdyaXRlQ2FwYWNpdHkoKSBtZXRob2QgdG8gZW5hYmxlIGl0LlwiLFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIGlmICghd3JpdGVBdXRvU2NhbGVBdHRyaWJ1dGUuX3NjYWxpbmdQb2xpY3lDcmVhdGVkKSB7XG4gICAgICAgIGVycm9ycy5wdXNoKFxuICAgICAgICAgIFwiQSBnbG9iYWwgVGFibGUgdGhhdCB1c2VzIFBST1ZJU0lPTkVEIGFzIHRoZSBiaWxsaW5nIG1vZGUgbmVlZHMgYXV0by1zY2FsZWQgd3JpdGUgY2FwYWNpdHkgd2l0aCBhIHBvbGljeS4gXCIgK1xuICAgICAgICAgICAgXCJDYWxsIG9uZSBvZiB0aGUgc2NhbGVPbiooKSBtZXRob2RzIG9mIHRoZSBvYmplY3QgcmV0dXJuZWQgZnJvbSBhdXRvU2NhbGVXcml0ZUNhcGFjaXR5KClcIixcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGVycm9ycztcbiAgfVxuXG4gIHByaXZhdGUgdmFsaWRhdGVQcm92aXNpb25pbmcocHJvcHM6IHtcbiAgICByZWFkQ2FwYWNpdHk/OiBudW1iZXI7XG4gICAgd3JpdGVDYXBhY2l0eT86IG51bWJlcjtcbiAgfSkge1xuICAgIGlmICh0aGlzLmJpbGxpbmdNb2RlID09PSBCaWxsaW5nTW9kZS5QQVlfUEVSX1JFUVVFU1QpIHtcbiAgICAgIGlmIChcbiAgICAgICAgcHJvcHMucmVhZENhcGFjaXR5ICE9PSB1bmRlZmluZWQgfHxcbiAgICAgICAgcHJvcHMud3JpdGVDYXBhY2l0eSAhPT0gdW5kZWZpbmVkXG4gICAgICApIHtcbiAgICAgICAgLy8gdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIFwiWW91IGNhbm5vdCBwcm92aXNpb24gcmVhZCBhbmQgd3JpdGUgY2FwYWNpdHkgZm9yIGEgdGFibGUgd2l0aCBQQVlfUEVSX1JFUVVFU1QgYmlsbGluZyBtb2RlXCIsXG4gICAgICAgICAgLy8gdGhpcyxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHZhbGlkYXRlUHJvdmlzaW9uaW5nR1NJKHByb3BzOiBHbG9iYWxTZWNvbmRhcnlJbmRleFByb3BzKSB7XG4gICAgaWYgKHRoaXMuYmlsbGluZ01vZGUgPT09IEJpbGxpbmdNb2RlLlBBWV9QRVJfUkVRVUVTVCkge1xuICAgICAgaWYgKFxuICAgICAgICBwcm9wcy5yZWFkQ2FwYWNpdHkgIT09IHVuZGVmaW5lZCB8fFxuICAgICAgICBwcm9wcy53cml0ZUNhcGFjaXR5ICE9PSB1bmRlZmluZWRcbiAgICAgICkge1xuICAgICAgICAvLyB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKFxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgXCJZb3UgY2Fubm90IHByb3Zpc2lvbiByZWFkIGFuZCB3cml0ZSBjYXBhY2l0eSBmb3IgYSBHU0kgd2l0aCBQQVlfUEVSX1JFUVVFU1QgYmlsbGluZyBtb2RlIG9uIHRoZSB0YWJsZVwiLFxuICAgICAgICAgIC8vIHRoaXMsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSB2YWxpZGF0ZUluZGV4TmFtZShpbmRleE5hbWU6IHN0cmluZykge1xuICAgIGlmICh0aGlzLnNlY29uZGFyeUluZGV4U2NoZW1hcy5oYXMoaW5kZXhOYW1lKSkge1xuICAgICAgLy8gdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYEEgZHVwbGljYXRlIGluZGV4IG5hbWUsICR7aW5kZXhOYW1lfSwgaXMgbm90IGFsbG93ZWRgLFxuICAgICAgICAvLyB0aGlzLFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHZhbGlkYXRlTm9uS2V5QXR0cmlidXRlcyhub25LZXlBdHRyaWJ1dGVzOiBzdHJpbmdbXSkge1xuICAgIGlmICh0aGlzLm5vbktleUF0dHJpYnV0ZXMuc2l6ZSArIG5vbktleUF0dHJpYnV0ZXMubGVuZ3RoID4gMTAwKSB7XG4gICAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcihcbiAgICAgICAgXCJBIG1heGltdW0gbnVtYmVyIG9mIG5vbktleUF0dHJpYnV0ZXMgYWNyb3NzIGFsbCBvZiBzZWNvbmRhcnkgaW5kZXhlcyBpcyAxMDBcIixcbiAgICAgICk7XG4gICAgfVxuICAgIG5vbktleUF0dHJpYnV0ZXMuZm9yRWFjaCgoYXR0KSA9PiB0aGlzLm5vbktleUF0dHJpYnV0ZXMuYWRkKGF0dCkpO1xuICB9XG5cbiAgcHJpdmF0ZSByZW5kZXJQb2ludEluVGltZVJlY292ZXJ5KFxuICAgIHByb3BzOiBUYWJsZVByb3BzLFxuICApOiBkeW5hbW9kYlRhYmxlLkR5bmFtb2RiVGFibGVQb2ludEluVGltZVJlY292ZXJ5IHwgdW5kZWZpbmVkIHtcbiAgICBpZiAoXG4gICAgICBwcm9wcy5wb2ludEluVGltZVJlY292ZXJ5U3BlY2lmaWNhdGlvbiAhPT0gdW5kZWZpbmVkICYmXG4gICAgICBwcm9wcy5wb2ludEluVGltZVJlY292ZXJ5ICE9PSB1bmRlZmluZWRcbiAgICApIHtcbiAgICAgIC8vIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIFwiYHBvaW50SW5UaW1lUmVjb3ZlcnlTcGVjaWZpY2F0aW9uYCBhbmQgYHBvaW50SW5UaW1lUmVjb3ZlcnlgIGFyZSBzZXQuIFVzZSBgcG9pbnRJblRpbWVSZWNvdmVyeVNwZWNpZmljYXRpb25gIG9ubHkuXCIsXG4gICAgICAgIC8vIHRoaXMsXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IHNwZWMgPSBwcm9wcy5wb2ludEluVGltZVJlY292ZXJ5U3BlY2lmaWNhdGlvbjtcbiAgICBpZiAoc3BlYz8ucmVjb3ZlcnlQZXJpb2RJbkRheXMpIHtcbiAgICAgIC8vIFRPRE86IFVwZ3JhZGUgcHJvdmlkZXIgdG8gNS45OC4wIHRvIHN1cHBvcnQgcmVjb3ZlcnlQZXJpb2RJbkRheXNcbiAgICAgIEFubm90YXRpb25zLm9mKHRoaXMpLmFkZFdhcm5pbmcoXG4gICAgICAgIFwiV2FybmluZzogcmVjb3ZlcnlQZXJpb2RJbkRheXMgaXMgbm90IHN1cHBvcnRlZCB1bnRpbCBwcm92aWRlciBhd3MgaXMgdXBncmFkZWQgdG8gNS45OC4wIGFuZCB3aWxsIGJlIGlnbm9yZWQuXCIsXG4gICAgICApO1xuICAgIH1cblxuICAgIGNvbnN0IGVuYWJsZWQgPVxuICAgICAgc3BlYz8ucG9pbnRJblRpbWVSZWNvdmVyeUVuYWJsZWQgPz8gcHJvcHMucG9pbnRJblRpbWVSZWNvdmVyeTtcbiAgICBpZiAoZW5hYmxlZCA9PT0gdW5kZWZpbmVkKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIHJldHVybiB7IGVuYWJsZWQgfTtcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRJbmRleFByb2plY3Rpb24oXG4gICAgcHJvcHM6IFNlY29uZGFyeUluZGV4UHJvcHMsXG4gICk6IFBpY2s8XG4gICAgZHluYW1vZGJUYWJsZS5EeW5hbW9kYlRhYmxlR2xvYmFsU2Vjb25kYXJ5SW5kZXgsXG4gICAgXCJwcm9qZWN0aW9uVHlwZVwiIHwgXCJub25LZXlBdHRyaWJ1dGVzXCJcbiAgPiB7XG4gICAgaWYgKFxuICAgICAgcHJvcHMucHJvamVjdGlvblR5cGUgPT09IFByb2plY3Rpb25UeXBlLklOQ0xVREUgJiZcbiAgICAgICFwcm9wcy5ub25LZXlBdHRyaWJ1dGVzXG4gICAgKSB7XG4gICAgICAvLyB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKFxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgTm9uLWtleSBhdHRyaWJ1dGVzIHNob3VsZCBiZSBzcGVjaWZpZWQgd2hlbiB1c2luZyAke1Byb2plY3Rpb25UeXBlLklOQ0xVREV9IHByb2plY3Rpb24gdHlwZWAsXG4gICAgICAgIC8vIHRoaXMsXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAoXG4gICAgICBwcm9wcy5wcm9qZWN0aW9uVHlwZSAhPT0gUHJvamVjdGlvblR5cGUuSU5DTFVERSAmJlxuICAgICAgcHJvcHMubm9uS2V5QXR0cmlidXRlc1xuICAgICkge1xuICAgICAgLy8gdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYE5vbi1rZXkgYXR0cmlidXRlcyBzaG91bGQgbm90IGJlIHNwZWNpZmllZCB3aGVuIG5vdCB1c2luZyAke1Byb2plY3Rpb25UeXBlLklOQ0xVREV9IHByb2plY3Rpb24gdHlwZWAsXG4gICAgICAgIC8vIHRoaXMsXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAocHJvcHMubm9uS2V5QXR0cmlidXRlcykge1xuICAgICAgdGhpcy52YWxpZGF0ZU5vbktleUF0dHJpYnV0ZXMocHJvcHMubm9uS2V5QXR0cmlidXRlcyk7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBwcm9qZWN0aW9uVHlwZTogcHJvcHMucHJvamVjdGlvblR5cGUgPz8gUHJvamVjdGlvblR5cGUuQUxMLFxuICAgICAgbm9uS2V5QXR0cmlidXRlczogcHJvcHMubm9uS2V5QXR0cmlidXRlcyxcbiAgICB9O1xuICB9XG5cbiAgLy8gVE9ETzoga2V5VHlwZSBpcyB1bnVzZWRcbiAgcHJpdmF0ZSBhZGRLZXkoYXR0cmlidXRlOiBBdHRyaWJ1dGUsIF9rZXlUeXBlOiBzdHJpbmcpIHtcbiAgICBjb25zdCBleGlzdGluZ0F0dHIgPSB0aGlzLmF0dHJpYnV0ZURlZmluaXRpb25zSW50ZXJuYWwuZmluZChcbiAgICAgIChkZWYpID0+IGRlZi5uYW1lID09PSBhdHRyaWJ1dGUubmFtZSxcbiAgICApO1xuICAgIGlmIChleGlzdGluZ0F0dHIgJiYgZXhpc3RpbmdBdHRyLnR5cGUgIT09IGF0dHJpYnV0ZS50eXBlKSB7XG4gICAgICAvLyB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKFxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgVW5hYmxlIHRvIHNwZWNpZnkgJHthdHRyaWJ1dGUubmFtZX0gYXMgJHthdHRyaWJ1dGUudHlwZX0gYmVjYXVzZSBpdCB3YXMgYWxyZWFkeSBkZWZpbmVkIGFzICR7ZXhpc3RpbmdBdHRyLnR5cGV9YCxcbiAgICAgICAgLy8gdGhpcyxcbiAgICAgICk7XG4gICAgfVxuICAgIGlmICghZXhpc3RpbmdBdHRyKSB7XG4gICAgICB0aGlzLmF0dHJpYnV0ZURlZmluaXRpb25zSW50ZXJuYWwucHVzaCh7XG4gICAgICAgIG5hbWU6IGF0dHJpYnV0ZS5uYW1lLFxuICAgICAgICB0eXBlOiBhdHRyaWJ1dGUudHlwZSxcbiAgICAgIH0pO1xuICAgIH1cbiAgICAvLyBGb3IgdGhlIG1haW4gdGFibGUsIGhhc2hLZXkgYW5kIHJhbmdlS2V5IGFyZSBzZXQgZGlyZWN0bHkgb24gdGhlIHJlc291cmNlLlxuICAgIC8vIEZvciBHU0lzL0xTSXMsIHRoZXkgYXJlIHBhcnQgb2YgdGhlaXIgcmVzcGVjdGl2ZSBibG9ja3MuXG4gIH1cblxuICBwcml2YXRlIHJlZ2lzdGVyQXR0cmlidXRlKGF0dHJpYnV0ZTogQXR0cmlidXRlKSB7XG4gICAgY29uc3QgZXhpc3RpbmdEZWYgPSB0aGlzLmF0dHJpYnV0ZURlZmluaXRpb25zSW50ZXJuYWwuZmluZChcbiAgICAgIChkZWYpID0+IGRlZi5uYW1lID09PSBhdHRyaWJ1dGUubmFtZSxcbiAgICApO1xuICAgIGlmIChleGlzdGluZ0RlZiAmJiBleGlzdGluZ0RlZi50eXBlICE9PSBhdHRyaWJ1dGUudHlwZSkge1xuICAgICAgLy8gdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYFVuYWJsZSB0byBzcGVjaWZ5ICR7YXR0cmlidXRlLm5hbWV9IGFzICR7YXR0cmlidXRlLnR5cGV9IGJlY2F1c2UgaXQgd2FzIGFscmVhZHkgZGVmaW5lZCBhcyAke2V4aXN0aW5nRGVmLnR5cGV9YCxcbiAgICAgICAgLy8gdGhpcyxcbiAgICAgICk7XG4gICAgfVxuICAgIGlmICghZXhpc3RpbmdEZWYpIHtcbiAgICAgIHRoaXMuYXR0cmlidXRlRGVmaW5pdGlvbnNJbnRlcm5hbC5wdXNoKHtcbiAgICAgICAgbmFtZTogYXR0cmlidXRlLm5hbWUsXG4gICAgICAgIHR5cGU6IGF0dHJpYnV0ZS50eXBlLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgLy8gQ29tbWVudGluZyBvdXQgbWFrZVNjYWxpbmdSb2xlIG1ldGhvZCAtIFRlcnJhZm9ybSBoYW5kbGVzIHNlcnZpY2UtbGlua2VkIHJvbGVzIGF1dG9tYXRpY2FsbHlcbiAgLy8gVW5saWtlIEFXUyBDREsgQ2xvdWRGb3JtYXRpb24gaW1wbGVtZW50YXRpb24sIFRlcnJhZm9ybSBBV1MgcHJvdmlkZXIgY3JlYXRlcyBhcHByb3ByaWF0ZVxuICAvLyBzZXJ2aWNlLWxpbmtlZCByb2xlcyB3aGVuIHJvbGVBcm4gaXMgb21pdHRlZCBmcm9tIGF3c19hcHBhdXRvc2NhbGluZ190YXJnZXQgcmVzb3VyY2VcbiAgLy8gcHJpdmF0ZSBtYWtlU2NhbGluZ1JvbGUoKTogaWFtLklSb2xlIHtcbiAgLy8gICAvLyBVc2UgYSBTZXJ2aWNlIExpbmtlZCBSb2xlLlxuICAvLyAgIC8vIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9hdXRvc2NhbGluZy9hcHBsaWNhdGlvbi91c2VyZ3VpZGUvYXBwbGljYXRpb24tYXV0by1zY2FsaW5nLXNlcnZpY2UtbGlua2VkLXJvbGVzLmh0bWxcbiAgLy8gICByZXR1cm4gaWFtLlJvbGUuZnJvbVJvbGVBcm4oXG4gIC8vICAgICB0aGlzLFxuICAvLyAgICAgXCJTY2FsaW5nUm9sZVwiLFxuICAvLyAgICAgdGhpcy5zdGFjay5mb3JtYXRBcm4oe1xuICAvLyAgICAgICBzZXJ2aWNlOiBcImlhbVwiLFxuICAvLyAgICAgICByZWdpb246IFwiXCIsIC8vIFNMUnMgYXJlIGdsb2JhbFxuICAvLyAgICAgICByZXNvdXJjZTpcbiAgLy8gICAgICAgICBcInJvbGUvYXdzLXNlcnZpY2Utcm9sZS9keW5hbW9kYi5hcHBsaWNhdGlvbi1hdXRvc2NhbGluZy5hbWF6b25hd3MuY29tXCIsXG4gIC8vICAgICAgIHJlc291cmNlTmFtZTogXCJBV1NTZXJ2aWNlUm9sZUZvckFwcGxpY2F0aW9uQXV0b1NjYWxpbmdfRHluYW1vREJUYWJsZVwiLFxuICAvLyAgICAgICAvLyBUT0RPOiBJcyB0aGlzIG5lZWRlZD9cbiAgLy8gICAgICAgLy8gYXJuRm9ybWF0OiBBcm5Gb3JtYXQuU0xBU0hfUkVTT1VSQ0VfU0xBU0hfUkVTT1VSQ0VfTkFNRSwgLy8gU3BlY2lhbCBmb3JtYXQgZm9yIFNMUnNcbiAgLy8gICAgIH0pLFxuICAvLyAgICk7XG4gIC8vIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyByZXBsaWNhIHRhYmxlc1xuICAgKlxuICAgKiBAcGFyYW0gcmVnaW9ucyByZWdpb25zIHdoZXJlIHRvIGNyZWF0ZSB0YWJsZXNcbiAgICovXG4gIHByaXZhdGUgcmVuZGVyUmVwbGljYXMoXG4gICAgcmVnaW9ucz86IHN0cmluZ1tdLFxuICAgIHJlcGxpY2FTcGVjaWZpY2F0aW9uPzogRHluYW1vZGJUYWJsZVJlcGxpY2FbXSxcbiAgKTogZHluYW1vZGJUYWJsZS5EeW5hbW9kYlRhYmxlUmVwbGljYVtdIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAocmVwbGljYVNwZWNpZmljYXRpb24gJiYgcmVwbGljYVNwZWNpZmljYXRpb24ubGVuZ3RoID4gMCkge1xuICAgICAgaWYgKFxuICAgICAgICAhVG9rZW4uaXNVbnJlc29sdmVkKHRoaXMuc3RhY2sucmVnaW9uKSAmJlxuICAgICAgICByZXBsaWNhU3BlY2lmaWNhdGlvbi5zb21lKFxuICAgICAgICAgIChyZXBsaWNhKSA9PiByZXBsaWNhLnJlZ2lvbk5hbWUgPT09IHRoaXMuc3RhY2sucmVnaW9uLFxuICAgICAgICApXG4gICAgICApIHtcbiAgICAgICAgLy8gdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIFwiYHJlcGxpY2FTcGVjaWZpY2F0aW9uYCBjYW5ub3QgaW5jbHVkZSB0aGUgcmVnaW9uIHdoZXJlIHRoaXMgc3RhY2sgaXMgZGVwbG95ZWQuXCIsXG4gICAgICAgICAgLy8gdGhpcyxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXBsaWNhU3BlY2lmaWNhdGlvbi5tYXAoKHJlcGxpY2EpID0+ICh7XG4gICAgICAgIHJlZ2lvbk5hbWU6IHJlcGxpY2EucmVnaW9uTmFtZSxcbiAgICAgICAga21zS2V5QXJuOiByZXBsaWNhLmVuY3J5cHRpb25LZXk/LmtleUFybixcbiAgICAgICAgcG9pbnRJblRpbWVSZWNvdmVyeTogcmVwbGljYS5wb2ludEluVGltZVJlY292ZXJ5LFxuICAgICAgICBwcm9wYWdhdGVUYWdzOiByZXBsaWNhLnByb3BhZ2F0ZVRhZ3MsXG4gICAgICB9KSk7XG4gICAgfVxuICAgIGlmICghcmVnaW9ucyB8fCByZWdpb25zLmxlbmd0aCA9PT0gMCkgcmV0dXJuIHVuZGVmaW5lZDtcblxuICAgIGlmIChcbiAgICAgICFUb2tlbi5pc1VucmVzb2x2ZWQodGhpcy5zdGFjay5yZWdpb24pICYmXG4gICAgICByZWdpb25zLmluY2x1ZGVzKHRoaXMuc3RhY2sucmVnaW9uKVxuICAgICkge1xuICAgICAgLy8gdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgXCJgcmVwbGljYXRpb25SZWdpb25zYCBjYW5ub3QgaW5jbHVkZSB0aGUgcmVnaW9uIHdoZXJlIHRoaXMgc3RhY2sgaXMgZGVwbG95ZWQuXCIsXG4gICAgICAgIC8vIHRoaXMsXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiBbLi4ubmV3IFNldChyZWdpb25zKV0ubWFwKChyZWdpb24pID0+ICh7XG4gICAgICByZWdpb25OYW1lOiByZWdpb24sXG4gICAgfSkpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGdldCBoYXNJbmRleCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gKFxuICAgICAgdGhpcy5nbG9iYWxTZWNvbmRhcnlJbmRleGVzSW50ZXJuYWwubGVuZ3RoICtcbiAgICAgICAgdGhpcy5sb2NhbFNlY29uZGFyeUluZGV4ZXNJbnRlcm5hbC5sZW5ndGggPlxuICAgICAgMFxuICAgICk7XG4gIH1cblxuICBwcml2YXRlIHBhcnNlRW5jcnlwdGlvbihwcm9wczogVGFibGVQcm9wcyk6IHtcbiAgICBzc2VTcGVjaWZpY2F0aW9uPzogZHluYW1vZGJUYWJsZS5EeW5hbW9kYlRhYmxlU2VydmVyU2lkZUVuY3J5cHRpb247XG4gICAgZW5jcnlwdGlvbktleT86IGttcy5JS2V5O1xuICB9IHtcbiAgICBsZXQgZW5jcnlwdGlvblR5cGUgPSBwcm9wcy5lbmNyeXB0aW9uO1xuICAgIGlmIChlbmNyeXB0aW9uVHlwZSAhPSBudWxsICYmIHByb3BzLnNlcnZlclNpZGVFbmNyeXB0aW9uICE9IG51bGwpIHtcbiAgICAgIC8vIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIFwiT25seSBvbmUgb2YgZW5jcnlwdGlvbiBhbmQgc2VydmVyU2lkZUVuY3J5cHRpb24gY2FuIGJlIHNwZWNpZmllZCwgYnV0IGJvdGggd2VyZSBwcm92aWRlZFwiLFxuICAgICAgICAvLyB0aGlzLFxuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKHByb3BzLnNlcnZlclNpZGVFbmNyeXB0aW9uICYmIHByb3BzLmVuY3J5cHRpb25LZXkpIHtcbiAgICAgIC8vIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIFwiZW5jcnlwdGlvbktleSBjYW5ub3QgYmUgc3BlY2lmaWVkIHdoZW4gc2VydmVyU2lkZUVuY3J5cHRpb24gaXMgc3BlY2lmaWVkLiBVc2UgZW5jcnlwdGlvbiBpbnN0ZWFkXCIsXG4gICAgICAgIC8vIHRoaXMsXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmIChlbmNyeXB0aW9uVHlwZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBlbmNyeXB0aW9uVHlwZSA9XG4gICAgICAgIHByb3BzLmVuY3J5cHRpb25LZXkgIT0gbnVsbFxuICAgICAgICAgID8gVGFibGVFbmNyeXB0aW9uLkNVU1RPTUVSX01BTkFHRURcbiAgICAgICAgICA6IHByb3BzLnNlcnZlclNpZGVFbmNyeXB0aW9uXG4gICAgICAgICAgICA/IFRhYmxlRW5jcnlwdGlvbi5BV1NfTUFOQUdFRFxuICAgICAgICAgICAgOiB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgaWYgKFxuICAgICAgZW5jcnlwdGlvblR5cGUgIT09IFRhYmxlRW5jcnlwdGlvbi5DVVNUT01FUl9NQU5BR0VEICYmXG4gICAgICBwcm9wcy5lbmNyeXB0aW9uS2V5XG4gICAgKSB7XG4gICAgICAvLyB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKFxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBgZW5jcnlwdGlvbktleSBjYW5ub3QgYmUgc3BlY2lmaWVkIHVubGVzcyBlbmNyeXB0aW9uIGlzIHNldCB0byBUYWJsZUVuY3J5cHRpb24uQ1VTVE9NRVJfTUFOQUdFRCAoaXQgd2FzIHNldCB0byAke2VuY3J5cHRpb25UeXBlfSlgLFxuICAgICAgICAvLyB0aGlzLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBpbiB0aGlzIGNhc2UsIGVhY2ggcmVwbGljYSBzaG91bGQgc3BlY2lmeSBhIEN1c3RvbWVyIEtNUyBrZXkuXG4gICAgaWYgKFxuICAgICAgZW5jcnlwdGlvblR5cGUgPT09IFRhYmxlRW5jcnlwdGlvbi5DVVNUT01FUl9NQU5BR0VEICYmXG4gICAgICBwcm9wcy5yZXBsaWNhdGlvblJlZ2lvbnNcbiAgICApIHtcbiAgICAgIC8vIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IoXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIFwiVGFibGVFbmNyeXB0aW9uLkNVU1RPTUVSX01BTkFHRUQgaXMgbm90IHN1cHBvcnRlZCBieSBEeW5hbW9EQiBHbG9iYWwgVGFibGVzICh3aGVyZSByZXBsaWNhdGlvblJlZ2lvbnMgd2FzIHNldClcIixcbiAgICAgICAgLy8gdGhpcyxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgaWYgKFxuICAgICAgcHJvcHMucmVwbGljYVNwZWNpZmljYXRpb24gJiZcbiAgICAgIHByb3BzLnJlcGxpY2FTcGVjaWZpY2F0aW9uLmxlbmd0aCA+IDAgJiZcbiAgICAgIGVuY3J5cHRpb25UeXBlID09PSBUYWJsZUVuY3J5cHRpb24uQ1VTVE9NRVJfTUFOQUdFRFxuICAgICkge1xuICAgICAgaWYgKFxuICAgICAgICBwcm9wcy5yZXBsaWNhU3BlY2lmaWNhdGlvbi5zb21lKFxuICAgICAgICAgIChyZXBsaWNhKSA9PiAhcmVwbGljYS5lbmNyeXB0aW9uS2V5LCAvLyBDaGVjayBpZiBhbnkgcmVwbGljYSBpcyBtaXNzaW5nIGFuIGVuY3J5cHRpb24ga2V5XG4gICAgICAgIClcbiAgICAgICkge1xuICAgICAgICAvLyB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKFxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgXCJXaGVuIHVzaW5nIHJlcGxpY2FTcGVjaWZpY2F0aW9uLCBlYWNoIHJlcGxpY2EgbXVzdCBzcGVjaWZ5IGFuIGVuY3J5cHRpb25LZXkgaWYgVGFibGVFbmNyeXB0aW9uLkNVU1RPTUVSX01BTkFHRUQgaXMgdXNlZFwiLFxuICAgICAgICAgIC8vIHRoaXMsXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIC8vVmFsaWRhdGUgdGhhdCB0aGUga2V5cyBiZWxvbmcgdG8gdGhlIGNvcnJlY3QgcmVnaW9uc1xuICAgICAgaWYgKFxuICAgICAgICBwcm9wcy5yZXBsaWNhU3BlY2lmaWNhdGlvbi5zb21lKFxuICAgICAgICAgIChyZXBsaWNhKSA9PlxuICAgICAgICAgICAgcmVwbGljYS5lbmNyeXB0aW9uS2V5ICYmXG4gICAgICAgICAgICByZXBsaWNhLmVuY3J5cHRpb25LZXkuZW52LnJlZ2lvbiAhPT0gcmVwbGljYS5yZWdpb25OYW1lLFxuICAgICAgICApXG4gICAgICApIHtcbiAgICAgICAgLy8gdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIFwiV2hlbiB1c2luZyByZXBsaWNhU3BlY2lmaWNhdGlvbiwgZWFjaCByZXBsaWNhJ3MgZW5jcnlwdGlvbktleSBtdXN0IGJlIGluIHRoZSBzYW1lIHJlZ2lvbiBhcyBpdHMgcmVwbGljYVwiLFxuICAgICAgICAgIC8vIHRoaXMsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgc3dpdGNoIChlbmNyeXB0aW9uVHlwZSkge1xuICAgICAgY2FzZSBUYWJsZUVuY3J5cHRpb24uQ1VTVE9NRVJfTUFOQUdFRDpcbiAgICAgICAgY29uc3Qga2V5ID1cbiAgICAgICAgICBwcm9wcy5lbmNyeXB0aW9uS2V5ID8/XG4gICAgICAgICAgbmV3IGttcy5LZXkodGhpcywgXCJLZXlcIiwge1xuICAgICAgICAgICAgZGVzY3JpcHRpb246IGBDdXN0b21lci1tYW5hZ2VkIGtleSBhdXRvLWNyZWF0ZWQgZm9yIGVuY3J5cHRpbmcgRHluYW1vREIgdGFibGUgYXQgJHt0aGlzLm5vZGUucGF0aH1gLFxuICAgICAgICAgICAgZW5hYmxlS2V5Um90YXRpb246IHRydWUsXG4gICAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgc3NlU3BlY2lmaWNhdGlvbjogeyBlbmFibGVkOiB0cnVlLCBrbXNLZXlBcm46IGtleS5rZXlBcm4gfSxcbiAgICAgICAgICBlbmNyeXB0aW9uS2V5OiBrZXksXG4gICAgICAgIH07XG4gICAgICBjYXNlIFRhYmxlRW5jcnlwdGlvbi5BV1NfTUFOQUdFRDpcbiAgICAgICAgcmV0dXJuIHsgc3NlU3BlY2lmaWNhdGlvbjogeyBlbmFibGVkOiB0cnVlIH0gfTsgLy8gVXNlcyBhbGlhcy9hd3MvZHluYW1vZGIgYnkgZGVmYXVsdFxuICAgICAgY2FzZSBUYWJsZUVuY3J5cHRpb24uREVGQVVMVDpcbiAgICAgICAgcmV0dXJuIHsgc3NlU3BlY2lmaWNhdGlvbjogeyBlbmFibGVkOiBmYWxzZSB9IH07IC8vIEFXUy1vd25lZCBrZXlcbiAgICAgIGNhc2UgdW5kZWZpbmVkOlxuICAgICAgICByZXR1cm4geyBzc2VTcGVjaWZpY2F0aW9uOiB1bmRlZmluZWQgfTsgLy8gRGVmYXVsdHMgdG8gQVdTLW93bmVkIGtleVxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgLy8gdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgIGBVbmV4cGVjdGVkICdlbmNyeXB0aW9uVHlwZSc6ICR7ZW5jcnlwdGlvblR5cGV9YCxcbiAgICAgICAgICAvLyB0aGlzLFxuICAgICAgICApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgcmVuZGVySW1wb3J0U291cmNlU3BlY2lmaWNhdGlvbihcbiAgICBpbXBvcnRTb3VyY2U/OiBJbXBvcnRTb3VyY2VTcGVjaWZpY2F0aW9uLFxuICApOiBkeW5hbW9kYlRhYmxlLkR5bmFtb2RiVGFibGVJbXBvcnRUYWJsZSB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCFpbXBvcnRTb3VyY2UpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgY29uc3QgcmVuZGVyZWRJbnB1dEZvcm1hdCA9IGltcG9ydFNvdXJjZS5pbnB1dEZvcm1hdC5fcmVuZGVyKCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGlucHV0Rm9ybWF0OiByZW5kZXJlZElucHV0Rm9ybWF0LmlucHV0Rm9ybWF0LFxuICAgICAgaW5wdXRGb3JtYXRPcHRpb25zOiByZW5kZXJlZElucHV0Rm9ybWF0LmlucHV0Rm9ybWF0T3B0aW9ucyxcbiAgICAgIGlucHV0Q29tcHJlc3Npb25UeXBlOiBpbXBvcnRTb3VyY2UuY29tcHJlc3Npb25UeXBlLFxuICAgICAgczNCdWNrZXRTb3VyY2U6IHtcbiAgICAgICAgYnVja2V0OiBpbXBvcnRTb3VyY2UuYnVja2V0LmJ1Y2tldE5hbWUsXG4gICAgICAgIGJ1Y2tldE93bmVyOiBpbXBvcnRTb3VyY2UuYnVja2V0T3duZXIsXG4gICAgICAgIGtleVByZWZpeDogaW1wb3J0U291cmNlLmtleVByZWZpeCxcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxufVxuXG5pbnRlcmZhY2UgU2NhbGFibGVBdHRyaWJ1dGVQYWlyIHtcbiAgc2NhbGFibGVSZWFkQXR0cmlidXRlPzogU2NhbGFibGVUYWJsZUF0dHJpYnV0ZTtcbiAgc2NhbGFibGVXcml0ZUF0dHJpYnV0ZT86IFNjYWxhYmxlVGFibGVBdHRyaWJ1dGU7XG59XG4iXX0=