@angular/router 16.0.0-next.4 → 16.0.0-next.6
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/esm2022/src/apply_redirects.mjs +112 -0
- package/{esm2020 → esm2022}/src/components/empty_outlet.mjs +4 -4
- package/esm2022/src/create_url_tree.mjs +418 -0
- package/{esm2020 → esm2022}/src/directives/router_link.mjs +4 -4
- package/{esm2020 → esm2022}/src/directives/router_link_active.mjs +4 -4
- package/esm2022/src/directives/router_outlet.mjs +336 -0
- package/esm2022/src/index.mjs +30 -0
- package/esm2022/src/navigation_transition.mjs +397 -0
- package/esm2022/src/operators/activate_routes.mjs +192 -0
- package/{esm2020 → esm2022}/src/operators/check_guards.mjs +1 -1
- package/esm2022/src/operators/recognize.mjs +16 -0
- package/{esm2020 → esm2022}/src/page_title_strategy.mjs +7 -7
- package/esm2022/src/provide_router.mjs +507 -0
- package/esm2022/src/recognize.mjs +360 -0
- package/{esm2020 → esm2022}/src/route_reuse_strategy.mjs +7 -7
- package/esm2022/src/router.mjs +724 -0
- package/esm2022/src/router_config.mjs +18 -0
- package/esm2022/src/router_config_loader.mjs +132 -0
- package/esm2022/src/router_module.mjs +220 -0
- package/{esm2020 → esm2022}/src/router_outlet_context.mjs +4 -4
- package/esm2022/src/router_preloader.mjs +167 -0
- package/{esm2020 → esm2022}/src/router_scroller.mjs +4 -4
- package/esm2022/src/router_state.mjs +408 -0
- package/{esm2020 → esm2022}/src/url_handling_strategy.mjs +7 -7
- package/esm2022/src/url_tree.mjs +642 -0
- package/esm2022/src/utils/navigations.mjs +42 -0
- package/esm2022/src/utils/type_guards.mjs +54 -0
- package/{esm2020 → esm2022}/src/version.mjs +1 -1
- package/{esm2020 → esm2022}/testing/src/router_testing_harness.mjs +7 -7
- package/{esm2020 → esm2022}/testing/src/router_testing_module.mjs +10 -10
- package/{fesm2020 → fesm2022}/router.mjs +799 -787
- package/fesm2022/router.mjs.map +1 -0
- package/{fesm2020 → fesm2022}/testing.mjs +16 -16
- package/{fesm2020 → fesm2022}/testing.mjs.map +1 -1
- package/{fesm2020 → fesm2022}/upgrade.mjs +1 -1
- package/index.d.ts +92 -5
- package/package.json +14 -24
- package/testing/index.d.ts +1 -1
- package/upgrade/index.d.ts +1 -1
- package/esm2020/src/apply_redirects.mjs +0 -331
- package/esm2020/src/create_url_tree.mjs +0 -417
- package/esm2020/src/directives/router_outlet.mjs +0 -259
- package/esm2020/src/index.mjs +0 -30
- package/esm2020/src/navigation_transition.mjs +0 -399
- package/esm2020/src/operators/activate_routes.mjs +0 -177
- package/esm2020/src/operators/apply_redirects.mjs +0 -14
- package/esm2020/src/operators/recognize.mjs +0 -14
- package/esm2020/src/provide_router.mjs +0 -477
- package/esm2020/src/recognize.mjs +0 -270
- package/esm2020/src/router.mjs +0 -710
- package/esm2020/src/router_config.mjs +0 -19
- package/esm2020/src/router_config_loader.mjs +0 -131
- package/esm2020/src/router_module.mjs +0 -216
- package/esm2020/src/router_preloader.mjs +0 -167
- package/esm2020/src/router_state.mjs +0 -409
- package/esm2020/src/url_tree.mjs +0 -631
- package/esm2020/src/utils/navigations.mjs +0 -42
- package/esm2020/src/utils/type_guards.mjs +0 -54
- package/fesm2015/router.mjs +0 -7001
- package/fesm2015/router.mjs.map +0 -1
- package/fesm2015/testing.mjs +0 -270
- package/fesm2015/testing.mjs.map +0 -1
- package/fesm2015/upgrade.mjs +0 -146
- package/fesm2015/upgrade.mjs.map +0 -1
- package/fesm2020/router.mjs.map +0 -1
- /package/{esm2020 → esm2022}/index.mjs +0 -0
- /package/{esm2020 → esm2022}/public_api.mjs +0 -0
- /package/{esm2020 → esm2022}/router.mjs +0 -0
- /package/{esm2020 → esm2022}/src/create_router_state.mjs +0 -0
- /package/{esm2020 → esm2022}/src/errors.mjs +0 -0
- /package/{esm2020 → esm2022}/src/events.mjs +0 -0
- /package/{esm2020 → esm2022}/src/models.mjs +0 -0
- /package/{esm2020 → esm2022}/src/models_deprecated.mjs +0 -0
- /package/{esm2020 → esm2022}/src/navigation_canceling_error.mjs +0 -0
- /package/{esm2020 → esm2022}/src/operators/prioritized_guard_value.mjs +0 -0
- /package/{esm2020 → esm2022}/src/operators/resolve_data.mjs +0 -0
- /package/{esm2020 → esm2022}/src/operators/switch_tap.mjs +0 -0
- /package/{esm2020 → esm2022}/src/private_export.mjs +0 -0
- /package/{esm2020 → esm2022}/src/shared.mjs +0 -0
- /package/{esm2020 → esm2022}/src/utils/collection.mjs +0 -0
- /package/{esm2020 → esm2022}/src/utils/config.mjs +0 -0
- /package/{esm2020 → esm2022}/src/utils/config_matching.mjs +0 -0
- /package/{esm2020 → esm2022}/src/utils/functional_guards.mjs +0 -0
- /package/{esm2020 → esm2022}/src/utils/preactivation.mjs +0 -0
- /package/{esm2020 → esm2022}/src/utils/tree.mjs +0 -0
- /package/{esm2020 → esm2022}/testing/index.mjs +0 -0
- /package/{esm2020 → esm2022}/testing/public_api.mjs +0 -0
- /package/{esm2020 → esm2022}/testing/src/testing.mjs +0 -0
- /package/{esm2020 → esm2022}/testing/testing.mjs +0 -0
- /package/{esm2020 → esm2022}/upgrade/index.mjs +0 -0
- /package/{esm2020 → esm2022}/upgrade/public_api.mjs +0 -0
- /package/{esm2020 → esm2022}/upgrade/src/upgrade.mjs +0 -0
- /package/{esm2020 → esm2022}/upgrade/upgrade.mjs +0 -0
- /package/{fesm2020 → fesm2022}/upgrade.mjs.map +0 -0
package/esm2020/src/router.mjs
DELETED
|
@@ -1,710 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright Google LLC All Rights Reserved.
|
|
4
|
-
*
|
|
5
|
-
* Use of this source code is governed by an MIT-style license that can be
|
|
6
|
-
* found in the LICENSE file at https://angular.io/license
|
|
7
|
-
*/
|
|
8
|
-
import { Location } from '@angular/common';
|
|
9
|
-
import { inject, Injectable, NgZone, ɵConsole as Console, ɵRuntimeError as RuntimeError } from '@angular/core';
|
|
10
|
-
import { createSegmentGroupFromRoute, createUrlTreeFromSegmentGroup } from './create_url_tree';
|
|
11
|
-
import { IMPERATIVE_NAVIGATION } from './events';
|
|
12
|
-
import { NavigationTransitions } from './navigation_transition';
|
|
13
|
-
import { TitleStrategy } from './page_title_strategy';
|
|
14
|
-
import { RouteReuseStrategy } from './route_reuse_strategy';
|
|
15
|
-
import { ROUTER_CONFIGURATION } from './router_config';
|
|
16
|
-
import { ROUTES } from './router_config_loader';
|
|
17
|
-
import { createEmptyState } from './router_state';
|
|
18
|
-
import { UrlHandlingStrategy } from './url_handling_strategy';
|
|
19
|
-
import { containsTree, isUrlTree, UrlSerializer, UrlTree } from './url_tree';
|
|
20
|
-
import { standardizeConfig, validateConfig } from './utils/config';
|
|
21
|
-
import * as i0 from "@angular/core";
|
|
22
|
-
const NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode;
|
|
23
|
-
function defaultErrorHandler(error) {
|
|
24
|
-
throw error;
|
|
25
|
-
}
|
|
26
|
-
function defaultMalformedUriErrorHandler(error, urlSerializer, url) {
|
|
27
|
-
return urlSerializer.parse('/');
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* The equivalent `IsActiveMatchOptions` options for `Router.isActive` is called with `true`
|
|
31
|
-
* (exact = true).
|
|
32
|
-
*/
|
|
33
|
-
export const exactMatchOptions = {
|
|
34
|
-
paths: 'exact',
|
|
35
|
-
fragment: 'ignored',
|
|
36
|
-
matrixParams: 'ignored',
|
|
37
|
-
queryParams: 'exact'
|
|
38
|
-
};
|
|
39
|
-
/**
|
|
40
|
-
* The equivalent `IsActiveMatchOptions` options for `Router.isActive` is called with `false`
|
|
41
|
-
* (exact = false).
|
|
42
|
-
*/
|
|
43
|
-
export const subsetMatchOptions = {
|
|
44
|
-
paths: 'subset',
|
|
45
|
-
fragment: 'ignored',
|
|
46
|
-
matrixParams: 'ignored',
|
|
47
|
-
queryParams: 'subset'
|
|
48
|
-
};
|
|
49
|
-
/**
|
|
50
|
-
* @description
|
|
51
|
-
*
|
|
52
|
-
* A service that provides navigation among views and URL manipulation capabilities.
|
|
53
|
-
*
|
|
54
|
-
* @see `Route`.
|
|
55
|
-
* @see [Routing and Navigation Guide](guide/router).
|
|
56
|
-
*
|
|
57
|
-
* @ngModule RouterModule
|
|
58
|
-
*
|
|
59
|
-
* @publicApi
|
|
60
|
-
*/
|
|
61
|
-
class Router {
|
|
62
|
-
// TODO(b/260747083): This should not exist and navigationId should be private in
|
|
63
|
-
// `NavigationTransitions`
|
|
64
|
-
get navigationId() {
|
|
65
|
-
return this.navigationTransitions.navigationId;
|
|
66
|
-
}
|
|
67
|
-
/**
|
|
68
|
-
* The ɵrouterPageId of whatever page is currently active in the browser history. This is
|
|
69
|
-
* important for computing the target page id for new navigations because we need to ensure each
|
|
70
|
-
* page id in the browser history is 1 more than the previous entry.
|
|
71
|
-
*/
|
|
72
|
-
get browserPageId() {
|
|
73
|
-
return this.location.getState()?.ɵrouterPageId;
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* An event stream for routing events.
|
|
77
|
-
*/
|
|
78
|
-
get events() {
|
|
79
|
-
// TODO(atscott): This _should_ be events.asObservable(). However, this change requires internal
|
|
80
|
-
// cleanup: tests are doing `(route.events as Subject<Event>).next(...)`. This isn't
|
|
81
|
-
// allowed/supported but we still have to fix these or file bugs against the teams before making
|
|
82
|
-
// the change.
|
|
83
|
-
return this.navigationTransitions.events;
|
|
84
|
-
}
|
|
85
|
-
constructor() {
|
|
86
|
-
this.disposed = false;
|
|
87
|
-
/**
|
|
88
|
-
* The id of the currently active page in the router.
|
|
89
|
-
* Updated to the transition's target id on a successful navigation.
|
|
90
|
-
*
|
|
91
|
-
* This is used to track what page the router last activated. When an attempted navigation fails,
|
|
92
|
-
* the router can then use this to compute how to restore the state back to the previously active
|
|
93
|
-
* page.
|
|
94
|
-
*/
|
|
95
|
-
this.currentPageId = 0;
|
|
96
|
-
this.console = inject(Console);
|
|
97
|
-
this.isNgZoneEnabled = false;
|
|
98
|
-
this.options = inject(ROUTER_CONFIGURATION, { optional: true }) || {};
|
|
99
|
-
/**
|
|
100
|
-
* A handler for navigation errors in this NgModule.
|
|
101
|
-
*
|
|
102
|
-
* @deprecated Subscribe to the `Router` events and watch for `NavigationError` instead.
|
|
103
|
-
* `provideRouter` has the `withNavigationErrorHandler` feature to make this easier.
|
|
104
|
-
* @see `withNavigationErrorHandler`
|
|
105
|
-
*/
|
|
106
|
-
this.errorHandler = this.options.errorHandler || defaultErrorHandler;
|
|
107
|
-
/**
|
|
108
|
-
* A handler for errors thrown by `Router.parseUrl(url)`
|
|
109
|
-
* when `url` contains an invalid character.
|
|
110
|
-
* The most common case is a `%` sign
|
|
111
|
-
* that's not encoded and is not part of a percent encoded sequence.
|
|
112
|
-
*
|
|
113
|
-
* @deprecated URI parsing errors should be handled in the `UrlSerializer`.
|
|
114
|
-
*
|
|
115
|
-
* @see `RouterModule`
|
|
116
|
-
*/
|
|
117
|
-
this.malformedUriErrorHandler = this.options.malformedUriErrorHandler || defaultMalformedUriErrorHandler;
|
|
118
|
-
/**
|
|
119
|
-
* True if at least one navigation event has occurred,
|
|
120
|
-
* false otherwise.
|
|
121
|
-
*/
|
|
122
|
-
this.navigated = false;
|
|
123
|
-
this.lastSuccessfulId = -1;
|
|
124
|
-
/**
|
|
125
|
-
* A strategy for extracting and merging URLs.
|
|
126
|
-
* Used for AngularJS to Angular migrations.
|
|
127
|
-
*
|
|
128
|
-
* @deprecated Configure using `providers` instead:
|
|
129
|
-
* `{provide: UrlHandlingStrategy, useClass: MyStrategy}`.
|
|
130
|
-
*/
|
|
131
|
-
this.urlHandlingStrategy = inject(UrlHandlingStrategy);
|
|
132
|
-
/**
|
|
133
|
-
* A strategy for re-using routes.
|
|
134
|
-
*
|
|
135
|
-
* @deprecated Configure using `providers` instead:
|
|
136
|
-
* `{provide: RouteReuseStrategy, useClass: MyStrategy}`.
|
|
137
|
-
*/
|
|
138
|
-
this.routeReuseStrategy = inject(RouteReuseStrategy);
|
|
139
|
-
/**
|
|
140
|
-
* A strategy for setting the title based on the `routerState`.
|
|
141
|
-
*
|
|
142
|
-
* @deprecated Configure using `providers` instead:
|
|
143
|
-
* `{provide: TitleStrategy, useClass: MyStrategy}`.
|
|
144
|
-
*/
|
|
145
|
-
this.titleStrategy = inject(TitleStrategy);
|
|
146
|
-
/**
|
|
147
|
-
* How to handle a navigation request to the current URL.
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
* @deprecated Configure this through `provideRouter` or `RouterModule.forRoot` instead.
|
|
151
|
-
* @see `withRouterConfig`
|
|
152
|
-
* @see `provideRouter`
|
|
153
|
-
* @see `RouterModule`
|
|
154
|
-
*/
|
|
155
|
-
this.onSameUrlNavigation = this.options.onSameUrlNavigation || 'ignore';
|
|
156
|
-
/**
|
|
157
|
-
* How to merge parameters, data, resolved data, and title from parent to child
|
|
158
|
-
* routes. One of:
|
|
159
|
-
*
|
|
160
|
-
* - `'emptyOnly'` : Inherit parent parameters, data, and resolved data
|
|
161
|
-
* for path-less or component-less routes.
|
|
162
|
-
* - `'always'` : Inherit parent parameters, data, and resolved data
|
|
163
|
-
* for all child routes.
|
|
164
|
-
*
|
|
165
|
-
* @deprecated Configure this through `provideRouter` or `RouterModule.forRoot` instead.
|
|
166
|
-
* @see `withRouterConfig`
|
|
167
|
-
* @see `provideRouter`
|
|
168
|
-
* @see `RouterModule`
|
|
169
|
-
*/
|
|
170
|
-
this.paramsInheritanceStrategy = this.options.paramsInheritanceStrategy || 'emptyOnly';
|
|
171
|
-
/**
|
|
172
|
-
* Determines when the router updates the browser URL.
|
|
173
|
-
* By default (`"deferred"`), updates the browser URL after navigation has finished.
|
|
174
|
-
* Set to `'eager'` to update the browser URL at the beginning of navigation.
|
|
175
|
-
* You can choose to update early so that, if navigation fails,
|
|
176
|
-
* you can show an error message with the URL that failed.
|
|
177
|
-
*
|
|
178
|
-
* @deprecated Configure this through `provideRouter` or `RouterModule.forRoot` instead.
|
|
179
|
-
* @see `withRouterConfig`
|
|
180
|
-
* @see `provideRouter`
|
|
181
|
-
* @see `RouterModule`
|
|
182
|
-
*/
|
|
183
|
-
this.urlUpdateStrategy = this.options.urlUpdateStrategy || 'deferred';
|
|
184
|
-
/**
|
|
185
|
-
* Configures how the Router attempts to restore state when a navigation is cancelled.
|
|
186
|
-
*
|
|
187
|
-
* 'replace' - Always uses `location.replaceState` to set the browser state to the state of the
|
|
188
|
-
* router before the navigation started. This means that if the URL of the browser is updated
|
|
189
|
-
* _before_ the navigation is canceled, the Router will simply replace the item in history rather
|
|
190
|
-
* than trying to restore to the previous location in the session history. This happens most
|
|
191
|
-
* frequently with `urlUpdateStrategy: 'eager'` and navigations with the browser back/forward
|
|
192
|
-
* buttons.
|
|
193
|
-
*
|
|
194
|
-
* 'computed' - Will attempt to return to the same index in the session history that corresponds
|
|
195
|
-
* to the Angular route when the navigation gets cancelled. For example, if the browser back
|
|
196
|
-
* button is clicked and the navigation is cancelled, the Router will trigger a forward navigation
|
|
197
|
-
* and vice versa.
|
|
198
|
-
*
|
|
199
|
-
* Note: the 'computed' option is incompatible with any `UrlHandlingStrategy` which only
|
|
200
|
-
* handles a portion of the URL because the history restoration navigates to the previous place in
|
|
201
|
-
* the browser history rather than simply resetting a portion of the URL.
|
|
202
|
-
*
|
|
203
|
-
* The default value is `replace`.
|
|
204
|
-
*
|
|
205
|
-
* @deprecated Configure this through `provideRouter` or `RouterModule.forRoot` instead.
|
|
206
|
-
* @see `withRouterConfig`
|
|
207
|
-
* @see `provideRouter`
|
|
208
|
-
* @see `RouterModule`
|
|
209
|
-
*/
|
|
210
|
-
this.canceledNavigationResolution = this.options.canceledNavigationResolution || 'replace';
|
|
211
|
-
this.config = inject(ROUTES, { optional: true })?.flat() ?? [];
|
|
212
|
-
this.navigationTransitions = inject(NavigationTransitions);
|
|
213
|
-
this.urlSerializer = inject(UrlSerializer);
|
|
214
|
-
this.location = inject(Location);
|
|
215
|
-
this.isNgZoneEnabled = inject(NgZone) instanceof NgZone && NgZone.isInAngularZone();
|
|
216
|
-
this.resetConfig(this.config);
|
|
217
|
-
this.currentUrlTree = new UrlTree();
|
|
218
|
-
this.rawUrlTree = this.currentUrlTree;
|
|
219
|
-
this.browserUrlTree = this.currentUrlTree;
|
|
220
|
-
this.routerState = createEmptyState(this.currentUrlTree, null);
|
|
221
|
-
this.navigationTransitions.setupNavigations(this).subscribe(t => {
|
|
222
|
-
this.lastSuccessfulId = t.id;
|
|
223
|
-
this.currentPageId = t.targetPageId;
|
|
224
|
-
}, e => {
|
|
225
|
-
this.console.warn(`Unhandled Navigation Error: ${e}`);
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
|
-
/** @internal */
|
|
229
|
-
resetRootComponentType(rootComponentType) {
|
|
230
|
-
// TODO: vsavkin router 4.0 should make the root component set to null
|
|
231
|
-
// this will simplify the lifecycle of the router.
|
|
232
|
-
this.routerState.root.component = rootComponentType;
|
|
233
|
-
this.navigationTransitions.rootComponentType = rootComponentType;
|
|
234
|
-
}
|
|
235
|
-
/**
|
|
236
|
-
* Sets up the location change listener and performs the initial navigation.
|
|
237
|
-
*/
|
|
238
|
-
initialNavigation() {
|
|
239
|
-
this.setUpLocationChangeListener();
|
|
240
|
-
if (!this.navigationTransitions.hasRequestedNavigation) {
|
|
241
|
-
const state = this.location.getState();
|
|
242
|
-
this.navigateToSyncWithBrowser(this.location.path(true), IMPERATIVE_NAVIGATION, state);
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
/**
|
|
246
|
-
* Sets up the location change listener. This listener detects navigations triggered from outside
|
|
247
|
-
* the Router (the browser back/forward buttons, for example) and schedules a corresponding Router
|
|
248
|
-
* navigation so that the correct events, guards, etc. are triggered.
|
|
249
|
-
*/
|
|
250
|
-
setUpLocationChangeListener() {
|
|
251
|
-
// Don't need to use Zone.wrap any more, because zone.js
|
|
252
|
-
// already patch onPopState, so location change callback will
|
|
253
|
-
// run into ngZone
|
|
254
|
-
if (!this.locationSubscription) {
|
|
255
|
-
this.locationSubscription = this.location.subscribe(event => {
|
|
256
|
-
const source = event['type'] === 'popstate' ? 'popstate' : 'hashchange';
|
|
257
|
-
if (source === 'popstate') {
|
|
258
|
-
// The `setTimeout` was added in #12160 and is likely to support Angular/AngularJS
|
|
259
|
-
// hybrid apps.
|
|
260
|
-
setTimeout(() => {
|
|
261
|
-
this.navigateToSyncWithBrowser(event['url'], source, event.state);
|
|
262
|
-
}, 0);
|
|
263
|
-
}
|
|
264
|
-
});
|
|
265
|
-
}
|
|
266
|
-
}
|
|
267
|
-
/**
|
|
268
|
-
* Schedules a router navigation to synchronize Router state with the browser state.
|
|
269
|
-
*
|
|
270
|
-
* This is done as a response to a popstate event and the initial navigation. These
|
|
271
|
-
* two scenarios represent times when the browser URL/state has been updated and
|
|
272
|
-
* the Router needs to respond to ensure its internal state matches.
|
|
273
|
-
*/
|
|
274
|
-
navigateToSyncWithBrowser(url, source, state) {
|
|
275
|
-
const extras = { replaceUrl: true };
|
|
276
|
-
// TODO: restoredState should always include the entire state, regardless
|
|
277
|
-
// of navigationId. This requires a breaking change to update the type on
|
|
278
|
-
// NavigationStart’s restoredState, which currently requires navigationId
|
|
279
|
-
// to always be present. The Router used to only restore history state if
|
|
280
|
-
// a navigationId was present.
|
|
281
|
-
// The stored navigationId is used by the RouterScroller to retrieve the scroll
|
|
282
|
-
// position for the page.
|
|
283
|
-
const restoredState = state?.navigationId ? state : null;
|
|
284
|
-
// Separate to NavigationStart.restoredState, we must also restore the state to
|
|
285
|
-
// history.state and generate a new navigationId, since it will be overwritten
|
|
286
|
-
if (state) {
|
|
287
|
-
const stateCopy = { ...state };
|
|
288
|
-
delete stateCopy.navigationId;
|
|
289
|
-
delete stateCopy.ɵrouterPageId;
|
|
290
|
-
if (Object.keys(stateCopy).length !== 0) {
|
|
291
|
-
extras.state = stateCopy;
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
const urlTree = this.parseUrl(url);
|
|
295
|
-
this.scheduleNavigation(urlTree, source, restoredState, extras);
|
|
296
|
-
}
|
|
297
|
-
/** The current URL. */
|
|
298
|
-
get url() {
|
|
299
|
-
return this.serializeUrl(this.currentUrlTree);
|
|
300
|
-
}
|
|
301
|
-
/**
|
|
302
|
-
* Returns the current `Navigation` object when the router is navigating,
|
|
303
|
-
* and `null` when idle.
|
|
304
|
-
*/
|
|
305
|
-
getCurrentNavigation() {
|
|
306
|
-
return this.navigationTransitions.currentNavigation;
|
|
307
|
-
}
|
|
308
|
-
/**
|
|
309
|
-
* The `Navigation` object of the most recent navigation to succeed and `null` if there
|
|
310
|
-
* has not been a successful navigation yet.
|
|
311
|
-
*/
|
|
312
|
-
get lastSuccessfulNavigation() {
|
|
313
|
-
return this.navigationTransitions.lastSuccessfulNavigation;
|
|
314
|
-
}
|
|
315
|
-
/**
|
|
316
|
-
* Resets the route configuration used for navigation and generating links.
|
|
317
|
-
*
|
|
318
|
-
* @param config The route array for the new configuration.
|
|
319
|
-
*
|
|
320
|
-
* @usageNotes
|
|
321
|
-
*
|
|
322
|
-
* ```
|
|
323
|
-
* router.resetConfig([
|
|
324
|
-
* { path: 'team/:id', component: TeamCmp, children: [
|
|
325
|
-
* { path: 'simple', component: SimpleCmp },
|
|
326
|
-
* { path: 'user/:name', component: UserCmp }
|
|
327
|
-
* ]}
|
|
328
|
-
* ]);
|
|
329
|
-
* ```
|
|
330
|
-
*/
|
|
331
|
-
resetConfig(config) {
|
|
332
|
-
NG_DEV_MODE && validateConfig(config);
|
|
333
|
-
this.config = config.map(standardizeConfig);
|
|
334
|
-
this.navigated = false;
|
|
335
|
-
this.lastSuccessfulId = -1;
|
|
336
|
-
}
|
|
337
|
-
/** @nodoc */
|
|
338
|
-
ngOnDestroy() {
|
|
339
|
-
this.dispose();
|
|
340
|
-
}
|
|
341
|
-
/** Disposes of the router. */
|
|
342
|
-
dispose() {
|
|
343
|
-
this.navigationTransitions.complete();
|
|
344
|
-
if (this.locationSubscription) {
|
|
345
|
-
this.locationSubscription.unsubscribe();
|
|
346
|
-
this.locationSubscription = undefined;
|
|
347
|
-
}
|
|
348
|
-
this.disposed = true;
|
|
349
|
-
}
|
|
350
|
-
/**
|
|
351
|
-
* Appends URL segments to the current URL tree to create a new URL tree.
|
|
352
|
-
*
|
|
353
|
-
* @param commands An array of URL fragments with which to construct the new URL tree.
|
|
354
|
-
* If the path is static, can be the literal URL string. For a dynamic path, pass an array of path
|
|
355
|
-
* segments, followed by the parameters for each segment.
|
|
356
|
-
* The fragments are applied to the current URL tree or the one provided in the `relativeTo`
|
|
357
|
-
* property of the options object, if supplied.
|
|
358
|
-
* @param navigationExtras Options that control the navigation strategy.
|
|
359
|
-
* @returns The new URL tree.
|
|
360
|
-
*
|
|
361
|
-
* @usageNotes
|
|
362
|
-
*
|
|
363
|
-
* ```
|
|
364
|
-
* // create /team/33/user/11
|
|
365
|
-
* router.createUrlTree(['/team', 33, 'user', 11]);
|
|
366
|
-
*
|
|
367
|
-
* // create /team/33;expand=true/user/11
|
|
368
|
-
* router.createUrlTree(['/team', 33, {expand: true}, 'user', 11]);
|
|
369
|
-
*
|
|
370
|
-
* // you can collapse static segments like this (this works only with the first passed-in value):
|
|
371
|
-
* router.createUrlTree(['/team/33/user', userId]);
|
|
372
|
-
*
|
|
373
|
-
* // If the first segment can contain slashes, and you do not want the router to split it,
|
|
374
|
-
* // you can do the following:
|
|
375
|
-
* router.createUrlTree([{segmentPath: '/one/two'}]);
|
|
376
|
-
*
|
|
377
|
-
* // create /team/33/(user/11//right:chat)
|
|
378
|
-
* router.createUrlTree(['/team', 33, {outlets: {primary: 'user/11', right: 'chat'}}]);
|
|
379
|
-
*
|
|
380
|
-
* // remove the right secondary node
|
|
381
|
-
* router.createUrlTree(['/team', 33, {outlets: {primary: 'user/11', right: null}}]);
|
|
382
|
-
*
|
|
383
|
-
* // assuming the current url is `/team/33/user/11` and the route points to `user/11`
|
|
384
|
-
*
|
|
385
|
-
* // navigate to /team/33/user/11/details
|
|
386
|
-
* router.createUrlTree(['details'], {relativeTo: route});
|
|
387
|
-
*
|
|
388
|
-
* // navigate to /team/33/user/22
|
|
389
|
-
* router.createUrlTree(['../22'], {relativeTo: route});
|
|
390
|
-
*
|
|
391
|
-
* // navigate to /team/44/user/22
|
|
392
|
-
* router.createUrlTree(['../../team/44/user/22'], {relativeTo: route});
|
|
393
|
-
*
|
|
394
|
-
* Note that a value of `null` or `undefined` for `relativeTo` indicates that the
|
|
395
|
-
* tree should be created relative to the root.
|
|
396
|
-
* ```
|
|
397
|
-
*/
|
|
398
|
-
createUrlTree(commands, navigationExtras = {}) {
|
|
399
|
-
const { relativeTo, queryParams, fragment, queryParamsHandling, preserveFragment } = navigationExtras;
|
|
400
|
-
const f = preserveFragment ? this.currentUrlTree.fragment : fragment;
|
|
401
|
-
let q = null;
|
|
402
|
-
switch (queryParamsHandling) {
|
|
403
|
-
case 'merge':
|
|
404
|
-
q = { ...this.currentUrlTree.queryParams, ...queryParams };
|
|
405
|
-
break;
|
|
406
|
-
case 'preserve':
|
|
407
|
-
q = this.currentUrlTree.queryParams;
|
|
408
|
-
break;
|
|
409
|
-
default:
|
|
410
|
-
q = queryParams || null;
|
|
411
|
-
}
|
|
412
|
-
if (q !== null) {
|
|
413
|
-
q = this.removeEmptyProps(q);
|
|
414
|
-
}
|
|
415
|
-
let relativeToUrlSegmentGroup;
|
|
416
|
-
try {
|
|
417
|
-
const relativeToSnapshot = relativeTo ? relativeTo.snapshot : this.routerState.snapshot.root;
|
|
418
|
-
relativeToUrlSegmentGroup = createSegmentGroupFromRoute(relativeToSnapshot);
|
|
419
|
-
}
|
|
420
|
-
catch (e) {
|
|
421
|
-
// This is strictly for backwards compatibility with tests that create
|
|
422
|
-
// invalid `ActivatedRoute` mocks.
|
|
423
|
-
// Note: the difference between having this fallback for invalid `ActivatedRoute` setups and
|
|
424
|
-
// just throwing is ~500 test failures. Fixing all of those tests by hand is not feasible at
|
|
425
|
-
// the moment.
|
|
426
|
-
if (typeof commands[0] !== 'string' || !commands[0].startsWith('/')) {
|
|
427
|
-
// Navigations that were absolute in the old way of creating UrlTrees
|
|
428
|
-
// would still work because they wouldn't attempt to match the
|
|
429
|
-
// segments in the `ActivatedRoute` to the `currentUrlTree` but
|
|
430
|
-
// instead just replace the root segment with the navigation result.
|
|
431
|
-
// Non-absolute navigations would fail to apply the commands because
|
|
432
|
-
// the logic could not find the segment to replace (so they'd act like there were no
|
|
433
|
-
// commands).
|
|
434
|
-
commands = [];
|
|
435
|
-
}
|
|
436
|
-
relativeToUrlSegmentGroup = this.currentUrlTree.root;
|
|
437
|
-
}
|
|
438
|
-
return createUrlTreeFromSegmentGroup(relativeToUrlSegmentGroup, commands, q, f ?? null);
|
|
439
|
-
}
|
|
440
|
-
/**
|
|
441
|
-
* Navigates to a view using an absolute route path.
|
|
442
|
-
*
|
|
443
|
-
* @param url An absolute path for a defined route. The function does not apply any delta to the
|
|
444
|
-
* current URL.
|
|
445
|
-
* @param extras An object containing properties that modify the navigation strategy.
|
|
446
|
-
*
|
|
447
|
-
* @returns A Promise that resolves to 'true' when navigation succeeds,
|
|
448
|
-
* to 'false' when navigation fails, or is rejected on error.
|
|
449
|
-
*
|
|
450
|
-
* @usageNotes
|
|
451
|
-
*
|
|
452
|
-
* The following calls request navigation to an absolute path.
|
|
453
|
-
*
|
|
454
|
-
* ```
|
|
455
|
-
* router.navigateByUrl("/team/33/user/11");
|
|
456
|
-
*
|
|
457
|
-
* // Navigate without updating the URL
|
|
458
|
-
* router.navigateByUrl("/team/33/user/11", { skipLocationChange: true });
|
|
459
|
-
* ```
|
|
460
|
-
*
|
|
461
|
-
* @see [Routing and Navigation guide](guide/router)
|
|
462
|
-
*
|
|
463
|
-
*/
|
|
464
|
-
navigateByUrl(url, extras = {
|
|
465
|
-
skipLocationChange: false
|
|
466
|
-
}) {
|
|
467
|
-
if (NG_DEV_MODE) {
|
|
468
|
-
if (this.isNgZoneEnabled && !NgZone.isInAngularZone()) {
|
|
469
|
-
this.console.warn(`Navigation triggered outside Angular zone, did you forget to call 'ngZone.run()'?`);
|
|
470
|
-
}
|
|
471
|
-
if (url instanceof UrlTree && url._warnIfUsedForNavigation) {
|
|
472
|
-
this.console.warn(url._warnIfUsedForNavigation);
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
const urlTree = isUrlTree(url) ? url : this.parseUrl(url);
|
|
476
|
-
const mergedTree = this.urlHandlingStrategy.merge(urlTree, this.rawUrlTree);
|
|
477
|
-
return this.scheduleNavigation(mergedTree, IMPERATIVE_NAVIGATION, null, extras);
|
|
478
|
-
}
|
|
479
|
-
/**
|
|
480
|
-
* Navigate based on the provided array of commands and a starting point.
|
|
481
|
-
* If no starting route is provided, the navigation is absolute.
|
|
482
|
-
*
|
|
483
|
-
* @param commands An array of URL fragments with which to construct the target URL.
|
|
484
|
-
* If the path is static, can be the literal URL string. For a dynamic path, pass an array of path
|
|
485
|
-
* segments, followed by the parameters for each segment.
|
|
486
|
-
* The fragments are applied to the current URL or the one provided in the `relativeTo` property
|
|
487
|
-
* of the options object, if supplied.
|
|
488
|
-
* @param extras An options object that determines how the URL should be constructed or
|
|
489
|
-
* interpreted.
|
|
490
|
-
*
|
|
491
|
-
* @returns A Promise that resolves to `true` when navigation succeeds, to `false` when navigation
|
|
492
|
-
* fails,
|
|
493
|
-
* or is rejected on error.
|
|
494
|
-
*
|
|
495
|
-
* @usageNotes
|
|
496
|
-
*
|
|
497
|
-
* The following calls request navigation to a dynamic route path relative to the current URL.
|
|
498
|
-
*
|
|
499
|
-
* ```
|
|
500
|
-
* router.navigate(['team', 33, 'user', 11], {relativeTo: route});
|
|
501
|
-
*
|
|
502
|
-
* // Navigate without updating the URL, overriding the default behavior
|
|
503
|
-
* router.navigate(['team', 33, 'user', 11], {relativeTo: route, skipLocationChange: true});
|
|
504
|
-
* ```
|
|
505
|
-
*
|
|
506
|
-
* @see [Routing and Navigation guide](guide/router)
|
|
507
|
-
*
|
|
508
|
-
*/
|
|
509
|
-
navigate(commands, extras = { skipLocationChange: false }) {
|
|
510
|
-
validateCommands(commands);
|
|
511
|
-
return this.navigateByUrl(this.createUrlTree(commands, extras), extras);
|
|
512
|
-
}
|
|
513
|
-
/** Serializes a `UrlTree` into a string */
|
|
514
|
-
serializeUrl(url) {
|
|
515
|
-
return this.urlSerializer.serialize(url);
|
|
516
|
-
}
|
|
517
|
-
/** Parses a string into a `UrlTree` */
|
|
518
|
-
parseUrl(url) {
|
|
519
|
-
let urlTree;
|
|
520
|
-
try {
|
|
521
|
-
urlTree = this.urlSerializer.parse(url);
|
|
522
|
-
}
|
|
523
|
-
catch (e) {
|
|
524
|
-
urlTree = this.malformedUriErrorHandler(e, this.urlSerializer, url);
|
|
525
|
-
}
|
|
526
|
-
return urlTree;
|
|
527
|
-
}
|
|
528
|
-
isActive(url, matchOptions) {
|
|
529
|
-
let options;
|
|
530
|
-
if (matchOptions === true) {
|
|
531
|
-
options = { ...exactMatchOptions };
|
|
532
|
-
}
|
|
533
|
-
else if (matchOptions === false) {
|
|
534
|
-
options = { ...subsetMatchOptions };
|
|
535
|
-
}
|
|
536
|
-
else {
|
|
537
|
-
options = matchOptions;
|
|
538
|
-
}
|
|
539
|
-
if (isUrlTree(url)) {
|
|
540
|
-
return containsTree(this.currentUrlTree, url, options);
|
|
541
|
-
}
|
|
542
|
-
const urlTree = this.parseUrl(url);
|
|
543
|
-
return containsTree(this.currentUrlTree, urlTree, options);
|
|
544
|
-
}
|
|
545
|
-
removeEmptyProps(params) {
|
|
546
|
-
return Object.keys(params).reduce((result, key) => {
|
|
547
|
-
const value = params[key];
|
|
548
|
-
if (value !== null && value !== undefined) {
|
|
549
|
-
result[key] = value;
|
|
550
|
-
}
|
|
551
|
-
return result;
|
|
552
|
-
}, {});
|
|
553
|
-
}
|
|
554
|
-
/** @internal */
|
|
555
|
-
scheduleNavigation(rawUrl, source, restoredState, extras, priorPromise) {
|
|
556
|
-
if (this.disposed) {
|
|
557
|
-
return Promise.resolve(false);
|
|
558
|
-
}
|
|
559
|
-
let resolve;
|
|
560
|
-
let reject;
|
|
561
|
-
let promise;
|
|
562
|
-
if (priorPromise) {
|
|
563
|
-
resolve = priorPromise.resolve;
|
|
564
|
-
reject = priorPromise.reject;
|
|
565
|
-
promise = priorPromise.promise;
|
|
566
|
-
}
|
|
567
|
-
else {
|
|
568
|
-
promise = new Promise((res, rej) => {
|
|
569
|
-
resolve = res;
|
|
570
|
-
reject = rej;
|
|
571
|
-
});
|
|
572
|
-
}
|
|
573
|
-
let targetPageId;
|
|
574
|
-
if (this.canceledNavigationResolution === 'computed') {
|
|
575
|
-
// If the `ɵrouterPageId` exist in the state then `targetpageId` should have the value of
|
|
576
|
-
// `ɵrouterPageId`. This is the case for something like a page refresh where we assign the
|
|
577
|
-
// target id to the previously set value for that page.
|
|
578
|
-
if (restoredState && restoredState.ɵrouterPageId) {
|
|
579
|
-
targetPageId = restoredState.ɵrouterPageId;
|
|
580
|
-
}
|
|
581
|
-
else {
|
|
582
|
-
// If we're replacing the URL or doing a silent navigation, we do not want to increment the
|
|
583
|
-
// page id because we aren't pushing a new entry to history.
|
|
584
|
-
if (extras.replaceUrl || extras.skipLocationChange) {
|
|
585
|
-
targetPageId = this.browserPageId ?? 0;
|
|
586
|
-
}
|
|
587
|
-
else {
|
|
588
|
-
targetPageId = (this.browserPageId ?? 0) + 1;
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
}
|
|
592
|
-
else {
|
|
593
|
-
// This is unused when `canceledNavigationResolution` is not computed.
|
|
594
|
-
targetPageId = 0;
|
|
595
|
-
}
|
|
596
|
-
this.navigationTransitions.handleNavigationRequest({
|
|
597
|
-
targetPageId,
|
|
598
|
-
source,
|
|
599
|
-
restoredState,
|
|
600
|
-
currentUrlTree: this.currentUrlTree,
|
|
601
|
-
currentRawUrl: this.currentUrlTree,
|
|
602
|
-
rawUrl,
|
|
603
|
-
extras,
|
|
604
|
-
resolve,
|
|
605
|
-
reject,
|
|
606
|
-
promise,
|
|
607
|
-
currentSnapshot: this.routerState.snapshot,
|
|
608
|
-
currentRouterState: this.routerState
|
|
609
|
-
});
|
|
610
|
-
// Make sure that the error is propagated even though `processNavigations` catch
|
|
611
|
-
// handler does not rethrow
|
|
612
|
-
return promise.catch((e) => {
|
|
613
|
-
return Promise.reject(e);
|
|
614
|
-
});
|
|
615
|
-
}
|
|
616
|
-
/** @internal */
|
|
617
|
-
setBrowserUrl(url, transition) {
|
|
618
|
-
const path = this.urlSerializer.serialize(url);
|
|
619
|
-
const state = {
|
|
620
|
-
...transition.extras.state,
|
|
621
|
-
...this.generateNgRouterState(transition.id, transition.targetPageId)
|
|
622
|
-
};
|
|
623
|
-
if (this.location.isCurrentPathEqualTo(path) || !!transition.extras.replaceUrl) {
|
|
624
|
-
this.location.replaceState(path, '', state);
|
|
625
|
-
}
|
|
626
|
-
else {
|
|
627
|
-
this.location.go(path, '', state);
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
/**
|
|
631
|
-
* Performs the necessary rollback action to restore the browser URL to the
|
|
632
|
-
* state before the transition.
|
|
633
|
-
* @internal
|
|
634
|
-
*/
|
|
635
|
-
restoreHistory(transition, restoringFromCaughtError = false) {
|
|
636
|
-
if (this.canceledNavigationResolution === 'computed') {
|
|
637
|
-
const targetPagePosition = this.currentPageId - transition.targetPageId;
|
|
638
|
-
// The navigator change the location before triggered the browser event,
|
|
639
|
-
// so we need to go back to the current url if the navigation is canceled.
|
|
640
|
-
// Also, when navigation gets cancelled while using url update strategy eager, then we need to
|
|
641
|
-
// go back. Because, when `urlUpdateStrategy` is `eager`; `setBrowserUrl` method is called
|
|
642
|
-
// before any verification.
|
|
643
|
-
const browserUrlUpdateOccurred = (transition.source === 'popstate' || this.urlUpdateStrategy === 'eager' ||
|
|
644
|
-
this.currentUrlTree === this.getCurrentNavigation()?.finalUrl);
|
|
645
|
-
if (browserUrlUpdateOccurred && targetPagePosition !== 0) {
|
|
646
|
-
this.location.historyGo(targetPagePosition);
|
|
647
|
-
}
|
|
648
|
-
else if (this.currentUrlTree === this.getCurrentNavigation()?.finalUrl &&
|
|
649
|
-
targetPagePosition === 0) {
|
|
650
|
-
// We got to the activation stage (where currentUrlTree is set to the navigation's
|
|
651
|
-
// finalUrl), but we weren't moving anywhere in history (skipLocationChange or replaceUrl).
|
|
652
|
-
// We still need to reset the router state back to what it was when the navigation started.
|
|
653
|
-
this.resetState(transition);
|
|
654
|
-
// TODO(atscott): resetting the `browserUrlTree` should really be done in `resetState`.
|
|
655
|
-
// Investigate if this can be done by running TGP.
|
|
656
|
-
this.browserUrlTree = transition.currentUrlTree;
|
|
657
|
-
this.resetUrlToCurrentUrlTree();
|
|
658
|
-
}
|
|
659
|
-
else {
|
|
660
|
-
// The browser URL and router state was not updated before the navigation cancelled so
|
|
661
|
-
// there's no restoration needed.
|
|
662
|
-
}
|
|
663
|
-
}
|
|
664
|
-
else if (this.canceledNavigationResolution === 'replace') {
|
|
665
|
-
// TODO(atscott): It seems like we should _always_ reset the state here. It would be a no-op
|
|
666
|
-
// for `deferred` navigations that haven't change the internal state yet because guards
|
|
667
|
-
// reject. For 'eager' navigations, it seems like we also really should reset the state
|
|
668
|
-
// because the navigation was cancelled. Investigate if this can be done by running TGP.
|
|
669
|
-
if (restoringFromCaughtError) {
|
|
670
|
-
this.resetState(transition);
|
|
671
|
-
}
|
|
672
|
-
this.resetUrlToCurrentUrlTree();
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
resetState(t) {
|
|
676
|
-
this.routerState = t.currentRouterState;
|
|
677
|
-
this.currentUrlTree = t.currentUrlTree;
|
|
678
|
-
// Note here that we use the urlHandlingStrategy to get the reset `rawUrlTree` because it may be
|
|
679
|
-
// configured to handle only part of the navigation URL. This means we would only want to reset
|
|
680
|
-
// the part of the navigation handled by the Angular router rather than the whole URL. In
|
|
681
|
-
// addition, the URLHandlingStrategy may be configured to specifically preserve parts of the URL
|
|
682
|
-
// when merging, such as the query params so they are not lost on a refresh.
|
|
683
|
-
this.rawUrlTree = this.urlHandlingStrategy.merge(this.currentUrlTree, t.rawUrl);
|
|
684
|
-
}
|
|
685
|
-
resetUrlToCurrentUrlTree() {
|
|
686
|
-
this.location.replaceState(this.urlSerializer.serialize(this.rawUrlTree), '', this.generateNgRouterState(this.lastSuccessfulId, this.currentPageId));
|
|
687
|
-
}
|
|
688
|
-
generateNgRouterState(navigationId, routerPageId) {
|
|
689
|
-
if (this.canceledNavigationResolution === 'computed') {
|
|
690
|
-
return { navigationId, ɵrouterPageId: routerPageId };
|
|
691
|
-
}
|
|
692
|
-
return { navigationId };
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
Router.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: Router, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
696
|
-
Router.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: Router, providedIn: 'root' });
|
|
697
|
-
export { Router };
|
|
698
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0-next.4", ngImport: i0, type: Router, decorators: [{
|
|
699
|
-
type: Injectable,
|
|
700
|
-
args: [{ providedIn: 'root' }]
|
|
701
|
-
}], ctorParameters: function () { return []; } });
|
|
702
|
-
function validateCommands(commands) {
|
|
703
|
-
for (let i = 0; i < commands.length; i++) {
|
|
704
|
-
const cmd = commands[i];
|
|
705
|
-
if (cmd == null) {
|
|
706
|
-
throw new RuntimeError(4008 /* RuntimeErrorCode.NULLISH_COMMAND */, NG_DEV_MODE && `The requested path contains ${cmd} segment at index ${i}`);
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvcm91dGVyL3NyYy9yb3V0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztHQU1HO0FBRUgsT0FBTyxFQUFDLFFBQVEsRUFBQyxNQUFNLGlCQUFpQixDQUFDO0FBQ3pDLE9BQU8sRUFBQyxNQUFNLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBUSxRQUFRLElBQUksT0FBTyxFQUFFLGFBQWEsSUFBSSxZQUFZLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFHbkgsT0FBTyxFQUFDLDJCQUEyQixFQUFFLDZCQUE2QixFQUFDLE1BQU0sbUJBQW1CLENBQUM7QUFFN0YsT0FBTyxFQUFRLHFCQUFxQixFQUFvQixNQUFNLFVBQVUsQ0FBQztBQUV6RSxPQUFPLEVBQXFELHFCQUFxQixFQUFvQyxNQUFNLHlCQUF5QixDQUFDO0FBQ3JKLE9BQU8sRUFBQyxhQUFhLEVBQUMsTUFBTSx1QkFBdUIsQ0FBQztBQUNwRCxPQUFPLEVBQUMsa0JBQWtCLEVBQUMsTUFBTSx3QkFBd0IsQ0FBQztBQUMxRCxPQUFPLEVBQUMsb0JBQW9CLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUNyRCxPQUFPLEVBQUMsTUFBTSxFQUFDLE1BQU0sd0JBQXdCLENBQUM7QUFDOUMsT0FBTyxFQUFDLGdCQUFnQixFQUFjLE1BQU0sZ0JBQWdCLENBQUM7QUFFN0QsT0FBTyxFQUFDLG1CQUFtQixFQUFDLE1BQU0seUJBQXlCLENBQUM7QUFDNUQsT0FBTyxFQUFDLFlBQVksRUFBd0IsU0FBUyxFQUFtQixhQUFhLEVBQUUsT0FBTyxFQUFDLE1BQU0sWUFBWSxDQUFDO0FBQ2xILE9BQU8sRUFBQyxpQkFBaUIsRUFBRSxjQUFjLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQzs7QUFHakUsTUFBTSxXQUFXLEdBQUcsT0FBTyxTQUFTLEtBQUssV0FBVyxJQUFJLENBQUMsQ0FBQyxTQUFTLENBQUM7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QjtRQUM5QixJQUFJLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FDdEIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxFQUFFLEVBQUUsRUFDakQsSUFBSSxDQUFDLHFCQUFxQixDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQztJQUM3RSxDQUFDO0lBRU8scUJBQXFCLENBQUMsWUFBb0IsRUFBRSxZQUFxQjtRQUN2RSxJQUFJLElBQUksQ0FBQyw0QkFBNEIsS0FBSyxVQUFVLEVBQUU7WUFDcEQsT0FBTyxFQUFDLFlBQVksRUFBRSxhQUFhLEVBQUUsWUFBWSxFQUFDLENBQUM7U0FDcEQ7UUFDRCxPQUFPLEVBQUMsWUFBWSxFQUFDLENBQUM7SUFDeEIsQ0FBQzs7OEdBandCVSxNQUFNO2tIQUFOLE1BQU0sY0FETSxNQUFNO1NBQ2xCLE1BQU07c0dBQU4sTUFBTTtrQkFEbEIsVUFBVTttQkFBQyxFQUFDLFVBQVUsRUFBRSxNQUFNLEVBQUM7O0FBcXdCaEMsU0FBUyxnQkFBZ0IsQ0FBQyxRQUFrQjtJQUMxQyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtRQUN4QyxNQUFNLEdBQUcsR0FBRyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDeEIsSUFBSSxHQUFHLElBQUksSUFBSSxFQUFFO1lBQ2YsTUFBTSxJQUFJLFlBQVksOENBRWxCLFdBQVcsSUFBSSwrQkFBK0IsR0FBRyxxQkFBcUIsQ0FBQyxFQUFFLENBQUMsQ0FBQztTQUNoRjtLQUNGO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCBHb29nbGUgTExDIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9hbmd1bGFyLmlvL2xpY2Vuc2VcbiAqL1xuXG5pbXBvcnQge0xvY2F0aW9ufSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtpbmplY3QsIEluamVjdGFibGUsIE5nWm9uZSwgVHlwZSwgybVDb25zb2xlIGFzIENvbnNvbGUsIMm1UnVudGltZUVycm9yIGFzIFJ1bnRpbWVFcnJvcn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge09ic2VydmFibGUsIG9mLCBTdWJzY3JpcHRpb25MaWtlfSBmcm9tICdyeGpzJztcblxuaW1wb3J0IHtjcmVhdGVTZWdtZW50R3JvdXBGcm9tUm91dGUsIGNyZWF0ZVVybFRyZWVGcm9tU2VnbWVudEdyb3VwfSBmcm9tICcuL2NyZWF0ZV91cmxfdHJlZSc7XG5pbXBvcnQge1J1bnRpbWVFcnJvckNvZGV9IGZyb20gJy4vZXJyb3JzJztcbmltcG9ydCB7RXZlbnQsIElNUEVSQVRJVkVfTkFWSUdBVElPTiwgTmF2aWdhdGlvblRyaWdnZXJ9IGZyb20gJy4vZXZlbnRzJztcbmltcG9ydCB7TmF2aWdhdGlvbkJlaGF2aW9yT3B0aW9ucywgT25TYW1lVXJsTmF2aWdhdGlvbiwgUm91dGVzfSBmcm9tICcuL21vZGVscyc7XG5pbXBvcnQge05hdmlnYXRpb24sIE5hdmlnYXRpb25FeHRyYXMsIE5hdmlnYXRpb25UcmFuc2l0aW9uLCBOYXZpZ2F0aW9uVHJhbnNpdGlvbnMsIFJlc3RvcmVkU3RhdGUsIFVybENyZWF0aW9uT3B0aW9uc30gZnJvbSAnLi9uYXZpZ2F0aW9uX3RyYW5zaXRpb24nO1xuaW1wb3J0IHtUaXRsZVN0cmF0ZWd5fSBmcm9tICcuL3BhZ2VfdGl0bGVfc3RyYXRlZ3knO1xuaW1wb3J0IHtSb3V0ZVJldXNlU3RyYXRlZ3l9IGZyb20gJy4vcm91dGVfcmV1c2Vfc3RyYXRlZ3knO1xuaW1wb3J0IHtST1VURVJfQ09ORklHVVJBVElPTn0gZnJvbSAnLi9yb3V0ZXJfY29uZmlnJztcbmltcG9ydCB7Uk9VVEVTfSBmcm9tICcuL3JvdXRlcl9jb25maWdfbG9hZGVyJztcbmltcG9ydCB7Y3JlYXRlRW1wdHlTdGF0ZSwgUm91dGVyU3RhdGV9IGZyb20gJy4vcm91dGVyX3N0YXRlJztcbmltcG9ydCB7UGFyYW1zfSBmcm9tICcuL3NoYXJlZCc7XG5pbXBvcnQge1VybEhhbmRsaW5nU3RyYXRlZ3l9IGZyb20gJy4vdXJsX2hhbmRsaW5nX3N0cmF0ZWd5JztcbmltcG9ydCB7Y29udGFpbnNUcmVlLCBJc0FjdGl2ZU1hdGNoT3B0aW9ucywgaXNVcmxUcmVlLCBVcmxTZWdtZW50R3JvdXAsIFVybFNlcmlhbGl6ZXIsIFVybFRyZWV9IGZyb20gJy4vdXJsX3RyZWUnO1xuaW1wb3J0IHtzdGFuZGFyZGl6ZUNvbmZpZywgdmFsaWRhdGVDb25maWd9IGZyb20gJy4vdXRpbHMvY29uZmlnJztcblxuXG5jb25zdCBOR19ERVZfTU9ERSA9IHR5cGVvZiBuZ0Rldk1vZGUgPT09ICd1bmRlZmluZWQnIHx8ICEhbmdEZXZNb2RlO1xuXG5mdW5jdGlvbiBkZWZhdWx0RXJyb3JIYW5kbGVyKGVycm9yOiBhbnkpOiBhbnkge1xuICB0aHJvdyBlcnJvcjtcbn1cblxuZnVuY3Rpb24gZGVmYXVsdE1hbGZvcm1lZFVyaUVycm9ySGFuZGxlcihcbiAgICBlcnJvcjogVVJJRXJyb3IsIHVybFNlcmlhbGl6ZXI6IFVybFNlcmlhbGl6ZXIsIHVybDogc3RyaW5nKTogVXJsVHJlZSB7XG4gIHJldHVybiB1cmxTZXJpYWxpemVyLnBhcnNlKCcvJyk7XG59XG5cbi8qKlxuICogVGhlIGVxdWl2YWxlbnQgYElzQWN0aXZlTWF0Y2hPcHRpb25zYCBvcHRpb25zIGZvciBgUm91dGVyLmlzQWN0aXZlYCBpcyBjYWxsZWQgd2l0aCBgdHJ1ZWBcbiAqIChleGFjdCA9IHRydWUpLlxuICovXG5leHBvcnQgY29uc3QgZXhhY3RNYXRjaE9wdGlvbnM6IElzQWN0aXZlTWF0Y2hPcHRpb25zID0ge1xuICBwYXRoczogJ2V4YWN0JyxcbiAgZnJhZ21lbnQ6ICdpZ25vcmVkJyxcbiAgbWF0cml4UGFyYW1zOiAnaWdub3JlZCcsXG4gIHF1ZXJ5UGFyYW1zOiAnZXhhY3QnXG59O1xuXG4vKipcbiAqIFRoZSBlcXVpdmFsZW50IGBJc0FjdGl2ZU1hdGNoT3B0aW9uc2Agb3B0aW9ucyBmb3IgYFJvdXRlci5pc0FjdGl2ZWAgaXMgY2FsbGVkIHdpdGggYGZhbHNlYFxuICogKGV4YWN0ID0gZmFsc2UpLlxuICovXG5leHBvcnQgY29uc3Qgc3Vic2V0TWF0Y2hPcHRpb25zOiBJc0FjdGl2ZU1hdGNoT3B0aW9ucyA9IHtcbiAgcGF0aHM6ICdzdWJzZXQnLFxuICBmcmFnbWVudDogJ2lnbm9yZWQnLFxuICBtYXRyaXhQYXJhbXM6ICdpZ25vcmVkJyxcbiAgcXVlcnlQYXJhbXM6ICdzdWJzZXQnXG59O1xuXG4vKipcbiAqIEBkZXNjcmlwdGlvblxuICpcbiAqIEEgc2VydmljZSB0aGF0IHByb3ZpZGVzIG5hdmlnYXRpb24gYW1vbmcgdmlld3MgYW5kIFVSTCBtYW5pcHVsYXRpb24gY2FwYWJpbGl0aWVzLlxuICpcbiAqIEBzZWUgYFJvdXRlYC5cbiAqIEBzZWUgW1JvdXRpbmcgYW5kIE5hdmlnYXRpb24gR3VpZGVdKGd1aWRlL3JvdXRlcikuXG4gKlxuICogQG5nTW9kdWxlIFJvdXRlck1vZHVsZVxuICpcbiAqIEBwdWJsaWNBcGlcbiAqL1xuQEluamVjdGFibGUoe3Byb3ZpZGVkSW46ICdyb290J30pXG5leHBvcnQgY2xhc3MgUm91dGVyIHtcbiAgLyoqXG4gICAqIFJlcHJlc2VudHMgdGhlIGFjdGl2YXRlZCBgVXJsVHJlZWAgdGhhdCB0aGUgYFJvdXRlcmAgaXMgY29uZmlndXJlZCB0byBoYW5kbGUgKHRocm91Z2hcbiAgICogYFVybEhhbmRsaW5nU3RyYXRlZ3lgKS4gVGhhdCBpcywgYWZ0ZXIgd2UgZmluZCB0aGUgcm91dGUgY29uZmlnIHRyZWUgdGhhdCB3ZSdyZSBnb2luZyB0b1xuICAgKiBhY3RpdmF0ZSwgcnVuIGd1YXJkcywgYW5kIGFyZSBqdXN0IGFib3V0IHRvIGFjdGl2YXRlIHRoZSByb3V0ZSwgd2Ugc2V0IHRoZSBjdXJyZW50VXJsVHJlZS5cbiAgICpcbiAgICogVGhpcyBzaG91bGQgbWF0Y2ggdGhlIGBicm93c2VyVXJsVHJlZWAgd2hlbiBhIG5hdmlnYXRpb24gc3VjY2VlZHMuIElmIHRoZVxuICAgKiBgVXJsSGFuZGxpbmdTdHJhdGVneS5zaG91bGRQcm9jZXNzVXJsYCBpcyBgZmFsc2VgLCBvbmx5IHRoZSBgYnJvd3NlclVybFRyZWVgIGlzIHVwZGF0ZWQuXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgY3VycmVudFVybFRyZWU6IFVybFRyZWU7XG4gIC8qKlxuICAgKiBNZWFudCB0byByZXByZXNlbnQgdGhlIGVudGlyZSBicm93c2VyIHVybCBhZnRlciBhIHN1Y2Nlc3NmdWwgbmF2aWdhdGlvbi4gSW4gdGhlIGxpZmUgb2YgYVxuICAgKiBuYXZpZ2F0aW9uIHRyYW5zaXRpb246XG4gICAqIDEuIFRoZSByYXdVcmwgcmVwcmVzZW50cyB0aGUgZnVsbCBVUkwgdGhhdCdzIGJlaW5nIG5hdmlnYXRlZCB0b1xuICAgKiAyLiBXZSBhcHBseSByZWRpcmVjdHMsIHdoaWNoIG1pZ2h0IG9ubHkgYXBwbHkgdG8gX3BhcnRfIG9mIHRoZSBVUkwgKGR1ZSB0b1xuICAgKiBgVXJsSGFuZGxpbmdTdHJhdGVneWApLlxuICAgKiAzLiBSaWdodCBiZWZvcmUgYWN0aXZhdGlvbiAoYmVjYXVzZSB3ZSBhc3N1bWUgYWN0aXZhdGlvbiB3aWxsIHN1Y2NlZWQpLCB3ZSB1cGRhdGUgdGhlXG4gICAqIHJhd1VybFRyZWUgdG8gYmUgYSBjb21iaW5hdGlvbiBvZiB0aGUgdXJsQWZ0ZXJSZWRpcmVjdHMgKGFnYWluLCB0aGlzIG1pZ2h0IG9ubHkgYXBwbHkgdG8gcGFydFxuICAgKiBvZiB0aGUgaW5pdGlhbCB1cmwpIGFuZCB0aGUgcmF3VXJsIG9mIHRoZSB0cmFuc2l0aW9uICh3aGljaCB3YXMgdGhlIG9yaWdpbmFsIG5hdmlnYXRpb24gdXJsIGluXG4gICAqIGl0cyBmdWxsIGZvcm0pLlxuICAgKiBAaW50ZXJuYWxcbiAgICpcbiAgICogTm90ZSB0aGF0IHRoaXMgaXMgX29ubHlfIGhlcmUgdG8gc3VwcG9ydCBgVXJsSGFuZGxpbmdTdHJhdGVneS5leHRyYWN0YCBhbmRcbiAgICogYFVybEhhbmRsaW5nU3RyYXRlZ3kuc2hvdWxkUHJvY2Vzc1VybGAuIElmIHRob3NlIGRpZG4ndCBleGlzdCwgd2UgY291bGQgZ2V0IGJ5IHdpdGhcbiAgICogYGN1cnJlbnRVcmxUcmVlYCBhbG9uZS4gSWYgYSBuZXcgUm91dGVyIHdlcmUgdG8gYmUgcHJvdmlkZWQgKGkuZS4gb25lIHRoYXQgd29ya3Mgd2l0aCB0aGVcbiAgICogYnJvd3NlciBuYXZpZ2F0aW9uIEFQSSksIHdlIHNob3VsZCB0aGluayBhYm91dCB3aGV0aGVyIHRoaXMgY29tcGxleGl0eSBzaG91bGQgYmUgY2FycmllZCBvdmVyLlxuICAgKlxuICAgKiAtIGV4dHJhY3Q6IGByYXdVcmxUcmVlYCBpcyBuZWVkZWQgYmVjYXVzZSBgZXh0cmFjdGAgbWF5IG9ubHkgcmV0dXJuIHBhcnRcbiAgICogb2YgdGhlIG5hdmlnYXRpb24gVVJMLiBUaHVzLCBgY3VycmVudFVybFRyZWVgIG1heSBvbmx5IHJlcHJlc2VudCBfcGFydF8gb2YgdGhlIGJyb3dzZXIgVVJMLlxuICAgKiBXaGVuIGEgbmF2aWdhdGlvbiBnZXRzIGNhbmNlbGxlZCBhbmQgd2UgbmVlZCB0byByZXNldCB0aGUgVVJMIG9yIGEgbmV3IG5hdmlnYXRpb24gb2NjdXJzLCB3ZVxuICAgKiBuZWVkIHRvIGtub3cgdGhlIF93aG9sZV8gYnJvd3NlciBVUkwsIG5vdCBqdXN0IHRoZSBwYXJ0IGhhbmRsZWQgYnkgVXJsSGFuZGxpbmdTdHJhdGVneS5cbiAgICogLSBzaG91bGRQcm9jZXNzVXJsOiBXaGVuIHRoaXMgcmV0dXJucyBgZmFsc2VgLCB0aGUgcm91dGVyIGp1c3QgaWdub3JlcyB0aGUgbmF2aWdhdGlvbiBidXQgc3RpbGxcbiAgICogdXBkYXRlcyB0aGUgYHJhd1VybFRyZWVgIHdpdGggdGhlIGFzc3VtcHRpb24gdGhhdCB0aGUgbmF2aWdhdGlvbiB3YXMgY2F1c2VkIGJ5IHRoZSBsb2NhdGlvblxuICAgKiBjaGFuZ2UgbGlzdGVuZXIgZHVlIHRvIGEgVVJMIHVwZGF0ZSBieSB0aGUgQW5ndWxhckpTIHJvdXRlci4gSW4gdGhpcyBjYXNlLCB3ZSBzdGlsbCBuZWVkIHRvXG4gICAqIGtub3cgd2hhdCB0aGUgYnJvd3NlcidzIFVSTCBpcyBmb3IgZnV0dXJlIG5hdmlnYXRpb25zLlxuICAgKlxuICAgKi9cbiAgcmF3VXJsVHJlZTogVXJsVHJlZTtcbiAgLyoqXG4gICAqIE1lYW50IHRvIHJlcHJlc2VudCB0aGUgcGFydCBvZiB0aGUgYnJvd3NlciB1cmwgdGhhdCB0aGUgYFJvdXRlcmAgaXMgc2V0IHVwIHRvIGhhbmRsZSAodmlhIHRoZVxuICAgKiBgVXJsSGFuZGxpbmdTdHJhdGVneWApLiBUaGlzIHZhbHVlIGlzIHVwZGF0ZWQgaW1tZWRpYXRlbHkgYWZ0ZXIgdGhlIGJyb3dzZXIgdXJsIGlzIHVwZGF0ZWQgKG9yXG4gICAqIHRoZSBicm93c2VyIHVybCB1cGRhdGUgaXMgc2tpcHBlZCB2aWEgYHNraXBMb2NhdGlvbkNoYW5nZWApLiBXaXRoIHRoYXQsIG5vdGUgdGhhdFxuICAgKiBgYnJvd3NlclVybFRyZWVgIF9tYXkgbm90XyByZWZsZWN0IHRoZSBhY3R1YWwgYnJvd3NlciBVUkwgZm9yIHR3byByZWFzb25zOlxuICAgKlxuICAgKiAxLiBgVXJsSGFuZGxpbmdTdHJhdGVneWAgb25seSBoYW5kbGVzIHBhcnQgb2YgdGhlIFVSTFxuICAgKiAyLiBgc2tpcExvY2F0aW9uQ2hhbmdlYCBkb2VzIG5vdCB1cGRhdGUgdGhlIGJyb3dzZXIgdXJsLlxuICAgKlxuICAgKiBTbyB0byByZWl0ZXJhdGUsIGBicm93c2VyVXJsVHJlZWAgb25seSByZXByZXNlbnRzIHRoZSBSb3V0ZXIncyBpbnRlcm5hbCB1bmRlcnN0YW5kaW5nIG9mIHRoZVxuICAgKiBjdXJyZW50IHJvdXRlLCBlaXRoZXIgYmVmb3JlIGd1YXJkcyB3aXRoIGB1cmxVcGRhdGVTdHJhdGVneSA9PT0gJ2VhZ2VyJ2Agb3IgcmlnaHQgYmVmb3JlXG4gICAqIGFjdGl2YXRpb24gd2l0aCBgJ2RlZmVycmVkJ2AuXG4gICAqXG4gICAqIFRoaXMgc2hvdWxkIG1hdGNoIHRoZSBgY3VycmVudFVybFRyZWVgIHdoZW4gdGhlIG5hdmlnYXRpb24gc3VjY2VlZHMuXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgYnJvd3NlclVybFRyZWU6IFVybFRyZWU7XG4gIHByaXZhdGUgZGlzcG9zZWQgPSBmYWxzZTtcblxuICBwcml2YXRlIGxvY2F0aW9uU3Vic2NyaXB0aW9uPzogU3Vic2NyaXB0aW9uTGlrZTtcbiAgLy8gVE9ETyhiLzI2MDc0NzA4Myk6IFRoaXMgc2hvdWxkIG5vdCBleGlzdCBhbmQgbmF2aWdhdGlvbklkIHNob3VsZCBiZSBwcml2YXRlIGluXG4gIC8vIGBOYXZpZ2F0aW9uVHJhbnNpdGlvbnNgXG4gIHByaXZhdGUgZ2V0IG5hdmlnYXRpb25JZCgpIHtcbiAgICByZXR1cm4gdGhpcy5uYXZpZ2F0aW9uVHJhbnNpdGlvbnMubmF2aWdhdGlvbklkO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBpZCBvZiB0aGUgY3VycmVudGx5IGFjdGl2ZSBwYWdlIGluIHRoZSByb3V0ZXIuXG4gICAqIFVwZGF0ZWQgdG8gdGhlIHRyYW5zaXRpb24ncyB0YXJnZXQgaWQgb24gYSBzdWNjZXNzZnVsIG5hdmlnYXRpb24uXG4gICAqXG4gICAqIFRoaXMgaXMgdXNlZCB0byB0cmFjayB3aGF0IHBhZ2UgdGhlIHJvdXRlciBsYXN0IGFjdGl2YXRlZC4gV2hlbiBhbiBhdHRlbXB0ZWQgbmF2aWdhdGlvbiBmYWlscyxcbiAgICogdGhlIHJvdXRlciBjYW4gdGhlbiB1c2UgdGhpcyB0byBjb21wdXRlIGhvdyB0byByZXN0b3JlIHRoZSBzdGF0ZSBiYWNrIHRvIHRoZSBwcmV2aW91c2x5IGFjdGl2ZVxuICAgKiBwYWdlLlxuICAgKi9cbiAgcHJpdmF0ZSBjdXJyZW50UGFnZUlkOiBudW1iZXIgPSAwO1xuICAvKipcbiAgICogVGhlIMm1cm91dGVyUGFnZUlkIG9mIHdoYXRldmVyIHBhZ2UgaXMgY3VycmVudGx5IGFjdGl2ZSBpbiB0aGUgYnJvd3NlciBoaXN0b3J5LiBUaGlzIGlzXG4gICAqIGltcG9ydGFudCBmb3IgY29tcHV0aW5nIHRoZSB0YXJnZXQgcGFnZSBpZCBmb3IgbmV3IG5hdmlnYXRpb25zIGJlY2F1c2Ugd2UgbmVlZCB0byBlbnN1cmUgZWFjaFxuICAgKiBwYWdlIGlkIGluIHRoZSBicm93c2VyIGhpc3RvcnkgaXMgMSBtb3JlIHRoYW4gdGhlIHByZXZpb3VzIGVudHJ5LlxuICAgKi9cbiAgcHJpdmF0ZSBnZXQgYnJvd3NlclBhZ2VJZCgpOiBudW1iZXJ8dW5kZWZpbmVkIHtcbiAgICByZXR1cm4gKHRoaXMubG9jYXRpb24uZ2V0U3RhdGUoKSBhcyBSZXN0b3JlZFN0YXRlIHwgbnVsbCk/Lsm1cm91dGVyUGFnZUlkO1xuICB9XG4gIHByaXZhdGUgY29uc29sZSA9IGluamVjdChDb25zb2xlKTtcbiAgcHJpdmF0ZSBpc05nWm9uZUVuYWJsZWQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAvKipcbiAgICogQW4gZXZlbnQgc3RyZWFtIGZvciByb3V0aW5nIGV2ZW50cy5cbiAgICovXG4gIHB1YmxpYyBnZXQgZXZlbnRzKCk6IE9ic2VydmFibGU8RXZlbnQ+IHtcbiAgICAvLyBUT0RPKGF0c2NvdHQpOiBUaGlzIF9zaG91bGRfIGJlIGV2ZW50cy5hc09ic2VydmFibGUoKS4gSG93ZXZlciwgdGhpcyBjaGFuZ2UgcmVxdWlyZXMgaW50ZXJuYWxcbiAgICAvLyBjbGVhbnVwOiB0ZXN0cyBhcmUgZG9pbmcgYChyb3V0ZS5ldmVudHMgYXMgU3ViamVjdDxFdmVudD4pLm5leHQoLi4uKWAuIFRoaXMgaXNuJ3RcbiAgICAvLyBhbGxvd2VkL3N1cHBvcnRlZCBidXQgd2Ugc3RpbGwgaGF2ZSB0byBmaXggdGhlc2Ugb3IgZmlsZSBidWdzIGFnYWluc3QgdGhlIHRlYW1zIGJlZm9yZSBtYWtpbmdcbiAgICAvLyB0aGUgY2hhbmdlLlxuICAgIHJldHVybiB0aGlzLm5hdmlnYXRpb25UcmFuc2l0aW9ucy5ldmVudHM7XG4gIH1cbiAgLyoqXG4gICAqIFRoZSBjdXJyZW50IHN0YXRlIG9mIHJvdXRpbmcgaW4gdGhpcyBOZ01vZHVsZS5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSByb3V0ZXJTdGF0ZTogUm91dGVyU3RhdGU7XG5cbiAgcHJpdmF0ZSBvcHRpb25zID0gaW5qZWN0KFJPVVRFUl9DT05GSUdVUkFUSU9OLCB7b3B0aW9uYWw6IHRydWV9KSB8fCB7fTtcblxuICAvKipcbiAgICogQSBoYW5kbGVyIGZvciBuYXZpZ2F0aW9uIGVycm9ycyBpbiB0aGlzIE5nTW9kdWxlLlxuICAgKlxuICAgKiBAZGVwcmVjYXRlZCBTdWJzY3JpYmUgdG8gdGhlIGBSb3V0ZXJgIGV2ZW50cyBhbmQgd2F0Y2ggZm9yIGBOYXZpZ2F0aW9uRXJyb3JgIGluc3RlYWQuXG4gICAqICAgYHByb3ZpZGVSb3V0ZXJgIGhhcyB0aGUgYHdpdGhOYXZpZ2F0aW9uRXJyb3JIYW5kbGVyYCBmZWF0dXJlIHRvIG1ha2UgdGhpcyBlYXNpZXIuXG4gICAqIEBzZWUgYHdpdGhOYXZpZ2F0aW9uRXJyb3JIYW5kbGVyYFxuICAgKi9cbiAgZXJyb3JIYW5kbGVyID0gdGhpcy5vcHRpb25zLmVycm9ySGFuZGxlciB8fCBkZWZhdWx0RXJyb3JIYW5kbGVyO1xuXG4gIC8qKlxuICAgKiBBIGhhbmRsZXIgZm9yIGVycm9ycyB0aHJvd24gYnkgYFJvdXRlci5wYXJzZVVybCh1cmwpYFxuICAgKiB3aGVuIGB1cmxgIGNvbnRhaW5zIGFuIGludmFsaWQgY2hhcmFjdGVyLlxuICAgKiBUaGUgbW9zdCBjb21tb24gY2FzZSBpcyBhIGAlYCBzaWduXG4gICAqIHRoYXQncyBub3QgZW5jb2RlZCBhbmQgaXMgbm90IHBhcnQgb2YgYSBwZXJjZW50IGVuY29kZWQgc2VxdWVuY2UuXG4gICAqXG4gICAqIEBkZXByZWNhdGVkIFVSSSBwYXJzaW5nIGVycm9ycyBzaG91bGQgYmUgaGFuZGxlZCBpbiB0aGUgYFVybFNlcmlhbGl6ZXJgLlxuICAgKlxuICAgKiBAc2VlIGBSb3V0ZXJNb2R1bGVgXG4gICAqL1xuICBtYWxmb3JtZWRVcmlFcnJvckhhbmRsZXIgPVxuICAgICAgdGhpcy5vcHRpb25zLm1hbGZvcm1lZFVyaUVycm9ySGFuZGxlciB8fCBkZWZhdWx0TWFsZm9ybWVkVXJpRXJyb3JIYW5kbGVyO1xuXG4gIC8qKlxuICAgKiBUcnVlIGlmIGF0IGxlYXN0IG9uZSBuYXZpZ2F0aW9uIGV2ZW50IGhhcyBvY2N1cnJlZCxcbiAgICogZmFsc2Ugb3RoZXJ3aXNlLlxuICAgKi9cbiAgbmF2aWdhdGVkOiBib29sZWFuID0gZmFsc2U7XG4gIHByaXZhdGUgbGFzdFN1Y2Nlc3NmdWxJZDogbnVtYmVyID0gLTE7XG5cbiAgLyoqXG4gICAqIEEgc3RyYXRlZ3kgZm9yIGV4dHJhY3RpbmcgYW5kIG1lcmdpbmcgVVJMcy5cbiAgICogVXNlZCBmb3IgQW5ndWxhckpTIHRvIEFuZ3VsYXIgbWlncmF0aW9ucy5cbiAgICpcbiAgICogQGRlcHJlY2F0ZWQgQ29uZmlndXJlIHVzaW5nIGBwcm92aWRlcnNgIGluc3RlYWQ6XG4gICAqICAgYHtwcm92aWRlOiBVcmxIYW5kbGluZ1N0cmF0ZWd5LCB1c2VDbGFzczogTXlTdHJhdGVneX1gLlxuICAgKi9cbiAgdXJsSGFuZGxpbmdTdHJhdGVneSA9IGluamVjdChVcmxIYW5kbGluZ1N0cmF0ZWd5KTtcblxuICAvKipcbiAgICogQSBzdHJhdGVneSBmb3IgcmUtdXNpbmcgcm91dGVzLlxuICAgKlxuICAgKiBAZGVwcmVjYXRlZCBDb25maWd1cmUgdXNpbmcgYHByb3ZpZGVyc2AgaW5zdGVhZDpcbiAgICogICBge3Byb3ZpZGU6IFJvdXRlUmV1c2VTdHJhdGVneSwgdXNlQ2xhc3M6IE15U3RyYXRlZ3l9YC5cbiAgICovXG4gIHJvdXRlUmV1c2VTdHJhdGVneSA9IGluamVjdChSb3V0ZVJldXNlU3RyYXRlZ3kpO1xuXG4gIC8qKlxuICAgKiBBIHN0cmF0ZWd5IGZvciBzZXR0aW5nIHRoZSB0aXRsZSBiYXNlZCBvbiB0aGUgYHJvdXRlclN0YXRlYC5cbiAgICpcbiAgICogQGRlcHJlY2F0ZWQgQ29uZmlndXJlIHVzaW5nIGBwcm92aWRlcnNgIGluc3RlYWQ6XG4gICAqICAgYHtwcm92aWRlOiBUaXRsZVN0cmF0ZWd5LCB1c2VDbGFzczogTXlTdHJhdGVneX1gLlxuICAgKi9cbiAgdGl0bGVTdHJhdGVneT86IFRpdGxlU3RyYXRlZ3kgPSBpbmplY3QoVGl0bGVTdHJhdGVneSk7XG5cbiAgLyoqXG4gICAqIEhvdyB0byBoYW5kbGUgYSBuYXZpZ2F0aW9uIHJlcXVlc3QgdG8gdGhlIGN1cnJlbnQgVVJMLlxuICAgKlxuICAgKlxuICAgKiBAZGVwcmVjYXRlZCBDb25maWd1cmUgdGhpcyB0aHJvdWdoIGBwcm92aWRlUm91dGVyYCBvciBgUm91dGVyTW9kdWxlLmZvclJvb3RgIGluc3RlYWQuXG4gICAqIEBzZWUgYHdpdGhSb3V0ZXJDb25maWdgXG4gICAqIEBzZWUgYHByb3ZpZGVSb3V0ZXJgXG4gICAqIEBzZWUgYFJvdXRlck1vZHVsZWBcbiAgICovXG4gIG9uU2FtZVVybE5hdmlnYXRpb246IE9uU2FtZVVybE5hdmlnYXRpb24gPSB0aGlzLm9wdGlvbnMub25TYW1lVXJsTmF2aWdhdGlvbiB8fCAnaWdub3JlJztcblxuICAvKipcbiAgICogSG93IHRvIG1lcmdlIHBhcmFtZXRlcnMsIGRhdGEsIHJlc29sdmVkIGRhdGEsIGFuZCB0aXRsZSBmcm9tIHBhcmVudCB0byBjaGlsZFxuICAgKiByb3V0ZXMuIE9uZSBvZjpcbiAgICpcbiAgICogLSBgJ2VtcHR5T25seSdgIDogSW5oZXJpdCBwYXJlbnQgcGFyYW1ldGVycywgZGF0YSwgYW5kIHJlc29sdmVkIGRhdGFcbiAgICogZm9yIHBhdGgtbGVzcyBvciBjb21wb25lbnQtbGVzcyByb3V0ZXMuXG4gICAqIC0gYCdhbHdheXMnYCA6IEluaGVyaXQgcGFyZW50IHBhcmFtZXRlcnMsIGRhdGEsIGFuZCByZXNvbHZlZCBkYXRhXG4gICAqIGZvciBhbGwgY2hpbGQgcm91dGVzLlxuICAgKlxuICAgKiBAZGVwcmVjYXRlZCBDb25maWd1cmUgdGhpcyB0aHJvdWdoIGBwcm92aWRlUm91dGVyYCBvciBgUm91dGVyTW9kdWxlLmZvclJvb3RgIGluc3RlYWQuXG4gICAqIEBzZWUgYHdpdGhSb3V0ZXJDb25maWdgXG4gICAqIEBzZWUgYHByb3ZpZGVSb3V0ZXJgXG4gICAqIEBzZWUgYFJvdXRlck1vZHVsZWBcbiAgICovXG4gIHBhcmFtc0luaGVyaXRhbmNlU3RyYXRlZ3k6ICdlbXB0eU9ubHknfCdhbHdheXMnID1cbiAgICAgIHRoaXMub3B0aW9ucy5wYXJhbXNJbmhlcml0YW5jZVN0cmF0ZWd5IHx8ICdlbXB0eU9ubHknO1xuXG4gIC8qKlxuICAgKiBEZXRlcm1pbmVzIHdoZW4gdGhlIHJvdXRlciB1cGRhdGVzIHRoZSBicm93c2VyIFVSTC5cbiAgICogQnkgZGVmYXVsdCAoYFwiZGVmZXJyZWRcImApLCB1cGRhdGVzIHRoZSBicm93c2VyIFVSTCBhZnRlciBuYXZpZ2F0aW9uIGhhcyBmaW5pc2hlZC5cbiAgICogU2V0IHRvIGAnZWFnZXInYCB0byB1cGRhdGUgdGhlIGJyb3dzZXIgVVJMIGF0IHRoZSBiZWdpbm5pbmcgb2YgbmF2aWdhdGlvbi5cbiAgICogWW91IGNhbiBjaG9vc2UgdG8gdXBkYXRlIGVhcmx5IHNvIHRoYXQsIGlmIG5hdmlnYXRpb24gZmFpbHMsXG4gICAqIHlvdSBjYW4gc2hvdyBhbiBlcnJvciBtZXNzYWdlIHdpdGggdGhlIFVSTCB0aGF0IGZhaWxlZC5cbiAgICpcbiAgICogQGRlcHJlY2F0ZWQgQ29uZmlndXJlIHRoaXMgdGhyb3VnaCBgcHJvdmlkZVJvdXRlcmAgb3IgYFJvdXRlck1vZHVsZS5mb3JSb290YCBpbnN0ZWFkLlxuICAgKiBAc2VlIGB3aXRoUm91dGVyQ29uZmlnYFxuICAgKiBAc2VlIGBwcm92aWRlUm91dGVyYFxuICAgKiBAc2VlIGBSb3V0ZXJNb2R1bGVgXG4gICAqL1xuICB1cmxVcGRhdGVTdHJhdGVneTogJ2RlZmVycmVkJ3wnZWFnZXInID0gdGhpcy5vcHRpb25zLnVybFVwZGF0ZVN0cmF0ZWd5IHx8ICdkZWZlcnJlZCc7XG5cbiAgLyoqXG4gICAqIENvbmZpZ3VyZXMgaG93IHRoZSBSb3V0ZXIgYXR0ZW1wdHMgdG8gcmVzdG9yZSBzdGF0ZSB3aGVuIGEgbmF2aWdhdGlvbiBpcyBjYW5jZWxsZWQuXG4gICAqXG4gICAqICdyZXBsYWNlJyAtIEFsd2F5cyB1c2VzIGBsb2NhdGlvbi5yZXBsYWNlU3RhdGVgIHRvIHNldCB0aGUgYnJvd3NlciBzdGF0ZSB0byB0aGUgc3RhdGUgb2YgdGhlXG4gICAqIHJvdXRlciBiZWZvcmUgdGhlIG5hdmlnYXRpb24gc3RhcnRlZC4gVGhpcyBtZWFucyB0aGF0IGlmIHRoZSBVUkwgb2YgdGhlIGJyb3dzZXIgaXMgdXBkYXRlZFxuICAgKiBfYmVmb3JlXyB0aGUgbmF2aWdhdGlvbiBpcyBjYW5jZWxlZCwgdGhlIFJvdXRlciB3aWxsIHNpbXBseSByZXBsYWNlIHRoZSBpdGVtIGluIGhpc3RvcnkgcmF0aGVyXG4gICAqIHRoYW4gdHJ5aW5nIHRvIHJlc3RvcmUgdG8gdGhlIHByZXZpb3VzIGxvY2F0aW9uIGluIHRoZSBzZXNzaW9uIGhpc3RvcnkuIFRoaXMgaGFwcGVucyBtb3N0XG4gICAqIGZyZXF1ZW50bHkgd2l0aCBgdXJsVXBkYXRlU3RyYXRlZ3k6ICdlYWdlcidgIGFuZCBuYXZpZ2F0aW9ucyB3aXRoIHRoZSBicm93c2VyIGJhY2svZm9yd2FyZFxuICAgKiBidXR0b25zLlxuICAgKlxuICAgKiAnY29tcHV0ZWQnIC0gV2lsbCBhdHRlbXB0IHRvIHJldHVybiB0byB0aGUgc2FtZSBpbmRleCBpbiB0aGUgc2Vzc2lvbiBoaXN0b3J5IHRoYXQgY29ycmVzcG9uZHNcbiAgICogdG8gdGhlIEFuZ3VsYXIgcm91dGUgd2hlbiB0aGUgbmF2aWdhdGlvbiBnZXRzIGNhbmNlbGxlZC4gRm9yIGV4YW1wbGUsIGlmIHRoZSBicm93c2VyIGJhY2tcbiAgICogYnV0dG9uIGlzIGNsaWNrZWQgYW5kIHRoZSBuYXZpZ2F0aW9uIGlzIGNhbmNlbGxlZCwgdGhlIFJvdXRlciB3aWxsIHRyaWdnZXIgYSBmb3J3YXJkIG5hdmlnYXRpb25cbiAgICogYW5kIHZpY2UgdmVyc2EuXG4gICAqXG4gICAqIE5vdGU6IHRoZSAnY29tcHV0ZWQnIG9wdGlvbiBpcyBpbmNvbXBhdGlibGUgd2l0aCBhbnkgYFVybEhhbmRsaW5nU3RyYXRlZ3lgIHdoaWNoIG9ubHlcbiAgICogaGFuZGxlcyBhIHBvcnRpb24gb2YgdGhlIFVSTCBiZWNhdXNlIHRoZSBoaXN0b3J5IHJlc3RvcmF0aW9uIG5hdmlnYXRlcyB0byB0aGUgcHJldmlvdXMgcGxhY2UgaW5cbiAgICogdGhlIGJyb3dzZXIgaGlzdG9yeSByYXRoZXIgdGhhbiBzaW1wbHkgcmVzZXR0aW5nIGEgcG9ydGlvbiBvZiB0aGUgVVJMLlxuICAgKlxuICAgKiBUaGUgZGVmYXVsdCB2YWx1ZSBpcyBgcmVwbGFjZWAuXG4gICAqXG4gICAqIEBkZXByZWNhdGVkIENvbmZpZ3VyZSB0aGlzIHRocm91Z2ggYHByb3ZpZGVSb3V0ZXJgIG9yIGBSb3V0ZXJNb2R1bGUuZm9yUm9vdGAgaW5zdGVhZC5cbiAgICogQHNlZSBgd2l0aFJvdXRlckNvbmZpZ2BcbiAgICogQHNlZSBgcHJvdmlkZVJvdXRlcmBcbiAgICogQHNlZSBgUm91dGVyTW9kdWxlYFxuICAgKi9cbiAgY2FuY2VsZWROYXZpZ2F0aW9uUmVzb2x1dGlvbjogJ3JlcGxhY2UnfCdjb21wdXRlZCcgPVxuICAgICAgdGhpcy5vcHRpb25zLmNhbmNlbGVkTmF2aWdhdGlvblJlc29sdXRpb24gfHwgJ3JlcGxhY2UnO1xuXG4gIGNvbmZpZzogUm91dGVzID0gaW5qZWN0KFJPVVRFUywge29wdGlvbmFsOiB0cnVlfSk/LmZsYXQoKSA/PyBbXTtcblxuICBwcml2YXRlIHJlYWRvbmx5IG5hdmlnYXRpb25UcmFuc2l0aW9ucyA9IGluamVjdChOYXZpZ2F0aW9uVHJhbnNpdGlvbnMpO1xuICBwcml2YXRlIHJlYWRvbmx5IHVybFNlcmlhbGl6ZXIgPSBpbmplY3QoVXJsU2VyaWFsaXplcik7XG4gIHByaXZhdGUgcmVhZG9ubHkgbG9jYXRpb24gPSBpbmplY3QoTG9jYXRpb24pO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMuaXNOZ1pvbmVFbmFibGVkID0gaW5qZWN0KE5nWm9uZSkgaW5zdGFuY2VvZiBOZ1pvbmUgJiYgTmdab25lLmlzSW5Bbmd1bGFyWm9uZSgpO1xuXG4gICAgdGhpcy5yZXNldENvbmZpZyh0aGlzLmNvbmZpZyk7XG4gICAgdGhpcy5jdXJyZW50VXJsVHJlZSA9IG5ldyBVcmxUcmVlKCk7XG4gICAgdGhpcy5yYXdVcmxUcmVlID0gdGhpcy5jdXJyZW50VXJsVHJlZTtcbiAgICB0aGlzLmJyb3dzZXJVcmxUcmVlID0gdGhpcy5jdXJyZW50VXJsVHJlZTtcblxuICAgIHRoaXMucm91dGVyU3RhdGUgPSBjcmVhdGVFbXB0eVN0YXRlKHRoaXMuY3VycmVudFVybFRyZWUsIG51bGwpO1xuXG4gICAgdGhpcy5uYXZpZ2F0aW9uVHJhbnNpdGlvbnMuc2V0dXBOYXZpZ2F0aW9ucyh0aGlzKS5zdWJzY3JpYmUoXG4gICAgICAgIHQgPT4ge1xuICAgICAgICAgIHRoaXMubGFzdFN1Y2Nlc3NmdWxJZCA9IHQuaWQ7XG4gICAgICAgICAgdGhpcy5jdXJyZW50UGFnZUlkID0gdC50YXJnZXRQYWdlSWQ7XG4gICAgICAgIH0sXG4gICAgICAgIGUgPT4ge1xuICAgICAgICAgIHRoaXMuY29uc29sZS53YXJuKGBVbmhhbmRsZWQgTmF2aWdhdGlvbiBFcnJvcjogJHtlfWApO1xuICAgICAgICB9KTtcbiAgfVxuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgcmVzZXRSb290Q29tcG9uZW50VHlwZShyb290Q29tcG9uZW50VHlwZTogVHlwZTxhbnk+KTogdm9pZCB7XG4gICAgLy8gVE9ETzogdnNhdmtpbiByb3V0ZXIgNC4wIHNob3VsZCBtYWtlIHRoZSByb290IGNvbXBvbmVudCBzZXQgdG8gbnVsbFxuICAgIC8vIHRoaXMgd2lsbCBzaW1wbGlmeSB0aGUgbGlmZWN5Y2xlIG9mIHRoZSByb3V0ZXIuXG4gICAgdGhpcy5yb3V0ZXJTdGF0ZS5yb290LmNvbXBvbmVudCA9IHJvb3RDb21wb25lbnRUeXBlO1xuICAgIHRoaXMubmF2aWdhdGlvblRyYW5zaXRpb25zLnJvb3RDb21wb25lbnRUeXBlID0gcm9vdENvbXBvbmVudFR5cGU7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB1cCB0aGUgbG9jYXRpb24gY2hhbmdlIGxpc3RlbmVyIGFuZCBwZXJmb3JtcyB0aGUgaW5pdGlhbCBuYXZpZ2F0aW9uLlxuICAgKi9cbiAgaW5pdGlhbE5hdmlnYXRpb24oKTogdm9pZCB7XG4gICAgdGhpcy5zZXRVcExvY2F0aW9uQ2hhbmdlTGlzdGVuZXIoKTtcbiAgICBpZiAoIXRoaXMubmF2aWdhdGlvblRyYW5zaXRpb25zLmhhc1JlcXVlc3RlZE5hdmlnYXRpb24pIHtcbiAgICAgIGNvbnN0IHN0YXRlID0gdGhpcy5sb2NhdGlvbi5nZXRTdGF0ZSgpIGFzIFJlc3RvcmVkU3RhdGU7XG4gICAgICB0aGlzLm5hdmlnYXRlVG9TeW5jV2l0aEJyb3dzZXIodGhpcy5sb2NhdGlvbi5wYXRoKHRydWUpLCBJTVBFUkFUSVZFX05BVklHQVRJT04sIHN0YXRlKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB1cCB0aGUgbG9jYXRpb24gY2hhbmdlIGxpc3RlbmVyLiBUaGlzIGxpc3RlbmVyIGRldGVjdHMgbmF2aWdhdGlvbnMgdHJpZ2dlcmVkIGZyb20gb3V0c2lkZVxuICAgKiB0aGUgUm91dGVyICh0aGUgYnJvd3NlciBiYWNrL2ZvcndhcmQgYnV0dG9ucywgZm9yIGV4YW1wbGUpIGFuZCBzY2hlZHVsZXMgYSBjb3JyZXNwb25kaW5nIFJvdXRlclxuICAgKiBuYXZpZ2F0aW9uIHNvIHRoYXQgdGhlIGNvcnJlY3QgZXZlbnRzLCBndWFyZHMsIGV0Yy4gYXJlIHRyaWdnZXJlZC5cbiAgICovXG4gIHNldFVwTG9jYXRpb25DaGFuZ2VMaXN0ZW5lcigpOiB2b2lkIHtcbiAgICAvLyBEb24ndCBuZWVkIHRvIHVzZSBab25lLndyYXAgYW55IG1vcmUsIGJlY2F1c2Ugem9uZS5qc1xuICAgIC8vIGFscmVhZHkgcGF0Y2ggb25Qb3BTdGF0ZSwgc28gbG9jYXRpb24gY2hhbmdlIGNhbGxiYWNrIHdpbGxcbiAgICAvLyBydW4gaW50byBuZ1pvbmVcbiAgICBpZiAoIXRoaXMubG9jYXRpb25TdWJzY3JpcHRpb24pIHtcbiAgICAgIHRoaXMubG9jYXRpb25TdWJzY3JpcHRpb24gPSB0aGlzLmxvY2F0aW9uLnN1YnNjcmliZShldmVudCA9PiB7XG4gICAgICAgIGNvbnN0IHNvdXJjZSA9IGV2ZW50Wyd0eXBlJ10gPT09ICdwb3BzdGF0ZScgPyAncG9wc3RhdGUnIDogJ2hhc2hjaGFuZ2UnO1xuICAgICAgICBpZiAoc291cmNlID09PSAncG9wc3RhdGUnKSB7XG4gICAgICAgICAgLy8gVGhlIGBzZXRUaW1lb3V0YCB3YXMgYWRkZWQgaW4gIzEyMTYwIGFuZCBpcyBsaWtlbHkgdG8gc3VwcG9ydCBBbmd1bGFyL0FuZ3VsYXJKU1xuICAgICAgICAgIC8vIGh5YnJpZCBhcHBzLlxuICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5uYXZpZ2F0ZVRvU3luY1dpdGhCcm93c2VyKGV2ZW50Wyd1cmwnXSEsIHNvdXJjZSwgZXZlbnQuc3RhdGUpO1xuICAgICAgICAgIH0sIDApO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2NoZWR1bGVzIGEgcm91dGVyIG5hdmlnYXRpb24gdG8gc3luY2hyb25pemUgUm91dGVyIHN0YXRlIHdpdGggdGhlIGJyb3dzZXIgc3RhdGUuXG4gICAqXG4gICAqIFRoaXMgaXMgZG9uZSBhcyBhIHJlc3BvbnNlIHRvIGEgcG9wc3RhdGUgZXZlbnQgYW5kIHRoZSBpbml0aWFsIG5hdmlnYXRpb24uIFRoZXNlXG4gICAqIHR3byBzY2VuYXJpb3MgcmVwcmVzZW50IHRpbWVzIHdoZW4gdGhlIGJyb3dzZXIgVVJML3N0YXRlIGhhcyBiZWVuIHVwZGF0ZWQgYW5kXG4gICAqIHRoZSBSb3V0ZXIgbmVlZHMgdG8gcmVzcG9uZCB0byBlbnN1cmUgaXRzIGludGVybmFsIHN0YXRlIG1hdGNoZXMuXG4gICAqL1xuICBwcml2YXRlIG5hdmlnYXRlVG9TeW5jV2l0aEJyb3dzZXIoXG4gICAgICB1cmw6IHN0cmluZywgc291cmNlOiBOYXZpZ2F0aW9uVHJpZ2dlciwgc3RhdGU6IFJlc3RvcmVkU3RhdGV8dW5kZWZpbmVkKSB7XG4gICAgY29uc3QgZXh0cmFzOiBOYXZpZ2F0aW9uRXh0cmFzID0ge3JlcGxhY2VVcmw6IHRydWV9O1xuXG4gICAgLy8gVE9ETzogcmVzdG9yZWRTdGF0ZSBzaG91bGQgYWx3YXlzIGluY2x1ZGUgdGhlIGVudGlyZSBzdGF0ZSwgcmVnYXJkbGVzc1xuICAgIC8vIG9mIG5hdmlnYXRpb25JZC4gVGhpcyByZXF1aXJlcyBhIGJyZWFraW5nIGNoYW5nZSB0byB1cGRhdGUgdGhlIHR5cGUgb25cbiAgICAvLyBOYXZpZ2F0aW9uU3RhcnTigJlzIHJlc3RvcmVkU3RhdGUsIHdoaWNoIGN1cnJlbnRseSByZXF1aXJlcyBuYXZpZ2F0aW9uSWRcbiAgICAvLyB0byBhbHdheXMgYmUgcHJlc2VudC4gVGhlIFJvdXRlciB1c2VkIHRvIG9ubHkgcmVzdG9yZSBoaXN0b3J5IHN0YXRlIGlmXG4gICAgLy8gYSBuYXZpZ2F0aW9uSWQgd2FzIHByZXNlbnQuXG5cbiAgICAvLyBUaGUgc3RvcmVkIG5hdmlnYXRpb25JZCBpcyB1c2VkIGJ5IHRoZSBSb3V0ZXJTY3JvbGxlciB0byByZXRyaWV2ZSB0aGUgc2Nyb2xsXG4gICAgLy8gcG9zaXRpb24gZm9yIHRoZSBwYWdlLlxuICAgIGNvbnN0IHJlc3RvcmVkU3RhdGUgPSBzdGF0ZT8ubmF2aWdhdGlvbklkID8gc3RhdGUgOiBudWxsO1xuXG4gICAgLy8gU2VwYXJhdGUgdG8gTmF2aWdhdGlvblN0YXJ0LnJlc3RvcmVkU3RhdGUsIHdlIG11c3QgYWxzbyByZXN0b3JlIHRoZSBzdGF0ZSB0b1xuICAgIC8vIGhpc3Rvcnkuc3RhdGUgYW5kIGdlbmVyYXRlIGEgbmV3IG5hdmlnYXRpb25JZCwgc2luY2UgaXQgd2lsbCBiZSBvdmVyd3JpdHRlblxuICAgIGlmIChzdGF0ZSkge1xuICAgICAgY29uc3Qgc3RhdGVDb3B5ID0gey4uLnN0YXRlfSBhcyBQYXJ0aWFsPFJlc3RvcmVkU3RhdGU+O1xuICAgICAgZGVsZXRlIHN0YXRlQ29weS5uYXZpZ2F0aW9uSWQ7XG4gICAgICBkZWxldGUgc3RhdGVDb3B5Lsm1cm91dGVyUGFnZUlkO1xuICAgICAgaWYgKE9iamVjdC5rZXlzKHN0YXRlQ29weSkubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgIGV4dHJhcy5zdGF0ZSA9IHN0YXRlQ29weTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCB1cmxUcmVlID0gdGhpcy5wYXJzZVVybCh1cmwpO1xuICAgIHRoaXMuc2NoZWR1bGVOYXZpZ2F0aW9uKHVybFRyZWUsIHNvdXJjZSwgcmVzdG9yZWRTdGF0ZSwgZXh0cmFzKTtcbiAgfVxuXG4gIC8qKiBUaGUgY3VycmVudCBVUkwuICovXG4gIGdldCB1cmwoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5zZXJpYWxpemVVcmwodGhpcy5jdXJyZW50VXJsVHJlZSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgY3VycmVudCBgTmF2aWdhdGlvbmAgb2JqZWN0IHdoZW4gdGhlIHJvdXRlciBpcyBuYXZpZ2F0aW5nLFxuICAgKiBhbmQgYG51bGxgIHdoZW4gaWRsZS5cbiAgICovXG4gIGdldEN1cnJlbnROYXZpZ2F0aW9uKCk6IE5hdmlnYXRpb258bnVsbCB7XG4gICAgcmV0dXJuIHRoaXMubmF2aWdhdGlvblRyYW5zaXRpb25zLmN1cnJlbnROYXZpZ2F0aW9uO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBgTmF2aWdhdGlvbmAgb2JqZWN0IG9mIHRoZSBtb3N0IHJlY2VudCBuYXZpZ2F0aW9uIHRvIHN1Y2NlZWQgYW5kIGBudWxsYCBpZiB0aGVyZVxuICAgKiAgICAgaGFzIG5vdCBiZWVuIGEgc3VjY2Vzc2Z1bCBuYXZpZ2F0aW9uIHlldC5cbiAgICovXG4gIGdldCBsYXN0U3VjY2Vzc2Z1bE5hdmlnYXRpb24oKTogTmF2aWdhdGlvbnxudWxsIHtcbiAgICByZXR1cm4gdGhpcy5uYXZpZ2F0aW9uVHJhbnNpdGlvbnMubGFzdFN1Y2Nlc3NmdWxOYXZpZ2F0aW9uO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc2V0cyB0aGUgcm91dGUgY29uZmlndXJhdGlvbiB1c2VkIGZvciBuYXZpZ2F0aW9uIGFuZCBnZW5lcmF0aW5nIGxpbmtzLlxuICAgKlxuICAgKiBAcGFyYW0gY29uZmlnIFRoZSByb3V0ZSBhcnJheSBmb3IgdGhlIG5ldyBjb25maWd1cmF0aW9uLlxuICAgKlxuICAgKiBAdXNhZ2VOb3Rlc1xuICAgKlxuICAgKiBgYGBcbiAgICogcm91dGVyLnJlc2V0Q29uZmlnKFtcbiAgICogIHsgcGF0aDogJ3RlYW0vOmlkJywgY29tcG9uZW50OiBUZWFtQ21wLCBjaGlsZHJlbjogW1xuICAgKiAgICB7IHBhdGg6ICdzaW1wbGUnLCBjb21wb25lbnQ6IFNpbXBsZUNtcCB9LFxuICAgKiAgICB7IHBhdGg6ICd1c2VyLzpuYW1lJywgY29tcG9uZW50OiBVc2VyQ21wIH1cbiAgICogIF19XG4gICAqIF0pO1xuICAgKiBgYGBcbiAgICovXG4gIHJlc2V0Q29uZmlnKGNvbmZpZzogUm91dGVzKTogdm9pZCB7XG4gICAgTkdfREVWX01PREUgJiYgdmFsaWRhdGVDb25maWcoY29uZmlnKTtcbiAgICB0aGlzLmNvbmZpZyA9IGNvbmZpZy5tYXAoc3RhbmRhcmRpemVDb25maWcpO1xuICAgIHRoaXMubmF2aWdhdGVkID0gZmFsc2U7XG4gICAgdGhpcy5sYXN0U3VjY2Vzc2Z1bElkID0gLTE7XG4gIH1cblxuICAvKiogQG5vZG9jICovXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMuZGlzcG9zZSgpO1xuICB9XG5cbiAgLyoqIERpc3Bvc2VzIG9mIHRoZSByb3V0ZXIuICovXG4gIGRpc3Bvc2UoKTogdm9pZCB7XG4gICAgdGhpcy5uYXZpZ2F0aW9uVHJhbnNpdGlvbnMuY29tcGxldGUoKTtcbiAgICBpZiAodGhpcy5sb2NhdGlvblN1YnNjcmlwdGlvbikge1xuICAgICAgdGhpcy5sb2NhdGlvblN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgICAgdGhpcy5sb2NhdGlvblN1YnNjcmlwdGlvbiA9IHVuZGVmaW5lZDtcbiAgICB9XG4gICAgdGhpcy5kaXNwb3NlZCA9IHRydWU7XG4gIH1cblxuICAvKipcbiAgICogQXBwZW5kcyBVUkwgc2VnbWVudHMgdG8gdGhlIGN1cnJlbnQgVVJMIHRyZWUgdG8gY3JlYXRlIGEgbmV3IFVSTCB0cmVlLlxuICAgKlxuICAgKiBAcGFyYW0gY29tbWFuZHMgQW4gYXJyYXkgb2YgVVJMIGZyYWdtZW50cyB3aXRoIHdoaWNoIHRvIGNvbnN0cnVjdCB0aGUgbmV3IFVSTCB0cmVlLlxuICAgKiBJZiB0aGUgcGF0aCBpcyBzdGF0aWMsIGNhbiBiZSB0aGUgbGl0ZXJhbCBVUkwgc3RyaW5nLiBGb3IgYSBkeW5hbWljIHBhdGgsIHBhc3MgYW4gYXJyYXkgb2YgcGF0aFxuICAgKiBzZWdtZW50cywgZm9sbG93ZWQgYnkgdGhlIHBhcmFtZXRlcnMgZm9yIGVhY2ggc2VnbWVudC5cbiAgICogVGhlIGZyYWdtZW50cyBhcmUgYXBwbGllZCB0byB0aGUgY3VycmVudCBVUkwgdHJlZSBvciB0aGUgb25lIHByb3ZpZGVkICBpbiB0aGUgYHJlbGF0aXZlVG9gXG4gICAqIHByb3BlcnR5IG9mIHRoZSBvcHRpb25zIG9iamVjdCwgaWYgc3VwcGxpZWQuXG4gICAqIEBwYXJhbSBuYXZpZ2F0aW9uRXh0cmFzIE9wdGlvbnMgdGhhdCBjb250cm9sIHRoZSBuYXZpZ2F0aW9uIHN0cmF0ZWd5LlxuICAgKiBAcmV0dXJucyBUaGUgbmV3IFVSTCB0cmVlLlxuICAgKlxuICAgKiBAdXNhZ2VOb3Rlc1xuICAgKlxuICAgKiBgYGBcbiAgICogLy8gY3JlYXRlIC90ZWFtLzMzL3VzZXIvMTFcbiAgICogcm91dGVyLmNyZWF0ZVVybFRyZWUoWycvdGVhbScsIDMzLCAndXNlcicsIDExXSk7XG4gICAqXG4gICAqIC8vIGNyZWF0ZSAvdGVhbS8zMztleHBhbmQ9dHJ1ZS91c2VyLzExXG4gICAqIHJvdXRlci5jcmVhdGVVcmxUcmVlKFsnL3RlYW0nLCAzMywge2V4cGFuZDogdHJ1ZX0sICd1c2VyJywgMTFdKTtcbiAgICpcbiAgICogLy8geW91IGNhbiBjb2xsYXBzZSBzdGF0aWMgc2VnbWVudHMgbGlrZSB0aGlzICh0aGlzIHdvcmtzIG9ubHkgd2l0aCB0aGUgZmlyc3QgcGFzc2VkLWluIHZhbHVlKTpcbiAgICogcm91dGVyLmNyZWF0ZVVybFRyZWUoWycvdGVhbS8zMy91c2VyJywgdXNlcklkXSk7XG4gICAqXG4gICAqIC8vIElmIHRoZSBmaXJzdCBzZWdtZW50IGNhbiBjb250YWluIHNsYXNoZXMsIGFuZCB5b3UgZG8gbm90IHdhbnQgdGhlIHJvdXRlciB0byBzcGxpdCBpdCxcbiAgICogLy8geW91IGNhbiBkbyB0aGUgZm9sbG93aW5nOlxuICAgKiByb3V0ZXIuY3JlYXRlVXJsVHJlZShbe3NlZ21lbnRQYXRoOiAnL29uZS90d28nfV0pO1xuICAgKlxuICAgKiAvLyBjcmVhdGUgL3RlYW0vMzMvKHVzZXIvMTEvL3JpZ2h0OmNoYXQpXG4gICAqIHJvdXRlci5jcmVhdGVVcmxUcmVlKFsnL3RlYW0nLCAzMywge291dGxldHM6IHtwcmltYXJ5OiAndXNlci8xMScsIHJpZ2h0OiAnY2hhdCd9fV0pO1xuICAgKlxuICAgKiAvLyByZW1vdmUgdGhlIHJpZ2h0IHNlY29uZGFyeSBub2RlXG4gICAqIHJvdXRlci5jcmVhdGVVcmxUcmVlKFsnL3RlYW0nLCAzMywge291dGxldHM6IHtwcmltYXJ5OiAndXNlci8xMScsIHJpZ2h0OiBudWxsfX1dKTtcbiAgICpcbiAgICogLy8gYXNzdW1pbmcgdGhlIGN1cnJlbnQgdXJsIGlzIGAvdGVhbS8zMy91c2VyLzExYCBhbmQgdGhlIHJvdXRlIHBvaW50cyB0byBgdXNlci8xMWBcbiAgICpcbiAgICogLy8gbmF2aWdhdGUgdG8gL3RlYW0vMzMvdXNlci8xMS9kZXRhaWxzXG4gICAqIHJvdXRlci5jcmVhdGVVcmxUcmVlKFsnZGV0YWlscyddLCB7cmVsYXRpdmVUbzogcm91dGV9KTtcbiAgICpcbiAgICogLy8gbmF2aWdhdGUgdG8gL3RlYW0vMzMvdXNlci8yMlxuICAgKiByb3V0ZXIuY3JlYXRlVXJsVHJlZShbJy4uLzIyJ10sIHtyZWxhdGl2ZVRvOiByb3V0ZX0pO1xuICAgKlxuICAgKiAvLyBuYXZpZ2F0ZSB0byAvdGVhbS80NC91c2VyLzIyXG4gICAqIHJvdXRlci5jcmVhdGVVcmxUcmVlKFsnLi4vLi4vdGVhbS80NC91c2VyLzIyJ10sIHtyZWxhdGl2ZVRvOiByb3V0ZX0pO1xuICAgKlxuICAgKiBOb3RlIHRoYXQgYSB2YWx1ZSBvZiBgbnVsbGAgb3IgYHVuZGVmaW5lZGAgZm9yIGByZWxhdGl2ZVRvYCBpbmRpY2F0ZXMgdGhhdCB0aGVcbiAgICogdHJlZSBzaG91bGQgYmUgY3JlYXRlZCByZWxhdGl2ZSB0byB0aGUgcm9vdC5cbiAgICogYGBgXG4gICAqL1xuICBjcmVhdGVVcmxUcmVlKGNvbW1hbmRzOiBhbnlbXSwgbmF2aWdhdGlvbkV4dHJhczogVXJsQ3JlYXRpb25PcHRpb25zID0ge30pOiBVcmxUcmVlIHtcbiAgICBjb25zdCB7cmVsYXRpdmVUbywgcXVlcnlQYXJhbXMsIGZyYWdtZW50LCBxdWVyeVBhcmFtc0hhbmRsaW5nLCBwcmVzZXJ2ZUZyYWdtZW50fSA9XG4gICAgICAgIG5hdmlnYXRpb25FeHRyYXM7XG4gICAgY29uc3QgZiA9IHByZXNlcnZlRnJhZ21lbnQgPyB0aGlzLmN1cnJlbnRVcmxUcmVlLmZyYWdtZW50IDogZnJhZ21lbnQ7XG4gICAgbGV0IHE6IFBhcmFtc3xudWxsID0gbnVsbDtcbiAgICBzd2l0Y2ggKHF1ZXJ5UGFyYW1zSGFuZGxpbmcpIHtcbiAgICAgIGNhc2UgJ21lcmdlJzpcbiAgICAgICAgcSA9IHsuLi50aGlzLmN1cnJlbnRVcmxUcmVlLnF1ZXJ5UGFyYW1zLCAuLi5xdWVyeVBhcmFtc307XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAncHJlc2VydmUnOlxuICAgICAgICBxID0gdGhpcy5jdXJyZW50VXJsVHJlZS5xdWVyeVBhcmFtcztcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICBxID0gcXVlcnlQYXJhbXMgfHwgbnVsbDtcbiAgICB9XG4gICAgaWYgKHEgIT09IG51bGwpIHtcbiAgICAgIHEgPSB0aGlzLnJlbW92ZUVtcHR5UHJvcHMocSk7XG4gICAgfVxuXG4gICAgbGV0IHJlbGF0aXZlVG9VcmxTZWdtZW50R3JvdXA6IFVybFNlZ21lbnRHcm91cHx1bmRlZmluZWQ7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlbGF0aXZlVG9TbmFwc2hvdCA9IHJlbGF0aXZlVG8gPyByZWxhdGl2ZVRvLnNuYXBzaG90IDogdGhpcy5yb3V0ZXJTdGF0ZS5zbmFwc2hvdC5yb290O1xuICAgICAgcmVsYXRpdmVUb1VybFNlZ21lbnRHcm91cCA9IGNyZWF0ZVNlZ21lbnRHcm91cEZyb21Sb3V0ZShyZWxhdGl2ZVRvU25hcHNob3QpO1xuICAgIH0gY2F0Y2ggKGU6IHVua25vd24pIHtcbiAgICAgIC8vIFRoaXMgaXMgc3RyaWN0bHkgZm9yIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5IHdpdGggdGVzdHMgdGhhdCBjcmVhdGVcbiAgICAgIC8vIGludmFsaWQgYEFjdGl2YXRlZFJvdXRlYCBtb2Nrcy5cbiAgICAgIC8vIE5vdGU6IHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gaGF2aW5nIHRoaXMgZmFsbGJhY2sgZm9yIGludmFsaWQgYEFjdGl2YXRlZFJvdXRlYCBzZXR1cHMgYW5kXG4gICAgICAvLyBqdXN0IHRocm93aW5nIGlzIH41MDAgdGVzdCBmYWlsdXJlcy4gRml4aW5nIGFsbCBvZiB0aG9zZSB0ZXN0cyBieSBoYW5kIGlzIG5vdCBmZWFzaWJsZSBhdFxuICAgICAgLy8gdGhlIG1vbWVudC5cbiAgICAgIGlmICh0eXBlb2YgY29tbWFuZHNbMF0gIT09ICdzdHJpbmcnIHx8ICFjb21tYW5kc1swXS5zdGFydHNXaXRoKCcvJykpIHtcbiAgICAgICAgLy8gTmF2aWdhdGlvbnMgdGhhdCB3ZXJlIGFic29sdXRlIGluIHRoZSBvbGQgd2F5IG9mIGNyZWF0aW5nIFVybFRyZWVzXG4gICAgICAgIC8vIHdvdWxkIHN0aWxsIHdvcmsgYmVjYXVzZSB0aGV5IHdvdWxkbid0IGF0dGVtcHQgdG8gbWF0Y2ggdGhlXG4gICAgICAgIC8vIHNlZ21lbnRzIGluIHRoZSBgQWN0aXZhdGVkUm91dGVgIHRvIHRoZSBgY3VycmVudFVybFRyZWVgIGJ1dFxuICAgICAgICAvLyBpbnN0ZWFkIGp1c3QgcmVwbGFjZSB0aGUgcm9vdCBzZWdtZW50IHdpdGggdGhlIG5hdmlnYXRpb24gcmVzdWx0LlxuICAgICAgICAvLyBOb24tYWJzb2x1dGUgbmF2aWdhdGlvbnMgd291bGQgZmFpbCB0byBhcHBseSB0aGUgY29tbWFuZHMgYmVjYXVzZVxuICAgICAgICAvLyB0aGUgbG9naWMgY291bGQgbm90IGZpbmQgdGhlIHNlZ21lbnQgdG8gcmVwbGFjZSAoc28gdGhleSdkIGFjdCBsaWtlIHRoZXJlIHdlcmUgbm9cbiAgICAgICAgLy8gY29tbWFuZHMpLlxuICAgICAgICBjb21tYW5kcyA9IFtdO1xuICAgICAgfVxuICAgICAgcmVsYXRpdmVUb1VybFNlZ21lbnRHcm91cCA9IHRoaXMuY3VycmVudFVybFRyZWUucm9vdDtcbiAgICB9XG4gICAgcmV0dXJuIGNyZWF0ZVVybFRyZWVGcm9tU2VnbWVudEdyb3VwKHJlbGF0aXZlVG9VcmxTZWdtZW50R3JvdXAsIGNvbW1hbmRzLCBxLCBmID8/IG51bGwpO1xuICB9XG5cbiAgLyoqXG4gICAqIE5hdmlnYXRlcyB0byBhIHZpZXcgdXNpbmcgYW4gYWJzb2x1dGUgcm91dGUgcGF0aC5cbiAgICpcbiAgICogQHBhcmFtIHVybCBBbiBhYnNvbHV0ZSBwYXRoIGZvciBhIGRlZmluZWQgcm91dGUuIFRoZSBmdW5jdGlvbiBkb2VzIG5vdCBhcHBseSBhbnkgZGVsdGEgdG8gdGhlXG4gICAqICAgICBjdXJyZW50IFVSTC5cbiAgICogQHBhcmFtIGV4dHJhcyBBbiBvYmplY3QgY29udGFpbmluZyBwcm9wZXJ0aWVzIHRoYXQgbW9kaWZ5IHRoZSBuYXZpZ2F0aW9uIHN0cmF0ZWd5LlxuICAgKlxuICAgKiBAcmV0dXJucyBBIFByb21pc2UgdGhhdCByZXNvbHZlcyB0byAndHJ1ZScgd2hlbiBuYXZpZ2F0aW9uIHN1Y2NlZWRzLFxuICAgKiB0byAnZmFsc2UnIHdoZW4gbmF2aWdhdGlvbiBmYWlscywgb3IgaXMgcmVqZWN0ZWQgb24gZXJyb3IuXG4gICAqXG4gICAqIEB1c2FnZU5vdGVzXG4gICAqXG4gICAqIFRoZSBmb2xsb3dpbmcgY2FsbHMgcmVxdWVzdCBuYXZpZ2F0aW9uIHRvIGFuIGFic29sdXRlIHBhdGguXG4gICAqXG4gICAqIGBgYFxuICAgKiByb3V0ZXIubmF2aWdhdGVCeVVybChcIi90ZWFtLzMzL3VzZXIvMTFcIik7XG4gICAqXG4gICAqIC8vIE5hdmlnYXRlIHdpdGhvdXQgdXBkYXRpbmcgdGhlIFVSTFxuICAgKiByb3V0ZXIubmF2aWdhdGVCeVVybChcIi90ZWFtLzMzL3VzZXIvMTFcIiwgeyBza2lwTG9jYXRpb25DaGFuZ2U6IHRydWUgfSk7XG4gICAqIGBgYFxuICAgKlxuICAgKiBAc2VlIFtSb3V0aW5nIGFuZCBOYXZpZ2F0aW9uIGd1aWRlXShndWlkZS9yb3V0ZXIpXG4gICAqXG4gICAqL1xuICBuYXZpZ2F0ZUJ5VXJsKHVybDogc3RyaW5nfFVybFRyZWUsIGV4dHJhczogTmF2aWdhdGlvbkJlaGF2aW9yT3B0aW9ucyA9IHtcbiAgICBza2lwTG9jYXRpb25DaGFuZ2U6IGZhbHNlXG4gIH0pOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBpZiAoTkdfREVWX01PREUpIHtcbiAgICAgIGlmICh0aGlzLmlzTmdab25lRW5hYmxlZCAmJiAhTmdab25lLmlzSW5Bbmd1bGFyWm9uZSgpKSB7XG4gICAgICAgIHRoaXMuY29uc29sZS53YXJuKFxuICAgICAgICAgICAgYE5hdmlnYXRpb24gdHJpZ2dlcmVkIG91dHNpZGUgQW5ndWxhciB6b25lLCBkaWQgeW91IGZvcmdldCB0byBjYWxsICduZ1pvbmUucnVuKCknP2ApO1xuICAgICAgfVxuICAgICAgaWYgKHVybCBpbnN0YW5jZW9mIFVybFRyZWUgJiYgdXJsLl93YXJuSWZVc2VkRm9yTmF2aWdhdGlvbikge1xuICAgICAgICB0aGlzLmNvbnNvbGUud2Fybih1cmwuX3dhcm5JZlVzZWRGb3JOYXZpZ2F0aW9uKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCB1cmxUcmVlID0gaXNVcmxUcmVlKHVybCkgPyB1cmwgOiB0aGlzLnBhcnNlVXJsKHVybCk7XG4gICAgY29uc3QgbWVyZ2VkVHJlZSA9IHRoaXMudXJsSGFuZGxpbmdTdHJhdGVneS5tZXJnZSh1cmxUcmVlLCB0aGlzLnJhd1VybFRyZWUpO1xuXG4gICAgcmV0dXJuIHRoaXMuc2NoZWR1bGVOYXZpZ2F0aW9uKG1lcmdlZFRyZWUsIElNUEVSQVRJVkVfTkFWSUdBVElPTiwgbnVsbCwgZXh0cmFzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBOYXZpZ2F0ZSBiYXNlZCBvbiB0aGUgcHJvdmlkZWQgYXJyYXkgb2YgY29tbWFuZHMgYW5kIGEgc3RhcnRpbmcgcG9pbnQuXG4gICAqIElmIG5vIHN0YXJ0aW5nIHJvdXRlIGlzIHByb3ZpZGVkLCB0aGUgbmF2aWdhdGlvbiBpcyBhYnNvbHV0ZS5cbiAgICpcbiAgICogQHBhcmFtIGNvbW1hbmRzIEFuIGFycmF5IG9mIFVSTCBmcmFnbWVudHMgd2l0aCB3aGljaCB0byBjb25zdHJ1Y3QgdGhlIHRhcmdldCBVUkwuXG4gICAqIElmIHRoZSBwYXRoIGlzIHN0YXRpYywgY2FuIGJlIHRoZSBsaXRlcmFsIFVSTCBzdHJpbmcuIEZvciBhIGR5bmFtaWMgcGF0aCwgcGFzcyBhbiBhcnJheSBvZiBwYXRoXG4gICAqIHNlZ21lbnRzLCBmb2xsb3dlZCBieSB0aGUgcGFyYW1ldGVycyBmb3IgZWFjaCBzZWdtZW50LlxuICAgKiBUaGUgZnJhZ21lbnRzIGFyZSBhcHBsaWVkIHRvIHRoZSBjdXJyZW50IFVSTCBvciB0aGUgb25lIHByb3ZpZGVkICBpbiB0aGUgYHJlbGF0aXZlVG9gIHByb3BlcnR5XG4gICAqIG9mIHRoZSBvcHRpb25zIG9iamVjdCwgaWYgc3VwcGxpZWQuXG4gICAqIEBwYXJhbSBleHRyYXMgQW4gb3B0aW9ucyBvYmplY3QgdGhhdCBkZXRlcm1pbmVzIGhvdyB0aGUgVVJMIHNob3VsZCBiZSBjb25zdHJ1Y3RlZCBvclxuICAgKiAgICAgaW50ZXJwcmV0ZWQuXG4gICAqXG4gICAqIEByZXR1cm5zIEEgUHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGB0cnVlYCB3aGVuIG5hdmlnYXRpb24gc3VjY2VlZHMsIHRvIGBmYWxzZWAgd2hlbiBuYXZpZ2F0aW9uXG4gICAqICAgICBmYWlscyxcbiAgICogb3IgaXMgcmVqZWN0ZWQgb24gZXJyb3IuXG4gICAqXG4gICAqIEB1c2FnZU5vdGVzXG4gICAqXG4gICAqIFRoZSBmb2xsb3dpbmcgY2FsbHMgcmVxdWVzdCBuYXZpZ2F0aW9uIHRvIGEgZHluYW1pYyByb3V0ZSBwYXRoIHJlbGF0aXZlIHRvIHRoZSBjdXJyZW50IFVSTC5cbiAgICpcbiAgICogYGBgXG4gICAqIHJvdXRlci5uYXZpZ2F0ZShbJ3RlYW0nLCAzMywgJ3VzZXInLCAxMV0sIHtyZWxhdGl2ZVRvOiByb3V0ZX0pO1xuICAgKlxuICAgKiAvLyBOYXZpZ2F0ZSB3aXRob3V0IHVwZGF0aW5nIHRoZSBVUkwsIG92ZXJyaWRpbmcgdGhlIGRlZmF1bHQgYmVoYXZpb3JcbiAgICogcm91dGVyLm5hdmlnYXRlKFsndGVhbScsIDMzLCAndXNlcicsIDExXSwge3JlbGF0aXZlVG86IHJvdXRlLCBza2lwTG9jYXRpb25DaGFuZ2U6IHRydWV9KTtcbiAgICogYGBgXG4gICAqXG4gICAqIEBzZWUgW1JvdXRpbmcgYW5kIE5hdmlnYXRpb24gZ3VpZGVdKGd1aWRlL3JvdXRlcilcbiAgICpcbiAgICovXG4gIG5hdmlnYXRlKGNvbW1hbmRzOiBhbnlbXSwgZXh0cmFzOiBOYXZpZ2F0aW9uRXh0cmFzID0ge3NraXBMb2NhdGlvbkNoYW5nZTogZmFsc2V9KTpcbiAgICAgIFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIHZhbGlkYXRlQ29tbWFuZHMoY29tbWFuZHMpO1xuICAgIHJldHVybiB0aGlzLm5hdmlnYXRlQnlVcmwodGhpcy5jcmVhdGVVcmxUcmVlKGNvbW1hbmRzLCBleHRyYXMpLCBleHRyYXMpO1xuICB9XG5cbiAgLyoqIFNlcmlhbGl6ZXMgYSBgVXJsVHJlZWAgaW50byBhIHN0cmluZyAqL1xuICBzZXJpYWxpemVVcmwodXJsOiBVcmxUcmVlKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy51cmxTZXJpYWxpemVyLnNlcmlhbGl6ZSh1cmwpO1xuICB9XG5cbiAgLyoqIFBhcnNlcyBhIHN0cmluZyBpbnRvIGEgYFVybFRyZWVgICovXG4gIHBhcnNlVXJsKHVybDogc3RyaW5nKTogVXJsVHJlZSB7XG4gICAgbGV0IHVybFRyZWU6IFVybFRyZWU7XG4gICAgdHJ5IHtcbiAgICAgIHVybFRyZWUgPSB0aGlzLnVybFNlcmlhbGl6ZXIucGFyc2UodXJsKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICB1cmxUcmVlID0gdGhpcy5tYWxmb3JtZWRVcmlFcnJvckhhbmRsZXIoZSBhcyBVUklFcnJvciwgdGhpcy51cmxTZXJpYWxpemVyLCB1cmwpO1xuICAgIH1cbiAgICByZXR1cm4gdXJsVHJlZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHdoZXRoZXIgdGhlIHVybCBpcyBhY3RpdmF0ZWQuXG4gICAqXG4gICAqIEBkZXByZWNhdGVkXG4gICAqIFVzZSBgSXNBY3RpdmVNYXRjaE9wdGlvbnNgIGluc3RlYWQuXG4gICAqXG4gICAqIC0gVGhlIGVxdWl2YWxlbnQgYElzQWN0aXZlTWF0Y2hPcHRpb25zYCBmb3IgYHRydWVgIGlzXG4gICAqIGB7cGF0aHM6ICdleGFjdCcsIHF1ZXJ5UGFyYW1zOiAnZXhhY3QnLCBmcmFnbWVudDogJ2lnbm9yZWQnLCBtYXRyaXhQYXJhbXM6ICdpZ25vcmVkJ31gLlxuICAgKiAtIFRoZSBlcXVpdmFsZW50IGZvciBgZmFsc2VgIGlzXG4gICAqIGB7cGF0aHM6ICdzdWJzZXQnLCBxdWVyeVBhcmFtczogJ3N1YnNldCcsIGZyYWdtZW50OiAnaWdub3JlZCcsIG1hdHJpeFBhcmFtczogJ2lnbm9yZWQnfWAuXG4gICAqL1xuICBpc0FjdGl2ZSh1cmw6IHN0cmluZ3xVcmxUcmVlLCBleGFjdDogYm9vbGVhbik6IGJvb2xlYW47XG4gIC8qKlxuICAgKiBSZXR1cm5zIHdoZXRoZXIgdGhlIHVybCBpcyBhY3RpdmF0ZWQuXG4gICAqL1xuICBpc0FjdGl2ZSh1cmw6IHN0cmluZ3xVcmxUcmVlLCBtYXRjaE9wdGlvbnM6IElzQWN0aXZlTWF0Y2hPcHRpb25zKTogYm9vbGVhbjtcbiAgLyoqIEBpbnRlcm5hbCAqL1xuICBpc0FjdGl2ZSh1cmw6IHN0cmluZ3xVcmxUcmVlLCBtYXRjaE9wdGlvbnM6IGJvb2xlYW58SXNBY3RpdmVNYXRjaE9wdGlvbnMpOiBib29sZWFuO1xuICBpc0FjdGl2ZSh1cmw6IHN0cmluZ3xVcmxUcmVlLCBtYXRjaE9wdGlvbnM6IGJvb2xlYW58SXNBY3RpdmVNYXRjaE9wdGlvbnMpOiBib29sZWFuIHtcbiAgICBsZXQgb3B0aW9uczogSXNBY3RpdmVNYXRjaE9wdGlvbnM7XG4gICAgaWYgKG1hdGNoT3B0aW9ucyA9PT0gdHJ1ZSkge1xuICAgICAgb3B0aW9ucyA9IHsuLi5leGFjdE1hdGNoT3B0aW9uc307XG4gICAgfSBlbHNlIGlmIChtYXRjaE9wdGlvbnMgPT09IGZhbHNlKSB7XG4gICAgICBvcHRpb25zID0gey4uLnN1YnNldE1hdGNoT3B0aW9uc307XG4gICAgfSBlbHNlIHtcbiAgICAgIG9wdGlvbnMgPSBtYXRjaE9wdGlvbnM7XG4gICAgfVxuICAgIGlmIChpc1VybFRyZWUodXJsKSkge1xuICAgICAgcmV0dXJuIGNvbnRhaW5zVHJlZSh0aGlzLmN1cnJlbnRVcmxUcmVlLCB1cmwsIG9wdGlvbnMpO1xuICAgIH1cblxuICAgIGNvbnN0IHVybFRyZWUgPSB0aGlzLnBhcnNlVXJsKHVybCk7XG4gICAgcmV0dXJuIGNvbnRhaW5zVHJlZSh0aGlzLmN1cnJlbnRVcmxUcmVlLCB1cmxUcmVlLCBvcHRpb25zKTtcbiAgfVxuXG4gIHByaXZhdGUgcmVtb3ZlRW1wdHlQcm9wcyhwYXJhbXM6IFBhcmFtcyk6IFBhcmFtcyB7XG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKHBhcmFtcykucmVkdWNlKChyZXN1bHQ6IFBhcmFtcywga2V5OiBzdHJpbmcpID0+IHtcbiAgICAgIGNvbnN0IHZhbHVlOiBhbnkgPSBwYXJhbXNba2V5XTtcbiAgICAgIGlmICh2YWx1ZSAhPT0gbnVsbCAmJiB2YWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJlc3VsdFtrZXldID0gdmFsdWU7XG4gICAgICB9XG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0sIHt9KTtcbiAgfVxuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgc2NoZWR1bGVOYXZpZ2F0aW9uKFxuICAgICAgcmF3VXJsOiBVcmxUcmVlLCBzb3VyY2U6IE5hdmlnYXRpb25UcmlnZ2VyLCByZXN0b3JlZFN0YXRlOiBSZXN0b3JlZFN0YXRlfG51bGwsXG4gICAgICBleHRyYXM6IE5hdmlnYXRpb25FeHRyYXMsXG4gICAgICBwcmlvclByb21pc2U/OiB7cmVzb2x2ZTogYW55LCByZWplY3Q6IGFueSwgcHJvbWlzZTogUHJvbWlzZTxib29sZWFuPn0pOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBpZiAodGhpcy5kaXNwb3NlZCkge1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShmYWxzZSk7XG4gICAgfVxuXG4gICAgbGV0IHJlc29sdmU6IGFueTtcbiAgICBsZXQgcmVqZWN0OiBhbnk7XG4gICAgbGV0IHByb21pc2U6IFByb21pc2U8Ym9vbGVhbj47XG4gICAgaWYgKHByaW9yUHJvbWlzZSkge1xuICAgICAgcmVzb2x2ZSA9IHByaW9yUHJvbWlzZS5yZXNvbHZlO1xuICAgICAgcmVqZWN0ID0gcHJpb3JQcm9taXNlLnJlamVjdDtcbiAgICAgIHByb21pc2UgPSBwcmlvclByb21pc2UucHJvbWlzZTtcbiAgICB9IGVsc2Uge1xuICAgICAgcHJvbWlzZSA9IG5ldyBQcm9taXNlPGJvb2xlYW4+KChyZXMsIHJlaikgPT4ge1xuICAgICAgICByZXNvbHZlID0gcmVzO1xuICAgICAgICByZWplY3QgPSByZWo7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBsZXQgdGFyZ2V0UGFnZUlkOiBudW1iZXI7XG4gICAgaWYgKHRoaXMuY2FuY2VsZWROYXZpZ2F0aW9uUmVzb2x1dGlvbiA9PT0gJ2NvbXB1dGVkJykge1xuICAgICAgLy8gSWYgdGhlIGDJtXJvdXRlclBhZ2VJZGAgZXhpc3QgaW4gdGhlIHN0YXRlIHRoZW4gYHRhcmdldHBhZ2VJZGAgc2hvdWxkIGhhdmUgdGhlIHZhbHVlIG9mXG4gICAgICAvLyBgybVyb3V0ZXJQYWdlSWRgLiBUaGlzIGlzIHRoZSBjYXNlIGZvciBzb21ldGhpbmcgbGlrZSBhIHBhZ2UgcmVmcmVzaCB3aGVyZSB3ZSBhc3NpZ24gdGhlXG4gICAgICAvLyB0YXJnZXQgaWQgdG8gdGhlIHByZXZpb3VzbHkgc2V0IHZhbHVlIGZvciB0aGF0IHBhZ2UuXG4gICAgICBpZiAocmVzdG9yZWRTdGF0ZSAmJiByZXN0b3JlZFN0YXRlLsm1cm91dGVyUGFnZUlkKSB7XG4gICAgICAgIHRhcmdldFBhZ2VJZCA9IHJlc3RvcmVkU3RhdGUuybVyb3V0ZXJQYWdlSWQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBJZiB3ZSdyZSByZXBsYWNpbmcgdGhlIFVSTCBvciBkb2luZyBhIHNpbGVudCBuYXZpZ2F0aW9uLCB3ZSBkbyBub3Qgd2FudCB0byBpbmNyZW1lbnQgdGhlXG4gICAgICAgIC8vIHBhZ2UgaWQgYmVjYXVzZSB3ZSBhcmVuJ3QgcHVzaGluZyBhIG5ldyBlbnRyeSB0byBoaXN0b3J5LlxuICAgICAgICBpZiAoZXh0cmFzLnJlcGxhY2VVcmwgfHwgZXh0cmFzLnNraXBMb2NhdGlvbkNoYW5nZSkge1xuICAgICAgICAgIHRhcmdldFBhZ2VJZCA9IHRoaXMuYnJvd3NlclBhZ2VJZCA/PyAwO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRhcmdldFBhZ2VJZCA9ICh0aGlzLmJyb3dzZXJQYWdlSWQgPz8gMCkgKyAxO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIFRoaXMgaXMgdW51c2VkIHdoZW4gYGNhbmNlbGVkTmF2aWdhdGlvblJlc29sdXRpb25gIGlzIG5vdCBjb21wdXRlZC5cbiAgICAgIHRhcmdldFBhZ2VJZCA9IDA7XG4gICAgfVxuXG4gICAgdGhpcy5uYXZpZ2F0aW9uVHJhbnNpdGlvbnMuaGFuZGxlTmF2aWdhdGlvblJlcXVlc3Qoe1xuICAgICAgdGFyZ2V0UGFnZUlkLFxuICAgICAgc291cmNlLFxuICAgICAgcmVzdG9yZWRTdGF0ZSxcbiAgICAgIGN1cnJlbnRVcmxUcmVlOiB0aGlzLmN1cnJlbnRVcmxUcmVlLFxuICAgICAgY3VycmVudFJhd1VybDogdGhpcy5jdXJyZW50VXJsVHJlZSxcbiAgICAgIHJhd1VybCxcbiAgICAgIGV4dHJhcyxcbiAgICAgIHJlc29sdmUsXG4gICAgICByZWplY3QsXG4gICAgICBwcm9taXNlLFxuICAgICAgY3VycmVudFNuYXBzaG90OiB0aGlzLnJvdXRlclN0YXRlLnNuYXBzaG90LFxuICAgICAgY3VycmVudFJvdXRlclN0YXRlOiB0aGlzLnJvdXRlclN0YXRlXG4gICAgfSk7XG5cbiAgICAvLyBNYWtlIHN1cmUgdGhhdCB0aGUgZXJyb3IgaXMgcHJvcGFnYXRlZCBldmVuIHRob3VnaCBgcHJvY2Vzc05hdmlnYXRpb25zYCBjYXRjaFxuICAgIC8vIGhhbmRsZXIgZG9lcyBub3QgcmV0aHJvd1xuICAgIHJldHVybiBwcm9taXNlLmNhdGNoKChlOiBhbnkpID0+IHtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlKTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKiBAaW50ZXJuYWwgKi9cbiAgc2V0QnJvd3NlclVybCh1cmw6IFVybFRyZWUsIHRyYW5zaXRpb246IE5hdmlnYXRpb25UcmFuc2l0aW9uKSB7XG4gICAgY29uc3QgcGF0aCA9IHRoaXMudXJsU2VyaWFsaXplci5zZXJpYWxpemUodXJsKTtcbiAgICBjb25zdCBzdGF0ZSA9IHtcbiAgICAgIC4uLnRyYW5zaXRpb24uZXh0cmFzLnN0YXRlLFxuICAgICAgLi4udGhpcy5nZW5lcmF0ZU5nUm91dGVyU3RhdGUodHJhbnNpdGlvbi5pZCwgdHJhbnNpdGlvbi50YXJnZXRQYWdlSWQpXG4gICAgfTtcbiAgICBpZiAodGhpcy5sb2NhdGlvbi5pc0N1cnJlbnRQYXRoRXF1YWxUbyhwYXRoKSB8fCAhIXRyYW5zaXRpb24uZXh0cmFzLnJlcGxhY2VVcmwpIHtcbiAgICAgIHRoaXMubG9jYXRpb24ucmVwbGFjZVN0YXRlKHBhdGgsICcnLCBzdGF0ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubG9jYXRpb24uZ28ocGF0aCwgJycsIHN0YXRlKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUGVyZm9ybXMgdGhlIG5lY2Vzc2FyeSByb2xsYmFjayBhY3Rpb24gdG8gcmVzdG9yZSB0aGUgYnJvd3NlciBVUkwgdG8gdGhlXG4gICAqIHN0YXRlIGJlZm9yZSB0aGUgdHJhbnNpdGlvbi5cbiAgICogQGludGVybmFsXG4gICAqL1xuICByZXN0b3JlSGlzdG9yeSh0cmFuc2l0aW9uOiBOYXZpZ2F0aW9uVHJhbnNpdGlvbiwgcmVzdG9yaW5nRnJvbUNhdWdodEVycm9yID0gZmFsc2UpIHtcbiAgICBpZiAodGhpcy5jYW5jZWxlZE5hdmlnYXRpb25SZXNvbHV0aW9uID09PSAnY29tcHV0ZWQnKSB7XG4gICAgICBjb25zdCB0YXJnZXRQYWdlUG9zaXRpb24gPSB0aGlzLmN1cnJlbnRQYWdlSWQgLSB0cmFuc2l0aW9uLnRhcmdldFBhZ2VJZDtcbiAgICAgIC8vIFRoZSBuYXZpZ2F0b3IgY2hhbmdlIHRoZSBsb2NhdGlvbiBiZWZvcmUgdHJpZ2dlcmVkIHRoZSBicm93c2VyIGV2ZW50LFxuICAgICAgLy8gc28gd2UgbmVlZCB0byBnbyBiYWNrIHRvIHRoZSBjdXJyZW50IHVybCBpZiB0aGUgbmF2aWdhdGlvbiBpcyBjYW5jZWxlZC5cbiAgICAgIC8vIEFsc28sIHdoZW4gbmF2aWdhdGlvbiBnZXRzIGNhbmNlbGxlZCB3aGlsZSB1c2luZyB1cmwgdXBkYXRlIHN0cmF0ZWd5IGVhZ2VyLCB0aGVuIHdlIG5lZWQgdG9cbiAgICAgIC8vIGdvIGJhY2suIEJlY2F1c2UsIHdoZW4gYHVybFVwZGF0ZVN0cmF0ZWd5YCBpcyBgZWFnZXJgOyBgc2V0QnJvd3NlclVybGAgbWV0aG9kIGlzIGNhbGxlZFxuICAgICAgLy8gYmVmb3JlIGFueSB2ZXJpZmljYXRpb24uXG4gICAgICBjb25zdCBicm93c2VyVXJsVXBkYXRlT2NjdXJyZWQgPVxuICAgICAgICAgICh0cmFuc2l0aW9uLnNvdXJjZSA9PT0gJ3BvcHN0YXRlJyB8fCB0aGlzLnVybFVwZGF0ZVN0cmF0ZWd5ID09PSAnZWFnZXInIHx8XG4gICAgICAgICAgIHRoaXMuY3VycmVudFVybFRyZWUgPT09IHRoaXMuZ2V0Q3VycmVudE5hdmlnYXRpb24oKT8uZmluYWxVcmwpO1xuICAgICAgaWYgKGJyb3dzZXJVcmxVcGRhdGVPY2N1cnJlZCAmJiB0YXJnZXRQYWdlUG9zaXRpb24gIT09IDApIHtcbiAgICAgICAgdGhpcy5sb2NhdGlvbi5oaXN0b3J5R28odGFyZ2V0UGFnZVBvc2l0aW9uKTtcbiAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgdGhpcy5jdXJyZW50VXJsVHJlZSA9PT0gdGhpcy5nZXRDdXJyZW50TmF2aWdhdGlvbigpPy5maW5hbFVybCAmJlxuICAgICAgICAgIHRhcmdldFBhZ2VQb3NpdGlvbiA9PT0gMCkge1xuICAgICAgICAvLyBXZSBnb3QgdG8gdGhlIGFjdGl2YXRpb24gc3RhZ2UgKHdoZXJlIGN1cnJlbnRVcmxUcmVlIGlzIHNldCB0byB0aGUgbmF2aWdhdGlvbidzXG4gICAgICAgIC8vIGZpbmFsVXJsKSwgYnV0IHdlIHdlcmVuJ3QgbW92aW5nIGFueXdoZXJlIGluIGhpc3RvcnkgKHNraXBMb2NhdGlvbkNoYW5nZSBvciByZXBsYWNlVXJsKS5cbiAgICAgICAgLy8gV2Ugc3RpbGwgbmVlZCB0byByZXNldCB0aGUgcm91dGVyIHN0YXRlIGJhY2sgdG8gd2hhdCBpdCB3YXMgd2hlbiB0aGUgbmF2aWdhdGlvbiBzdGFydGVkLlxuICAgICAgICB0aGlzLnJlc2V0U3RhdGUodHJhbnNpdGlvbik7XG4gICAgICAgIC8vIFRPRE8oYXRzY290dCk6IHJlc2V0dGluZyB0aGUgYGJyb3dzZXJVcmxUcmVlYCBzaG91bGQgcmVhbGx5IGJlIGRvbmUgaW4gYHJlc2V0U3RhdGVgLlxuICAgICAgICAvLyBJbnZlc3RpZ2F0ZSBpZiB0aGlzIGNhbiBiZSBkb25lIGJ5IHJ1bm5pbmcgVEdQLlxuICAgICAgICB0aGlzLmJyb3dzZXJVcmxUcmVlID0gdHJhbnNpdGlvbi5jdXJyZW50VXJsVHJlZTtcbiAgICAgICAgdGhpcy5yZXNldFVybFRvQ3VycmVudFVybFRyZWUoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIFRoZSBicm93c2VyIFVSTCBhbmQgcm91dGVyIHN0YXRlIHdhcyBub3QgdXBkYXRlZCBiZWZvcmUgdGhlIG5hdmlnYXRpb24gY2FuY2VsbGVkIHNvXG4gICAgICAgIC8vIHRoZXJlJ3Mgbm8gcmVzdG9yYXRpb24gbmVlZGVkLlxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAodGhpcy5jYW5jZWxlZE5hdmlnYXRpb25SZXNvbHV0aW9uID09PSAncmVwbGFjZScpIHtcbiAgICAgIC8vIFRPRE8oYXRzY290dCk6IEl0IHNlZW1zIGxpa2Ugd2Ugc2hvdWxkIF9hbHdheXNfIHJlc2V0IHRoZSBzdGF0ZSBoZXJlLiBJdCB3b3VsZCBiZSBhIG5vLW9wXG4gICAgICAvLyBmb3IgYGRlZmVycmVkYCBuYXZpZ2F0aW9ucyB0aGF0IGhhdmVuJ3QgY2hhbmdlIHRoZSBpbnRlcm5hbCBzdGF0ZSB5ZXQgYmVjYXVzZSBndWFyZHNcbiAgICAgIC8vIHJlamVjdC4gRm9yICdlYWdlcicgbmF2aWdhdGlvbnMsIGl0IHNlZW1zIGxpa2Ugd2UgYWxzbyByZWFsbHkgc2hvdWxkIHJlc2V0IHRoZSBzdGF0ZVxuICAgICAgLy8gYmVjYXVzZSB0aGUgbmF2aWdhdGlvbiB3YXMgY2FuY2VsbGVkLiBJbnZlc3RpZ2F0ZSBpZiB0aGlzIGNhbiBiZSBkb25lIGJ5IHJ1bm5pbmcgVEdQLlxuICAgICAgaWYgKHJlc3RvcmluZ0Zyb21DYXVnaHRFcnJvcikge1xuICAgICAgICB0aGlzLnJlc2V0U3RhdGUodHJhbnNpdGlvbik7XG4gICAgICB9XG4gICAgICB0aGlzLnJlc2V0VXJsVG9DdXJyZW50VXJsVHJlZSgpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgcmVzZXRTdGF0ZSh0OiBOYXZpZ2F0aW9uVHJhbnNpdGlvbik6IHZvaWQge1xuICAgICh0aGlzIGFzIHtyb3V0ZXJTdGF0ZTogUm91dGVyU3RhdGV9KS5yb3V0ZXJTdGF0ZSA9IHQuY3VycmVudFJvdXRlclN0YXRlO1xuICAgIHRoaXMuY3VycmVudFVybFRyZWUgPSB0LmN1cnJlbnRVcmxUcmVlO1xuICAgIC8vIE5vdGUgaGVyZSB0aGF0IHdlIHVzZSB0aGUgdXJsSGFuZGxpbmdTdHJhdGVneSB0byBnZXQgdGhlIHJlc2V0IGByYXdVcmxUcmVlYCBiZWNhdXNlIGl0IG1heSBiZVxuICAgIC8vIGNvbmZpZ3VyZWQgdG8gaGFuZGxlIG9ubHkgcGFydCBvZiB0aGUgbmF2aWdhdGlvbiBVUkwuIFRoaXMgbWVhbnMgd2Ugd291bGQgb25seSB3YW50IHRvIHJlc2V0XG4gICAgLy8gdGhlIHBhcnQgb2YgdGhlIG5hdmlnYXRpb24gaGFuZGxlZCBieSB0aGUgQW5ndWxhciByb3V0ZXIgcmF0aGVyIHRoYW4gdGhlIHdob2xlIFVSTC4gSW5cbiAgICAvLyBhZGRpdGlvbiwgdGhlIFVSTEhhbmRsaW5nU3RyYXRlZ3kgbWF5IGJlIGNvbmZpZ3VyZWQgdG8gc3BlY2lmaWNhbGx5IHByZXNlcnZlIHBhcnRzIG9mIHRoZSBVUkxcbiAgICAvLyB3aGVuIG1lcmdpbmcsIHN1Y2ggYXMgdGhlIHF1ZXJ5IHBhcmFtcyBzbyB0aGV5IGFyZSBub3QgbG9zdCBvbiBhIHJlZnJlc2guXG4gICAgdGhpcy5yYXdVcmxUcmVlID0gdGhpcy51cmxIYW5kbGluZ1N0cmF0ZWd5Lm1lcmdlKHRoaXMuY3VycmVudFVybFRyZWUsIHQucmF3VXJsKTtcbiAgfVxuXG4gIHByaXZhdGUgcmVzZXRVcmxUb0N1cnJlbnRVcmxUcmVlKCk6IHZvaWQge1xuICAgIHRoaXMubG9jYXRpb24ucmVwbGFjZVN0YXRlKFxuICAgICAgICB0aGlzLnVybFNlcmlhbGl6ZXIuc2VyaWFsaXplKHRoaXMucmF3VXJsVHJlZSksICcnLFxuICAgICAgICB0aGlzLmdlbmVyYXRlTmdSb3V0ZXJTdGF0ZSh0aGlzLmxhc3RTdWNjZXNzZnVsSWQsIHRoaXMuY3VycmVudFBhZ2VJZCkpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZW5lcmF0ZU5nUm91dGVyU3RhdGUobmF2aWdhdGlvbklkOiBudW1iZXIsIHJvdXRlclBhZ2VJZD86IG51bWJlcikge1xuICAgIGlmICh0aGlzLmNhbmNlbGVkTmF2aWdhdGlvblJlc29sdXRpb24gPT09ICdjb21wdXRlZCcpIHtcbiAgICAgIHJldHVybiB7bmF2aWdhdGlvbklkLCDJtXJvdXRlclBhZ2VJZDogcm91dGVyUGFnZUlkfTtcbiAgICB9XG4gICAgcmV0dXJuIHtuYXZpZ2F0aW9uSWR9O1xuICB9XG59XG5cbmZ1bmN0aW9uIHZhbGlkYXRlQ29tbWFuZHMoY29tbWFuZHM6IHN0cmluZ1tdKTogdm9pZCB7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgY29tbWFuZHMubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBjbWQgPSBjb21tYW5kc1tpXTtcbiAgICBpZiAoY21kID09IG51bGwpIHtcbiAgICAgIHRocm93IG5ldyBSdW50aW1lRXJyb3IoXG4gICAgICAgICAgUnVudGltZUVycm9yQ29kZS5OVUxMSVNIX0NPTU1BTkQsXG4gICAgICAgICAgTkdfREVWX01PREUgJiYgYFRoZSByZXF1ZXN0ZWQgcGF0aCBjb250YWlucyAke2NtZH0gc2VnbWVudCBhdCBpbmRleCAke2l9YCk7XG4gICAgfVxuICB9XG59XG4iXX0=
|