@aws-cdk/aws-mediaconnect-alpha 2.263.0-alpha.0
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.
- package/.jsii +28415 -0
- package/.jsii.tabl.json.gz +0 -0
- package/.warnings.jsii.js +592 -0
- package/LICENSE +201 -0
- package/NOTICE +2 -0
- package/README.md +1280 -0
- package/awslint.json +50 -0
- package/grants.json +42 -0
- package/lib/bridge-output.d.ts +54 -0
- package/lib/bridge-output.js +122 -0
- package/lib/bridge-source.d.ts +79 -0
- package/lib/bridge-source.js +217 -0
- package/lib/bridge.d.ts +419 -0
- package/lib/bridge.js +490 -0
- package/lib/flow-entitlement.d.ts +86 -0
- package/lib/flow-entitlement.js +152 -0
- package/lib/flow-output.d.ts +329 -0
- package/lib/flow-output.js +415 -0
- package/lib/flow-source-configuration.d.ts +558 -0
- package/lib/flow-source-configuration.js +595 -0
- package/lib/flow-source.d.ts +116 -0
- package/lib/flow-source.js +190 -0
- package/lib/flow.d.ts +975 -0
- package/lib/flow.js +1065 -0
- package/lib/gateway.d.ts +142 -0
- package/lib/gateway.js +236 -0
- package/lib/index.d.ts +14 -0
- package/lib/index.js +31 -0
- package/lib/mediaconnect-grants.generated.d.ts +53 -0
- package/lib/mediaconnect-grants.generated.js +136 -0
- package/lib/router-input.d.ts +686 -0
- package/lib/router-input.js +1095 -0
- package/lib/router-network-interface.d.ts +153 -0
- package/lib/router-network-interface.js +245 -0
- package/lib/router-output.d.ts +557 -0
- package/lib/router-output.js +789 -0
- package/lib/shared.d.ts +548 -0
- package/lib/shared.js +668 -0
- package/package.json +118 -0
- package/rosetta/_generated.ts-fixture +6 -0
- package/rosetta/default.ts-fixture +68 -0
|
@@ -0,0 +1,1095 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
3
|
+
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
|
4
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
5
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
6
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
7
|
+
var _, done = false;
|
|
8
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
9
|
+
var context = {};
|
|
10
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
11
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
12
|
+
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
|
|
13
|
+
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
|
|
14
|
+
if (kind === "accessor") {
|
|
15
|
+
if (result === void 0) continue;
|
|
16
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
17
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
|
18
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
|
19
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
|
20
|
+
}
|
|
21
|
+
else if (_ = accept(result)) {
|
|
22
|
+
if (kind === "field") initializers.unshift(_);
|
|
23
|
+
else descriptor[key] = _;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
27
|
+
done = true;
|
|
28
|
+
};
|
|
29
|
+
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
|
|
30
|
+
var useValue = arguments.length > 2;
|
|
31
|
+
for (var i = 0; i < initializers.length; i++) {
|
|
32
|
+
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
33
|
+
}
|
|
34
|
+
return useValue ? value : void 0;
|
|
35
|
+
};
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
exports.RouterInput = exports.RouterInputConfiguration = exports.RouterInputProtocol = exports.SourcePriorityConfig = exports.PrimarySource = exports.ForwardErrorCorrection = exports.RouterInputTier = exports.RoutingScope = exports.RouterInputProtocolOptions = void 0;
|
|
38
|
+
const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
|
|
39
|
+
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
|
40
|
+
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
|
41
|
+
const aws_cloudwatch_1 = require("aws-cdk-lib/aws-cloudwatch");
|
|
42
|
+
const aws_mediaconnect_1 = require("aws-cdk-lib/aws-mediaconnect");
|
|
43
|
+
const helpers_internal_1 = require("aws-cdk-lib/core/lib/helpers-internal");
|
|
44
|
+
const metadata_resource_1 = require("aws-cdk-lib/core/lib/metadata-resource");
|
|
45
|
+
const prop_injectable_1 = require("aws-cdk-lib/core/lib/prop-injectable");
|
|
46
|
+
const mediaconnect_grants_generated_1 = require("./mediaconnect-grants.generated");
|
|
47
|
+
const shared_1 = require("./shared");
|
|
48
|
+
/**
|
|
49
|
+
* Protocol options available for Router Input configurations
|
|
50
|
+
*/
|
|
51
|
+
class RouterInputProtocolOptions {
|
|
52
|
+
value;
|
|
53
|
+
static [JSII_RTTI_SYMBOL_1] = { fqn: "@aws-cdk/aws-mediaconnect-alpha.RouterInputProtocolOptions", version: "2.263.0-alpha.0" };
|
|
54
|
+
/** Real-time Transport Protocol */
|
|
55
|
+
static RTP = new RouterInputProtocolOptions('RTP');
|
|
56
|
+
/** Reliable Internet Stream Transport */
|
|
57
|
+
static RIST = new RouterInputProtocolOptions('RIST');
|
|
58
|
+
/** Secure Reliable Transport - Caller mode */
|
|
59
|
+
static SRT_CALLER = new RouterInputProtocolOptions('SRT_CALLER');
|
|
60
|
+
/** Secure Reliable Transport - Listener mode */
|
|
61
|
+
static SRT_LISTENER = new RouterInputProtocolOptions('SRT_LISTENER');
|
|
62
|
+
/**
|
|
63
|
+
* Use a custom protocol value
|
|
64
|
+
* @param value The protocol string value
|
|
65
|
+
*/
|
|
66
|
+
static of(value) {
|
|
67
|
+
return new RouterInputProtocolOptions(value);
|
|
68
|
+
}
|
|
69
|
+
/** @param value The protocol string value */
|
|
70
|
+
constructor(value) {
|
|
71
|
+
this.value = value;
|
|
72
|
+
}
|
|
73
|
+
/** Returns the string value */
|
|
74
|
+
toString() {
|
|
75
|
+
return this.value;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
exports.RouterInputProtocolOptions = RouterInputProtocolOptions;
|
|
79
|
+
/**
|
|
80
|
+
* Routing scope for the Router Input
|
|
81
|
+
*/
|
|
82
|
+
class RoutingScope {
|
|
83
|
+
value;
|
|
84
|
+
static [JSII_RTTI_SYMBOL_1] = { fqn: "@aws-cdk/aws-mediaconnect-alpha.RoutingScope", version: "2.263.0-alpha.0" };
|
|
85
|
+
/** Route traffic within the same AWS region */
|
|
86
|
+
static REGIONAL = new RoutingScope('REGIONAL');
|
|
87
|
+
/** Route traffic globally across AWS regions */
|
|
88
|
+
static GLOBAL = new RoutingScope('GLOBAL');
|
|
89
|
+
/**
|
|
90
|
+
* Use a custom routing scope value
|
|
91
|
+
* @param value The routing scope string value
|
|
92
|
+
*/
|
|
93
|
+
static of(value) {
|
|
94
|
+
return new RoutingScope(value);
|
|
95
|
+
}
|
|
96
|
+
/** @param value The routing scope string value */
|
|
97
|
+
constructor(value) {
|
|
98
|
+
this.value = value;
|
|
99
|
+
}
|
|
100
|
+
/** Returns the string value */
|
|
101
|
+
toString() {
|
|
102
|
+
return this.value;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
exports.RoutingScope = RoutingScope;
|
|
106
|
+
/**
|
|
107
|
+
* Routing tier based on your maximum bitrate requirements.
|
|
108
|
+
*/
|
|
109
|
+
class RouterInputTier {
|
|
110
|
+
value;
|
|
111
|
+
static [JSII_RTTI_SYMBOL_1] = { fqn: "@aws-cdk/aws-mediaconnect-alpha.RouterInputTier", version: "2.263.0-alpha.0" };
|
|
112
|
+
/** Supports a maximum bitrate up to 100 megabits per second. */
|
|
113
|
+
static INPUT_100 = new RouterInputTier('INPUT_100');
|
|
114
|
+
/** Supports a maximum bitrate up to 50 megabits per second. */
|
|
115
|
+
static INPUT_50 = new RouterInputTier('INPUT_50');
|
|
116
|
+
/** Supports a maximum bitrate up to 20 megabits per second. */
|
|
117
|
+
static INPUT_20 = new RouterInputTier('INPUT_20');
|
|
118
|
+
/**
|
|
119
|
+
* Use a custom tier value
|
|
120
|
+
* @param value The tier string value
|
|
121
|
+
*/
|
|
122
|
+
static of(value) {
|
|
123
|
+
return new RouterInputTier(value);
|
|
124
|
+
}
|
|
125
|
+
/** @param value The tier string value */
|
|
126
|
+
constructor(value) {
|
|
127
|
+
this.value = value;
|
|
128
|
+
}
|
|
129
|
+
/** Returns the string value */
|
|
130
|
+
toString() {
|
|
131
|
+
return this.value;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
exports.RouterInputTier = RouterInputTier;
|
|
135
|
+
/**
|
|
136
|
+
* Forward Error Correction (FEC) options for RTP protocol
|
|
137
|
+
*/
|
|
138
|
+
var ForwardErrorCorrection;
|
|
139
|
+
(function (ForwardErrorCorrection) {
|
|
140
|
+
/** Enable Forward Error Correction */
|
|
141
|
+
ForwardErrorCorrection["ENABLED"] = "ENABLED";
|
|
142
|
+
/** Disable Forward Error Correction */
|
|
143
|
+
ForwardErrorCorrection["DISABLED"] = "DISABLED";
|
|
144
|
+
})(ForwardErrorCorrection || (exports.ForwardErrorCorrection = ForwardErrorCorrection = {}));
|
|
145
|
+
/**
|
|
146
|
+
* Identifies which protocol in a failover configuration's protocols array is primary.
|
|
147
|
+
*/
|
|
148
|
+
var PrimarySource;
|
|
149
|
+
(function (PrimarySource) {
|
|
150
|
+
/** The first protocol in the failover protocols array. */
|
|
151
|
+
PrimarySource[PrimarySource["FIRST_SOURCE"] = 0] = "FIRST_SOURCE";
|
|
152
|
+
/** The second protocol in the failover protocols array. */
|
|
153
|
+
PrimarySource[PrimarySource["SECOND_SOURCE"] = 1] = "SECOND_SOURCE";
|
|
154
|
+
})(PrimarySource || (exports.PrimarySource = PrimarySource = {}));
|
|
155
|
+
/**
|
|
156
|
+
* Internal CFN-level values for the source priority mode.
|
|
157
|
+
* @internal
|
|
158
|
+
*/
|
|
159
|
+
var SourcePriorityMode;
|
|
160
|
+
(function (SourcePriorityMode) {
|
|
161
|
+
/** Both sources are equal priority — the service picks one. */
|
|
162
|
+
SourcePriorityMode["NO_PRIORITY"] = "NO_PRIORITY";
|
|
163
|
+
/** One source is primary, the other is backup. */
|
|
164
|
+
SourcePriorityMode["PRIMARY_SECONDARY"] = "PRIMARY_SECONDARY";
|
|
165
|
+
})(SourcePriorityMode || (SourcePriorityMode = {}));
|
|
166
|
+
/**
|
|
167
|
+
* Source priority configuration for failover Router Input configurations.
|
|
168
|
+
*/
|
|
169
|
+
class SourcePriorityConfig {
|
|
170
|
+
_mode;
|
|
171
|
+
_primary;
|
|
172
|
+
static [JSII_RTTI_SYMBOL_1] = { fqn: "@aws-cdk/aws-mediaconnect-alpha.SourcePriorityConfig", version: "2.263.0-alpha.0" };
|
|
173
|
+
/**
|
|
174
|
+
* Treat both sources with equal priority — MediaConnect picks one when needed.
|
|
175
|
+
*/
|
|
176
|
+
static none() {
|
|
177
|
+
return new SourcePriorityConfig(SourcePriorityMode.NO_PRIORITY, undefined);
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Designate one of the two sources as primary; the other is treated as backup.
|
|
181
|
+
*/
|
|
182
|
+
static primarySecondary(primary) {
|
|
183
|
+
try {
|
|
184
|
+
jsiiDeprecationWarnings._aws_cdk_aws_mediaconnect_alpha_PrimarySource(primary);
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
|
188
|
+
Error.captureStackTrace(error, this.primarySecondary);
|
|
189
|
+
}
|
|
190
|
+
throw error;
|
|
191
|
+
}
|
|
192
|
+
return new SourcePriorityConfig(SourcePriorityMode.PRIMARY_SECONDARY, primary);
|
|
193
|
+
}
|
|
194
|
+
constructor(_mode, _primary) {
|
|
195
|
+
this._mode = _mode;
|
|
196
|
+
this._primary = _primary;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Resolve the configuration to its CFN shape.
|
|
200
|
+
* @internal
|
|
201
|
+
*/
|
|
202
|
+
_bind() {
|
|
203
|
+
return {
|
|
204
|
+
sourcePriorityMode: this._mode,
|
|
205
|
+
primarySourceIndex: this._primary,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
exports.SourcePriorityConfig = SourcePriorityConfig;
|
|
210
|
+
/**
|
|
211
|
+
* Identifies which configuration type a port conflict check is being performed for.
|
|
212
|
+
* @internal
|
|
213
|
+
*/
|
|
214
|
+
var ProtocolConfigType;
|
|
215
|
+
(function (ProtocolConfigType) {
|
|
216
|
+
/** Failover-mode router input configuration. */
|
|
217
|
+
ProtocolConfigType["FAILOVER"] = "failover";
|
|
218
|
+
/** Merge-mode router input configuration. */
|
|
219
|
+
ProtocolConfigType["MERGE"] = "merge";
|
|
220
|
+
})(ProtocolConfigType || (ProtocolConfigType = {}));
|
|
221
|
+
/**
|
|
222
|
+
* Factory class for creating Router Input protocol configurations
|
|
223
|
+
*/
|
|
224
|
+
class RouterInputProtocol {
|
|
225
|
+
static [JSII_RTTI_SYMBOL_1] = { fqn: "@aws-cdk/aws-mediaconnect-alpha.RouterInputProtocol", version: "2.263.0-alpha.0" };
|
|
226
|
+
/**
|
|
227
|
+
* Create an RTP protocol configuration
|
|
228
|
+
* @param props RTP protocol properties
|
|
229
|
+
* @returns RouterInputProtocol instance configured for RTP
|
|
230
|
+
*/
|
|
231
|
+
static rtp(props) {
|
|
232
|
+
try {
|
|
233
|
+
jsiiDeprecationWarnings._aws_cdk_aws_mediaconnect_alpha_RtpProtocolProps(props);
|
|
234
|
+
}
|
|
235
|
+
catch (error) {
|
|
236
|
+
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
|
237
|
+
Error.captureStackTrace(error, this.rtp);
|
|
238
|
+
}
|
|
239
|
+
throw error;
|
|
240
|
+
}
|
|
241
|
+
RouterInputProtocol.validatePort(props.port);
|
|
242
|
+
return new RouterInputProtocol(RouterInputProtocolOptions.RTP, {
|
|
243
|
+
rtp: {
|
|
244
|
+
port: props.port,
|
|
245
|
+
forwardErrorCorrection: props.forwardErrorCorrection,
|
|
246
|
+
},
|
|
247
|
+
}, props.port);
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Create a RIST protocol configuration
|
|
251
|
+
* @param props RIST protocol properties
|
|
252
|
+
* @returns RouterInputProtocol instance configured for RIST
|
|
253
|
+
*/
|
|
254
|
+
static rist(props) {
|
|
255
|
+
try {
|
|
256
|
+
jsiiDeprecationWarnings._aws_cdk_aws_mediaconnect_alpha_RistProtocolProps(props);
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
|
260
|
+
Error.captureStackTrace(error, this.rist);
|
|
261
|
+
}
|
|
262
|
+
throw error;
|
|
263
|
+
}
|
|
264
|
+
RouterInputProtocol.validatePort(props.port);
|
|
265
|
+
return new RouterInputProtocol(RouterInputProtocolOptions.RIST, {
|
|
266
|
+
rist: {
|
|
267
|
+
port: props.port,
|
|
268
|
+
recoveryLatencyMilliseconds: props.recoveryLatency.toMilliseconds(),
|
|
269
|
+
},
|
|
270
|
+
}, props.port);
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Create an SRT Listener protocol configuration
|
|
274
|
+
* @param props SRT Listener protocol properties
|
|
275
|
+
* @returns RouterInputProtocol instance configured for SRT Listener
|
|
276
|
+
*/
|
|
277
|
+
static srtListener(props) {
|
|
278
|
+
try {
|
|
279
|
+
jsiiDeprecationWarnings._aws_cdk_aws_mediaconnect_alpha_SrtListenerProtocolProps(props);
|
|
280
|
+
}
|
|
281
|
+
catch (error) {
|
|
282
|
+
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
|
283
|
+
Error.captureStackTrace(error, this.srtListener);
|
|
284
|
+
}
|
|
285
|
+
throw error;
|
|
286
|
+
}
|
|
287
|
+
RouterInputProtocol.validatePort(props.port);
|
|
288
|
+
return new RouterInputProtocol(RouterInputProtocolOptions.SRT_LISTENER, {
|
|
289
|
+
srtListener: {
|
|
290
|
+
port: props.port,
|
|
291
|
+
minimumLatencyMilliseconds: props.minimumLatency.toMilliseconds(),
|
|
292
|
+
},
|
|
293
|
+
}, props.port, props.decryptionConfiguration);
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Create an SRT Caller protocol configuration
|
|
297
|
+
* @param props SRT Caller protocol properties
|
|
298
|
+
* @returns RouterInputProtocol instance configured for SRT Caller
|
|
299
|
+
*/
|
|
300
|
+
static srtCaller(props) {
|
|
301
|
+
try {
|
|
302
|
+
jsiiDeprecationWarnings._aws_cdk_aws_mediaconnect_alpha_SrtCallerProtocolProps(props);
|
|
303
|
+
}
|
|
304
|
+
catch (error) {
|
|
305
|
+
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
|
306
|
+
Error.captureStackTrace(error, this.srtCaller);
|
|
307
|
+
}
|
|
308
|
+
throw error;
|
|
309
|
+
}
|
|
310
|
+
RouterInputProtocol.validateSrtCallerPort(props.sourcePort);
|
|
311
|
+
return new RouterInputProtocol(RouterInputProtocolOptions.SRT_CALLER, {
|
|
312
|
+
srtCaller: {
|
|
313
|
+
sourceAddress: props.sourceAddress,
|
|
314
|
+
sourcePort: props.sourcePort,
|
|
315
|
+
minimumLatencyMilliseconds: props.minimumLatency.toMilliseconds(),
|
|
316
|
+
streamId: props.streamId,
|
|
317
|
+
},
|
|
318
|
+
}, undefined, props.decryptionConfiguration);
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Validate that port is within the valid range (3000-30000)
|
|
322
|
+
*/
|
|
323
|
+
static validatePort(port) {
|
|
324
|
+
if (!aws_cdk_lib_1.Token.isUnresolved(port) && (port < 3000 || port > 30000)) {
|
|
325
|
+
throw new aws_cdk_lib_1.UnscopedValidationError((0, helpers_internal_1.lit) `RouterInputPortRange`, `Port must be between 3000 and 30000, got ${port}`);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Validate that SRT Caller port is within the valid range (0-65535)
|
|
330
|
+
*/
|
|
331
|
+
static validateSrtCallerPort(port) {
|
|
332
|
+
if (!aws_cdk_lib_1.Token.isUnresolved(port) && (port < 0 || port > 65535)) {
|
|
333
|
+
throw new aws_cdk_lib_1.UnscopedValidationError((0, helpers_internal_1.lit) `SrtCallerPortRange`, `SRT Caller port must be between 0 and 65535, got ${port}`);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
_protocolName;
|
|
337
|
+
_config;
|
|
338
|
+
_port;
|
|
339
|
+
_decryption;
|
|
340
|
+
constructor(protocolName, config, port, decryption) {
|
|
341
|
+
this._protocolName = protocolName;
|
|
342
|
+
this._config = config;
|
|
343
|
+
this._port = port;
|
|
344
|
+
this._decryption = decryption;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Resolve this protocol to its CFN-ready form. Returns the protocol identifier,
|
|
348
|
+
* the CFN configuration shape (with SRT decryption auto-role materialized if needed),
|
|
349
|
+
* and the ingest port if the protocol has one.
|
|
350
|
+
*
|
|
351
|
+
* @param scope Construct that scopes the auto-created decryption role
|
|
352
|
+
* @param routerInputArn Optional ARN of the consuming router input — when provided,
|
|
353
|
+
* scopes the auto-created decryption role's trust policy.
|
|
354
|
+
*
|
|
355
|
+
* @internal
|
|
356
|
+
*/
|
|
357
|
+
_bind(scope, routerInputArn) {
|
|
358
|
+
if (!this._decryption) {
|
|
359
|
+
return { name: this._protocolName, config: this._config, port: this._port };
|
|
360
|
+
}
|
|
361
|
+
const decryptionConfiguration = (0, shared_1.renderRouterSrtEncryption)(scope, 'DecryptionRole', this._decryption, routerInputArn);
|
|
362
|
+
if (this._config.srtListener) {
|
|
363
|
+
return {
|
|
364
|
+
name: this._protocolName,
|
|
365
|
+
port: this._port,
|
|
366
|
+
config: { srtListener: { ...this._config.srtListener, decryptionConfiguration } },
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
if (this._config.srtCaller) {
|
|
370
|
+
return {
|
|
371
|
+
name: this._protocolName,
|
|
372
|
+
port: this._port,
|
|
373
|
+
config: { srtCaller: { ...this._config.srtCaller, decryptionConfiguration } },
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
return { name: this._protocolName, config: this._config, port: this._port };
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Compute the ingest URL (scheme://ipAddress:port) for this protocol, if it has
|
|
380
|
+
* a listening port.
|
|
381
|
+
*
|
|
382
|
+
* @internal
|
|
383
|
+
*/
|
|
384
|
+
_ingestUrl(ipAddress) {
|
|
385
|
+
if (this._port === undefined)
|
|
386
|
+
return undefined;
|
|
387
|
+
return renderIngestUrl(this._protocolName.value, this._port, ipAddress);
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* The listening port for this protocol, if it has one. Undefined for SRT caller
|
|
391
|
+
* (which has a `sourcePort` pointing at the upstream listener, not a port the input
|
|
392
|
+
* itself listens on).
|
|
393
|
+
*
|
|
394
|
+
* @internal
|
|
395
|
+
*/
|
|
396
|
+
_listeningPort() {
|
|
397
|
+
return this._port;
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* Whether two protocols share the same protocol identifier.
|
|
401
|
+
*
|
|
402
|
+
* @internal
|
|
403
|
+
*/
|
|
404
|
+
_matchesKind(other) {
|
|
405
|
+
return this._protocolName.value === other._protocolName.value;
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* Whether this protocol is SRT (Caller or Listener).
|
|
409
|
+
*
|
|
410
|
+
* @internal
|
|
411
|
+
*/
|
|
412
|
+
_isSrt() {
|
|
413
|
+
return this._protocolName.value === RouterInputProtocolOptions.SRT_CALLER.value
|
|
414
|
+
|| this._protocolName.value === RouterInputProtocolOptions.SRT_LISTENER.value;
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Validate port compatibility between this protocol and another in a failover or
|
|
418
|
+
* merge configuration. Throws on conflicts appropriate to the protocol kind.
|
|
419
|
+
*
|
|
420
|
+
* @internal
|
|
421
|
+
*/
|
|
422
|
+
_validatePortConflicts(other, configType) {
|
|
423
|
+
const protocolValue = this._protocolName.value;
|
|
424
|
+
if (protocolValue === RouterInputProtocolOptions.RIST.value) {
|
|
425
|
+
const rist1 = this._config.rist;
|
|
426
|
+
const rist2 = other._config.rist;
|
|
427
|
+
if (rist1 && rist2 && 'port' in rist1 && 'port' in rist2) {
|
|
428
|
+
const port1 = rist1.port;
|
|
429
|
+
const port2 = rist2.port;
|
|
430
|
+
if (port1 === port2) {
|
|
431
|
+
throw new aws_cdk_lib_1.UnscopedValidationError((0, helpers_internal_1.lit) `DuplicateRistPort`, `${configType} configuration cannot use the same RIST port ${port1} for both protocols, ` +
|
|
432
|
+
'each protocol must use a different port number');
|
|
433
|
+
}
|
|
434
|
+
if (Math.abs(port1 - port2) < 2) {
|
|
435
|
+
throw new aws_cdk_lib_1.UnscopedValidationError((0, helpers_internal_1.lit) `ConsecutiveRistPort`, `${configType} configuration cannot use consecutive RIST ports ${Math.min(port1, port2)} and ${Math.max(port1, port2)}, ` +
|
|
436
|
+
'RIST protocols require non-consecutive ports to avoid overlapping ranges (e.g., use 6000 and 6002)');
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
if (protocolValue === RouterInputProtocolOptions.RTP.value) {
|
|
442
|
+
const rtp1 = this._config.rtp;
|
|
443
|
+
const rtp2 = other._config.rtp;
|
|
444
|
+
if (rtp1 && rtp2 && 'port' in rtp1 && 'port' in rtp2 && rtp1.port === rtp2.port) {
|
|
445
|
+
throw new aws_cdk_lib_1.UnscopedValidationError((0, helpers_internal_1.lit) `DuplicateRtpPort`, `${configType} configuration cannot use the same RTP port ${rtp1.port} for both protocols, ` +
|
|
446
|
+
'each protocol must use a different port number');
|
|
447
|
+
}
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
if (protocolValue === RouterInputProtocolOptions.SRT_LISTENER.value) {
|
|
451
|
+
const srt1 = this._config.srtListener;
|
|
452
|
+
const srt2 = other._config.srtListener;
|
|
453
|
+
if (srt1 && srt2 && 'port' in srt1 && 'port' in srt2 && srt1.port === srt2.port) {
|
|
454
|
+
throw new aws_cdk_lib_1.UnscopedValidationError((0, helpers_internal_1.lit) `DuplicateSrtListenerPort`, `${configType} configuration cannot use the same SRT Listener port ${srt1.port} for both protocols, ` +
|
|
455
|
+
'each protocol must use a different port number');
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
exports.RouterInputProtocol = RouterInputProtocol;
|
|
461
|
+
/**
|
|
462
|
+
* Factory class for creating Router Input configurations
|
|
463
|
+
*/
|
|
464
|
+
class RouterInputConfiguration {
|
|
465
|
+
static [JSII_RTTI_SYMBOL_1] = { fqn: "@aws-cdk/aws-mediaconnect-alpha.RouterInputConfiguration", version: "2.263.0-alpha.0" };
|
|
466
|
+
/**
|
|
467
|
+
* Create a standard Router Input configuration with a single protocol
|
|
468
|
+
* @param props Standard configuration properties
|
|
469
|
+
* @returns RouterInputConfiguration instance for standard setup
|
|
470
|
+
*/
|
|
471
|
+
static standard(props) {
|
|
472
|
+
try {
|
|
473
|
+
jsiiDeprecationWarnings._aws_cdk_aws_mediaconnect_alpha_StandardConfigurationProps(props);
|
|
474
|
+
}
|
|
475
|
+
catch (error) {
|
|
476
|
+
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
|
477
|
+
Error.captureStackTrace(error, this.standard);
|
|
478
|
+
}
|
|
479
|
+
throw error;
|
|
480
|
+
}
|
|
481
|
+
return new StandardRouterInputConfig(props);
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* Create a failover Router Input configuration with two matching protocols
|
|
485
|
+
* @param props Failover configuration properties
|
|
486
|
+
* @returns RouterInputConfiguration instance for failover setup
|
|
487
|
+
* @throws Error if protocols don't match or count is not exactly 2
|
|
488
|
+
*/
|
|
489
|
+
static failover(props) {
|
|
490
|
+
try {
|
|
491
|
+
jsiiDeprecationWarnings._aws_cdk_aws_mediaconnect_alpha_FailoverConfigurationProps(props);
|
|
492
|
+
}
|
|
493
|
+
catch (error) {
|
|
494
|
+
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
|
495
|
+
Error.captureStackTrace(error, this.failover);
|
|
496
|
+
}
|
|
497
|
+
throw error;
|
|
498
|
+
}
|
|
499
|
+
if (!aws_cdk_lib_1.Token.isUnresolved(props.protocols) && props.protocols.length !== 2) {
|
|
500
|
+
throw new aws_cdk_lib_1.UnscopedValidationError((0, helpers_internal_1.lit) `FailoverProtocolCount`, `Failover configuration requires exactly 2 protocols, got ${props.protocols.length}`);
|
|
501
|
+
}
|
|
502
|
+
if (!props.protocols[0]._matchesKind(props.protocols[1])) {
|
|
503
|
+
throw new aws_cdk_lib_1.UnscopedValidationError((0, helpers_internal_1.lit) `FailoverProtocolMismatch`, 'Protocols must match');
|
|
504
|
+
}
|
|
505
|
+
props.protocols[0]._validatePortConflicts(props.protocols[1], ProtocolConfigType.FAILOVER);
|
|
506
|
+
return new FailoverRouterInputConfig(props);
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* Create a merge Router Input configuration with two matching non-SRT protocols
|
|
510
|
+
* @param props Merge configuration properties
|
|
511
|
+
* @returns RouterInputConfiguration instance for merge setup
|
|
512
|
+
* @throws Error if protocols don't match, count is not exactly 2, or SRT protocols are used
|
|
513
|
+
*/
|
|
514
|
+
static merge(props) {
|
|
515
|
+
try {
|
|
516
|
+
jsiiDeprecationWarnings._aws_cdk_aws_mediaconnect_alpha_MergeConfigurationProps(props);
|
|
517
|
+
}
|
|
518
|
+
catch (error) {
|
|
519
|
+
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
|
520
|
+
Error.captureStackTrace(error, this.merge);
|
|
521
|
+
}
|
|
522
|
+
throw error;
|
|
523
|
+
}
|
|
524
|
+
if (!aws_cdk_lib_1.Token.isUnresolved(props.protocols) && props.protocols.length !== 2) {
|
|
525
|
+
throw new aws_cdk_lib_1.UnscopedValidationError((0, helpers_internal_1.lit) `MergeProtocolCount`, `Merge configuration requires exactly 2 protocols, got ${props.protocols.length}`);
|
|
526
|
+
}
|
|
527
|
+
if (props.protocols.some(p => p._isSrt())) {
|
|
528
|
+
throw new aws_cdk_lib_1.UnscopedValidationError((0, helpers_internal_1.lit) `MergeSrtNotSupported`, 'SRT protocols are not supported in merge configuration');
|
|
529
|
+
}
|
|
530
|
+
if (!props.protocols[0]._matchesKind(props.protocols[1])) {
|
|
531
|
+
throw new aws_cdk_lib_1.UnscopedValidationError((0, helpers_internal_1.lit) `MergeProtocolMismatch`, 'Protocols must match');
|
|
532
|
+
}
|
|
533
|
+
props.protocols[0]._validatePortConflicts(props.protocols[1], ProtocolConfigType.MERGE);
|
|
534
|
+
return new MergeRouterInputConfig(props);
|
|
535
|
+
}
|
|
536
|
+
/**
|
|
537
|
+
* Create a MediaConnect Flow Router Input configuration without connecting to a specific flow
|
|
538
|
+
* Use this when you want to prepare the router input for a flow connection later
|
|
539
|
+
* @param props MediaConnect Flow configuration properties without connection
|
|
540
|
+
* @returns RouterInputConfiguration instance for MediaConnect Flow setup without connection
|
|
541
|
+
*/
|
|
542
|
+
static mediaConnectFlowWithoutConnection(props) {
|
|
543
|
+
try {
|
|
544
|
+
jsiiDeprecationWarnings._aws_cdk_aws_mediaconnect_alpha_MediaConnectFlowConfigurationWithoutConnectionProps(props);
|
|
545
|
+
}
|
|
546
|
+
catch (error) {
|
|
547
|
+
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
|
548
|
+
Error.captureStackTrace(error, this.mediaConnectFlowWithoutConnection);
|
|
549
|
+
}
|
|
550
|
+
throw error;
|
|
551
|
+
}
|
|
552
|
+
return new MediaConnectFlowRouterInputConfig({ sourceTransitDecryption: props.sourceTransitDecryption }, props.availabilityZone);
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* Create a MediaConnect Flow Router Input configuration.
|
|
556
|
+
*
|
|
557
|
+
* Use this when the source flow already exists and you want to connect immediately.
|
|
558
|
+
*
|
|
559
|
+
* @param props MediaConnect Flow configuration properties
|
|
560
|
+
* @returns RouterInputConfiguration instance for MediaConnect Flow setup
|
|
561
|
+
*/
|
|
562
|
+
static mediaConnectFlow(props) {
|
|
563
|
+
try {
|
|
564
|
+
jsiiDeprecationWarnings._aws_cdk_aws_mediaconnect_alpha_MediaConnectFlowConfigurationProps(props);
|
|
565
|
+
}
|
|
566
|
+
catch (error) {
|
|
567
|
+
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
|
568
|
+
Error.captureStackTrace(error, this.mediaConnectFlow);
|
|
569
|
+
}
|
|
570
|
+
throw error;
|
|
571
|
+
}
|
|
572
|
+
return new MediaConnectFlowRouterInputConfig({
|
|
573
|
+
flow: props.flow,
|
|
574
|
+
flowOutput: props.flowOutput,
|
|
575
|
+
sourceTransitDecryption: props.sourceTransitDecryption,
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
/**
|
|
579
|
+
* Create a MediaLive Channel Router Input configuration.
|
|
580
|
+
*
|
|
581
|
+
* Use this when the source MediaLive channel already exists and you want to
|
|
582
|
+
* ingest from one of its outputs immediately.
|
|
583
|
+
*
|
|
584
|
+
* @param props MediaLive channel configuration properties
|
|
585
|
+
* @returns RouterInputConfiguration instance for MediaLive channel setup
|
|
586
|
+
*/
|
|
587
|
+
static mediaLiveChannel(props) {
|
|
588
|
+
try {
|
|
589
|
+
jsiiDeprecationWarnings._aws_cdk_aws_mediaconnect_alpha_MediaLiveChannelConfigurationProps(props);
|
|
590
|
+
}
|
|
591
|
+
catch (error) {
|
|
592
|
+
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
|
593
|
+
Error.captureStackTrace(error, this.mediaLiveChannel);
|
|
594
|
+
}
|
|
595
|
+
throw error;
|
|
596
|
+
}
|
|
597
|
+
return new MediaLiveChannelRouterInputConfig({
|
|
598
|
+
mediaLiveChannelArn: props.mediaLiveChannelArn,
|
|
599
|
+
mediaLiveChannelOutputName: props.mediaLiveChannelOutputName,
|
|
600
|
+
mediaLivePipelineId: props.mediaLivePipelineId,
|
|
601
|
+
sourceTransitDecryption: props.sourceTransitDecryption,
|
|
602
|
+
});
|
|
603
|
+
}
|
|
604
|
+
/**
|
|
605
|
+
* Create a MediaLive Channel Router Input configuration without a specific channel connection.
|
|
606
|
+
*
|
|
607
|
+
* Use this when you want to set up the router input before the target MediaLive channel exists.
|
|
608
|
+
*
|
|
609
|
+
* @param props MediaLive channel no-connection properties
|
|
610
|
+
* @returns RouterInputConfiguration instance for MediaLive channel setup without connection
|
|
611
|
+
*/
|
|
612
|
+
static mediaLiveChannelWithoutConnection(props) {
|
|
613
|
+
try {
|
|
614
|
+
jsiiDeprecationWarnings._aws_cdk_aws_mediaconnect_alpha_MediaLiveChannelConfigurationWithoutConnectionProps(props);
|
|
615
|
+
}
|
|
616
|
+
catch (error) {
|
|
617
|
+
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
|
618
|
+
Error.captureStackTrace(error, this.mediaLiveChannelWithoutConnection);
|
|
619
|
+
}
|
|
620
|
+
throw error;
|
|
621
|
+
}
|
|
622
|
+
return new MediaLiveChannelRouterInputConfig({ sourceTransitDecryption: props.sourceTransitDecryption }, props.availabilityZone);
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
exports.RouterInputConfiguration = RouterInputConfiguration;
|
|
626
|
+
/**
|
|
627
|
+
* Render an ingest URL string (scheme://ip:port). Used by `_ingestUrl()` on individual
|
|
628
|
+
* protocols and composed into the per-config-variant `_endpoints()` results.
|
|
629
|
+
*
|
|
630
|
+
* Extracts the base protocol for the URL scheme (e.g. SRT_LISTENER → srt, RTP → rtp).
|
|
631
|
+
*/
|
|
632
|
+
function renderIngestUrl(protocolName, port, ipAddress) {
|
|
633
|
+
const scheme = protocolName.toLowerCase().split('_')[0];
|
|
634
|
+
return aws_cdk_lib_1.Fn.join('', [`${scheme}://`, ipAddress, `:${port}`]);
|
|
635
|
+
}
|
|
636
|
+
/**
|
|
637
|
+
* Concrete variant: standard (single-protocol) router input configuration.
|
|
638
|
+
* @internal
|
|
639
|
+
*/
|
|
640
|
+
class StandardRouterInputConfig extends RouterInputConfiguration {
|
|
641
|
+
props;
|
|
642
|
+
constructor(props) {
|
|
643
|
+
super();
|
|
644
|
+
this.props = props;
|
|
645
|
+
}
|
|
646
|
+
_bind(scope, routerInputArn) {
|
|
647
|
+
const protocol = this.props.protocol._bind(scope, routerInputArn);
|
|
648
|
+
return {
|
|
649
|
+
config: {
|
|
650
|
+
standard: {
|
|
651
|
+
networkInterfaceArn: this.props.networkInterface.routerNetworkInterfaceArn,
|
|
652
|
+
protocol: protocol.name.value,
|
|
653
|
+
protocolConfiguration: protocol.config,
|
|
654
|
+
},
|
|
655
|
+
},
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
_endpoints(ipAddress) {
|
|
659
|
+
const url = this.props.protocol._ingestUrl(ipAddress);
|
|
660
|
+
const port = this.props.protocol._listeningPort();
|
|
661
|
+
if (url === undefined || port === undefined)
|
|
662
|
+
return undefined;
|
|
663
|
+
return [{ url, port }];
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
/**
|
|
667
|
+
* Concrete variant: failover router input configuration.
|
|
668
|
+
* @internal
|
|
669
|
+
*/
|
|
670
|
+
class FailoverRouterInputConfig extends RouterInputConfiguration {
|
|
671
|
+
props;
|
|
672
|
+
constructor(props) {
|
|
673
|
+
super();
|
|
674
|
+
this.props = props;
|
|
675
|
+
}
|
|
676
|
+
_bind(scope, routerInputArn) {
|
|
677
|
+
const priority = (this.props.sourcePriority ?? SourcePriorityConfig.none())._bind();
|
|
678
|
+
return {
|
|
679
|
+
config: {
|
|
680
|
+
failover: {
|
|
681
|
+
networkInterfaceArn: this.props.networkInterface.routerNetworkInterfaceArn,
|
|
682
|
+
protocolConfigurations: this.props.protocols.map(p => p._bind(scope, routerInputArn).config),
|
|
683
|
+
sourcePriorityMode: priority.sourcePriorityMode,
|
|
684
|
+
primarySourceIndex: priority.primarySourceIndex,
|
|
685
|
+
},
|
|
686
|
+
},
|
|
687
|
+
};
|
|
688
|
+
}
|
|
689
|
+
_endpoints(ipAddress) {
|
|
690
|
+
const endpoints = [];
|
|
691
|
+
for (const p of this.props.protocols) {
|
|
692
|
+
const url = p._ingestUrl(ipAddress);
|
|
693
|
+
const port = p._listeningPort();
|
|
694
|
+
if (url === undefined || port === undefined)
|
|
695
|
+
return undefined;
|
|
696
|
+
endpoints.push({ url, port });
|
|
697
|
+
}
|
|
698
|
+
return endpoints;
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
* Concrete variant: merge router input configuration.
|
|
703
|
+
* @internal
|
|
704
|
+
*/
|
|
705
|
+
class MergeRouterInputConfig extends RouterInputConfiguration {
|
|
706
|
+
props;
|
|
707
|
+
constructor(props) {
|
|
708
|
+
super();
|
|
709
|
+
this.props = props;
|
|
710
|
+
}
|
|
711
|
+
_bind(scope, routerInputArn) {
|
|
712
|
+
return {
|
|
713
|
+
config: {
|
|
714
|
+
merge: {
|
|
715
|
+
networkInterfaceArn: this.props.networkInterface.routerNetworkInterfaceArn,
|
|
716
|
+
protocolConfigurations: this.props.protocols.map(p => p._bind(scope, routerInputArn).config),
|
|
717
|
+
mergeRecoveryWindowMilliseconds: this.props.mergeRecoveryWindow.toMilliseconds(),
|
|
718
|
+
},
|
|
719
|
+
},
|
|
720
|
+
};
|
|
721
|
+
}
|
|
722
|
+
_endpoints(ipAddress) {
|
|
723
|
+
const endpoints = [];
|
|
724
|
+
for (const p of this.props.protocols) {
|
|
725
|
+
const url = p._ingestUrl(ipAddress);
|
|
726
|
+
const port = p._listeningPort();
|
|
727
|
+
if (url === undefined || port === undefined)
|
|
728
|
+
return undefined;
|
|
729
|
+
endpoints.push({ url, port });
|
|
730
|
+
}
|
|
731
|
+
return endpoints;
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
/**
|
|
735
|
+
* Concrete variant: MediaConnect Flow router input configuration (with or without connection).
|
|
736
|
+
* @internal
|
|
737
|
+
*/
|
|
738
|
+
class MediaConnectFlowRouterInputConfig extends RouterInputConfiguration {
|
|
739
|
+
options;
|
|
740
|
+
availabilityZone;
|
|
741
|
+
constructor(options, availabilityZone) {
|
|
742
|
+
super();
|
|
743
|
+
this.options = options;
|
|
744
|
+
this.availabilityZone = availabilityZone;
|
|
745
|
+
}
|
|
746
|
+
_bind(scope, routerInputArn) {
|
|
747
|
+
return {
|
|
748
|
+
config: {
|
|
749
|
+
mediaConnectFlow: {
|
|
750
|
+
flowArn: this.options.flow?.flowArn,
|
|
751
|
+
flowOutputArn: this.options.flowOutput?.flowOutputArn,
|
|
752
|
+
sourceTransitDecryption: (0, shared_1.renderTransitEncryption)(scope, 'SourceTransitDecryptionRole', this.options.sourceTransitDecryption, routerInputArn),
|
|
753
|
+
},
|
|
754
|
+
},
|
|
755
|
+
availabilityZone: this.availabilityZone,
|
|
756
|
+
};
|
|
757
|
+
}
|
|
758
|
+
_endpoints(_ipAddress) {
|
|
759
|
+
return undefined;
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
/**
|
|
763
|
+
* Concrete variant: MediaLive Channel router input configuration (with or without connection).
|
|
764
|
+
* @internal
|
|
765
|
+
*/
|
|
766
|
+
class MediaLiveChannelRouterInputConfig extends RouterInputConfiguration {
|
|
767
|
+
options;
|
|
768
|
+
availabilityZone;
|
|
769
|
+
constructor(options, availabilityZone) {
|
|
770
|
+
super();
|
|
771
|
+
this.options = options;
|
|
772
|
+
this.availabilityZone = availabilityZone;
|
|
773
|
+
}
|
|
774
|
+
_bind(scope, routerInputArn) {
|
|
775
|
+
return {
|
|
776
|
+
config: {
|
|
777
|
+
mediaLiveChannel: {
|
|
778
|
+
mediaLiveChannelArn: this.options.mediaLiveChannelArn,
|
|
779
|
+
mediaLiveChannelOutputName: this.options.mediaLiveChannelOutputName,
|
|
780
|
+
mediaLivePipelineId: this.options.mediaLivePipelineId,
|
|
781
|
+
sourceTransitDecryption: (0, shared_1.renderTransitEncryption)(scope, 'SourceTransitDecryptionRole', this.options.sourceTransitDecryption, routerInputArn),
|
|
782
|
+
},
|
|
783
|
+
},
|
|
784
|
+
availabilityZone: this.availabilityZone,
|
|
785
|
+
};
|
|
786
|
+
}
|
|
787
|
+
_endpoints(_ipAddress) {
|
|
788
|
+
return undefined;
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
/**
|
|
792
|
+
* A MediaConnect Router Input that receives media streams and routes them to outputs.
|
|
793
|
+
*
|
|
794
|
+
* Router Inputs support multiple configuration types:
|
|
795
|
+
* - Standard: Single protocol input
|
|
796
|
+
* - Failover: Two matching protocols for redundancy
|
|
797
|
+
* - Merge: Two matching non-SRT protocols for stream merging
|
|
798
|
+
* - MediaConnect Flow: Input from an existing MediaConnect Flow
|
|
799
|
+
*/
|
|
800
|
+
class RouterInputBase extends aws_cdk_lib_1.Resource {
|
|
801
|
+
/**
|
|
802
|
+
* A reference to this Router Input resource.
|
|
803
|
+
* Required by the auto-generated IRouterInputRef interface.
|
|
804
|
+
*/
|
|
805
|
+
get routerInputRef() {
|
|
806
|
+
return { routerInputArn: this.routerInputArn };
|
|
807
|
+
}
|
|
808
|
+
/**
|
|
809
|
+
* Create a CloudWatch metric for this router input.
|
|
810
|
+
*/
|
|
811
|
+
metric(metricName, props) {
|
|
812
|
+
return new aws_cloudwatch_1.Metric({
|
|
813
|
+
metricName,
|
|
814
|
+
namespace: 'AWS/MediaConnect',
|
|
815
|
+
...props,
|
|
816
|
+
dimensionsMap: {
|
|
817
|
+
RouterInputARN: this.routerInputArn,
|
|
818
|
+
...props?.dimensionsMap,
|
|
819
|
+
},
|
|
820
|
+
}).attachTo(this);
|
|
821
|
+
}
|
|
822
|
+
/**
|
|
823
|
+
* Metric for the bitrate of the router input's payload.
|
|
824
|
+
*/
|
|
825
|
+
metricBitrate(props) {
|
|
826
|
+
return this.metric('RouterInputBitRate', {
|
|
827
|
+
statistic: 'avg',
|
|
828
|
+
period: aws_cdk_lib_1.Duration.seconds(60),
|
|
829
|
+
unit: aws_cloudwatch_1.Unit.BITS_PER_SECOND,
|
|
830
|
+
...props,
|
|
831
|
+
});
|
|
832
|
+
}
|
|
833
|
+
/**
|
|
834
|
+
* Metric for packets lost in transit that were not recovered by error correction.
|
|
835
|
+
*/
|
|
836
|
+
metricNotRecoveredPackets(props) {
|
|
837
|
+
return this.metric('RouterInputNotRecoveredPackets', {
|
|
838
|
+
statistic: 'sum',
|
|
839
|
+
period: aws_cdk_lib_1.Duration.seconds(60),
|
|
840
|
+
unit: aws_cloudwatch_1.Unit.COUNT,
|
|
841
|
+
...props,
|
|
842
|
+
});
|
|
843
|
+
}
|
|
844
|
+
/**
|
|
845
|
+
* Metric for the total number of packets received by the router input.
|
|
846
|
+
*/
|
|
847
|
+
metricTotalPackets(props) {
|
|
848
|
+
return this.metric('RouterInputTotalPackets', {
|
|
849
|
+
statistic: 'sum',
|
|
850
|
+
period: aws_cdk_lib_1.Duration.seconds(60),
|
|
851
|
+
unit: aws_cloudwatch_1.Unit.COUNT,
|
|
852
|
+
...props,
|
|
853
|
+
});
|
|
854
|
+
}
|
|
855
|
+
/**
|
|
856
|
+
* Metric for the router input connection state (1 connected, 0 disconnected). Applies to SRT sources only.
|
|
857
|
+
*/
|
|
858
|
+
metricConnected(props) {
|
|
859
|
+
return this.metric('RouterInputConnected', {
|
|
860
|
+
statistic: 'min',
|
|
861
|
+
period: aws_cdk_lib_1.Duration.seconds(60),
|
|
862
|
+
unit: aws_cloudwatch_1.Unit.NONE,
|
|
863
|
+
...props,
|
|
864
|
+
});
|
|
865
|
+
}
|
|
866
|
+
/**
|
|
867
|
+
* Metric for continuity counter errors in the transport stream.
|
|
868
|
+
*/
|
|
869
|
+
metricContinuityCounterErrors(props) {
|
|
870
|
+
return this.metric('RouterInputCCErrors', {
|
|
871
|
+
statistic: 'sum',
|
|
872
|
+
period: aws_cdk_lib_1.Duration.seconds(60),
|
|
873
|
+
unit: aws_cloudwatch_1.Unit.COUNT,
|
|
874
|
+
...props,
|
|
875
|
+
});
|
|
876
|
+
}
|
|
877
|
+
/**
|
|
878
|
+
* Metric for the recovery latency of the input stream. Applies to RIST, SRT, and RTP-FEC.
|
|
879
|
+
*/
|
|
880
|
+
metricLatency(props) {
|
|
881
|
+
return this.metric('RouterInputLatency', {
|
|
882
|
+
statistic: 'avg',
|
|
883
|
+
period: aws_cdk_lib_1.Duration.seconds(60),
|
|
884
|
+
unit: aws_cloudwatch_1.Unit.MILLISECONDS,
|
|
885
|
+
...props,
|
|
886
|
+
});
|
|
887
|
+
}
|
|
888
|
+
/**
|
|
889
|
+
* Metric for the number of times the router input has switched sources in Failover mode.
|
|
890
|
+
*/
|
|
891
|
+
metricFailoverSwitches(props) {
|
|
892
|
+
return this.metric('RouterInputFailoverSwitches', {
|
|
893
|
+
statistic: 'sum',
|
|
894
|
+
period: aws_cdk_lib_1.Duration.seconds(60),
|
|
895
|
+
unit: aws_cloudwatch_1.Unit.COUNT,
|
|
896
|
+
...props,
|
|
897
|
+
});
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
/**
|
|
901
|
+
* Defines an AWS Elemental MediaConnect Router Input.
|
|
902
|
+
*/
|
|
903
|
+
let RouterInput = (() => {
|
|
904
|
+
let _classDecorators = [prop_injectable_1.propertyInjectable];
|
|
905
|
+
let _classDescriptor;
|
|
906
|
+
let _classExtraInitializers = [];
|
|
907
|
+
let _classThis;
|
|
908
|
+
let _classSuper = RouterInputBase;
|
|
909
|
+
var RouterInput = class extends _classSuper {
|
|
910
|
+
static { _classThis = this; }
|
|
911
|
+
static {
|
|
912
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
913
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
914
|
+
RouterInput = _classThis = _classDescriptor.value;
|
|
915
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
916
|
+
}
|
|
917
|
+
static [JSII_RTTI_SYMBOL_1] = { fqn: "@aws-cdk/aws-mediaconnect-alpha.RouterInput", version: "2.263.0-alpha.0" };
|
|
918
|
+
/** Uniquely identifies this class. */
|
|
919
|
+
static PROPERTY_INJECTION_ID = '@aws-cdk.aws-mediaconnect-alpha.RouterInput';
|
|
920
|
+
/**
|
|
921
|
+
* Import an existing Router Input from its ARN.
|
|
922
|
+
*
|
|
923
|
+
* Use `fromRouterInputAttributes()` instead if you need to expose `routerInputId`
|
|
924
|
+
* or `ipAddress` on the imported construct.
|
|
925
|
+
*
|
|
926
|
+
* @param scope The parent construct
|
|
927
|
+
* @param id The construct id
|
|
928
|
+
* @param routerInputArn The ARN of the Router Input
|
|
929
|
+
* @returns A Router Input construct
|
|
930
|
+
*/
|
|
931
|
+
static fromRouterInputArn(scope, id, routerInputArn) {
|
|
932
|
+
return RouterInput.fromRouterInputAttributes(scope, id, { routerInputArn });
|
|
933
|
+
}
|
|
934
|
+
/**
|
|
935
|
+
* Import an existing Router Input from its attributes.
|
|
936
|
+
*
|
|
937
|
+
* Provide `routerInputId` and/or `ipAddress` when importing an input that was deployed
|
|
938
|
+
* externally — otherwise accessing those properties on the imported construct will throw.
|
|
939
|
+
*
|
|
940
|
+
* @param scope The parent construct
|
|
941
|
+
* @param id The construct id
|
|
942
|
+
* @param attrs The Router Input attributes
|
|
943
|
+
* @returns A Router Input construct
|
|
944
|
+
*/
|
|
945
|
+
static fromRouterInputAttributes(scope, id, attrs) {
|
|
946
|
+
try {
|
|
947
|
+
jsiiDeprecationWarnings._aws_cdk_aws_mediaconnect_alpha_RouterInputAttributes(attrs);
|
|
948
|
+
}
|
|
949
|
+
catch (error) {
|
|
950
|
+
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
|
951
|
+
Error.captureStackTrace(error, this.fromRouterInputAttributes);
|
|
952
|
+
}
|
|
953
|
+
throw error;
|
|
954
|
+
}
|
|
955
|
+
class Import extends RouterInputBase {
|
|
956
|
+
routerInputArn = attrs.routerInputArn;
|
|
957
|
+
createdAt = undefined;
|
|
958
|
+
updatedAt = undefined;
|
|
959
|
+
transitEncryptionSecret = undefined;
|
|
960
|
+
grants = mediaconnect_grants_generated_1.RouterInputGrants.fromRouterInput(this);
|
|
961
|
+
get endpoints() {
|
|
962
|
+
throw new aws_cdk_lib_1.ValidationError((0, helpers_internal_1.lit) `RouterInputEndpointsNotAvailableImported`, `'endpoints' is not available on imported RouterInput ${this.node.path}; only RouterInputs constructed in this app for listening protocol variants (RTP, RIST, SRT listener, including failover and merge) expose ingest endpoints`, this);
|
|
963
|
+
}
|
|
964
|
+
get routerInputId() {
|
|
965
|
+
if (attrs.routerInputId)
|
|
966
|
+
return attrs.routerInputId;
|
|
967
|
+
throw new aws_cdk_lib_1.ValidationError((0, helpers_internal_1.lit) `RouterInputIdNotProvided`, `'routerInputId' is not available on imported RouterInput ${this.node.path}; pass it via fromRouterInputAttributes`, this);
|
|
968
|
+
}
|
|
969
|
+
get ipAddress() {
|
|
970
|
+
if (attrs.ipAddress)
|
|
971
|
+
return attrs.ipAddress;
|
|
972
|
+
throw new aws_cdk_lib_1.ValidationError((0, helpers_internal_1.lit) `RouterInputIpAddressNotProvided`, `'ipAddress' is not available on imported RouterInput ${this.node.path}; pass it via fromRouterInputAttributes`, this);
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
return new Import(scope, id);
|
|
976
|
+
}
|
|
977
|
+
/**
|
|
978
|
+
* Returns the maximum bitrate in Mbps for a known tier, or undefined for custom tiers.
|
|
979
|
+
*/
|
|
980
|
+
static tierLimitMbps(tier) {
|
|
981
|
+
if (tier.value === RouterInputTier.INPUT_20.value)
|
|
982
|
+
return 20;
|
|
983
|
+
if (tier.value === RouterInputTier.INPUT_50.value)
|
|
984
|
+
return 50;
|
|
985
|
+
if (tier.value === RouterInputTier.INPUT_100.value)
|
|
986
|
+
return 100;
|
|
987
|
+
return undefined;
|
|
988
|
+
}
|
|
989
|
+
routerInputArn;
|
|
990
|
+
routerInputId;
|
|
991
|
+
ipAddress;
|
|
992
|
+
createdAt;
|
|
993
|
+
updatedAt;
|
|
994
|
+
_endpoints;
|
|
995
|
+
transitEncryptionSecret;
|
|
996
|
+
grants;
|
|
997
|
+
get endpoints() {
|
|
998
|
+
if (this._endpoints === undefined) {
|
|
999
|
+
throw new aws_cdk_lib_1.ValidationError((0, helpers_internal_1.lit) `RouterInputEndpointsNotAvailableConfig`, `'endpoints' is not available on this RouterInput ${this.node.path}; only listening protocol variants (RTP, RIST, SRT listener — including failover and merge built from those) expose ingest endpoints — SRT caller, MediaConnect Flow, and MediaLive Channel inputs do not`, this);
|
|
1000
|
+
}
|
|
1001
|
+
return this._endpoints;
|
|
1002
|
+
}
|
|
1003
|
+
constructor(scope, id, props) {
|
|
1004
|
+
super(scope, id, {
|
|
1005
|
+
physicalName: props.routerInputName ?? aws_cdk_lib_1.Lazy.string({ produce: () => aws_cdk_lib_1.Names.uniqueResourceName(this, { maxLength: 128 }) }),
|
|
1006
|
+
});
|
|
1007
|
+
try {
|
|
1008
|
+
jsiiDeprecationWarnings._aws_cdk_aws_mediaconnect_alpha_RouterInputProps(props);
|
|
1009
|
+
}
|
|
1010
|
+
catch (error) {
|
|
1011
|
+
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
|
|
1012
|
+
Error.captureStackTrace(error, RouterInput);
|
|
1013
|
+
}
|
|
1014
|
+
throw error;
|
|
1015
|
+
}
|
|
1016
|
+
// Validate router input name if provided
|
|
1017
|
+
if (props.routerInputName != null && props.routerInputName !== '' && !aws_cdk_lib_1.Token.isUnresolved(props.routerInputName)) {
|
|
1018
|
+
if (props.routerInputName.length > 128) {
|
|
1019
|
+
throw new aws_cdk_lib_1.ValidationError((0, helpers_internal_1.lit) `RouterInputNameLength`, `Router input name must be between 1 and 128 characters, got ${props.routerInputName.length}`, this);
|
|
1020
|
+
}
|
|
1021
|
+
if (!/^[a-zA-Z0-9-]+$/.test(props.routerInputName)) {
|
|
1022
|
+
throw new aws_cdk_lib_1.ValidationError((0, helpers_internal_1.lit) `RouterInputNameFormat`, `Router input name must contain only alphanumeric characters and hyphens, got '${props.routerInputName}'`, this);
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
// Validate maximum bitrate
|
|
1026
|
+
if (!props.maximumBitrate.isUnresolved() && props.maximumBitrate.toBps() < 1000000) {
|
|
1027
|
+
throw new aws_cdk_lib_1.ValidationError((0, helpers_internal_1.lit) `RouterInputMinBitrate`, `Maximum bitrate must be at least 1,000,000 bits/s (1 Mbps), got ${props.maximumBitrate.toBps()}`, this);
|
|
1028
|
+
}
|
|
1029
|
+
// Validate bitrate does not exceed tier limit
|
|
1030
|
+
const resolvedTier = props.tier ?? RouterInputTier.INPUT_20;
|
|
1031
|
+
const tierMbps = RouterInput.tierLimitMbps(resolvedTier);
|
|
1032
|
+
if ((0, shared_1.exceedsRouterTierBitrate)(tierMbps, props.maximumBitrate)) {
|
|
1033
|
+
throw new aws_cdk_lib_1.ValidationError((0, helpers_internal_1.lit) `RouterInputBitrateExceedsTier`, `Maximum bitrate ${props.maximumBitrate.toBps() / 1_000_000} Mbps exceeds the ${resolvedTier.value} tier limit of ${tierMbps} Mbps`, this);
|
|
1034
|
+
}
|
|
1035
|
+
// Validate maintenance time format
|
|
1036
|
+
if (props.maintenanceConfiguration) {
|
|
1037
|
+
(0, shared_1.validateMaintenanceTime)(props.maintenanceConfiguration.time);
|
|
1038
|
+
}
|
|
1039
|
+
// Enhanced CDK Analytics Telemetry
|
|
1040
|
+
(0, metadata_resource_1.addConstructMetadata)(this, props);
|
|
1041
|
+
const stack = aws_cdk_lib_1.Stack.of(this);
|
|
1042
|
+
const targetRegion = props.regionName ?? stack.region;
|
|
1043
|
+
// Wildcard the id — pinning the live ARN (attrArn) would create a role → router-input → role cycle.
|
|
1044
|
+
const routerInputArn = stack.formatArn({
|
|
1045
|
+
service: 'mediaconnect',
|
|
1046
|
+
region: targetRegion,
|
|
1047
|
+
resource: 'routerInput',
|
|
1048
|
+
resourceName: '*',
|
|
1049
|
+
arnFormat: aws_cdk_lib_1.ArnFormat.COLON_RESOURCE_NAME,
|
|
1050
|
+
});
|
|
1051
|
+
const configBind = props.configuration._bind(this, routerInputArn);
|
|
1052
|
+
// Validate AZ matches region if provided
|
|
1053
|
+
if (configBind.availabilityZone && !configBind.availabilityZone.startsWith(targetRegion)) {
|
|
1054
|
+
throw new aws_cdk_lib_1.ValidationError((0, helpers_internal_1.lit) `RouterInputAzRegionMismatch`, `Availability zone '${configBind.availabilityZone}' must be within region '${targetRegion}'`, this);
|
|
1055
|
+
}
|
|
1056
|
+
const transit = (0, shared_1.resolveTransitEncryption)(this, 'TransitEncryptionRole', props.transitEncryption, routerInputArn);
|
|
1057
|
+
const routerinput = new aws_mediaconnect_1.CfnRouterInput(this, 'Resource', {
|
|
1058
|
+
name: this.physicalName,
|
|
1059
|
+
maximumBitrate: props.maximumBitrate.toBps(),
|
|
1060
|
+
tier: (props.tier ?? RouterInputTier.INPUT_20).value,
|
|
1061
|
+
routingScope: props.routingScope.value,
|
|
1062
|
+
maintenanceConfiguration: props.maintenanceConfiguration ? {
|
|
1063
|
+
preferredDayTime: props.maintenanceConfiguration,
|
|
1064
|
+
} : {
|
|
1065
|
+
default: {},
|
|
1066
|
+
},
|
|
1067
|
+
configuration: configBind.config,
|
|
1068
|
+
transitEncryption: transit.config,
|
|
1069
|
+
regionName: targetRegion,
|
|
1070
|
+
availabilityZone: configBind.availabilityZone,
|
|
1071
|
+
tags: props.tags ? (0, shared_1.renderTags)(props.tags) : undefined,
|
|
1072
|
+
});
|
|
1073
|
+
this.routerInputArn = routerinput.attrArn;
|
|
1074
|
+
this.routerInputId = routerinput.attrId;
|
|
1075
|
+
this.ipAddress = routerinput.attrIpAddress;
|
|
1076
|
+
this.createdAt = routerinput.attrCreatedAt;
|
|
1077
|
+
this.updatedAt = routerinput.attrUpdatedAt;
|
|
1078
|
+
// Without this the router input can be created before the
|
|
1079
|
+
// policy is attached ("access denied" at create time). Ordering the grant before the
|
|
1080
|
+
// router input pulls the policy in as a dependency.
|
|
1081
|
+
transit.grant?.applyBefore(routerinput);
|
|
1082
|
+
// Compute ingest endpoints for protocol-based variants
|
|
1083
|
+
this._endpoints = props.configuration._endpoints(routerinput.attrIpAddress);
|
|
1084
|
+
// Store the transit encryption secret if explicitly provided
|
|
1085
|
+
this.transitEncryptionSecret = props.transitEncryption?.secret;
|
|
1086
|
+
this.grants = mediaconnect_grants_generated_1.RouterInputGrants.fromRouterInput(this);
|
|
1087
|
+
}
|
|
1088
|
+
static {
|
|
1089
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
1090
|
+
}
|
|
1091
|
+
};
|
|
1092
|
+
return RouterInput = _classThis;
|
|
1093
|
+
})();
|
|
1094
|
+
exports.RouterInput = RouterInput;
|
|
1095
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGVyLWlucHV0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsicm91dGVyLWlucHV0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUNBLDZDQUFxSTtBQUVySSwrREFBMEQ7QUFDMUQsbUVBQThEO0FBRzlELDRFQUE0RDtBQUM1RCw4RUFBOEU7QUFDOUUsMEVBQTBFO0FBSTFFLG1GQUFvRTtBQUdwRSxxQ0FBdUs7QUFFdks7O0dBRUc7QUFDSCxNQUFhLDBCQUEwQjtJQW1CRDs7SUFsQnBDLG1DQUFtQztJQUM1QixNQUFNLENBQVUsR0FBRyxHQUFHLElBQUksMEJBQTBCLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDbkUseUNBQXlDO0lBQ2xDLE1BQU0sQ0FBVSxJQUFJLEdBQUcsSUFBSSwwQkFBMEIsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNyRSw4Q0FBOEM7SUFDdkMsTUFBTSxDQUFVLFVBQVUsR0FBRyxJQUFJLDBCQUEwQixDQUFDLFlBQVksQ0FBQyxDQUFDO0lBQ2pGLGdEQUFnRDtJQUN6QyxNQUFNLENBQVUsWUFBWSxHQUFHLElBQUksMEJBQTBCLENBQUMsY0FBYyxDQUFDLENBQUM7SUFFckY7OztPQUdHO0lBQ0ksTUFBTSxDQUFDLEVBQUUsQ0FBQyxLQUFhO1FBQzVCLE9BQU8sSUFBSSwwQkFBMEIsQ0FBQyxLQUFLLENBQUMsQ0FBQztLQUM5QztJQUVELDZDQUE2QztJQUM3QyxZQUFvQyxLQUFhO1FBQWIsVUFBSyxHQUFMLEtBQUssQ0FBUTtLQUFJO0lBRXJELCtCQUErQjtJQUN4QixRQUFRO1FBQ2IsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDO0tBQ25COztBQXhCSCxnRUF5QkM7QUFrSkQ7O0dBRUc7QUFDSCxNQUFhLFlBQVk7SUFlYTs7SUFkcEMsK0NBQStDO0lBQ3hDLE1BQU0sQ0FBVSxRQUFRLEdBQUcsSUFBSSxZQUFZLENBQUMsVUFBVSxDQUFDLENBQUM7SUFD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QUFVLENBQUMsTUFBTTtnQkFDaEMsaUJBQWlCLEVBQUUsT0FBTyxDQUFDLE1BQU07Z0JBQ2pDLFVBQVUsRUFBRSxZQUFZO2dCQUN4QixnQkFBZ0IsRUFBRSxVQUFVLENBQUMsZ0JBQWdCO2dCQUM3QyxJQUFJLEVBQUUsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBQSxtQkFBVSxFQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUzthQUN0RCxDQUFDLENBQUM7WUFFSCxJQUFJLENBQUMsY0FBYyxHQUFHLFdBQVcsQ0FBQyxPQUFPLENBQUM7WUFDMUMsSUFBSSxDQUFDLGFBQWEsR0FBRyxXQUFXLENBQUMsTUFBTSxDQUFDO1lBQ3hDLElBQUksQ0FBQyxTQUFTLEdBQUcsV0FBVyxDQUFDLGFBQWEsQ0FBQztZQUMzQyxJQUFJLENBQUMsU0FBUyxHQUFHLFdBQVcsQ0FBQyxhQUFhLENBQUM7WUFDM0MsSUFBSSxDQUFDLFNBQVMsR0FBRyxXQUFXLENBQUMsYUFBYSxDQUFDO1lBRTNDLDBEQUEwRDtZQUMxRCxxRkFBcUY7WUFDckYsb0RBQW9EO1lBQ3BELE9BQU8sQ0FBQyxLQUFLLEVBQUUsV0FBVyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBRXhDLHVEQUF1RDtZQUN2RCxJQUFJLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQyxhQUFhLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUU1RSw2REFBNkQ7WUFDN0QsSUFBSSxDQUFDLHVCQUF1QixHQUFHLEtBQUssQ0FBQyxpQkFBaUIsRUFBRSxNQUFNLENBQUM7WUFDL0QsSUFBSSxDQUFDLE1BQU0sR0FBRyxpREFBaUIsQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLENBQUM7U0FDdkQ7O1lBM0xVLHVEQUFXOzs7OztBQUFYLGtDQUFXIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgeyBCaXRyYXRlLCBJUmVzb3VyY2UgfSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgeyBBcm5Gb3JtYXQsIER1cmF0aW9uLCBGbiwgTGF6eSwgTmFtZXMsIFJlc291cmNlLCBTdGFjaywgVG9rZW4sIFVuc2NvcGVkVmFsaWRhdGlvbkVycm9yLCBWYWxpZGF0aW9uRXJyb3IgfSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgdHlwZSB7IE1ldHJpY09wdGlvbnMgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtY2xvdWR3YXRjaCc7XG5pbXBvcnQgeyBNZXRyaWMsIFVuaXQgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtY2xvdWR3YXRjaCc7XG5pbXBvcnQgeyBDZm5Sb3V0ZXJJbnB1dCB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1tZWRpYWNvbm5lY3QnO1xuaW1wb3J0IHR5cGUgeyBJUm91dGVySW5wdXRSZWYsIFJvdXRlcklucHV0UmVmZXJlbmNlIH0gZnJvbSAnYXdzLWNkay1saWIvYXdzLW1lZGlhY29ubmVjdCc7XG5pbXBvcnQgdHlwZSB7IElTZWNyZXQgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtc2VjcmV0c21hbmFnZXInO1xuaW1wb3J0IHsgbGl0IH0gZnJvbSAnYXdzLWNkay1saWIvY29yZS9saWIvaGVscGVycy1pbnRlcm5hbCc7XG5pbXBvcnQgeyBhZGRDb25zdHJ1Y3RNZXRhZGF0YSB9IGZyb20gJ2F3cy1jZGstbGliL2NvcmUvbGliL21ldGFkYXRhLXJlc291cmNlJztcbmltcG9ydCB7IHByb3BlcnR5SW5qZWN0YWJsZSB9IGZyb20gJ2F3cy1jZGstbGliL2NvcmUvbGliL3Byb3AtaW5qZWN0YWJsZSc7XG5pbXBvcnQgdHlwZSB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0IHR5cGUgeyBJRmxvdyB9IGZyb20gJy4vZmxvdyc7XG5pbXBvcnQgdHlwZSB7IElGbG93T3V0cHV0IH0gZnJvbSAnLi9mbG93LW91dHB1dCc7XG5pbXBvcnQgeyBSb3V0ZXJJbnB1dEdyYW50cyB9IGZyb20gJy4vbWVkaWFjb25uZWN0LWdyYW50cy5nZW5lcmF0ZWQnO1xuaW1wb3J0IHR5cGUgeyBJUm91dGVyTmV0d29ya0ludGVyZmFjZSB9IGZyb20gJy4vcm91dGVyLW5ldHdvcmstaW50ZXJmYWNlJztcbmltcG9ydCB0eXBlIHsgTWFpbnRlbmFuY2VEYXksIE1lZGlhTGl2ZVBpcGVsaW5lLCBSb3V0ZXJTcnRFbmNyeXB0aW9uLCBUcmFuc2l0RW5jcnlwdGlvbiB9IGZyb20gJy4vc2hhcmVkJztcbmltcG9ydCB7IHJlbmRlclRhZ3MsIGV4Y2VlZHNSb3V0ZXJUaWVyQml0cmF0ZSwgcmVuZGVyUm91dGVyU3J0RW5jcnlwdGlvbiwgcmVuZGVyVHJhbnNpdEVuY3J5cHRpb24sIHJlc29sdmVUcmFuc2l0RW5jcnlwdGlvbiwgdmFsaWRhdGVNYWludGVuYW5jZVRpbWUgfSBmcm9tICcuL3NoYXJlZCc7XG5cbi8qKlxuICogUHJvdG9jb2wgb3B0aW9ucyBhdmFpbGFibGUgZm9yIFJvdXRlciBJbnB1dCBjb25maWd1cmF0aW9uc1xuICovXG5leHBvcnQgY2xhc3MgUm91dGVySW5wdXRQcm90b2NvbE9wdGlvbnMge1xuICAvKiogUmVhbC10aW1lIFRyYW5zcG9ydCBQcm90b2NvbCAqL1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IFJUUCA9IG5ldyBSb3V0ZXJJbnB1dFByb3RvY29sT3B0aW9ucygnUlRQJyk7XG4gIC8qKiBSZWxpYWJsZSBJbnRlcm5ldCBTdHJlYW0gVHJhbnNwb3J0ICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgUklTVCA9IG5ldyBSb3V0ZXJJbnB1dFByb3RvY29sT3B0aW9ucygnUklTVCcpO1xuICAvKiogU2VjdXJlIFJlbGlhYmxlIFRyYW5zcG9ydCAtIENhbGxlciBtb2RlICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgU1JUX0NBTExFUiA9IG5ldyBSb3V0ZXJJbnB1dFByb3RvY29sT3B0aW9ucygnU1JUX0NBTExFUicpO1xuICAvKiogU2VjdXJlIFJlbGlhYmxlIFRyYW5zcG9ydCAtIExpc3RlbmVyIG1vZGUgKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBTUlRfTElTVEVORVIgPSBuZXcgUm91dGVySW5wdXRQcm90b2NvbE9wdGlvbnMoJ1NSVF9MSVNURU5FUicpO1xuXG4gIC8qKlxuICAgKiBVc2UgYSBjdXN0b20gcHJvdG9jb2wgdmFsdWVcbiAgICogQHBhcmFtIHZhbHVlIFRoZSBwcm90b2NvbCBzdHJpbmcgdmFsdWVcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgb2YodmFsdWU6IHN0cmluZyk6IFJvdXRlcklucHV0UHJvdG9jb2xPcHRpb25zIHtcbiAgICByZXR1cm4gbmV3IFJvdXRlcklucHV0UHJvdG9jb2xPcHRpb25zKHZhbHVlKTtcbiAgfVxuXG4gIC8qKiBAcGFyYW0gdmFsdWUgVGhlIHByb3RvY29sIHN0cmluZyB2YWx1ZSAqL1xuICBwcml2YXRlIGNvbnN0cnVjdG9yKHB1YmxpYyByZWFkb25seSB2YWx1ZTogc3RyaW5nKSB7fVxuXG4gIC8qKiBSZXR1cm5zIHRoZSBzdHJpbmcgdmFsdWUgKi9cbiAgcHVibGljIHRvU3RyaW5nKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWU7XG4gIH1cbn1cblxuLyoqXG4gKiBBIHNpbmdsZSBpbmdlc3QgZW5kcG9pbnQgd2hlcmUgdGhlIHJvdXRlciBpbnB1dCBsaXN0ZW5zIGZvciB1cHN0cmVhbSBjb250ZW50LlxuICpcbiAqIEZhaWxvdmVyIGFuZCBtZXJnZSBjb25maWd1cmF0aW9ucyBleHBvc2UgdHdvIGVuZHBvaW50czsgc3RhbmRhcmQgY29uZmlndXJhdGlvbnNcbiAqIGV4cG9zZSBvbmUuIFJldHVybmVkIGJ5IHtAbGluayBJUm91dGVySW5wdXQuZW5kcG9pbnRzfS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBSb3V0ZXJJbnB1dEVuZHBvaW50IHtcbiAgLyoqXG4gICAqIFRoZSBmdWxsIGluZ2VzdCBVUkwgY29tYmluaW5nIHByb3RvY29sIHNjaGVtZSwgSVAsIGFuZCBwb3J0LiBGb3IgZXhhbXBsZTpcbiAgICogYHNydDovLzIwMy4wLjExMy4xMDo1MDAwYCBvciBgcnRwOi8vMjAzLjAuMTEzLjEwOjUwMDFgLlxuICAgKi9cbiAgcmVhZG9ubHkgdXJsOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBsaXN0ZW5pbmcgcG9ydCBhdCB3aGljaCB0aGUgcm91dGVyIGlucHV0IGFjY2VwdHMgdXBzdHJlYW0gY29udGVudC5cbiAgICovXG4gIHJlYWRvbmx5IHBvcnQ6IG51bWJlcjtcbn1cblxuLyoqXG4gKiBJbnRlcmZhY2UgZm9yIFJvdXRlciBJbnB1dFxuICovXG5leHBvcnQgaW50ZXJmYWNlIElSb3V0ZXJJbnB1dCBleHRlbmRzIElSZXNvdXJjZSwgSVJvdXRlcklucHV0UmVmIHtcbiAgLyoqXG4gICAqIFRoZSBBbWF6b24gUmVzb3VyY2UgTmFtZSAoQVJOKSBvZiB0aGUgcm91dGVyIGlucHV0LlxuICAgKlxuICAgKiBAYXR0cmlidXRlXG4gICAqL1xuICByZWFkb25seSByb3V0ZXJJbnB1dEFybjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgdW5pcXVlIGlkZW50aWZpZXIgb2YgdGhlIHJvdXRlciBpbnB1dC5cbiAgICpcbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcmVhZG9ubHkgcm91dGVySW5wdXRJZDogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgSVAgYWRkcmVzcyBvZiB0aGUgcm91dGVyIGlucHV0LlxuICAgKlxuICAgKiBAYXR0cmlidXRlXG4gICAqL1xuICByZWFkb25seSBpcEFkZHJlc3M6IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIHRpbWVzdGFtcCB3aGVuIHRoZSByb3V0ZXIgaW5wdXQgd2FzIGNyZWF0ZWQuXG4gICAqXG4gICAqIEBhdHRyaWJ1dGVcbiAgICovXG4gIHJlYWRvbmx5IGNyZWF0ZWRBdD86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIHRpbWVzdGFtcCB3aGVuIHRoZSByb3V0ZXIgaW5wdXQgd2FzIGxhc3QgdXBkYXRlZC5cbiAgICpcbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcmVhZG9ubHkgdXBkYXRlZEF0Pzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgaW5nZXN0IGVuZHBvaW50cyAoVVJMICsgcG9ydCkgd2hlcmUgdGhlIHJvdXRlciBpbnB1dCBsaXN0ZW5zLlxuICAgKlxuICAgKiBSZXR1cm5zIG9uZSBlbnRyeSBmb3Igc3RhbmRhcmQgcHJvdG9jb2wtYmFzZWQgdmFyaWFudHMgKFJUUCwgUklTVCwgU1JUIGxpc3RlbmVyKSxcbiAgICogYW5kIG9uZSBlbnRyeSBwZXIgc291cmNlIGZvciBmYWlsb3ZlciBhbmQgbWVyZ2UgY29uZmlndXJhdGlvbnMgYnVpbHQgZnJvbSB0aG9zZVxuICAgKiBwcm90b2NvbHMuIEZvciBleGFtcGxlIGEgZmFpbG92ZXIgUlRQIGlucHV0IHdpbGwgcmV0dXJuOlxuICAgKlxuICAgKiBgYGBcbiAgICogW1xuICAgKiAgIHsgdXJsOiAncnRwOi8vMjAzLjAuMTEzLjEwOjUwMDAnLCBwb3J0OiA1MDAwIH0sXG4gICAqICAgeyB1cmw6ICdydHA6Ly8yMDMuMC4xMTMuMTA6NTAwMScsIHBvcnQ6IDUwMDEgfSxcbiAgICogXVxuICAgKiBgYGBcbiAgICpcbiAgICogQWNjZXNzaW5nIHRoaXMgb24gU1JUIGNhbGxlciAod2hlcmUgdGhlIHJvdXRlciBpbnB1dCBkaWFscyBvdXQgdG8gYSByZW1vdGVcbiAgICogc291cmNlKSwgTWVkaWFDb25uZWN0IEZsb3csIE1lZGlhTGl2ZSBDaGFubmVsLCBvciBpbXBvcnRlZCBpbnB1dHMgdGhyb3dzIOKAlCB0aG9zZVxuICAgKiB2YXJpYW50cyBkbyBub3QgZXhwb3NlIGhvc3Q6cG9ydCBwYWlycyB0aGUgaW5wdXQgbGlzdGVucyBvbi5cbiAgICovXG4gIHJlYWRvbmx5IGVuZHBvaW50czogUm91dGVySW5wdXRFbmRwb2ludFtdO1xuXG4gIC8qKlxuICAgKiBUaGUgU2VjcmV0cyBNYW5hZ2VyIHNlY3JldCBjb250YWluaW5nIHRoZSB0cmFuc2l0IGVuY3J5cHRpb24gcGFzc3BocmFzZS5cbiAgICpcbiAgICogT25seSBhdmFpbGFibGUgd2hlbiB0aGUgUm91dGVyIElucHV0IHdhcyBjcmVhdGVkIHdpdGggZXhwbGljaXRcbiAgICogYHRyYW5zaXRFbmNyeXB0aW9uYCBjb25maWd1cmF0aW9uLiBOb3QgYXZhaWxhYmxlIGZvclxuICAgKiBhdXRvbWF0aWMgZW5jcnlwdGlvbiBvciBpbXBvcnRlZCBpbnB1dHMuXG4gICAqL1xuICByZWFkb25seSB0cmFuc2l0RW5jcnlwdGlvblNlY3JldD86IElTZWNyZXQ7XG5cbiAgLyoqXG4gICAqIENvbGxlY3Rpb24gb2YgZ3JhbnQgbWV0aG9kcyBmb3IgdGhpcyByb3V0ZXIgaW5wdXQuXG4gICAqL1xuICByZWFkb25seSBncmFudHM6IFJvdXRlcklucHV0R3JhbnRzO1xuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBDbG91ZFdhdGNoIG1ldHJpYyBmb3IgdGhpcyByb3V0ZXIgaW5wdXQuXG4gICAqXG4gICAqIFJvdXRlciBpbnB1dCBtZXRyaWNzIGFyZSBkaW1lbnNpb25lZCBieSBgUm91dGVySW5wdXRBUk5gLiBTZWUgdGhlIE1lZGlhQ29ubmVjdFxuICAgKiBkb2N1bWVudGF0aW9uIGZvciBhdmFpbGFibGUgbWV0cmljIG5hbWVzIChlLmcuIGBSb3V0ZXJJbnB1dEJpdFJhdGVgLFxuICAgKiBgUm91dGVySW5wdXROb3RSZWNvdmVyZWRQYWNrZXRzYCkuXG4gICAqL1xuICBtZXRyaWMobWV0cmljTmFtZTogc3RyaW5nLCBwcm9wcz86IE1ldHJpY09wdGlvbnMpOiBNZXRyaWM7XG5cbiAgLyoqXG4gICAqIE1ldHJpYyBmb3IgdGhlIGJpdHJhdGUgb2YgdGhlIHJvdXRlciBpbnB1dCdzIHBheWxvYWQuXG4gICAqIEBkZWZhdWx0IC0gYXZlcmFnZSBvdmVyIDYwIHNlY29uZHNcbiAgICovXG4gIG1ldHJpY0JpdHJhdGUocHJvcHM/OiBNZXRyaWNPcHRpb25zKTogTWV0cmljO1xuXG4gIC8qKlxuICAgKiBNZXRyaWMgZm9yIHBhY2tldHMgbG9zdCBpbiB0cmFuc2l0IHRoYXQgd2VyZSBub3QgcmVjb3ZlcmVkIGJ5IGVycm9yIGNvcnJlY3Rpb24uXG4gICAqIEBkZWZhdWx0IC0gc3VtIG92ZXIgNjAgc2Vjb25kc1xuICAgKi9cbiAgbWV0cmljTm90UmVjb3ZlcmVkUGFja2V0cyhwcm9wcz86IE1ldHJpY09wdGlvbnMpOiBNZXRyaWM7XG5cbiAgLyoqXG4gICAqIE1ldHJpYyBmb3IgdGhlIHRvdGFsIG51bWJlciBvZiBwYWNrZXRzIHJlY2VpdmVkIGJ5IHRoZSByb3V0ZXIgaW5wdXQuXG4gICAqIEBkZWZhdWx0IC0gc3VtIG92ZXIgNjAgc2Vjb25kc1xuICAgKi9cbiAgbWV0cmljVG90YWxQYWNrZXRzKHByb3BzPzogTWV0cmljT3B0aW9ucyk6IE1ldHJpYztcblxuICAvKipcbiAgICogTWV0cmljIGZvciB0aGUgcm91dGVyIGlucHV0IGNvbm5lY3Rpb24gc3RhdGUgKDEgY29ubmVjdGVkLCAwIGRpc2Nvbm5lY3RlZCkuIEFwcGxpZXMgdG8gU1JUIHNvdXJjZXMgb25seS5cbiAgICogQGRlZmF1bHQgLSBtaW5pbXVtIG92ZXIgNjAgc2Vjb25kc1xuICAgKi9cbiAgbWV0cmljQ29ubmVjdGVkKHByb3BzPzogTWV0cmljT3B0aW9ucyk6IE1ldHJpYztcblxuICAvKipcbiAgICogTWV0cmljIGZvciBjb250aW51aXR5IGNvdW50ZXIgZXJyb3JzIGluIHRoZSB0cmFuc3BvcnQgc3RyZWFtLlxuICAgKiBAZGVmYXVsdCAtIHN1bSBvdmVyIDYwIHNlY29uZHNcbiAgICovXG4gIG1ldHJpY0NvbnRpbnVpdHlDb3VudGVyRXJyb3JzKHByb3BzPzogTWV0cmljT3B0aW9ucyk6IE1ldHJpYztcblxuICAvKipcbiAgICogTWV0cmljIGZvciB0aGUgcmVjb3ZlcnkgbGF0ZW5jeSBvZiB0aGUgaW5wdXQgc3RyZWFtLiBBcHBsaWVzIHRvIFJJU1QsIFNSVCwgYW5kIFJUUC1GRUMuXG4gICAqIEBkZWZhdWx0IC0gYXZlcmFnZSBvdmVyIDYwIHNlY29uZHNcbiAgICovXG4gIG1ldHJpY0xhdGVuY3kocHJvcHM/OiBNZXRyaWNPcHRpb25zKTogTWV0cmljO1xuXG4gIC8qKlxuICAgKiBNZXRyaWMgZm9yIHRoZSBudW1iZXIgb2YgdGltZXMgdGhlIHJvdXRlciBpbnB1dCBoYXMgc3dpdGNoZWQgc291cmNlcyBpbiBGYWlsb3ZlciBtb2RlLlxuICAgKiBAZGVmYXVsdCAtIHN1bSBvdmVyIDYwIHNlY29uZHNcbiAgICovXG4gIG1ldHJpY0ZhaWxvdmVyU3dpdGNoZXMocHJvcHM/OiBNZXRyaWNPcHRpb25zKTogTWV0cmljO1xufVxuXG4vKipcbiAqIFJvdXRpbmcgc2NvcGUgZm9yIHRoZSBSb3V0ZXIgSW5wdXRcbiAqL1xuZXhwb3J0IGNsYXNzIFJvdXRpbmdTY29wZSB7XG4gIC8qKiBSb3V0ZSB0cmFmZmljIHdpdGhpbiB0aGUgc2FtZSBBV1MgcmVnaW9uICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgUkVHSU9OQUwgPSBuZXcgUm91dGluZ1Njb3BlKCdSRUdJT05BTCcpO1xuICAvKiogUm91dGUgdHJhZmZpYyBnbG9iYWxseSBhY3Jvc3MgQVdTIHJlZ2lvbnMgKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBHTE9CQUwgPSBuZXcgUm91dGluZ1Njb3BlKCdHTE9CQUwnKTtcblxuICAvKipcbiAgICogVXNlIGEgY3VzdG9tIHJvdXRpbmcgc2NvcGUgdmFsdWVcbiAgICogQHBhcmFtIHZhbHVlIFRoZSByb3V0aW5nIHNjb3BlIHN0cmluZyB2YWx1ZVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBvZih2YWx1ZTogc3RyaW5nKTogUm91dGluZ1Njb3BlIHtcbiAgICByZXR1cm4gbmV3IFJvdXRpbmdTY29wZSh2YWx1ZSk7XG4gIH1cblxuICAvKiogQHBhcmFtIHZhbHVlIFRoZSByb3V0aW5nIHNjb3BlIHN0cmluZyB2YWx1ZSAqL1xuICBwcml2YXRlIGNvbnN0cnVjdG9yKHB1YmxpYyByZWFkb25seSB2YWx1ZTogc3RyaW5nKSB7fVxuXG4gIC8qKiBSZXR1cm5zIHRoZSBzdHJpbmcgdmFsdWUgKi9cbiAgcHVibGljIHRvU3RyaW5nKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWU7XG4gIH1cbn1cblxuLyoqXG4gKiBSb3V0aW5nIHRpZXIgYmFzZWQgb24geW91ciBtYXhpbXVtIGJpdHJhdGUgcmVxdWlyZW1lbnRzLlxuICovXG5leHBvcnQgY2xhc3MgUm91dGVySW5wdXRUaWVyIHtcbiAgLyoqIFN1cHBvcnRzIGEgbWF4aW11bSBiaXRyYXRlIHVwIHRvIDEwMCBtZWdhYml0cyBwZXIgc2Vjb25kLiAqL1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IElOUFVUXzEwMCA9IG5ldyBSb3V0ZXJJbnB1dFRpZXIoJ0lOUFVUXzEwMCcpO1xuICAvKiogU3VwcG9ydHMgYSBtYXhpbXVtIGJpdHJhdGUgdXAgdG8gNTAgbWVnYWJpdHMgcGVyIHNlY29uZC4gKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBJTlBVVF81MCA9IG5ldyBSb3V0ZXJJbnB1dFRpZXIoJ0lOUFVUXzUwJyk7XG4gIC8qKiBTdXBwb3J0cyBhIG1heGltdW0gYml0cmF0ZSB1cCB0byAyMCBtZWdhYml0cyBwZXIgc2Vjb25kLiAqL1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IElOUFVUXzIwID0gbmV3IFJvdXRlcklucHV0VGllcignSU5QVVRfMjAnKTtcblxuICAvKipcbiAgICogVXNlIGEgY3VzdG9tIHRpZXIgdmFsdWVcbiAgICogQHBhcmFtIHZhbHVlIFRoZSB0aWVyIHN0cmluZyB2YWx1ZVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBvZih2YWx1ZTogc3RyaW5nKTogUm91dGVySW5wdXRUaWVyIHtcbiAgICByZXR1cm4gbmV3IFJvdXRlcklucHV0VGllcih2YWx1ZSk7XG4gIH1cblxuICAvKiogQHBhcmFtIHZhbHVlIFRoZSB0aWVyIHN0cmluZyB2YWx1ZSAqL1xuICBwcml2YXRlIGNvbnN0cnVjdG9yKHB1YmxpYyByZWFkb25seSB2YWx1ZTogc3RyaW5nKSB7fVxuXG4gIC8qKiBSZXR1cm5zIHRoZSBzdHJpbmcgdmFsdWUgKi9cbiAgcHVibGljIHRvU3RyaW5nKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMudmFsdWU7XG4gIH1cbn1cblxuLyoqXG4gKiBDb25maWd1cmF0aW9uIGZvciBzY2hlZHVsZWQgbWFpbnRlbmFuY2Ugd2luZG93c1xuICovXG5leHBvcnQgaW50ZXJmYWNlIE1haW50ZW5hbmNlQ29uZmlndXJhdGlvbiB7XG4gIC8qKiBEYXkgb2YgdGhlIHdlZWsgZm9yIG1haW50ZW5hbmNlIChlLmcuLCAnTW9uZGF5JywgJ1R1ZXNkYXknKSAqL1xuICByZWFkb25seSBkYXk6IE1haW50ZW5hbmNlRGF5O1xuICAvKiogVGltZSBvZiBkYXkgZm9yIG1haW50ZW5hbmNlIGluIEhIOk1NIGZvcm1hdCAoZS5nLiwgJzAyOjAwJykgKi9cbiAgcmVhZG9ubHkgdGltZTogc3RyaW5nO1xufVxuXG4vKipcbiAqIFByb3BlcnRpZXMgZm9yIGNyZWF0aW5nIGEgUm91dGVyIElucHV0XG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUm91dGVySW5wdXRQcm9wcyB7XG4gIC8qKlxuICAgKiBOYW1lIG9mIHRoZSBSb3V0ZXIgSW5wdXRcbiAgICogQGRlZmF1bHQgLSBHZW5lcmF0ZWQgYXV0b21hdGljYWxseVxuICAgKi9cbiAgcmVhZG9ubHkgcm91dGVySW5wdXROYW1lPzogc3RyaW5nO1xuICAvKiogTWF4aW11bSBiaXRyYXRlIGluIGJpdHMgcGVyIHNlY29uZCB0aGF0IHRoZSBSb3V0ZXIgSW5wdXQgY2FuIGhhbmRsZSAqL1xuICByZWFkb25seSBtYXhpbXVtQml0cmF0ZTogQml0cmF0ZTtcbiAgLyoqIFJvdXRpbmcgc2NvcGUgZm9yIHRoZSBSb3V0ZXIgSW5wdXQgKi9cbiAgcmVhZG9ubHkgcm91dGluZ1Njb3BlOiBSb3V0aW5nU2NvcGU7XG4gIC8qKlxuICAgKiBTZWxlY3QgYSB0aWVyIGJhc2VkIG9uIHlvdXIgbWF4aW11bSBiaXRyYXRlIHJlcXVpcmVtZW50cy5cbiAgICpcbiAgICogQGRlZmF1bHQgUm91dGVySW5wdXRUaWVyLklOUFVUXzIwXG4gICAqL1xuICByZWFkb25seSB0aWVyPzogUm91dGVySW5wdXRUaWVyO1xuICAvKiogQ29uZmlndXJhdGlvbiBmb3IgdGhlIFJvdXRlciBJbnB1dCAoc3RhbmRhcmQsIGZhaWxvdmVyLCBtZXJnZSwgb3IgTWVkaWFDb25uZWN0IGZsb3cpICovXG4gIHJlYWRvbmx5IGNvbmZpZ3VyYXRpb246IFJvdXRlcklucHV0Q29uZmlndXJhdGlvbjtcbiAgLyoqXG4gICAqIE1haW50ZW5hbmNlIHdpbmRvdyBjb25maWd1cmF0aW9uXG4gICAqIEBkZWZhdWx0IC0gRGVmYXVsdCBtYWludGVuYW5jZSB3aW5kb3cgd2lsbCBiZSB1c2VkXG4gICAqL1xuICByZWFkb25seSBtYWludGVuYW5jZUNvbmZpZ3VyYXRpb24/OiBNYWludGVuYW5jZUNvbmZpZ3VyYXRpb247XG4gIC8qKlxuICAgKiBBV1MgcmVnaW9uIHdoZXJlIHRoZSBSb3V0ZXIgSW5wdXQgd2lsbCBiZSBjcmVhdGVkIChpLmUuIHVzLWVhc3QtMSkuXG4gICAqXG4gICAqIE11c3QgbWF0Y2ggdGhlIHJlZ2lvbiBvZiB0aGUgZmxvd3MsIGZsb3cgb3V0cHV0cywgYW5kIG5ldHdvcmsgaW50ZXJmYWNlcyBpdCBjb25uZWN0cyB0byDigJRcbiAgICogTWVkaWFDb25uZWN0IHJlamVjdHMgYSBjcm9zcy1yZWdpb24gY29ubmVjdGlvbiBhdCBkZXBsb3kuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gU2FtZSBhcyB0aGUgc3RhY2sncyByZWdpb25cbiAgICovXG4gIHJlYWRvbmx5IHJlZ2lvbk5hbWU/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUYWdzIHRvIGFkZCB0byB0aGUgUm91dGVyIElucHV0XG4gICAqIEBkZWZhdWx0IC0gTm8gdGFnZ2luZ1xuICAgKi9cbiAgcmVhZG9ubHkgdGFncz86IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH07XG4gIC8qKlxuICAgKiBUcmFuc2l0IGVuY3J5cHRpb24gY29uZmlndXJhdGlvbiB1c2luZyBBV1MgU2VjcmV0cyBNYW5hZ2VyLlxuICAgKlxuICAgKiBXaGVuIHByb3ZpZGVkIHdpdGhvdXQgYSByb2xlLCBhIHNjb3BlZCBJQU0gcm9sZSBpcyBhdXRvbWF0aWNhbGx5IGNyZWF0ZWQgd2l0aCByZWFkXG4gICAqIGFjY2VzcyB0byB0aGUgc2VjcmV0LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIEF1dG9tYXRpYyBlbmNyeXB0aW9uIHdpbGwgYmUgY29uZmlndXJlZFxuICAgKi9cbiAgcmVhZG9ubHkgdHJhbnNpdEVuY3J5cHRpb24/OiBUcmFuc2l0RW5jcnlwdGlvbjtcbn1cblxuLyoqXG4gKiBBdHRyaWJ1dGVzIGZvciBpbXBvcnRpbmcgYW4gZXhpc3RpbmcgUm91dGVyIElucHV0LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJvdXRlcklucHV0QXR0cmlidXRlcyB7XG4gIC8qKlxuICAgKiBUaGUgQW1hem9uIFJlc291cmNlIE5hbWUgKEFSTikgb2YgdGhlIHJvdXRlciBpbnB1dC5cbiAgICovXG4gIHJlYWRvbmx5IHJvdXRlcklucHV0QXJuOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSB1bmlxdWUgaWRlbnRpZmllciBvZiB0aGUgcm91dGVyIGlucHV0LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGFjY2Vzc2luZyBgcm91dGVySW5wdXRJZGAgb24gdGhlIGltcG9ydGVkIGlucHV0IHRocm93czsgb25seSBwcm92aWRlIHdoZW4gYXZhaWxhYmxlLlxuICAgKi9cbiAgcmVhZG9ubHkgcm91dGVySW5wdXRJZD86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIElQIGFkZHJlc3MgdGhhdCB0aGUgcm91dGVyIGlucHV0IHVzZXMgdG8gaW5nZXN0IGNvbnRlbnQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gYWNjZXNzaW5nIGBpcEFkZHJlc3NgIG9uIHRoZSBpbXBvcnRlZCBpbnB1dCB0aHJvd3M7IG9ubHkgcHJvdmlkZSB3aGVuIGF2YWlsYWJsZS5cbiAgICovXG4gIHJlYWRvbmx5IGlwQWRkcmVzcz86IHN0cmluZztcbn1cblxuLyoqXG4gKiBGb3J3YXJkIEVycm9yIENvcnJlY3Rpb24gKEZFQykgb3B0aW9ucyBmb3IgUlRQIHByb3RvY29sXG4gKi9cbmV4cG9ydCBlbnVtIEZvcndhcmRFcnJvckNvcnJlY3Rpb24ge1xuICAvKiogRW5hYmxlIEZvcndhcmQgRXJyb3IgQ29ycmVjdGlvbiAqL1xuICBFTkFCTEVEPSdFTkFCTEVEJyxcbiAgLyoqIERpc2FibGUgRm9yd2FyZCBFcnJvciBDb3JyZWN0aW9uICovXG4gIERJU0FCTEVEPSdESVNBQkxFRCcsXG59XG5cbi8qKlxuICogSWRlbnRpZmllcyB3aGljaCBwcm90b2NvbCBpbiBhIGZhaWxvdmVyIGNvbmZpZ3VyYXRpb24ncyBwcm90b2NvbHMgYXJyYXkgaXMgcHJpbWFyeS5cbiAqL1xuZXhwb3J0IGVudW0gUHJpbWFyeVNvdXJjZSB7XG4gIC8qKiBUaGUgZmlyc3QgcHJvdG9jb2wgaW4gdGhlIGZhaWxvdmVyIHByb3RvY29scyBhcnJheS4gKi9cbiAgRklSU1RfU09VUkNFID0gMCxcbiAgLyoqIFRoZSBzZWNvbmQgcHJvdG9jb2wgaW4gdGhlIGZhaWxvdmVyIHByb3RvY29scyBhcnJheS4gKi9cbiAgU0VDT05EX1NPVVJDRSA9IDEsXG59XG5cbi8qKlxuICogSW50ZXJuYWwgQ0ZOLWxldmVsIHZhbHVlcyBmb3IgdGhlIHNvdXJjZSBwcmlvcml0eSBtb2RlLlxuICogQGludGVybmFsXG4gKi9cbmVudW0gU291cmNlUHJpb3JpdHlNb2RlIHtcbiAgLyoqIEJvdGggc291cmNlcyBhcmUgZXF1YWwgcHJpb3JpdHkg4oCUIHRoZSBzZXJ2aWNlIHBpY2tzIG9uZS4gKi9cbiAgTk9fUFJJT1JJVFkgPSAnTk9fUFJJT1JJVFknLFxuICAvKiogT25lIHNvdXJjZSBpcyBwcmltYXJ5LCB0aGUgb3RoZXIgaXMgYmFja3VwLiAqL1xuICBQUklNQVJZX1NFQ09OREFSWSA9ICdQUklNQVJZX1NFQ09OREFSWScsXG59XG5cbi8qKlxuICogU291cmNlIHByaW9yaXR5IGNvbmZpZ3VyYXRpb24gZm9yIGZhaWxvdmVyIFJvdXRlciBJbnB1dCBjb25maWd1cmF0aW9ucy5cbiAqL1xuZXhwb3J0IGNsYXNzIFNvdXJjZVByaW9yaXR5Q29uZmlnIHtcbiAgLyoqXG4gICAqIFRyZWF0IGJvdGggc291cmNlcyB3aXRoIGVxdWFsIHByaW9yaXR5IOKAlCBNZWRpYUNvbm5lY3QgcGlja3Mgb25lIHdoZW4gbmVlZGVkLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBub25lKCk6IFNvdXJjZVByaW9yaXR5Q29uZmlnIHtcbiAgICByZXR1cm4gbmV3IFNvdXJjZVByaW9yaXR5Q29uZmlnKFNvdXJjZVByaW9yaXR5TW9kZS5OT19QUklPUklUWSwgdW5kZWZpbmVkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXNpZ25hdGUgb25lIG9mIHRoZSB0d28gc291cmNlcyBhcyBwcmltYXJ5OyB0aGUgb3RoZXIgaXMgdHJlYXRlZCBhcyBiYWNrdXAuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHByaW1hcnlTZWNvbmRhcnkocHJpbWFyeTogUHJpbWFyeVNvdXJjZSk6IFNvdXJjZVByaW9yaXR5Q29uZmlnIHtcbiAgICByZXR1cm4gbmV3IFNvdXJjZVByaW9yaXR5Q29uZmlnKFNvdXJjZVByaW9yaXR5TW9kZS5QUklNQVJZX1NFQ09OREFSWSwgcHJpbWFyeSk7XG4gIH1cblxuICBwcml2YXRlIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgX21vZGU6IFNvdXJjZVByaW9yaXR5TW9kZSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9wcmltYXJ5OiBQcmltYXJ5U291cmNlIHwgdW5kZWZpbmVkLFxuICApIHt9XG5cbiAgLyoqXG4gICAqIFJlc29sdmUgdGhlIGNvbmZpZ3VyYXRpb24gdG8gaXRzIENGTiBzaGFwZS5cbiAgICogQGludGVybmFsXG4gICAqL1xuICBwdWJsaWMgX2JpbmQoKTogeyBzb3VyY2VQcmlvcml0eU1vZGU6IHN0cmluZzsgcHJpbWFyeVNvdXJjZUluZGV4PzogbnVtYmVyIH0ge1xuICAgIHJldHVybiB7XG4gICAgICBzb3VyY2VQcmlvcml0eU1vZGU6IHRoaXMuX21vZGUsXG4gICAgICBwcmltYXJ5U291cmNlSW5kZXg6IHRoaXMuX3ByaW1hcnksXG4gICAgfTtcbiAgfVxufVxuXG4vKipcbiAqIFByb3BlcnRpZXMgZm9yIFJUUCBwcm90b2NvbCBjb25maWd1cmF0aW9uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUnRwUHJvdG9jb2xQcm9wcyB7XG4gIC8qKiBQb3J0IG51bWJlciBmb3IgUlRQIHRyYWZmaWMgKi9cbiAgcmVhZG9ubHkgcG9ydDogbnVtYmVyO1xuICAvKipcbiAgICogRm9yd2FyZCBFcnJvciBDb3JyZWN0aW9uIHNldHRpbmdcbiAgICogQGRlZmF1bHQgLSB1bmRlZmluZWQ7IHdoZW4gb21pdHRlZCwgTWVkaWFDb25uZWN0IGFwcGxpZXMgRm9yd2FyZEVycm9yQ29ycmVjdGlvbi5ESVNBQkxFRCBhdCBkZXBsb3kgdGltZVxuICAgKi9cbiAgcmVhZG9ubHkgZm9yd2FyZEVycm9yQ29ycmVjdGlvbj86IEZvcndhcmRFcnJvckNvcnJlY3Rpb247XG59XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgUklTVCBwcm90b2NvbCBjb25maWd1cmF0aW9uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmlzdFByb3RvY29sUHJvcHMge1xuICAvKiogUG9ydCBudW1iZXIgZm9yIFJJU1QgdHJhZmZpYyAqL1xuICByZWFkb25seSBwb3J0OiBudW1iZXI7XG4gIC8qKiBSZWNvdmVyeSBsYXRlbmN5IGZvciBSSVNUICovXG4gIHJlYWRvbmx5IHJlY292ZXJ5TGF0ZW5jeTogRHVyYXRpb247XG59XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgU1JUIExpc3RlbmVyIHByb3RvY29sIGNvbmZpZ3VyYXRpb25cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTcnRMaXN0ZW5lclByb3RvY29sUHJvcHMge1xuICAvKiogUG9ydCBudW1iZXIgZm9yIFNSVCBsaXN0ZW5lciAqL1xuICByZWFkb25seSBwb3J0OiBudW1iZXI7XG4gIC8qKiBNaW5pbXVtIGxhdGVuY3kgZm9yIFNSVCAqL1xuICByZWFkb25seSBtaW5pbXVtTGF0ZW5jeTogRHVyYXRpb247XG4gIC8qKlxuICAgKiBPcHRpb25hbCBkZWNyeXB0aW9uIGNvbmZpZ3VyYXRpb24gZm9yIGVuY3J5cHRlZCBTUlQgc3RyZWFtc1xuICAgKiBAZGVmYXVsdCAtIE5vIGRlY3J5cHRpb25cbiAgICovXG4gIHJlYWRvbmx5IGRlY3J5cHRpb25Db25maWd1cmF0aW9uPzogUm91dGVyU3J0RW5jcnlwdGlvbjtcbn1cblxuLyoqXG4gKiBQcm9wZXJ0aWVzIGZvciBTUlQgQ2FsbGVyIHByb3RvY29sIGNvbmZpZ3VyYXRpb25cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTcnRDYWxsZXJQcm90b2NvbFByb3BzIHtcbiAgLyoqIFNvdXJjZSBJUCBhZGRyZXNzIHRvIGNvbm5lY3QgdG8gKi9cbiAgcmVhZG9ubHkgc291cmNlQWRkcmVzczogc3RyaW5nO1xuICAvKiogU291cmNlIHBvcnQgdG8gY29ubmVjdCB0byAqL1xuICByZWFkb25seSBzb3VyY2VQb3J0OiBudW1iZXI7XG4gIC8qKiBNaW5pbXVtIGxhdGVuY3kgZm9yIFNSVCAqL1xuICByZWFkb25seSBtaW5pbXVtTGF0ZW5jeTogRHVyYXRpb247XG4gIC8qKlxuICAgKiBPcHRpb25hbCBzdHJlYW0gSUQgZm9yIFNSVCBjb25uZWN0aW9uXG4gICAqIEBkZWZhdWx0IC0gTm8gc3RyZWFtIElEXG4gICAqL1xuICByZWFkb25seSBzdHJlYW1JZD86IHN0cmluZztcbiAgLyoqXG4gICAqIE9wdGlvbmFsIGRlY3J5cHRpb24gY29uZmlndXJhdGlvbiBmb3IgZW5jcnlwdGVkIFNSVCBzdHJlYW1zXG4gICAqIEBkZWZhdWx0IC0gTm8gZGVjcnlwdGlvblxuICAgKi9cbiAgcmVhZG9ubHkgZGVjcnlwdGlvbkNvbmZpZ3VyYXRpb24/OiBSb3V0ZXJTcnRFbmNyeXB0aW9uO1xufVxuXG4vKipcbiAqIElkZW50aWZpZXMgd2hpY2ggY29uZmlndXJhdGlvbiB0eXBlIGEgcG9ydCBjb25mbGljdCBjaGVjayBpcyBiZWluZyBwZXJmb3JtZWQgZm9yLlxuICogQGludGVybmFsXG4gKi9cbmVudW0gUHJvdG9jb2xDb25maWdUeXBlIHtcbiAgLyoqIEZhaWxvdmVyLW1vZGUgcm91dGVyIGlucHV0IGNvbmZpZ3VyYXRpb24uICovXG4gIEZBSUxPVkVSID0gJ2ZhaWxvdmVyJyxcbiAgLyoqIE1lcmdlLW1vZGUgcm91dGVyIGlucHV0IGNvbmZpZ3VyYXRpb24uICovXG4gIE1FUkdFID0gJ21lcmdlJyxcbn1cblxuLyoqXG4gKiBGYWN0b3J5IGNsYXNzIGZvciBjcmVhdGluZyBSb3V0ZXIgSW5wdXQgcHJvdG9jb2wgY29uZmlndXJhdGlvbnNcbiAqL1xuZXhwb3J0IGNsYXNzIFJvdXRlcklucHV0UHJvdG9jb2wge1xuICAvKipcbiAgICogQ3JlYXRlIGFuIFJUUCBwcm90b2NvbCBjb25maWd1cmF0aW9uXG4gICAqIEBwYXJhbSBwcm9wcyBSVFAgcHJvdG9jb2wgcHJvcGVydGllc1xuICAgKiBAcmV0dXJucyBSb3V0ZXJJbnB1dFByb3RvY29sIGluc3RhbmNlIGNvbmZpZ3VyZWQgZm9yIFJUUFxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBydHAocHJvcHM6IFJ0cFByb3RvY29sUHJvcHMpOiBSb3V0ZXJJbnB1dFByb3RvY29sIHtcbiAgICBSb3V0ZXJJbnB1dFByb3RvY29sLnZhbGlkYXRlUG9ydChwcm9wcy5wb3J0KTtcbiAgICByZXR1cm4gbmV3IFJvdXRlcklucHV0UHJvdG9jb2woUm91dGVySW5wdXRQcm90b2NvbE9wdGlvbnMuUlRQLCB7XG4gICAgICBydHA6IHtcbiAgICAgICAgcG9ydDogcHJvcHMucG9ydCxcbiAgICAgICAgZm9yd2FyZEVycm9yQ29ycmVjdGlvbjogcHJvcHMuZm9yd2FyZEVycm9yQ29ycmVjdGlvbixcbiAgICAgIH0sXG4gICAgfSwgcHJvcHMucG9ydCk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgUklTVCBwcm90b2NvbCBjb25maWd1cmF0aW9uXG4gICAqIEBwYXJhbSBwcm9wcyBSSVNUIHByb3RvY29sIHByb3BlcnRpZXNcbiAgICogQHJldHVybnMgUm91dGVySW5wdXRQcm90b2NvbCBpbnN0YW5jZSBjb25maWd1cmVkIGZvciBSSVNUXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHJpc3QocHJvcHM6IFJpc3RQcm90b2NvbFByb3BzKTogUm91dGVySW5wdXRQcm90b2NvbCB7XG4gICAgUm91dGVySW5wdXRQcm90b2NvbC52YWxpZGF0ZVBvcnQocHJvcHMucG9ydCk7XG4gICAgcmV0dXJuIG5ldyBSb3V0ZXJJbnB1dFByb3RvY29sKFJvdXRlcklucHV0UHJvdG9jb2xPcHRpb25zLlJJU1QsIHtcbiAgICAgIHJpc3Q6IHtcbiAgICAgICAgcG9ydDogcHJvcHMucG9ydCxcbiAgICAgICAgcmVjb3ZlcnlMYXRlbmN5TWlsbGlzZWNvbmRzOiBwcm9wcy5yZWNvdmVyeUxhdGVuY3kudG9NaWxsaXNlY29uZHMoKSxcbiAgICAgIH0sXG4gICAgfSwgcHJvcHMucG9ydCk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGFuIFNSVCBMaXN0ZW5lciBwcm90b2NvbCBjb25maWd1cmF0aW9uXG4gICAqIEBwYXJhbSBwcm9wcyBTUlQgTGlzdGVuZXIgcHJvdG9jb2wgcHJvcGVydGllc1xuICAgKiBAcmV0dXJucyBSb3V0ZXJJbnB1dFByb3RvY29sIGluc3RhbmNlIGNvbmZpZ3VyZWQgZm9yIFNSVCBMaXN0ZW5lclxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBzcnRMaXN0ZW5lcihwcm9wczogU3J0TGlzdGVuZXJQcm90b2NvbFByb3BzKTogUm91dGVySW5wdXRQcm90b2NvbCB7XG4gICAgUm91dGVySW5wdXRQcm90b2NvbC52YWxpZGF0ZVBvcnQocHJvcHMucG9ydCk7XG4gICAgcmV0dXJuIG5ldyBSb3V0ZXJJbnB1dFByb3RvY29sKFJvdXRlcklucHV0UHJvdG9jb2xPcHRpb25zLlNSVF9MSVNURU5FUiwge1xuICAgICAgc3J0TGlzdGVuZXI6IHtcbiAgICAgICAgcG9ydDogcHJvcHMucG9ydCxcbiAgICAgICAgbWluaW11bUxhdGVuY3lNaWxsaXNlY29uZHM6IHByb3BzLm1pbmltdW1MYXRlbmN5LnRvTWlsbGlzZWNvbmRzKCksXG4gICAgICB9LFxuICAgIH0sIHByb3BzLnBvcnQsIHByb3BzLmRlY3J5cHRpb25Db25maWd1cmF0aW9uKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYW4gU1JUIENhbGxlciBwcm90b2NvbCBjb25maWd1cmF0aW9uXG4gICAqIEBwYXJhbSBwcm9wcyBTUlQgQ2FsbGVyIHByb3RvY29sIHByb3BlcnRpZXNcbiAgICogQHJldHVybnMgUm91dGVySW5wdXRQcm90b2NvbCBpbnN0YW5jZSBjb25maWd1cmVkIGZvciBTUlQgQ2FsbGVyXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHNydENhbGxlcihwcm9wczogU3J0Q2FsbGVyUHJvdG9jb2xQcm9wcyk6IFJvdXRlcklucHV0UHJvdG9jb2wge1xuICAgIFJvdXRlcklucHV0UHJvdG9jb2wudmFsaWRhdGVTcnRDYWxsZXJQb3J0KHByb3BzLnNvdXJjZVBvcnQpO1xuICAgIHJldHVybiBuZXcgUm91dGVySW5wdXRQcm90b2NvbChSb3V0ZXJJbnB1dFByb3RvY29sT3B0aW9ucy5TUlRfQ0FMTEVSLCB7XG4gICAgICBzcnRDYWxsZXI6IHtcbiAgICAgICAgc291cmNlQWRkcmVzczogcHJvcHMuc291cmNlQWRkcmVzcyxcbiAgICAgICAgc291cmNlUG9ydDogcHJvcHMuc291cmNlUG9ydCxcbiAgICAgICAgbWluaW11bUxhdGVuY3lNaWxsaXNlY29uZHM6IHByb3BzLm1pbmltdW1MYXRlbmN5LnRvTWlsbGlzZWNvbmRzKCksXG4gICAgICAgIHN0cmVhbUlkOiBwcm9wcy5zdHJlYW1JZCxcbiAgICAgIH0sXG4gICAgfSwgdW5kZWZpbmVkLCBwcm9wcy5kZWNyeXB0aW9uQ29uZmlndXJhdGlvbik7XG4gIH1cblxuICAvKipcbiAgICogVmFsaWRhdGUgdGhhdCBwb3J0IGlzIHdpdGhpbiB0aGUgdmFsaWQgcmFuZ2UgKDMwMDAtMzAwMDApXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyB2YWxpZGF0ZVBvcnQocG9ydDogbnVtYmVyKTogdm9pZCB7XG4gICAgaWYgKCFUb2tlbi5pc1VucmVzb2x2ZWQocG9ydCkgJiYgKHBvcnQgPCAzMDAwIHx8IHBvcnQgPiAzMDAwMCkpIHtcbiAgICAgIHRocm93IG5ldyBVbnNjb3BlZFZhbGlkYXRpb25FcnJvcihsaXRgUm91dGVySW5wdXRQb3J0UmFuZ2VgLCBgUG9ydCBtdXN0IGJlIGJldHdlZW4gMzAwMCBhbmQgMzAwMDAsIGdvdCAke3BvcnR9YCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlIHRoYXQgU1JUIENhbGxlciBwb3J0IGlzIHdpdGhpbiB0aGUgdmFsaWQgcmFuZ2UgKDAtNjU1MzUpXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyB2YWxpZGF0ZVNydENhbGxlclBvcnQocG9ydDogbnVtYmVyKTogdm9pZCB7XG4gICAgaWYgKCFUb2tlbi5pc1VucmVzb2x2ZWQocG9ydCkgJiYgKHBvcnQgPCAwIHx8IHBvcnQgPiA2NTUzNSkpIHtcbiAgICAgIHRocm93IG5ldyBVbnNjb3BlZFZhbGlkYXRpb25FcnJvcihsaXRgU3J0Q2FsbGVyUG9ydFJhbmdlYCwgYFNSVCBDYWxsZXIgcG9ydCBtdXN0IGJlIGJldHdlZW4gMCBhbmQgNjU1MzUsIGdvdCAke3BvcnR9YCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBfcHJvdG9jb2xOYW1lOiBSb3V0ZXJJbnB1dFByb3RvY29sT3B0aW9ucztcbiAgcHJpdmF0ZSByZWFkb25seSBfY29uZmlnOiBDZm5Sb3V0ZXJJbnB1dC5Sb3V0ZXJJbnB1dFByb3RvY29sQ29uZmlndXJhdGlvblByb3BlcnR5O1xuICBwcml2YXRlIHJlYWRvbmx5IF9wb3J0PzogbnVtYmVyO1xuICBwcml2YXRlIHJlYWRvbmx5IF9kZWNyeXB0aW9uPzogUm91dGVyU3J0RW5jcnlwdGlvbjtcblxuICBwcml2YXRlIGNvbnN0cnVjdG9yKFxuICAgIHByb3RvY29sTmFtZTogUm91dGVySW5wdXRQcm90b2NvbE9wdGlvbnMsXG4gICAgY29uZmlnOiBDZm5Sb3V0ZXJJbnB1dC5Sb3V0ZXJJbnB1dFByb3RvY29sQ29uZmlndXJhdGlvblByb3BlcnR5LFxuICAgIHBvcnQ/OiBudW1iZXIsXG4gICAgZGVjcnlwdGlvbj86IFJvdXRlclNydEVuY3J5cHRpb24sXG4gICkge1xuICAgIHRoaXMuX3Byb3RvY29sTmFtZSA9IHByb3RvY29sTmFtZTtcbiAgICB0aGlzLl9jb25maWcgPSBjb25maWc7XG4gICAgdGhpcy5fcG9ydCA9IHBvcnQ7XG4gICAgdGhpcy5fZGVjcnlwdGlvbiA9IGRlY3J5cHRpb247XG4gIH1cblxuICAvKipcbiAgICogUmVzb2x2ZSB0aGlzIHByb3RvY29sIHRvIGl0cyBDRk4tcmVhZHkgZm9ybS4gUmV0dXJucyB0aGUgcHJvdG9jb2wgaWRlbnRpZmllcixcbiAgICogdGhlIENGTiBjb25maWd1cmF0aW9uIHNoYXBlICh3aXRoIFNSVCBkZWNyeXB0aW9uIGF1dG8tcm9sZSBtYXRlcmlhbGl6ZWQgaWYgbmVlZGVkKSxcbiAgICogYW5kIHRoZSBpbmdlc3QgcG9ydCBpZiB0aGUgcHJvdG9jb2wgaGFzIG9uZS5cbiAgICpcbiAgICogQHBhcmFtIHNjb3BlICAgICAgICAgQ29uc3RydWN0IHRoYXQgc2NvcGVzIHRoZSBhdXRvLWNyZWF0ZWQgZGVjcnlwdGlvbiByb2xlXG4gICAqIEBwYXJhbSByb3V0ZXJJbnB1dEFybiAgT3B0aW9uYWwgQVJOIG9mIHRoZSBjb25zdW1pbmcgcm91dGVyIGlucHV0IOKAlCB3aGVuIHByb3ZpZGVkLFxuICAgKiAgICAgICAgICAgICAgICAgICAgICAgIHNjb3BlcyB0aGUgYXV0by1jcmVhdGVkIGRlY3J5cHRpb24gcm9sZSdzIHRydXN0IHBvbGljeS5cbiAgICpcbiAgICogQGludGVybmFsXG4gICAqL1xuICBwdWJsaWMgX2JpbmQoc2NvcGU6IENvbnN0cnVjdCwgcm91dGVySW5wdXRBcm4/OiBzdHJpbmcpOiB7XG4gICAgbmFtZTogUm91dGVySW5wdXRQcm90b2NvbE9wdGlvbnM7XG4gICAgY29uZmlnOiBDZm5Sb3V0ZXJJbnB1dC5Sb3V0ZXJJbnB1dFByb3RvY29sQ29uZmlndXJhdGlvblByb3BlcnR5O1xuICAgIHBvcnQ/OiBudW1iZXI7XG4gIH0ge1xuICAgIGlmICghdGhpcy5fZGVjcnlwdGlvbikge1xuICAgICAgcmV0dXJuIHsgbmFtZTogdGhpcy5fcHJvdG9jb2xOYW1lLCBjb25maWc6IHRoaXMuX2NvbmZpZywgcG9ydDogdGhpcy5fcG9ydCB9O1xuICAgIH1cblxuICAgIGNvbnN0IGRlY3J5cHRpb25Db25maWd1cmF0aW9uID0gcmVuZGVyUm91dGVyU3J0RW5jcnlwdGlvbihzY29wZSwgJ0RlY3J5cHRpb25Sb2xlJywgdGhpcy5fZGVjcnlwdGlvbiwgcm91dGVySW5wdXRBcm4pO1xuXG4gICAgaWYgKHRoaXMuX2NvbmZpZy5zcnRMaXN0ZW5lcikge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgbmFtZTogdGhpcy5fcHJvdG9jb2xOYW1lLFxuICAgICAgICBwb3J0OiB0aGlzLl9wb3J0LFxuICAgICAgICBjb25maWc6IHsgc3J0TGlzdGVuZXI6IHsgLi4udGhpcy5fY29uZmlnLnNydExpc3RlbmVyLCBkZWNyeXB0aW9uQ29uZmlndXJhdGlvbiB9IH0sXG4gICAgICB9O1xuICAgIH1cbiAgICBpZiAodGhpcy5fY29uZmlnLnNydENhbGxlcikge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgbmFtZTogdGhpcy5fcHJvdG9jb2xOYW1lLFxuICAgICAgICBwb3J0OiB0aGlzLl9wb3J0LFxuICAgICAgICBjb25maWc6IHsgc3J0Q2FsbGVyOiB7IC4uLnRoaXMuX2NvbmZpZy5zcnRDYWxsZXIsIGRlY3J5cHRpb25Db25maWd1cmF0aW9uIH0gfSxcbiAgICAgIH07XG4gICAgfVxuICAgIHJldHVybiB7IG5hbWU6IHRoaXMuX3Byb3RvY29sTmFtZSwgY29uZmlnOiB0aGlzLl9jb25maWcsIHBvcnQ6IHRoaXMuX3BvcnQgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb21wdXRlIHRoZSBpbmdlc3QgVVJMIChzY2hlbWU6Ly9pcEFkZHJlc3M6cG9ydCkgZm9yIHRoaXMgcHJvdG9jb2wsIGlmIGl0IGhhc1xuICAgKiBhIGxpc3RlbmluZyBwb3J0LlxuICAgKlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIHB1YmxpYyBfaW5nZXN0VXJsKGlwQWRkcmVzczogc3RyaW5nKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAodGhpcy5fcG9ydCA9PT0gdW5kZWZpbmVkKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIHJldHVybiByZW5kZXJJbmdlc3RVcmwodGhpcy5fcHJvdG9jb2xOYW1lLnZhbHVlLCB0aGlzLl9wb3J0LCBpcEFkZHJlc3MpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBsaXN0ZW5pbmcgcG9ydCBmb3IgdGhpcyBwcm90b2NvbCwgaWYgaXQgaGFzIG9uZS4gVW5kZWZpbmVkIGZvciBTUlQgY2FsbGVyXG4gICAqICh3aGljaCBoYXMgYSBgc291cmNlUG9ydGAgcG9pbnRpbmcgYXQgdGhlIHVwc3RyZWFtIGxpc3RlbmVyLCBub3QgYSBwb3J0IHRoZSBpbnB1dFxuICAgKiBpdHNlbGYgbGlzdGVucyBvbikuXG4gICAqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHVibGljIF9saXN0ZW5pbmdQb3J0KCk6IG51bWJlciB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuX3BvcnQ7XG4gIH1cblxuICAvKipcbiAgICogV2hldGhlciB0d28gcHJvdG9jb2xzIHNoYXJlIHRoZSBzYW1lIHByb3RvY29sIGlkZW50aWZpZXIuXG4gICAqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHVibGljIF9tYXRjaGVzS2luZChvdGhlcjogUm91dGVySW5wdXRQcm90b2NvbCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9wcm90b2NvbE5hbWUudmFsdWUgPT09IG90aGVyLl9wcm90b2NvbE5hbWUudmFsdWU7XG4gIH1cblxuICAvKipcbiAgICogV2hldGhlciB0aGlzIHByb3RvY29sIGlzIFNSVCAoQ2FsbGVyIG9yIExpc3RlbmVyKS5cbiAgICpcbiAgICogQGludGVybmFsXG4gICAqL1xuICBwdWJsaWMgX2lzU3J0KCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9wcm90b2NvbE5hbWUudmFsdWUgPT09IFJvdXRlcklucHV0UHJvdG9jb2xPcHRpb25zLlNSVF9DQUxMRVIudmFsdWVcbiAgICAgIHx8IHRoaXMuX3Byb3RvY29sTmFtZS52YWx1ZSA9PT0gUm91dGVySW5wdXRQcm90b2NvbE9wdGlvbnMuU1JUX0xJU1RFTkVSLnZhbHVlO1xuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlIHBvcnQgY29tcGF0aWJpbGl0eSBiZXR3ZWVuIHRoaXMgcHJvdG9jb2wgYW5kIGFub3RoZXIgaW4gYSBmYWlsb3ZlciBvclxuICAgKiBtZXJnZSBjb25maWd1cmF0aW9uLiBUaHJvd3Mgb24gY29uZmxpY3RzIGFwcHJvcHJpYXRlIHRvIHRoZSBwcm90b2NvbCBraW5kLlxuICAgKlxuICAgKiBAaW50ZXJuYWxcbiAgICovXG4gIHB1YmxpYyBfdmFsaWRhdGVQb3J0Q29uZmxpY3RzKG90aGVyOiBSb3V0ZXJJbnB1dFByb3RvY29sLCBjb25maWdUeXBlOiBQcm90b2NvbENvbmZpZ1R5cGUpOiB2b2lkIHtcbiAgICBjb25zdCBwcm90b2NvbFZhbHVlID0gdGhpcy5fcHJvdG9jb2xOYW1lLnZhbHVlO1xuXG4gICAgaWYgKHByb3RvY29sVmFsdWUgPT09IFJvdXRlcklucHV0UHJvdG9jb2xPcHRpb25zLlJJU1QudmFsdWUpIHtcbiAgICAgIGNvbnN0IHJpc3QxID0gdGhpcy5fY29uZmlnLnJpc3Q7XG4gICAgICBjb25zdCByaXN0MiA9IG90aGVyLl9jb25maWcucmlzdDtcbiAgICAgIGlmIChyaXN0MSAmJiByaXN0MiAmJiAncG9ydCcgaW4gcmlzdDEgJiYgJ3BvcnQnIGluIHJpc3QyKSB7XG4gICAgICAgIGNvbnN0IHBvcnQxID0gcmlzdDEucG9ydDtcbiAgICAgICAgY29uc3QgcG9ydDIgPSByaXN0Mi5wb3J0O1xuICAgICAgICBpZiAocG9ydDEgPT09IHBvcnQyKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IFVuc2NvcGVkVmFsaWRhdGlvbkVycm9yKFxuICAgICAgICAgICAgbGl0YER1cGxpY2F0ZVJpc3RQb3J0YCxcbiAgICAgICAgICAgIGAke2NvbmZpZ1R5cGV9IGNvbmZpZ3VyYXRpb24gY2Fubm90IHVzZSB0aGUgc2FtZSBSSVNUIHBvcnQgJHtwb3J0MX0gZm9yIGJvdGggcHJvdG9jb2xzLCBgICtcbiAgICAgICAgICAgICdlYWNoIHByb3RvY29sIG11c3QgdXNlIGEgZGlmZmVyZW50IHBvcnQgbnVtYmVyJyxcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIGlmIChNYXRoLmFicyhwb3J0MSAtIHBvcnQyKSA8IDIpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgVW5zY29wZWRWYWxpZGF0aW9uRXJyb3IoXG4gICAgICAgICAgICBsaXRgQ29uc2VjdXRpdmVSaXN0UG9ydGAsXG4gICAgICAgICAgICBgJHtjb25maWdUeXBlfSBjb25maWd1cmF0aW9uIGNhbm5vdCB1c2UgY29uc2VjdXRpdmUgUklTVCBwb3J0cyAke01hdGgubWluKHBvcnQxLCBwb3J0Mil9IGFuZCAke01hdGgubWF4KHBvcnQxLCBwb3J0Mil9LCBgICtcbiAgICAgICAgICAgICdSSVNUIHByb3RvY29scyByZXF1aXJlIG5vbi1jb25zZWN1dGl2ZSBwb3J0cyB0byBhdm9pZCBvdmVybGFwcGluZyByYW5nZXMgKGUuZy4sIHVzZSA2MDAwIGFuZCA2MDAyKScsXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChwcm90b2NvbFZhbHVlID09PSBSb3V0ZXJJbnB1dFByb3RvY29sT3B0aW9ucy5SVFAudmFsdWUpIHtcbiAgICAgIGNvbnN0IHJ0cDEgPSB0aGlzLl9jb25maWcucnRwO1xuICAgICAgY29uc3QgcnRwMiA9IG90aGVyLl9jb25maWcucnRwO1xuICAgICAgaWYgKHJ0cDEgJiYgcnRwMiAmJiAncG9ydCcgaW4gcnRwMSAmJiAncG9ydCcgaW4gcnRwMiAmJiBydHAxLnBvcnQgPT09IHJ0cDIucG9ydCkge1xuICAgICAgICB0aHJvdyBuZXcgVW5zY29wZWRWYWxpZGF0aW9uRXJyb3IoXG4gICAgICAgICAgbGl0YER1cGxpY2F0ZVJ0cFBvcnRgLFxuICAgICAgICAgIGAke2NvbmZpZ1R5cGV9IGNvbmZpZ3VyYXRpb24gY2Fubm90IHVzZSB0aGUgc2FtZSBSVFAgcG9ydCAke3J0cDEucG9ydH0gZm9yIGJvdGggcHJvdG9jb2xzLCBgICtcbiAgICAgICAgICAnZWFjaCBwcm90b2NvbCBtdXN0IHVzZSBhIGRpZmZlcmVudCBwb3J0IG51bWJlcicsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHByb3RvY29sVmFsdWUgPT09IFJvdXRlcklucHV0UHJvdG9jb2xPcHRpb25zLlNSVF9MSVNURU5FUi52YWx1ZSkge1xuICAgICAgY29uc3Qgc3J0MSA9IHRoaXMuX2NvbmZpZy5zcnRMaXN0ZW5lcjtcbiAgICAgIGNvbnN0IHNydDIgPSBvdGhlci5fY29uZmlnLnNydExpc3RlbmVyO1xuICAgICAgaWYgKHNydDEgJiYgc3J0MiAmJiAncG9ydCcgaW4gc3J0MSAmJiAncG9ydCcgaW4gc3J0MiAmJiBzcnQxLnBvcnQgPT09IHNydDIucG9ydCkge1xuICAgICAgICB0aHJvdyBuZXcgVW5zY29wZWRWYWxpZGF0aW9uRXJyb3IoXG4gICAgICAgICAgbGl0YER1cGxpY2F0ZVNydExpc3RlbmVyUG9ydGAsXG4gICAgICAgICAgYCR7Y29uZmlnVHlwZX0gY29uZmlndXJhdGlvbiBjYW5ub3QgdXNlIHRoZSBzYW1lIFNSVCBMaXN0ZW5lciBwb3J0ICR7c3J0MS5wb3J0fSBmb3IgYm90aCBwcm90b2NvbHMsIGAgK1xuICAgICAgICAgICdlYWNoIHByb3RvY29sIG11c3QgdXNlIGEgZGlmZmVyZW50IHBvcnQgbnVtYmVyJyxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuLyoqXG4gKiBQcm9wZXJ0aWVzIGZvciBzdGFuZGFyZCBSb3V0ZXIgSW5wdXQgY29uZmlndXJhdGlvblxuICovXG5leHBvcnQgaW50ZXJmYWNlIFN0YW5kYXJkQ29uZmlndXJhdGlvblByb3BzIHtcbiAgLyoqIE5ldHdvcmsgaW50ZXJmYWNlIGZvciB0aGUgUm91dGVyIElucHV0ICovXG4gIHJlYWRvbmx5IG5ldHdvcmtJbnRlcmZhY2U6IElSb3V0ZXJOZXR3b3JrSW50ZXJmYWNlO1xuICAvKiogUHJvdG9jb2wgY29uZmlndXJhdGlvbiBmb3IgdGhlIGlucHV0ICovXG4gIHJlYWRvbmx5IHByb3RvY29sOiBSb3V0ZXJJbnB1dFByb3RvY29sO1xufVxuXG4vKipcbiAqIFByb3BlcnRpZXMgZm9yIGZhaWxvdmVyIFJvdXRlciBJbnB1dCBjb25maWd1cmF0aW9uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRmFpbG92ZXJDb25maWd1cmF0aW9uUHJvcHMge1xuICAvKiogTmV0d29yayBpbnRlcmZhY2UgZm9yIHRoZSBSb3V0ZXIgSW5wdXQgKi9cbiAgcmVhZG9ubHkgbmV0d29ya0ludGVyZmFjZTogSVJvdXRlck5ldHdvcmtJbnRlcmZhY2U7XG4gIC8qKiBBcnJheSBvZiBleGFjdGx5IDIgcHJvdG9jb2wgY29uZmlndXJhdGlvbnMgZm9yIGZhaWxvdmVyIChtdXN0IGJlIHNhbWUgcHJvdG9jb2wgdHlwZSkgKi9cbiAgcmVhZG9ubHkgcHJvdG9jb2xzOiBSb3V0ZXJJbnB1dFByb3RvY29sW107XG4gIC8qKlxuICAgKiBTb3VyY2UgcHJpb3JpdHkgY29uZmlndXJhdGlvbiBmb3IgZmFpbG92ZXIuXG4gICAqXG4gICAqIEBkZWZhdWx0IFNvdXJjZVByaW9yaXR5Q29uZmlnLm5vbmUoKVxuICAgKi9cbiAgcmVhZG9ubHkgc291cmNlUHJpb3JpdHk/OiBTb3VyY2VQcmlvcml0eUNvbmZpZztcbn1cblxuLyoqXG4gKiBQcm9wZXJ0aWVzIGZvciBtZXJnZSBSb3V0ZXIgSW5wdXQgY29uZmlndXJhdGlvblxuICovXG5leHBvcnQgaW50ZXJmYWNlIE1lcmdlQ29uZmlndXJhdGlvblByb3BzIHtcbiAgLyoqIE5ldHdvcmsgaW50ZXJmYWNlIGZvciB0aGUgUm91dGVyIElucHV0ICovXG4gIHJlYWRvbmx5IG5ldHdvcmtJbnRlcmZhY2U6IElSb3V0ZXJOZXR3b3JrSW50ZXJmYWNlO1xuICAvKiogQXJyYXkgb2YgZXhhY3RseSAyIHByb3RvY29sIGNvbmZpZ3VyYXRpb25zIGZvciBtZXJnZSAobXVzdCBiZSBzYW1lIG5vbi1TUlQgcHJvdG9jb2wgdHlwZSkgKi9cbiAgcmVhZG9ubHkgcHJvdG9jb2xzOiBSb3V0ZXJJbnB1dFByb3RvY29sW107XG4gIC8qKiBSZWNvdmVyeSB3aW5kb3cgZm9yIG1lcmdlIG9wZXJhdGlvbiAqL1xuICByZWFkb25seSBtZXJnZVJlY292ZXJ5V2luZG93OiBEdXJhdGlvbjtcbn1cblxuLyoqXG4gKiBQcm9wZXJ0aWVzIGZvciBNZWRpYUNvbm5lY3QgRmxvdyBSb3V0ZXIgSW5wdXQgY29uZmlndXJhdGlvblxuICovXG5leHBvcnQgaW50ZXJmYWNlIE1lZGlhQ29ubmVjdEZsb3dDb25maWd1cmF0aW9uUHJvcHMge1xuICAvKiogVGhlIE1lZGlhQ29ubmVjdCBmbG93IHRvIHVzZSBhcyBpbnB1dCAqL1xuICByZWFkb25seSBmbG93OiBJRmxvdztcbiAgLyoqIFRoZSBmbG93IG91dHB1dCB0aGF0IGZlZWRzIHRoaXMgcm91dGVyIGlucHV0ICovXG4gIHJlYWRvbmx5IGZsb3dPdXRwdXQ6IElGbG93T3V0cHV0O1xuICAvKipcbiAgICogT3B0aW9uYWwgdHJhbnNpdCBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb25cbiAgICogQGRlZmF1bHQgLSBBdXRvbWF0aWMgZW5jcnlwdGlvbiB3aWxsIGJlIHVzZWRcbiAgICovXG4gIHJlYWRvbmx5IHNvdXJjZVRyYW5zaXREZWNyeXB0aW9uPzogVHJhbnNpdEVuY3J5cHRpb247XG59XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgTWVkaWFDb25uZWN0IEZsb3cgUm91dGVyIElucHV0IGNvbmZpZ3VyYXRpb24gLSB3aXRob3V0IGEgY29ubmVjdGlvblxuICovXG5leHBvcnQgaW50ZXJmYWNlIE1lZGlhQ29ubmVjdEZsb3dDb25maWd1cmF0aW9uV2l0aG91dENvbm5lY3Rpb25Qcm9wcyB7XG4gIC8qKlxuICAgKiBBdmFpbGFiaWxpdHkgWm9uZSB0aGUgcm91dGVyIGlucHV0IHdpbGwgYmUgcGxhY2VkIGluLlxuICAgKi9cbiAgcmVhZG9ubHkgYXZhaWxhYmlsaXR5Wm9uZTogc3RyaW5nO1xuICAvKipcbiAgICogT3B0aW9uYWwgdHJhbnNpdCBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb25cbiAgICogQGRlZmF1bHQgLSBBdXRvbWF0aWMgZW5jcnlwdGlvbiB3aWxsIGJlIHVzZWRcbiAgICovXG4gIHJlYWRvbmx5IHNvdXJjZVRyYW5zaXREZWNyeXB0aW9uPzogVHJhbnNpdEVuY3J5cHRpb247XG59XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgTWVkaWFMaXZlIENoYW5uZWwgUm91dGVyIElucHV0IGNvbmZpZ3VyYXRpb24uXG4gKlxuICogVXNlIHRoaXMgd2hlbiB0aGUgTWVkaWFMaXZlIGNoYW5uZWwgYWxyZWFkeSBleGlzdHMgYW5kIHlvdSB3YW50IHRvIGluZ2VzdFxuICogZnJvbSBvbmUgb2YgaXRzIG91dHB1dHMgaW1tZWRpYXRlbHkuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTWVkaWFMaXZlQ2hhbm5lbENvbmZpZ3VyYXRpb25Qcm9wcyB7XG4gIC8qKlxuICAgKiBBUk4gb2YgdGhlIE1lZGlhTGl2ZSBjaGFubmVsIHRvIHVzZSBhcyBpbnB1dC5cbiAgICpcbiAgICogTm90ZTogVGhpcyB3aWxsIGNoYW5nZSB0byBhY2NlcHQgYSB0eXBlZCBNZWRpYUxpdmUgY2hhbm5lbCByZWZlcmVuY2VcbiAgICogd2hlbiB0aGUgQGF3cy1jZGsvYXdzLW1lZGlhbGl2ZS1hbHBoYSBMMiBjb25zdHJ1Y3QgaXMgcmVsZWFzZWQuXG4gICAqL1xuICByZWFkb25seSBtZWRpYUxpdmVDaGFubmVsQXJuOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIHRoZSBNZWRpYUxpdmUgY2hhbm5lbCBvdXRwdXQgdG8gY29ubmVjdCB0byB0aGlzIHJvdXRlciBpbnB1dC5cbiAgICovXG4gIHJlYWRvbmx5IG1lZGlhTGl2ZUNoYW5uZWxPdXRwdXROYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBNZWRpYUxpdmUgcGlwZWxpbmUgdG8gY29ubmVjdCB0byB0aGlzIHJvdXRlciBpbnB1dC5cbiAgICovXG4gIHJlYWRvbmx5IG1lZGlhTGl2ZVBpcGVsaW5lSWQ6IE1lZGlhTGl2ZVBpcGVsaW5lO1xuXG4gIC8qKlxuICAgKiBPcHRpb25hbCB0cmFuc2l0IGVuY3J5cHRpb24gY29uZmlndXJhdGlvbi5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBBdXRvbWF0aWMgZW5jcnlwdGlvbiB3aWxsIGJlIHVzZWRcbiAgICovXG4gIHJlYWRvbmx5IHNvdXJjZVRyYW5zaXREZWNyeXB0aW9uPzogVHJhbnNpdEVuY3J5cHRpb247XG59XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgTWVkaWFMaXZlIENoYW5uZWwgUm91dGVyIElucHV0IGNvbmZpZ3VyYXRpb24gd2l0aG91dCBhIHNwZWNpZmljIGNoYW5uZWwgY29ubmVjdGlvbi5cbiAqXG4gKiBVc2UgdGhpcyB3aGVuIHlvdSB3YW50IHRvIHNldCB1cCB0aGUgcm91dGVyIGlucHV0IGJlZm9yZSB0aGUgdGFyZ2V0IE1lZGlhTGl2ZSBjaGFubmVsIGV4aXN0cy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBNZWRpYUxpdmVDaGFubmVsQ29uZmlndXJhdGlvbldpdGhvdXRDb25uZWN0aW9uUHJvcHMge1xuICAvKipcbiAgICogQXZhaWxhYmlsaXR5IFpvbmUgdGhlIHJvdXRlciBpbnB1dCB3aWxsIGJlIHBsYWNlZCBpbi5cbiAgICovXG4gIHJlYWRvbmx5IGF2YWlsYWJpbGl0eVpvbmU6IHN0cmluZztcblxuICAvKipcbiAgICogT3B0aW9uYWwgdHJhbnNpdCBlbmNyeXB0aW9uIGNvbmZpZ3VyYXRpb24uXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gQXV0b21hdGljIGVuY3J5cHRpb24gd2lsbCBiZSB1c2VkXG4gICAqL1xuICByZWFkb25seSBzb3VyY2VUcmFuc2l0RGVjcnlwdGlvbj86IFRyYW5zaXRFbmNyeXB0aW9uO1xufVxuXG4vKipcbiAqIEZhY3RvcnkgY2xhc3MgZm9yIGNyZWF0aW5nIFJvdXRlciBJbnB1dCBjb25maWd1cmF0aW9uc1xuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgUm91dGVySW5wdXRDb25maWd1cmF0aW9uIHtcbiAgLyoqXG4gICAqIENyZWF0ZSBhIHN0YW5kYXJkIFJvdXRlciBJbnB1dCBjb25maWd1cmF0aW9uIHdpdGggYSBzaW5nbGUgcHJvdG9jb2xcbiAgICogQHBhcmFtIHByb3BzIFN0YW5kYXJkIGNvbmZpZ3VyYXRpb24gcHJvcGVydGllc1xuICAgKiBAcmV0dXJucyBSb3V0ZXJJbnB1dENvbmZpZ3VyYXRpb24gaW5zdGFuY2UgZm9yIHN0YW5kYXJkIHNldHVwXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHN0YW5kYXJkKHByb3BzOiBTdGFuZGFyZENvbmZpZ3VyYXRpb25Qcm9wcyk6IFJvdXRlcklucHV0Q29uZmlndXJhdGlvbiB7XG4gICAgcmV0dXJuIG5ldyBTdGFuZGFyZFJvdXRlcklucHV0Q29uZmlnKHByb3BzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBmYWlsb3ZlciBSb3V0ZXIgSW5wdXQgY29uZmlndXJhdGlvbiB3aXRoIHR3byBtYXRjaGluZyBwcm90b2NvbHNcbiAgICogQHBhcmFtIHByb3BzIEZhaWxvdmVyIGNvbmZpZ3VyYXRpb24gcHJvcGVydGllc1xuICAgKiBAcmV0dXJucyBSb3V0ZXJJbnB1dENvbmZpZ3VyYXRpb24gaW5zdGFuY2UgZm9yIGZhaWxvdmVyIHNldHVwXG4gICAqIEB0aHJvd3MgRXJyb3IgaWYgcHJvdG9jb2xzIGRvbid0IG1hdGNoIG9yIGNvdW50IGlzIG5vdCBleGFjdGx5IDJcbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZmFpbG92ZXIocHJvcHM6IEZhaWxvdmVyQ29uZmlndXJhdGlvblByb3BzKTogUm91dGVySW5wdXRDb25maWd1cmF0aW9uIHtcbiAgICBpZiAoIVRva2VuLmlzVW5yZXNvbHZlZChwcm9wcy5wcm90b2NvbHMpICYmIHByb3BzLnByb3RvY29scy5sZW5ndGggIT09IDIpIHtcbiAgICAgIHRocm93IG5ldyBVbnNjb3BlZFZhbGlkYXRpb25FcnJvcihsaXRgRmFpbG92ZXJQcm90b2NvbENvdW50YCwgYEZhaWxvdmVyIGNvbmZpZ3VyYXRpb24gcmVxdWlyZXMgZXhhY3RseSAyIHByb3RvY29scywgZ290ICR7cHJvcHMucHJvdG9jb2xzLmxlbmd0aH1gKTtcbiAgICB9XG4gICAgaWYgKCFwcm9wcy5wcm90b2NvbHNbMF0uX21hdGNoZXNLaW5kKHByb3BzLnByb3RvY29sc1sxXSkpIHtcbiAgICAgIHRocm93IG5ldyBVbnNjb3BlZFZhbGlkYXRpb25FcnJvcihsaXRgRmFpbG92ZXJQcm90b2NvbE1pc21hdGNoYCwgJ1Byb3RvY29scyBtdXN0IG1hdGNoJyk7XG4gICAgfVxuICAgIHByb3BzLnByb3RvY29sc1swXS5fdmFsaWRhdGVQb3J0Q29uZmxpY3RzKHByb3BzLnByb3RvY29sc1sxXSwgUHJvdG9jb2xDb25maWdUeXBlLkZBSUxPVkVSKTtcbiAgICByZXR1cm4gbmV3IEZhaWxvdmVyUm91dGVySW5wdXRDb25maWcocHJvcHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIG1lcmdlIFJvdXRlciBJbnB1dCBjb25maWd1cmF0aW9uIHdpdGggdHdvIG1hdGNoaW5nIG5vbi1TUlQgcHJvdG9jb2xzXG4gICAqIEBwYXJhbSBwcm9wcyBNZXJnZSBjb25maWd1cmF0aW9uIHByb3BlcnRpZXNcbiAgICogQHJldHVybnMgUm91dGVySW5wdXRDb25maWd1cmF0aW9uIGluc3RhbmNlIGZvciBtZXJnZSBzZXR1cFxuICAgKiBAdGhyb3dzIEVycm9yIGlmIHByb3RvY29scyBkb24ndCBtYXRjaCwgY291bnQgaXMgbm90IGV4YWN0bHkgMiwgb3IgU1JUIHByb3RvY29scyBhcmUgdXNlZFxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBtZXJnZShwcm9wczogTWVyZ2VDb25maWd1cmF0aW9uUHJvcHMpOiBSb3V0ZXJJbnB1dENvbmZpZ3VyYXRpb24ge1xuICAgIGlmICghVG9rZW4uaXNVbnJlc29sdmVkKHByb3BzLnByb3RvY29scykgJiYgcHJvcHMucHJvdG9jb2xzLmxlbmd0aCAhPT0gMikge1xuICAgICAgdGhyb3cgbmV3IFVuc2NvcGVkVmFsaWRhdGlvbkVycm9yKGxpdGBNZXJnZVByb3RvY29sQ291bnRgLCBgTWVyZ2UgY29uZmlndXJhdGlvbiByZXF1aXJlcyBleGFjdGx5IDIgcHJvdG9jb2xzLCBnb3QgJHtwcm9wcy5wcm90b2NvbHMubGVuZ3RofWApO1xuICAgIH1cbiAgICBpZiAocHJvcHMucHJvdG9jb2xzLnNvbWUocCA9PiBwLl9pc1NydCgpKSkge1xuICAgICAgdGhyb3cgbmV3IFVuc2NvcGVkVmFsaWRhdGlvbkVycm9yKGxpdGBNZXJnZVNydE5vdFN1cHBvcnRlZGAsICdTUlQgcHJvdG9jb2xzIGFyZSBub3Qgc3VwcG9ydGVkIGluIG1lcmdlIGNvbmZpZ3VyYXRpb24nKTtcbiAgICB9XG4gICAgaWYgKCFwcm9wcy5wcm90b2NvbHNbMF0uX21hdGNoZXNLaW5kKHByb3BzLnByb3RvY29sc1sxXSkpIHtcbiAgICAgIHRocm93IG5ldyBVbnNjb3BlZFZhbGlkYXRpb25FcnJvcihsaXRgTWVyZ2VQcm90b2NvbE1pc21hdGNoYCwgJ1Byb3RvY29scyBtdXN0IG1hdGNoJyk7XG4gICAgfVxuICAgIHByb3BzLnByb3RvY29sc1swXS5fdmFsaWRhdGVQb3J0Q29uZmxpY3RzKHByb3BzLnByb3RvY29sc1sxXSwgUHJvdG9jb2xDb25maWdUeXBlLk1FUkdFKTtcbiAgICByZXR1cm4gbmV3IE1lcmdlUm91dGVySW5wdXRDb25maWcocHJvcHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIE1lZGlhQ29ubmVjdCBGbG93IFJvdXRlciBJbnB1dCBjb25maWd1cmF0aW9uIHdpdGhvdXQgY29ubmVjdGluZyB0byBhIHNwZWNpZmljIGZsb3dcbiAgICogVXNlIHRoaXMgd2hlbiB5b3Ugd2FudCB0byBwcmVwYXJlIHRoZSByb3V0ZXIgaW5wdXQgZm9yIGEgZmxvdyBjb25uZWN0aW9uIGxhdGVyXG4gICAqIEBwYXJhbSBwcm9wcyBNZWRpYUNvbm5lY3QgRmxvdyBjb25maWd1cmF0aW9uIHByb3BlcnRpZXMgd2l0aG91dCBjb25uZWN0aW9uXG4gICAqIEByZXR1cm5zIFJvdXRlcklucHV0Q29uZmlndXJhdGlvbiBpbnN0YW5jZSBmb3IgTWVkaWFDb25uZWN0IEZsb3cgc2V0dXAgd2l0aG91dCBjb25uZWN0aW9uXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIG1lZGlhQ29ubmVjdEZsb3dXaXRob3V0Q29ubmVjdGlvbihwcm9wczogTWVkaWFDb25uZWN0Rmxvd0NvbmZpZ3VyYXRpb25XaXRob3V0Q29ubmVjdGlvblByb3BzKTogUm91dGVySW5wdXRDb25maWd1cmF0aW9uIHtcbiAgICByZXR1cm4gbmV3IE1lZGlhQ29ubmVjdEZsb3dSb3V0ZXJJbnB1dENvbmZpZyh7IHNvdXJjZVRyYW5zaXREZWNyeXB0aW9uOiBwcm9wcy5zb3VyY2VUcmFuc2l0RGVjcnlwdGlvbiB9LCBwcm9wcy5hdmFpbGFiaWxpdHlab25lKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBNZWRpYUNvbm5lY3QgRmxvdyBSb3V0ZXIgSW5wdXQgY29uZmlndXJhdGlvbi5cbiAgICpcbiAgICogVXNlIHRoaXMgd2hlbiB0aGUgc291cmNlIGZsb3cgYWxyZWFkeSBleGlzdHMgYW5kIHlvdSB3YW50IHRvIGNvbm5lY3QgaW1tZWRpYXRlbHkuXG4gICAqXG4gICAqIEBwYXJhbSBwcm9wcyBNZWRpYUNvbm5lY3QgRmxvdyBjb25maWd1cmF0aW9uIHByb3BlcnRpZXNcbiAgICogQHJldHVybnMgUm91dGVySW5wdXRDb25maWd1cmF0aW9uIGluc3RhbmNlIGZvciBNZWRpYUNvbm5lY3QgRmxvdyBzZXR1cFxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBtZWRpYUNvbm5lY3RGbG93KHByb3BzOiBNZWRpYUNvbm5lY3RGbG93Q29uZmlndXJhdGlvblByb3BzKTogUm91dGVySW5wdXRDb25maWd1cmF0aW9uIHtcbiAgICByZXR1cm4gbmV3IE1lZGlhQ29ubmVjdEZsb3dSb3V0ZXJJbnB1dENvbmZpZyh7XG4gICAgICBmbG93OiBwcm9wcy5mbG93LFxuICAgICAgZmxvd091dHB1dDogcHJvcHMuZmxvd091dHB1dCxcbiAgICAgIHNvdXJjZVRyYW5zaXREZWNyeXB0aW9uOiBwcm9wcy5zb3VyY2VUcmFuc2l0RGVjcnlwdGlvbixcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBNZWRpYUxpdmUgQ2hhbm5lbCBSb3V0ZXIgSW5wdXQgY29uZmlndXJhdGlvbi5cbiAgICpcbiAgICogVXNlIHRoaXMgd2hlbiB0aGUgc291cmNlIE1lZGlhTGl2ZSBjaGFubmVsIGFscmVhZHkgZXhpc3RzIGFuZCB5b3Ugd2FudCB0b1xuICAgKiBpbmdlc3QgZnJvbSBvbmUgb2YgaXRzIG91dHB1dHMgaW1tZWRpYXRlbHkuXG4gICAqXG4gICAqIEBwYXJhbSBwcm9wcyBNZWRpYUxpdmUgY2hhbm5lbCBjb25maWd1cmF0aW9uIHByb3BlcnRpZXNcbiAgICogQHJldHVybnMgUm91dGVySW5wdXRDb25maWd1cmF0aW9uIGluc3RhbmNlIGZvciBNZWRpYUxpdmUgY2hhbm5lbCBzZXR1cFxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBtZWRpYUxpdmVDaGFubmVsKHByb3BzOiBNZWRpYUxpdmVDaGFubmVsQ29uZmlndXJhdGlvblByb3BzKTogUm91dGVySW5wdXRDb25maWd1cmF0aW9uIHtcbiAgICByZXR1cm4gbmV3IE1lZGlhTGl2ZUNoYW5uZWxSb3V0ZXJJbnB1dENvbmZpZyh7XG4gICAgICBtZWRpYUxpdmVDaGFubmVsQXJuOiBwcm9wcy5tZWRpYUxpdmVDaGFubmVsQXJuLFxuICAgICAgbWVkaWFMaXZlQ2hhbm5lbE91dHB1dE5hbWU6IHByb3BzLm1lZGlhTGl2ZUNoYW5uZWxPdXRwdXROYW1lLFxuICAgICAgbWVkaWFMaXZlUGlwZWxpbmVJZDogcHJvcHMubWVkaWFMaXZlUGlwZWxpbmVJZCxcbiAgICAgIHNvdXJjZVRyYW5zaXREZWNyeXB0aW9uOiBwcm9wcy5zb3VyY2VUcmFuc2l0RGVjcnlwdGlvbixcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBNZWRpYUxpdmUgQ2hhbm5lbCBSb3V0ZXIgSW5wdXQgY29uZmlndXJhdGlvbiB3aXRob3V0IGEgc3BlY2lmaWMgY2hhbm5lbCBjb25uZWN0aW9uLlxuICAgKlxuICAgKiBVc2UgdGhpcyB3aGVuIHlvdSB3YW50IHRvIHNldCB1cCB0aGUgcm91dGVyIGlucHV0IGJlZm9yZSB0aGUgdGFyZ2V0IE1lZGlhTGl2ZSBjaGFubmVsIGV4aXN0cy5cbiAgICpcbiAgICogQHBhcmFtIHByb3BzIE1lZGlhTGl2ZSBjaGFubmVsIG5vLWNvbm5lY3Rpb24gcHJvcGVydGllc1xuICAgKiBAcmV0dXJucyBSb3V0ZXJJbnB1dENvbmZpZ3VyYXRpb24gaW5zdGFuY2UgZm9yIE1lZGlhTGl2ZSBjaGFubmVsIHNldHVwIHdpdGhvdXQgY29ubmVjdGlvblxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBtZWRpYUxpdmVDaGFubmVsV2l0aG91dENvbm5lY3Rpb24ocHJvcHM6IE1lZGlhTGl2ZUNoYW5uZWxDb25maWd1cmF0aW9uV2l0aG91dENvbm5lY3Rpb25Qcm9wcyk6IFJvdXRlcklucHV0Q29uZmlndXJhdGlvbiB7XG4gICAgcmV0dXJuIG5ldyBNZWRpYUxpdmVDaGFubmVsUm91dGVySW5wdXRDb25maWcoeyBzb3VyY2VUcmFuc2l0RGVjcnlwdGlvbjogcHJvcHMuc291cmNlVHJhbnNpdERlY3J5cHRpb24gfSwgcHJvcHMuYXZhaWxhYmlsaXR5Wm9uZSk7XG4gIH1cblxuICAvKipcbiAgICogUmVzb2x2ZSB0aGlzIGNvbmZpZ3VyYXRpb24gdG8gaXRzIENsb3VkRm9ybWF0aW9uIHNoYXBlLiBDYWxsZWQgYnkgdGhlIFJvdXRlcklucHV0XG4gICAqIGNvbnN0cnVjdG9yIOKAlCBlYWNoIGNvbmNyZXRlIHN1YmNsYXNzIHN1cHBsaWVzIGl0cyBvd24gdmFyaWFudC1zcGVjaWZpYyByZW5kZXJpbmcuXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHVibGljIGFic3RyYWN0IF9iaW5kKHNjb3BlOiBDb25zdHJ1Y3QsIHJvdXRlcklucHV0QXJuPzogc3RyaW5nKToge1xuICAgIGNvbmZpZzogQ2ZuUm91dGVySW5wdXQuUm91dGVySW5wdXRDb25maWd1cmF0aW9uUHJvcGVydHk7IGF2YWlsYWJpbGl0eVpvbmU/OiBzdHJpbmc7XG4gIH07XG5cbiAgLyoqXG4gICAqIENvbXB1dGUgdGhlIGluZ2VzdCBlbmRwb2ludHMgZm9yIHByb3RvY29sLWJhc2VkIGlucHV0cyB0aGF0IGxpc3RlbiBvbiBvbmUgb3IgbW9yZVxuICAgKiBwb3J0cy5cbiAgICpcbiAgICogUmV0dXJucyBgdW5kZWZpbmVkYCB3aGVuIHRoZSB2YXJpYW50IGhhcyBubyBjb25jZXB0IG9mIGEgbGlzdGVuIHBvcnQgKFNSVCBjYWxsZXIsXG4gICAqIE1lZGlhQ29ubmVjdCBGbG93LCBNZWRpYUxpdmUgQ2hhbm5lbCkuIFJldHVybnMgYW4gYXJyYXkgd2l0aCBvbmUgZW50cnkgZm9yXG4gICAqIHN0YW5kYXJkIHZhcmlhbnRzLCBhbmQgb25lIGVudHJ5IHBlciBzb3VyY2UgZm9yIGZhaWxvdmVyIGFuZCBtZXJnZS5cbiAgICogQGludGVybmFsXG4gICAqL1xuICBwdWJsaWMgYWJzdHJhY3QgX2VuZHBvaW50cyhpcEFkZHJlc3M6IHN0cmluZyk6IFJvdXRlcklucHV0RW5kcG9pbnRbXSB8IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBSZW5kZXIgYW4gaW5nZXN0IFVSTCBzdHJpbmcgKHNjaGVtZTovL2lwOnBvcnQpLiBVc2VkIGJ5IGBfaW5nZXN0VXJsKClgIG9uIGluZGl2aWR1YWxcbiAqIHByb3RvY29scyBhbmQgY29tcG9zZWQgaW50byB0aGUgcGVyLWNvbmZpZy12YXJpYW50IGBfZW5kcG9pbnRzKClgIHJlc3VsdHMuXG4gKlxuICogRXh0cmFjdHMgdGhlIGJhc2UgcHJvdG9jb2wgZm9yIHRoZSBVUkwgc2NoZW1lIChlLmcuIFNSVF9MSVNURU5FUiDihpIgc3J0LCBSVFAg4oaSIHJ0cCkuXG4gKi9cbmZ1bmN0aW9uIHJlbmRlckluZ2VzdFVybChwcm90b2NvbE5hbWU6IHN0cmluZywgcG9ydDogbnVtYmVyLCBpcEFkZHJlc3M6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IHNjaGVtZSA9IHByb3RvY29sTmFtZS50b0xvd2VyQ2FzZSgpLnNwbGl0KCdfJylbMF07XG4gIHJldHVybiBGbi5qb2luKCcnLCBbYCR7c2NoZW1lfTovL2AsIGlwQWRkcmVzcywgYDoke3BvcnR9YF0pO1xufVxuXG4vKipcbiAqIENvbmNyZXRlIHZhcmlhbnQ6IHN0YW5kYXJkIChzaW5nbGUtcHJvdG9jb2wpIHJvdXRlciBpbnB1dCBjb25maWd1cmF0aW9uLlxuICogQGludGVybmFsXG4gKi9cbmNsYXNzIFN0YW5kYXJkUm91dGVySW5wdXRDb25maWcgZXh0ZW5kcyBSb3V0ZXJJbnB1dENvbmZpZ3VyYXRpb24ge1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IHByb3BzOiBTdGFuZGFyZENvbmZpZ3VyYXRpb25Qcm9wcykgeyBzdXBlcigpOyB9XG5cbiAgcHVibGljIF9iaW5kKHNjb3BlOiBDb25zdHJ1Y3QsIHJvdXRlcklucHV0QXJuPzogc3RyaW5nKSB7XG4gICAgY29uc3QgcHJvdG9jb2wgPSB0aGlzLnByb3BzLnByb3RvY29sLl9iaW5kKHNjb3BlLCByb3V0ZXJJbnB1dEFybik7XG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbmZpZzoge1xuICAgICAgICBzdGFuZGFyZDoge1xuICAgICAgICAgIG5ldHdvcmtJbnRlcmZhY2VBcm46IHRoaXMucHJvcHMubmV0d29ya0ludGVyZmFjZS5yb3V0ZXJOZXR3b3JrSW50ZXJmYWNlQXJuLFxuICAgICAgICAgIHByb3RvY29sOiBwcm90b2NvbC5uYW1lLnZhbHVlLFxuICAgICAgICAgIHByb3RvY29sQ29uZmlndXJhdGlvbjogcHJvdG9jb2wuY29uZmlnLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9O1xuICB9XG5cbiAgcHVibGljIF9lbmRwb2ludHMoaXBBZGRyZXNzOiBzdHJpbmcpOiBSb3V0ZXJJbnB1dEVuZHBvaW50W10gfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IHVybCA9IHRoaXMucHJvcHMucHJvdG9jb2wuX2luZ2VzdFVybChpcEFkZHJlc3MpO1xuICAgIGNvbnN0IHBvcnQgPSB0aGlzLnByb3BzLnByb3RvY29sLl9saXN0ZW5pbmdQb3J0KCk7XG4gICAgaWYgKHVybCA9PT0gdW5kZWZpbmVkIHx8IHBvcnQgPT09IHVuZGVmaW5lZCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICByZXR1cm4gW3sgdXJsLCBwb3J0IH1dO1xuICB9XG59XG5cbi8qKlxuICogQ29uY3JldGUgdmFyaWFudDogZmFpbG92ZXIgcm91dGVyIGlucHV0IGNvbmZpZ3VyYXRpb24uXG4gKiBAaW50ZXJuYWxcbiAqL1xuY2xhc3MgRmFpbG92ZXJSb3V0ZXJJbnB1dENvbmZpZyBleHRlbmRzIFJvdXRlcklucHV0Q29uZmlndXJhdGlvbiB7XG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgcHJvcHM6IEZhaWxvdmVyQ29uZmlndXJhdGlvblByb3BzKSB7IHN1cGVyKCk7IH1cblxuICBwdWJsaWMgX2JpbmQoc2NvcGU6IENvbnN0cnVjdCwgcm91dGVySW5wdXRBcm4/OiBzdHJpbmcpIHtcbiAgICBjb25zdCBwcmlvcml0eSA9ICh0aGlzLnByb3BzLnNvdXJjZVByaW9yaXR5ID8/IFNvdXJjZVByaW9yaXR5Q29uZmlnLm5vbmUoKSkuX2JpbmQoKTtcbiAgICByZXR1cm4ge1xuICAgICAgY29uZmlnOiB7XG4gICAgICAgIGZhaWxvdmVyOiB7XG4gICAgICAgICAgbmV0d29ya0ludGVyZmFjZUFybjogdGhpcy5wcm9wcy5uZXR3b3JrSW50ZXJmYWNlLnJvdXRlck5ldHdvcmtJbnRlcmZhY2VBcm4sXG4gICAgICAgICAgcHJvdG9jb2xDb25maWd1cmF0aW9uczogdGhpcy5wcm9wcy5wcm90b2NvbHMubWFwKHAgPT4gcC5fYmluZChzY29wZSwgcm91dGVySW5wdXRBcm4pLmNvbmZpZyksXG4gICAgICAgICAgc291cmNlUHJpb3JpdHlNb2RlOiBwcmlvcml0eS5zb3VyY2VQcmlvcml0eU1vZGUsXG4gICAgICAgICAgcHJpbWFyeVNvdXJjZUluZGV4OiBwcmlvcml0eS5wcmltYXJ5U291cmNlSW5kZXgsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICBwdWJsaWMgX2VuZHBvaW50cyhpcEFkZHJlc3M6IHN0cmluZyk6IFJvdXRlcklucHV0RW5kcG9pbnRbXSB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgZW5kcG9pbnRzOiBSb3V0ZXJJbnB1dEVuZHBvaW50W10gPSBbXTtcbiAgICBmb3IgKGNvbnN0IHAgb2YgdGhpcy5wcm9wcy5wcm90b2NvbHMpIHtcbiAgICAgIGNvbnN0IHVybCA9IHAuX2luZ2VzdFVybChpcEFkZHJlc3MpO1xuICAgICAgY29uc3QgcG9ydCA9IHAuX2xpc3RlbmluZ1BvcnQoKTtcbiAgICAgIGlmICh1cmwgPT09IHVuZGVmaW5lZCB8fCBwb3J0ID09PSB1bmRlZmluZWQpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICBlbmRwb2ludHMucHVzaCh7IHVybCwgcG9ydCB9KTtcbiAgICB9XG4gICAgcmV0dXJuIGVuZHBvaW50cztcbiAgfVxufVxuXG4vKipcbiAqIENvbmNyZXRlIHZhcmlhbnQ6IG1lcmdlIHJvdXRlciBpbnB1dCBjb25maWd1cmF0aW9uLlxuICogQGludGVybmFsXG4gKi9cbmNsYXNzIE1lcmdlUm91dGVySW5wdXRDb25maWcgZXh0ZW5kcyBSb3V0ZXJJbnB1dENvbmZpZ3VyYXRpb24ge1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlYWRvbmx5IHByb3BzOiBNZXJnZUNvbmZpZ3VyYXRpb25Qcm9wcykgeyBzdXBlcigpOyB9XG5cbiAgcHVibGljIF9iaW5kKHNjb3BlOiBDb25zdHJ1Y3QsIHJvdXRlcklucHV0QXJuPzogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbmZpZzoge1xuICAgICAgICBtZXJnZToge1xuICAgICAgICAgIG5ldHdvcmtJbnRlcmZhY2VBcm46IHRoaXMucHJvcHMubmV0d29ya0ludGVyZmFjZS5yb3V0ZXJOZXR3b3JrSW50ZXJmYWNlQXJuLFxuICAgICAgICAgIHByb3RvY29sQ29uZmlndXJhdGlvbnM6IHRoaXMucHJvcHMucHJvdG9jb2xzLm1hcChwID0+IHAuX2JpbmQoc2NvcGUsIHJvdXRlcklucHV0QXJuKS5jb25maWcpLFxuICAgICAgICAgIG1lcmdlUmVjb3ZlcnlXaW5kb3dNaWxsaXNlY29uZHM6IHRoaXMucHJvcHMubWVyZ2VSZWNvdmVyeVdpbmRvdy50b01pbGxpc2Vjb25kcygpLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9O1xuICB9XG5cbiAgcHVibGljIF9lbmRwb2ludHMoaXBBZGRyZXNzOiBzdHJpbmcpOiBSb3V0ZXJJbnB1dEVuZHBvaW50W10gfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IGVuZHBvaW50czogUm91dGVySW5wdXRFbmRwb2ludFtdID0gW107XG4gICAgZm9yIChjb25zdCBwIG9mIHRoaXMucHJvcHMucHJvdG9jb2xzKSB7XG4gICAgICBjb25zdCB1cmwgPSBwLl9pbmdlc3RVcmwoaXBBZGRyZXNzKTtcbiAgICAgIGNvbnN0IHBvcnQgPSBwLl9saXN0ZW5pbmdQb3J0KCk7XG4gICAgICBpZiAodXJsID09PSB1bmRlZmluZWQgfHwgcG9ydCA9PT0gdW5kZWZpbmVkKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgZW5kcG9pbnRzLnB1c2goeyB1cmwsIHBvcnQgfSk7XG4gICAgfVxuICAgIHJldHVybiBlbmRwb2ludHM7XG4gIH1cbn1cblxuLyoqXG4gKiBJbnRlcm5hbCBvcHRpb25zIGZvciB7QGxpbmsgTWVkaWFDb25uZWN0Rmxvd1JvdXRlcklucHV0Q29uZmlnfS4gTm90IGV4cG9ydGVkOyBqc2lpIG5ldmVyIHNlZXMgdGhpcy5cbiAqL1xuaW50ZXJmYWNlIE1lZGlhQ29ubmVjdEZsb3dSb3V0ZXJJbnB1dE9wdGlvbnMge1xuICByZWFkb25seSBmbG93PzogSUZsb3c7XG4gIHJlYWRvbmx5IGZsb3dPdXRwdXQ/OiBJRmxvd091dHB1dDtcbiAgcmVhZG9ubHkgc291cmNlVHJhbnNpdERlY3J5cHRpb24/OiBUcmFuc2l0RW5jcnlwdGlvbjtcbn1cblxuLyoqXG4gKiBDb25jcmV0ZSB2YXJpYW50OiBNZWRpYUNvbm5lY3QgRmxvdyByb3V0ZXIgaW5wdXQgY29uZmlndXJhdGlvbiAod2l0aCBvciB3aXRob3V0IGNvbm5lY3Rpb24pLlxuICogQGludGVybmFsXG4gKi9cbmNsYXNzIE1lZGlhQ29ubmVjdEZsb3dSb3V0ZXJJbnB1dENvbmZpZyBleHRlbmRzIFJvdXRlcklucHV0Q29uZmlndXJhdGlvbiB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgb3B0aW9uczogTWVkaWFDb25uZWN0Rmxvd1JvdXRlcklucHV0T3B0aW9ucyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGF2YWlsYWJpbGl0eVpvbmU/OiBzdHJpbmcsXG4gICkgeyBzdXBlcigpOyB9XG5cbiAgcHVibGljIF9iaW5kKHNjb3BlOiBDb25zdHJ1Y3QsIHJvdXRlcklucHV0QXJuPzogc3RyaW5nKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGNvbmZpZzoge1xuICAgICAgICBtZWRpYUNvbm5lY3RGbG93OiB7XG4gICAgICAgICAgZmxvd0FybjogdGhpcy5vcHRpb25zLmZsb3c/LmZsb3dBcm4sXG4gICAgICAgICAgZmxvd091dHB1dEFybjogdGhpcy5vcHRpb25zLmZsb3dPdXRwdXQ/LmZsb3dPdXRwdXRBcm4sXG4gICAgICAgICAgc291cmNlVHJhbnNpdERlY3J5cHRpb246IHJlbmRlclRyYW5zaXRFbmNyeXB0aW9uKHNjb3BlLCAnU291cmNlVHJhbnNpdERlY3J5cHRpb25Sb2xlJywgdGhpcy5vcHRpb25zLnNvdXJjZVRyYW5zaXREZWNyeXB0aW9uLCByb3V0ZXJJbnB1dEFybiksXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgYXZhaWxhYmlsaXR5Wm9uZTogdGhpcy5hdmFpbGFiaWxpdHlab25lLFxuICAgIH07XG4gIH1cblxuICBwdWJsaWMgX2VuZHBvaW50cyhfaXBBZGRyZXNzOiBzdHJpbmcpOiBSb3V0ZXJJbnB1dEVuZHBvaW50W10gfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cbn1cblxuLyoqXG4gKiBJbnRlcm5hbCBvcHRpb25zIGZvciB7QGxpbmsgTWVkaWFMaXZlQ2hhbm5lbFJvdXRlcklucHV0Q29uZmlnfS4gTm90IGV4cG9ydGVkOyBqc2lpIG5ldmVyIHNlZXMgdGhpcy5cbiAqL1xuaW50ZXJmYWNlIE1lZGlhTGl2ZUNoYW5uZWxSb3V0ZXJJbnB1dE9wdGlvbnMge1xuICByZWFkb25seSBtZWRpYUxpdmVDaGFubmVsQXJuPzogc3RyaW5nO1xuICByZWFkb25seSBtZWRpYUxpdmVDaGFubmVsT3V0cHV0TmFtZT86IHN0cmluZztcbiAgcmVhZG9ubHkgbWVkaWFMaXZlUGlwZWxpbmVJZD86IE1lZGlhTGl2ZVBpcGVsaW5lO1xuICByZWFkb25seSBzb3VyY2VUcmFuc2l0RGVjcnlwdGlvbj86IFRyYW5zaXRFbmNyeXB0aW9uO1xufVxuXG4vKipcbiAqIENvbmNyZXRlIHZhcmlhbnQ6IE1lZGlhTGl2ZSBDaGFubmVsIHJvdXRlciBpbnB1dCBjb25maWd1cmF0aW9uICh3aXRoIG9yIHdpdGhvdXQgY29ubmVjdGlvbikuXG4gKiBAaW50ZXJuYWxcbiAqL1xuY2xhc3MgTWVkaWFMaXZlQ2hhbm5lbFJvdXRlcklucHV0Q29uZmlnIGV4dGVuZHMgUm91dGVySW5wdXRDb25maWd1cmF0aW9uIHtcbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBvcHRpb25zOiBNZWRpYUxpdmVDaGFubmVsUm91dGVySW5wdXRPcHRpb25zLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgYXZhaWxhYmlsaXR5Wm9uZT86IHN0cmluZyxcbiAgKSB7IHN1cGVyKCk7IH1cblxuICBwdWJsaWMgX2JpbmQoc2NvcGU6IENvbnN0cnVjdCwgcm91dGVySW5wdXRBcm4/OiBzdHJpbmcpIHtcbiAgICByZXR1cm4ge1xuICAgICAgY29uZmlnOiB7XG4gICAgICAgIG1lZGlhTGl2ZUNoYW5uZWw6IHtcbiAgICAgICAgICBtZWRpYUxpdmVDaGFubmVsQXJuOiB0aGlzLm9wdGlvbnMubWVkaWFMaXZlQ2hhbm5lbEFybixcbiAgICAgICAgICBtZWRpYUxpdmVDaGFubmVsT3V0cHV0TmFtZTogdGhpcy5vcHRpb25zLm1lZGlhTGl2ZUNoYW5uZWxPdXRwdXROYW1lLFxuICAgICAgICAgIG1lZGlhTGl2ZVBpcGVsaW5lSWQ6IHRoaXMub3B0aW9ucy5tZWRpYUxpdmVQaXBlbGluZUlkLFxuICAgICAgICAgIHNvdXJjZVRyYW5zaXREZWNyeXB0aW9uOiByZW5kZXJUcmFuc2l0RW5jcnlwdGlvbihzY29wZSwgJ1NvdXJjZVRyYW5zaXREZWNyeXB0aW9uUm9sZScsIHRoaXMub3B0aW9ucy5zb3VyY2VUcmFuc2l0RGVjcnlwdGlvbiwgcm91dGVySW5wdXRBcm4pLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIGF2YWlsYWJpbGl0eVpvbmU6IHRoaXMuYXZhaWxhYmlsaXR5Wm9uZSxcbiAgICB9O1xuICB9XG5cbiAgcHVibGljIF9lbmRwb2ludHMoX2lwQWRkcmVzczogc3RyaW5nKTogUm91dGVySW5wdXRFbmRwb2ludFtdIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59XG5cbi8qKlxuICogQSBNZWRpYUNvbm5lY3QgUm91dGVyIElucHV0IHRoYXQgcmVjZWl2ZXMgbWVkaWEgc3RyZWFtcyBhbmQgcm91dGVzIHRoZW0gdG8gb3V0cHV0cy5cbiAqXG4gKiBSb3V0ZXIgSW5wdXRzIHN1cHBvcnQgbXVsdGlwbGUgY29uZmlndXJhdGlvbiB0eXBlczpcbiAqIC0gU3RhbmRhcmQ6IFNpbmdsZSBwcm90b2NvbCBpbnB1dFxuICogLSBGYWlsb3ZlcjogVHdvIG1hdGNoaW5nIHByb3RvY29scyBmb3IgcmVkdW5kYW5jeVxuICogLSBNZXJnZTogVHdvIG1hdGNoaW5nIG5vbi1TUlQgcHJvdG9jb2xzIGZvciBzdHJlYW0gbWVyZ2luZ1xuICogLSBNZWRpYUNvbm5lY3QgRmxvdzogSW5wdXQgZnJvbSBhbiBleGlzdGluZyBNZWRpYUNvbm5lY3QgRmxvd1xuICovXG5hYnN0cmFjdCBjbGFzcyBSb3V0ZXJJbnB1dEJhc2UgZXh0ZW5kcyBSZXNvdXJjZSBpbXBsZW1lbnRzIElSb3V0ZXJJbnB1dCB7XG4gIHB1YmxpYyBhYnN0cmFjdCByZWFkb25seSByb3V0ZXJJbnB1dEFybjogc3RyaW5nO1xuICBwdWJsaWMgYWJzdHJhY3QgcmVhZG9ubHkgcm91dGVySW5wdXRJZDogc3RyaW5nO1xuICBwdWJsaWMgYWJzdHJhY3QgcmVhZG9ubHkgaXBBZGRyZXNzOiBzdHJpbmc7XG4gIHB1YmxpYyBhYnN0cmFjdCByZWFkb25seSBjcmVhdGVkQXQ/OiBzdHJpbmc7XG4gIHB1YmxpYyBhYnN0cmFjdCByZWFkb25seSB1cGRhdGVkQXQ/OiBzdHJpbmc7XG4gIHB1YmxpYyBhYnN0cmFjdCByZWFkb25seSBlbmRwb2ludHM6IFJvdXRlcklucHV0RW5kcG9pbnRbXTtcbiAgcHVibGljIGFic3RyYWN0IHJlYWRvbmx5IHRyYW5zaXRFbmNyeXB0aW9uU2VjcmV0PzogSVNlY3JldDtcbiAgcHVibGljIGFic3RyYWN0IHJlYWRvbmx5IGdyYW50czogUm91dGVySW5wdXRHcmFudHM7XG5cbiAgLyoqXG4gICAqIEEgcmVmZXJlbmNlIHRvIHRoaXMgUm91dGVyIElucHV0IHJlc291cmNlLlxuICAgKiBSZXF1aXJlZCBieSB0aGUgYXV0by1nZW5lcmF0ZWQgSVJvdXRlcklucHV0UmVmIGludGVyZmFjZS5cbiAgICovXG4gIHB1YmxpYyBnZXQgcm91dGVySW5wdXRSZWYoKTogUm91dGVySW5wdXRSZWZlcmVuY2Uge1xuICAgIHJldHVybiB7IHJvdXRlcklucHV0QXJuOiB0aGlzLnJvdXRlcklucHV0QXJuIH07XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgQ2xvdWRXYXRjaCBtZXRyaWMgZm9yIHRoaXMgcm91dGVyIGlucHV0LlxuICAgKi9cbiAgcHVibGljIG1ldHJpYyhtZXRyaWNOYW1lOiBzdHJpbmcsIHByb3BzPzogTWV0cmljT3B0aW9ucyk6IE1ldHJpYyB7XG4gICAgcmV0dXJuIG5ldyBNZXRyaWMoe1xuICAgICAgbWV0cmljTmFtZSxcbiAgICAgIG5hbWVzcGFjZTogJ0FXUy9NZWRpYUNvbm5lY3QnLFxuICAgICAgLi4ucHJvcHMsXG4gICAgICBkaW1lbnNpb25zTWFwOiB7XG4gICAgICAgIFJvdXRlcklucHV0QVJOOiB0aGlzLnJvdXRlcklucHV0QXJuLFxuICAgICAgICAuLi5wcm9wcz8uZGltZW5zaW9uc01hcCxcbiAgICAgIH0sXG4gICAgfSkuYXR0YWNoVG8odGhpcyk7XG4gIH1cblxuICAvKipcbiAgICogTWV0cmljIGZvciB0aGUgYml0cmF0ZSBvZiB0aGUgcm91dGVyIGlucHV0J3MgcGF5bG9hZC5cbiAgICovXG4gIHB1YmxpYyBtZXRyaWNCaXRyYXRlKHByb3BzPzogTWV0cmljT3B0aW9ucyk6IE1ldHJpYyB7XG4gICAgcmV0dXJuIHRoaXMubWV0cmljKCdSb3V0ZXJJbnB1dEJpdFJhdGUnLCB7XG4gICAgICBzdGF0aXN0aWM6ICdhdmcnLFxuICAgICAgcGVyaW9kOiBEdXJhdGlvbi5zZWNvbmRzKDYwKSxcbiAgICAgIHVuaXQ6IFVuaXQuQklUU19QRVJfU0VDT05ELFxuICAgICAgLi4ucHJvcHMsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogTWV0cmljIGZvciBwYWNrZXRzIGxvc3QgaW4gdHJhbnNpdCB0aGF0IHdlcmUgbm90IHJlY292ZXJlZCBieSBlcnJvciBjb3JyZWN0aW9uLlxuICAgKi9cbiAgcHVibGljIG1ldHJpY05vdFJlY292ZXJlZFBhY2tldHMocHJvcHM/OiBNZXRyaWNPcHRpb25zKTogTWV0cmljIHtcbiAgICByZXR1cm4gdGhpcy5tZXRyaWMoJ1JvdXRlcklucHV0Tm90UmVjb3ZlcmVkUGFja2V0cycsIHtcbiAgICAgIHN0YXRpc3RpYzogJ3N1bScsXG4gICAgICBwZXJpb2Q6IER1cmF0aW9uLnNlY29uZHMoNjApLFxuICAgICAgdW5pdDogVW5pdC5DT1VOVCxcbiAgICAgIC4uLnByb3BzLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldHJpYyBmb3IgdGhlIHRvdGFsIG51bWJlciBvZiBwYWNrZXRzIHJlY2VpdmVkIGJ5IHRoZSByb3V0ZXIgaW5wdXQuXG4gICAqL1xuICBwdWJsaWMgbWV0cmljVG90YWxQYWNrZXRzKHByb3BzPzogTWV0cmljT3B0aW9ucyk6IE1ldHJpYyB7XG4gICAgcmV0dXJuIHRoaXMubWV0cmljKCdSb3V0ZXJJbnB1dFRvdGFsUGFja2V0cycsIHtcbiAgICAgIHN0YXRpc3RpYzogJ3N1bScsXG4gICAgICBwZXJpb2Q6IER1cmF0aW9uLnNlY29uZHMoNjApLFxuICAgICAgdW5pdDogVW5pdC5DT1VOVCxcbiAgICAgIC4uLnByb3BzLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldHJpYyBmb3IgdGhlIHJvdXRlciBpbnB1dCBjb25uZWN0aW9uIHN0YXRlICgxIGNvbm5lY3RlZCwgMCBkaXNjb25uZWN0ZWQpLiBBcHBsaWVzIHRvIFNSVCBzb3VyY2VzIG9ubHkuXG4gICAqL1xuICBwdWJsaWMgbWV0cmljQ29ubmVjdGVkKHByb3BzPzogTWV0cmljT3B0aW9ucyk6IE1ldHJpYyB7XG4gICAgcmV0dXJuIHRoaXMubWV0cmljKCdSb3V0ZXJJbnB1dENvbm5lY3RlZCcsIHtcbiAgICAgIHN0YXRpc3RpYzogJ21pbicsXG4gICAgICBwZXJpb2Q6IER1cmF0aW9uLnNlY29uZHMoNjApLFxuICAgICAgdW5pdDogVW5pdC5OT05FLFxuICAgICAgLi4ucHJvcHMsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogTWV0cmljIGZvciBjb250aW51aXR5IGNvdW50ZXIgZXJyb3JzIGluIHRoZSB0cmFuc3BvcnQgc3RyZWFtLlxuICAgKi9cbiAgcHVibGljIG1ldHJpY0NvbnRpbnVpdHlDb3VudGVyRXJyb3JzKHByb3BzPzogTWV0cmljT3B0aW9ucyk6IE1ldHJpYyB7XG4gICAgcmV0dXJuIHRoaXMubWV0cmljKCdSb3V0ZXJJbnB1dENDRXJyb3JzJywge1xuICAgICAgc3RhdGlzdGljOiAnc3VtJyxcbiAgICAgIHBlcmlvZDogRHVyYXRpb24uc2Vjb25kcyg2MCksXG4gICAgICB1bml0OiBVbml0LkNPVU5ULFxuICAgICAgLi4ucHJvcHMsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogTWV0cmljIGZvciB0aGUgcmVjb3ZlcnkgbGF0ZW5jeSBvZiB0aGUgaW5wdXQgc3RyZWFtLiBBcHBsaWVzIHRvIFJJU1QsIFNSVCwgYW5kIFJUUC1GRUMuXG4gICAqL1xuICBwdWJsaWMgbWV0cmljTGF0ZW5jeShwcm9wcz86IE1ldHJpY09wdGlvbnMpOiBNZXRyaWMge1xuICAgIHJldHVybiB0aGlzLm1ldHJpYygnUm91dGVySW5wdXRMYXRlbmN5Jywge1xuICAgICAgc3RhdGlzdGljOiAnYXZnJyxcbiAgICAgIHBlcmlvZDogRHVyYXRpb24uc2Vjb25kcyg2MCksXG4gICAgICB1bml0OiBVbml0Lk1JTExJU0VDT05EUyxcbiAgICAgIC4uLnByb3BzLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldHJpYyBmb3IgdGhlIG51bWJlciBvZiB0aW1lcyB0aGUgcm91dGVyIGlucHV0IGhhcyBzd2l0Y2hlZCBzb3VyY2VzIGluIEZhaWxvdmVyIG1vZGUuXG4gICAqL1xuICBwdWJsaWMgbWV0cmljRmFpbG92ZXJTd2l0Y2hlcyhwcm9wcz86IE1ldHJpY09wdGlvbnMpOiBNZXRyaWMge1xuICAgIHJldHVybiB0aGlzLm1ldHJpYygnUm91dGVySW5wdXRGYWlsb3ZlclN3aXRjaGVzJywge1xuICAgICAgc3RhdGlzdGljOiAnc3VtJyxcbiAgICAgIHBlcmlvZDogRHVyYXRpb24uc2Vjb25kcyg2MCksXG4gICAgICB1bml0OiBVbml0LkNPVU5ULFxuICAgICAgLi4ucHJvcHMsXG4gICAgfSk7XG4gIH1cbn1cblxuLyoqXG4gKiBEZWZpbmVzIGFuIEFXUyBFbGVtZW50YWwgTWVkaWFDb25uZWN0IFJvdXRlciBJbnB1dC5cbiAqL1xuQHByb3BlcnR5SW5qZWN0YWJsZVxuZXhwb3J0IGNsYXNzIFJvdXRlcklucHV0IGV4dGVuZHMgUm91dGVySW5wdXRCYXNlIGltcGxlbWVudHMgSVJvdXRlcklucHV0IHtcbiAgLyoqIFVuaXF1ZWx5IGlkZW50aWZpZXMgdGhpcyBjbGFzcy4gKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBQUk9QRVJUWV9JTkpFQ1RJT05fSUQ6IHN0cmluZyA9ICdAYXdzLWNkay5hd3MtbWVkaWFjb25uZWN0LWFscGhhLlJvdXRlcklucHV0JztcblxuICAvKipcbiAgICogSW1wb3J0IGFuIGV4aXN0aW5nIFJvdXRlciBJbnB1dCBmcm9tIGl0cyBBUk4uXG4gICAqXG4gICAqIFVzZSBgZnJvbVJvdXRlcklucHV0QXR0cmlidXRlcygpYCBpbnN0ZWFkIGlmIHlvdSBuZWVkIHRvIGV4cG9zZSBgcm91dGVySW5wdXRJZGBcbiAgICogb3IgYGlwQWRkcmVzc2Agb24gdGhlIGltcG9ydGVkIGNvbnN0cnVjdC5cbiAgICpcbiAgICogQHBhcmFtIHNjb3BlIFRoZSBwYXJlbnQgY29uc3RydWN0XG4gICAqIEBwYXJhbSBpZCBUaGUgY29uc3RydWN0IGlkXG4gICAqIEBwYXJhbSByb3V0ZXJJbnB1dEFybiBUaGUgQVJOIG9mIHRoZSBSb3V0ZXIgSW5wdXRcbiAgICogQHJldHVybnMgQSBSb3V0ZXIgSW5wdXQgY29uc3RydWN0XG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGZyb21Sb3V0ZXJJbnB1dEFybihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCByb3V0ZXJJbnB1dEFybjogc3RyaW5nKTogSVJvdXRlcklucHV0IHtcbiAgICByZXR1cm4gUm91dGVySW5wdXQuZnJvbVJvdXRlcklucHV0QXR0cmlidXRlcyhzY29wZSwgaWQsIHsgcm91dGVySW5wdXRBcm4gfSk7XG4gIH1cblxuICAvKipcbiAgICogSW1wb3J0IGFuIGV4aXN0aW5nIFJvdXRlciBJbnB1dCBmcm9tIGl0cyBhdHRyaWJ1dGVzLlxuICAgKlxuICAgKiBQcm92aWRlIGByb3V0ZXJJbnB1dElkYCBhbmQvb3IgYGlwQWRkcmVzc2Agd2hlbiBpbXBvcnRpbmcgYW4gaW5wdXQgdGhhdCB3YXMgZGVwbG95ZWRcbiAgICogZXh0ZXJuYWxseSDigJQgb3RoZXJ3aXNlIGFjY2Vzc2luZyB0aG9zZSBwcm9wZXJ0aWVzIG9uIHRoZSBpbXBvcnRlZCBjb25zdHJ1Y3Qgd2lsbCB0aHJvdy5cbiAgICpcbiAgICogQHBhcmFtIHNjb3BlIFRoZSBwYXJlbnQgY29uc3RydWN0XG4gICAqIEBwYXJhbSBpZCBUaGUgY29uc3RydWN0IGlkXG4gICAqIEBwYXJhbSBhdHRycyBUaGUgUm91dGVyIElucHV0IGF0dHJpYnV0ZXNcbiAgICogQHJldHVybnMgQSBSb3V0ZXIgSW5wdXQgY29uc3RydWN0XG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGZyb21Sb3V0ZXJJbnB1dEF0dHJpYnV0ZXMoc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgYXR0cnM6IFJvdXRlcklucHV0QXR0cmlidXRlcyk6IElSb3V0ZXJJbnB1dCB7XG4gICAgY2xhc3MgSW1wb3J0IGV4dGVuZHMgUm91dGVySW5wdXRCYXNlIGltcGxlbWVudHMgSVJvdXRlcklucHV0IHtcbiAgICAgIHB1YmxpYyByZWFkb25seSByb3V0ZXJJbnB1dEFybiA9IGF0dHJzLnJvdXRlcklucHV0QXJuO1xuICAgICAgcHVibGljIHJlYWRvbmx5IGNyZWF0ZWRBdCA9IHVuZGVmaW5lZDtcbiAgICAgIHB1YmxpYyByZWFkb25seSB1cGRhdGVkQXQgPSB1bmRlZmluZWQ7XG4gICAgICBwdWJsaWMgcmVhZG9ubHkgdHJhbnNpdEVuY3J5cHRpb25TZWNyZXQgPSB1bmRlZmluZWQ7XG4gICAgICBwdWJsaWMgcmVhZG9ubHkgZ3JhbnRzID0gUm91dGVySW5wdXRHcmFudHMuZnJvbVJvdXRlcklucHV0KHRoaXMpO1xuXG4gICAgICBwdWJsaWMgZ2V0IGVuZHBvaW50cygpOiBSb3V0ZXJJbnB1dEVuZHBvaW50W10ge1xuICAgICAgICB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKFxuICAgICAgICAgIGxpdGBSb3V0ZXJJbnB1dEVuZHBvaW50c05vdEF2YWlsYWJsZUltcG9ydGVkYCxcbiAgICAgICAgICBgJ2VuZHBvaW50cycgaXMgbm90IGF2YWlsYWJsZSBvbiBpbXBvcnRlZCBSb3V0ZXJJbnB1dCAke3RoaXMubm9kZS5wYXRofTsgb25seSBSb3V0ZXJJbnB1dHMgY29uc3RydWN0ZWQgaW4gdGhpcyBhcHAgZm9yIGxpc3RlbmluZyBwcm90b2NvbCB2YXJpYW50cyAoUlRQLCBSSVNULCBTUlQgbGlzdGVuZXIsIGluY2x1ZGluZyBmYWlsb3ZlciBhbmQgbWVyZ2UpIGV4cG9zZSBpbmdlc3QgZW5kcG9pbnRzYCxcbiAgICAgICAgICB0aGlzLFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBwdWJsaWMgZ2V0IHJvdXRlcklucHV0SWQoKTogc3RyaW5nIHtcbiAgICAgICAgaWYgKGF0dHJzLnJvdXRlcklucHV0SWQpIHJldHVybiBhdHRycy5yb3V0ZXJJbnB1dElkO1xuICAgICAgICB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKFxuICAgICAgICAgIGxpdGBSb3V0ZXJJbnB1dElkTm90UHJvdmlkZWRgLFxuICAgICAgICAgIGAncm91dGVySW5wdXRJZCcgaXMgbm90IGF2YWlsYWJsZSBvbiBpbXBvcnRlZCBSb3V0ZXJJbnB1dCAke3RoaXMubm9kZS5wYXRofTsgcGFzcyBpdCB2aWEgZnJvbVJvdXRlcklucHV0QXR0cmlidXRlc2AsXG4gICAgICAgICAgdGhpcyxcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgcHVibGljIGdldCBpcEFkZHJlc3MoKTogc3RyaW5nIHtcbiAgICAgICAgaWYgKGF0dHJzLmlwQWRkcmVzcykgcmV0dXJuIGF0dHJzLmlwQWRkcmVzcztcbiAgICAgICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihcbiAgICAgICAgICBsaXRgUm91dGVySW5wdXRJcEFkZHJlc3NOb3RQcm92aWRlZGAsXG4gICAgICAgICAgYCdpcEFkZHJlc3MnIGlzIG5vdCBhdmFpbGFibGUgb24gaW1wb3J0ZWQgUm91dGVySW5wdXQgJHt0aGlzLm5vZGUucGF0aH07IHBhc3MgaXQgdmlhIGZyb21Sb3V0ZXJJbnB1dEF0dHJpYnV0ZXNgLFxuICAgICAgICAgIHRoaXMsXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBuZXcgSW1wb3J0KHNjb3BlLCBpZCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgbWF4aW11bSBiaXRyYXRlIGluIE1icHMgZm9yIGEga25vd24gdGllciwgb3IgdW5kZWZpbmVkIGZvciBjdXN0b20gdGllcnMuXG4gICAqL1xuICBwcml2YXRlIHN0YXRpYyB0aWVyTGltaXRNYnBzKHRpZXI6IFJvdXRlcklucHV0VGllcik6IG51bWJlciB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKHRpZXIudmFsdWUgPT09IFJvdXRlcklucHV0VGllci5JTlBVVF8yMC52YWx1ZSkgcmV0dXJuIDIwO1xuICAgIGlmICh0aWVyLnZhbHVlID09PSBSb3V0ZXJJbnB1dFRpZXIuSU5QVVRfNTAudmFsdWUpIHJldHVybiA1MDtcbiAgICBpZiAodGllci52YWx1ZSA9PT0gUm91dGVySW5wdXRUaWVyLklOUFVUXzEwMC52YWx1ZSkgcmV0dXJuIDEwMDtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgcHVibGljIHJlYWRvbmx5IHJvdXRlcklucHV0QXJuOiBzdHJpbmc7XG4gIHB1YmxpYyByZWFkb25seSByb3V0ZXJJbnB1dElkOiBzdHJpbmc7XG4gIHB1YmxpYyByZWFkb25seSBpcEFkZHJlc3M6IHN0cmluZztcbiAgcHVibGljIHJlYWRvbmx5IGNyZWF0ZWRBdD86IHN0cmluZztcbiAgcHVibGljIHJlYWRvbmx5IHVwZGF0ZWRBdD86IHN0cmluZztcbiAgcHJpdmF0ZSByZWFkb25seSBfZW5kcG9pbnRzOiBSb3V0ZXJJbnB1dEVuZHBvaW50W10gfCB1bmRlZmluZWQ7XG4gIHB1YmxpYyByZWFkb25seSB0cmFuc2l0RW5jcnlwdGlvblNlY3JldD86IElTZWNyZXQ7XG4gIHB1YmxpYyByZWFkb25seSBncmFudHM6IFJvdXRlcklucHV0R3JhbnRzO1xuXG4gIHB1YmxpYyBnZXQgZW5kcG9pbnRzKCk6IFJvdXRlcklucHV0RW5kcG9pbnRbXSB7XG4gICAgaWYgKHRoaXMuX2VuZHBvaW50cyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKFxuICAgICAgICBsaXRgUm91dGVySW5wdXRFbmRwb2ludHNOb3RBdmFpbGFibGVDb25maWdgLFxuICAgICAgICBgJ2VuZHBvaW50cycgaXMgbm90IGF2YWlsYWJsZSBvbiB0aGlzIFJvdXRlcklucHV0ICR7dGhpcy5ub2RlLnBhdGh9OyBvbmx5IGxpc3RlbmluZyBwcm90b2NvbCB2YXJpYW50cyAoUlRQLCBSSVNULCBTUlQgbGlzdGVuZXIg4oCUIGluY2x1ZGluZyBmYWlsb3ZlciBhbmQgbWVyZ2UgYnVpbHQgZnJvbSB0aG9zZSkgZXhwb3NlIGluZ2VzdCBlbmRwb2ludHMg4oCUIFNSVCBjYWxsZXIsIE1lZGlhQ29ubmVjdCBGbG93LCBhbmQgTWVkaWFMaXZlIENoYW5uZWwgaW5wdXRzIGRvIG5vdGAsXG4gICAgICAgIHRoaXMsXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fZW5kcG9pbnRzO1xuICB9XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IFJvdXRlcklucHV0UHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQsIHtcbiAgICAgIHBoeXNpY2FsTmFtZTogcHJvcHMucm91dGVySW5wdXROYW1lID8/IExhenkuc3RyaW5nKHsgcHJvZHVjZTogKCkgPT4gTmFtZXMudW5pcXVlUmVzb3VyY2VOYW1lKHRoaXMsIHsgbWF4TGVuZ3RoOiAxMjggfSkgfSksXG4gICAgfSk7XG5cbiAgICAvLyBWYWxpZGF0ZSByb3V0ZXIgaW5wdXQgbmFtZSBpZiBwcm92aWRlZFxuICAgIGlmIChwcm9wcy5yb3V0ZXJJbnB1dE5hbWUgIT0gbnVsbCAmJiBwcm9wcy5yb3V0ZXJJbnB1dE5hbWUgIT09ICcnICYmICFUb2tlbi5pc1VucmVzb2x2ZWQocHJvcHMucm91dGVySW5wdXROYW1lKSkge1xuICAgICAgaWYgKHByb3BzLnJvdXRlcklucHV0TmFtZS5sZW5ndGggPiAxMjgpIHtcbiAgICAgICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihsaXRgUm91dGVySW5wdXROYW1lTGVuZ3RoYCwgYFJvdXRlciBpbnB1dCBuYW1lIG11c3QgYmUgYmV0d2VlbiAxIGFuZCAxMjggY2hhcmFjdGVycywgZ290ICR7cHJvcHMucm91dGVySW5wdXROYW1lLmxlbmd0aH1gLCB0aGlzKTtcbiAgICAgIH1cbiAgICAgIGlmICghL15bYS16QS1aMC05LV0rJC8udGVzdChwcm9wcy5yb3V0ZXJJbnB1dE5hbWUpKSB7XG4gICAgICAgIHRocm93IG5ldyBWYWxpZGF0aW9uRXJyb3IobGl0YFJvdXRlcklucHV0TmFtZUZvcm1hdGAsIGBSb3V0ZXIgaW5wdXQgbmFtZSBtdXN0IGNvbnRhaW4gb25seSBhbHBoYW51bWVyaWMgY2hhcmFjdGVycyBhbmQgaHlwaGVucywgZ290ICcke3Byb3BzLnJvdXRlcklucHV0TmFtZX0nYCwgdGhpcyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gVmFsaWRhdGUgbWF4aW11bSBiaXRyYXRlXG4gICAgaWYgKCFwcm9wcy5tYXhpbXVtQml0cmF0ZS5pc1VucmVzb2x2ZWQoKSAmJiBwcm9wcy5tYXhpbXVtQml0cmF0ZS50b0JwcygpIDwgMTAwMDAwMCkge1xuICAgICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihsaXRgUm91dGVySW5wdXRNaW5CaXRyYXRlYCwgYE1heGltdW0gYml0cmF0ZSBtdXN0IGJlIGF0IGxlYXN0IDEsMDAwLDAwMCBiaXRzL3MgKDEgTWJwcyksIGdvdCAke3Byb3BzLm1heGltdW1CaXRyYXRlLnRvQnBzKCl9YCwgdGhpcyk7XG4gICAgfVxuXG4gICAgLy8gVmFsaWRhdGUgYml0cmF0ZSBkb2VzIG5vdCBleGNlZWQgdGllciBsaW1pdFxuICAgIGNvbnN0IHJlc29sdmVkVGllciA9IHByb3BzLnRpZXIgPz8gUm91dGVySW5wdXRUaWVyLklOUFVUXzIwO1xuICAgIGNvbnN0IHRpZXJNYnBzID0gUm91dGVySW5wdXQudGllckxpbWl0TWJwcyhyZXNvbHZlZFRpZXIpO1xuICAgIGlmIChleGNlZWRzUm91dGVyVGllckJpdHJhdGUodGllck1icHMsIHByb3BzLm1heGltdW1CaXRyYXRlKSkge1xuICAgICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihsaXRgUm91dGVySW5wdXRCaXRyYXRlRXhjZWVkc1RpZXJgLCBgTWF4aW11bSBiaXRyYXRlICR7cHJvcHMubWF4aW11bUJpdHJhdGUudG9CcHMoKSAvIDFfMDAwXzAwMH0gTWJwcyBleGNlZWRzIHRoZSAke3Jlc29sdmVkVGllci52YWx1ZX0gdGllciBsaW1pdCBvZiAke3RpZXJNYnBzfSBNYnBzYCwgdGhpcyk7XG4gICAgfVxuXG4gICAgLy8gVmFsaWRhdGUgbWFpbnRlbmFuY2UgdGltZSBmb3JtYXRcbiAgICBpZiAocHJvcHMubWFpbnRlbmFuY2VDb25maWd1cmF0aW9uKSB7XG4gICAgICB2YWxpZGF0ZU1haW50ZW5hbmNlVGltZShwcm9wcy5tYWludGVuYW5jZUNvbmZpZ3VyYXRpb24udGltZSk7XG4gICAgfVxuXG4gICAgLy8gRW5oYW5jZWQgQ0RLIEFuYWx5dGljcyBUZWxlbWV0cnlcbiAgICBhZGRDb25zdHJ1Y3RNZXRhZGF0YSh0aGlzLCBwcm9wcyk7XG5cbiAgICBjb25zdCBzdGFjayA9IFN0YWNrLm9mKHRoaXMpO1xuICAgIGNvbnN0IHRhcmdldFJlZ2lvbiA9IHByb3BzLnJlZ2lvbk5hbWUgPz8gc3RhY2sucmVnaW9uO1xuXG4gICAgLy8gV2lsZGNhcmQgdGhlIGlkIOKAlCBwaW5uaW5nIHRoZSBsaXZlIEFSTiAoYXR0ckFybikgd291bGQgY3JlYXRlIGEgcm9sZSDihpIgcm91dGVyLWlucHV0IOKGkiByb2xlIGN5Y2xlLlxuICAgIGNvbnN0IHJvdXRlcklucHV0QXJuID0gc3RhY2suZm9ybWF0QXJuKHtcbiAgICAgIHNlcnZpY2U6ICdtZWRpYWNvbm5lY3QnLFxuICAgICAgcmVnaW9uOiB0YXJnZXRSZWdpb24sXG4gICAgICByZXNvdXJjZTogJ3JvdXRlcklucHV0JyxcbiAgICAgIHJlc291cmNlTmFtZTogJyonLFxuICAgICAgYXJuRm9ybWF0OiBBcm5Gb3JtYXQuQ09MT05fUkVTT1VSQ0VfTkFNRSxcbiAgICB9KTtcblxuICAgIGNvbnN0IGNvbmZpZ0JpbmQgPSBwcm9wcy5jb25maWd1cmF0aW9uLl9iaW5kKHRoaXMsIHJvdXRlcklucHV0QXJuKTtcblxuICAgIC8vIFZhbGlkYXRlIEFaIG1hdGNoZXMgcmVnaW9uIGlmIHByb3ZpZGVkXG4gICAgaWYgKGNvbmZpZ0JpbmQuYXZhaWxhYmlsaXR5Wm9uZSAmJiAhY29uZmlnQmluZC5hdmFpbGFiaWxpdHlab25lLnN0YXJ0c1dpdGgodGFyZ2V0UmVnaW9uKSkge1xuICAgICAgdGhyb3cgbmV3IFZhbGlkYXRpb25FcnJvcihsaXRgUm91dGVySW5wdXRBelJlZ2lvbk1pc21hdGNoYCwgYEF2YWlsYWJpbGl0eSB6b25lICcke2NvbmZpZ0JpbmQuYXZhaWxhYmlsaXR5Wm9uZX0nIG11c3QgYmUgd2l0aGluIHJlZ2lvbiAnJHt0YXJnZXRSZWdpb259J2AsIHRoaXMpO1xuICAgIH1cblxuICAgIGNvbnN0IHRyYW5zaXQgPSByZXNvbHZlVHJhbnNpdEVuY3J5cHRpb24odGhpcywgJ1RyYW5zaXRFbmNyeXB0aW9uUm9sZScsIHByb3BzLnRyYW5zaXRFbmNyeXB0aW9uLCByb3V0ZXJJbnB1dEFybik7XG5cbiAgICBjb25zdCByb3V0ZXJpbnB1dCA9IG5ldyBDZm5Sb3V0ZXJJbnB1dCh0aGlzLCAnUmVzb3VyY2UnLCB7XG4gICAgICBuYW1lOiB0aGlzLnBoeXNpY2FsTmFtZSxcbiAgICAgIG1heGltdW1CaXRyYXRlOiBwcm9wcy5tYXhpbXVtQml0cmF0ZS50b0JwcygpLFxuICAgICAgdGllcjogKHByb3BzLnRpZXIgPz8gUm91dGVySW5wdXRUaWVyLklOUFVUXzIwKS52YWx1ZSxcbiAgICAgIHJvdXRpbmdTY29wZTogcHJvcHMucm91dGluZ1Njb3BlLnZhbHVlLFxuICAgICAgbWFpbnRlbmFuY2VDb25maWd1cmF0aW9uOiBwcm9wcy5tYWludGVuYW5jZUNvbmZpZ3VyYXRpb24gPyB7XG4gICAgICAgIHByZWZlcnJlZERheVRpbWU6IHByb3BzLm1haW50ZW5hbmNlQ29uZmlndXJhdGlvbixcbiAgICAgIH0gOiB7XG4gICAgICAgIGRlZmF1bHQ6IHt9LFxuICAgICAgfSxcbiAgICAgIGNvbmZpZ3VyYXRpb246IGNvbmZpZ0JpbmQuY29uZmlnLFxuICAgICAgdHJhbnNpdEVuY3J5cHRpb246IHRyYW5zaXQuY29uZmlnLFxuICAgICAgcmVnaW9uTmFtZTogdGFyZ2V0UmVnaW9uLFxuICAgICAgYXZhaWxhYmlsaXR5Wm9uZTogY29uZmlnQmluZC5hdmFpbGFiaWxpdHlab25lLFxuICAgICAgdGFnczogcHJvcHMudGFncyA/IHJlbmRlclRhZ3MocHJvcHMudGFncykgOiB1bmRlZmluZWQsXG4gICAgfSk7XG5cbiAgICB0aGlzLnJvdXRlcklucHV0QXJuID0gcm91dGVyaW5wdXQuYXR0ckFybjtcbiAgICB0aGlzLnJvdXRlcklucHV0SWQgPSByb3V0ZXJpbnB1dC5hdHRySWQ7XG4gICAgdGhpcy5pcEFkZHJlc3MgPSByb3V0ZXJpbnB1dC5hdHRySXBBZGRyZXNzO1xuICAgIHRoaXMuY3JlYXRlZEF0ID0gcm91dGVyaW5wdXQuYXR0ckNyZWF0ZWRBdDtcbiAgICB0aGlzLnVwZGF0ZWRBdCA9IHJvdXRlcmlucHV0LmF0dHJVcGRhdGVkQXQ7XG5cbiAgICAvLyBXaXRob3V0IHRoaXMgdGhlIHJvdXRlciBpbnB1dCBjYW4gYmUgY3JlYXRlZCBiZWZvcmUgdGhlXG4gICAgLy8gcG9saWN5IGlzIGF0dGFjaGVkIChcImFjY2VzcyBkZW5pZWRcIiBhdCBjcmVhdGUgdGltZSkuIE9yZGVyaW5nIHRoZSBncmFudCBiZWZvcmUgdGhlXG4gICAgLy8gcm91dGVyIGlucHV0IHB1bGxzIHRoZSBwb2xpY3kgaW4gYXMgYSBkZXBlbmRlbmN5LlxuICAgIHRyYW5zaXQuZ3JhbnQ/LmFwcGx5QmVmb3JlKHJvdXRlcmlucHV0KTtcblxuICAgIC8vIENvbXB1dGUgaW5nZXN0IGVuZHBvaW50cyBmb3IgcHJvdG9jb2wtYmFzZWQgdmFyaWFudHNcbiAgICB0aGlzLl9lbmRwb2ludHMgPSBwcm9wcy5jb25maWd1cmF0aW9uLl9lbmRwb2ludHMocm91dGVyaW5wdXQuYXR0cklwQWRkcmVzcyk7XG5cbiAgICAvLyBTdG9yZSB0aGUgdHJhbnNpdCBlbmNyeXB0aW9uIHNlY3JldCBpZiBleHBsaWNpdGx5IHByb3ZpZGVkXG4gICAgdGhpcy50cmFuc2l0RW5jcnlwdGlvblNlY3JldCA9IHByb3BzLnRyYW5zaXRFbmNyeXB0aW9uPy5zZWNyZXQ7XG4gICAgdGhpcy5ncmFudHMgPSBSb3V0ZXJJbnB1dEdyYW50cy5mcm9tUm91dGVySW5wdXQodGhpcyk7XG4gIH1cbn1cblxuIl19
|