1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.sra;
20
21 import java.time.ZonedDateTime;
22 import java.util.ArrayList;
23 import java.util.List;
24 import java.util.Objects;
25 import java.util.concurrent.atomic.AtomicInteger;
26 import java.util.function.Consumer;
27 import java.util.stream.Collectors;
28 import java.util.stream.Stream;
29 import org.apache.commons.lang3.BooleanUtils;
30 import org.apache.commons.lang3.StringUtils;
31 import org.apache.syncope.client.lib.AnonymousAuthenticationHandler;
32 import org.apache.syncope.client.lib.SyncopeClient;
33 import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
34 import org.apache.syncope.common.keymaster.client.api.ServiceOps;
35 import org.apache.syncope.common.keymaster.client.api.model.NetworkService;
36 import org.apache.syncope.common.lib.to.SRARouteTO;
37 import org.apache.syncope.common.lib.types.SRARouteFilter;
38 import org.apache.syncope.common.lib.types.SRARoutePredicate;
39 import org.apache.syncope.common.rest.api.service.SRARouteService;
40 import org.apache.syncope.sra.filters.ClientCertsToRequestHeaderFilterFactory;
41 import org.apache.syncope.sra.filters.CustomGatewayFilterFactory;
42 import org.apache.syncope.sra.filters.LinkRewriteGatewayFilterFactory;
43 import org.apache.syncope.sra.filters.PrincipalToRequestHeaderFilterFactory;
44 import org.apache.syncope.sra.filters.QueryParamToRequestHeaderFilterFactory;
45 import org.apache.syncope.sra.predicates.CustomRoutePredicateFactory;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48 import org.springframework.cloud.gateway.filter.GatewayFilter;
49 import org.springframework.cloud.gateway.filter.OrderedGatewayFilter;
50 import org.springframework.cloud.gateway.filter.factory.AddRequestHeaderGatewayFilterFactory;
51 import org.springframework.cloud.gateway.filter.factory.AddRequestParameterGatewayFilterFactory;
52 import org.springframework.cloud.gateway.filter.factory.AddResponseHeaderGatewayFilterFactory;
53 import org.springframework.cloud.gateway.filter.factory.DedupeResponseHeaderGatewayFilterFactory;
54 import org.springframework.cloud.gateway.filter.factory.FallbackHeadersGatewayFilterFactory;
55 import org.springframework.cloud.gateway.filter.factory.MapRequestHeaderGatewayFilterFactory;
56 import org.springframework.cloud.gateway.filter.factory.PrefixPathGatewayFilterFactory;
57 import org.springframework.cloud.gateway.filter.factory.PreserveHostHeaderGatewayFilterFactory;
58 import org.springframework.cloud.gateway.filter.factory.RedirectToGatewayFilterFactory;
59 import org.springframework.cloud.gateway.filter.factory.RemoveRequestHeaderGatewayFilterFactory;
60 import org.springframework.cloud.gateway.filter.factory.RemoveResponseHeaderGatewayFilterFactory;
61 import org.springframework.cloud.gateway.filter.factory.RequestHeaderToRequestUriGatewayFilterFactory;
62 import org.springframework.cloud.gateway.filter.factory.RequestRateLimiterGatewayFilterFactory;
63 import org.springframework.cloud.gateway.filter.factory.RequestSizeGatewayFilterFactory;
64 import org.springframework.cloud.gateway.filter.factory.RetryGatewayFilterFactory;
65 import org.springframework.cloud.gateway.filter.factory.RewriteLocationResponseHeaderGatewayFilterFactory;
66 import org.springframework.cloud.gateway.filter.factory.RewritePathGatewayFilterFactory;
67 import org.springframework.cloud.gateway.filter.factory.RewriteResponseHeaderGatewayFilterFactory;
68 import org.springframework.cloud.gateway.filter.factory.SaveSessionGatewayFilterFactory;
69 import org.springframework.cloud.gateway.filter.factory.SecureHeadersGatewayFilterFactory;
70 import org.springframework.cloud.gateway.filter.factory.SetPathGatewayFilterFactory;
71 import org.springframework.cloud.gateway.filter.factory.SetRequestHeaderGatewayFilterFactory;
72 import org.springframework.cloud.gateway.filter.factory.SetRequestHostHeaderGatewayFilterFactory;
73 import org.springframework.cloud.gateway.filter.factory.SetResponseHeaderGatewayFilterFactory;
74 import org.springframework.cloud.gateway.filter.factory.SetStatusGatewayFilterFactory;
75 import org.springframework.cloud.gateway.filter.factory.StripPrefixGatewayFilterFactory;
76 import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
77 import org.springframework.cloud.gateway.filter.ratelimit.RateLimiter;
78 import org.springframework.cloud.gateway.handler.AsyncPredicate;
79 import org.springframework.cloud.gateway.handler.predicate.AfterRoutePredicateFactory;
80 import org.springframework.cloud.gateway.handler.predicate.BeforeRoutePredicateFactory;
81 import org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateFactory;
82 import org.springframework.cloud.gateway.handler.predicate.CookieRoutePredicateFactory;
83 import org.springframework.cloud.gateway.handler.predicate.HeaderRoutePredicateFactory;
84 import org.springframework.cloud.gateway.handler.predicate.HostRoutePredicateFactory;
85 import org.springframework.cloud.gateway.handler.predicate.MethodRoutePredicateFactory;
86 import org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory;
87 import org.springframework.cloud.gateway.handler.predicate.QueryRoutePredicateFactory;
88 import org.springframework.cloud.gateway.handler.predicate.RemoteAddrRoutePredicateFactory;
89 import org.springframework.cloud.gateway.handler.predicate.WeightRoutePredicateFactory;
90 import org.springframework.cloud.gateway.route.Route;
91 import org.springframework.context.ConfigurableApplicationContext;
92 import org.springframework.core.Ordered;
93 import org.springframework.http.HttpMethod;
94 import org.springframework.http.HttpStatus;
95 import org.springframework.util.unit.DataSize;
96 import org.springframework.web.server.ServerWebExchange;
97
98 public class RouteProvider {
99
100 protected static final Logger LOG = LoggerFactory.getLogger(RouteProvider.class);
101
102 protected final ServiceOps serviceOps;
103
104 protected final ConfigurableApplicationContext ctx;
105
106 protected final String anonymousUser;
107
108 protected final String anonymousKey;
109
110 protected final boolean useGZIPCompression;
111
112 protected SyncopeClient client;
113
114 protected final List<SRARouteTO> routeTOs = new ArrayList<>();
115
116 public RouteProvider(
117 final ServiceOps serviceOps,
118 final ConfigurableApplicationContext ctx,
119 final String anonymousUser,
120 final String anonymousKey,
121 final boolean useGZIPCompression) {
122
123 this.serviceOps = serviceOps;
124 this.ctx = ctx;
125 this.anonymousUser = anonymousUser;
126 this.anonymousKey = anonymousKey;
127 this.useGZIPCompression = useGZIPCompression;
128 }
129
130 @SuppressWarnings("unchecked")
131 protected GatewayFilter toFilter(final SRARouteTO route, final SRARouteFilter gwfilter)
132 throws ClassNotFoundException, NumberFormatException {
133
134 GatewayFilter filter;
135
136 switch (gwfilter.getFactory()) {
137 case ADD_REQUEST_HEADER:
138 String[] addRequestHeaderArgs = gwfilter.getArgs().split(",");
139 filter = ctx.getBean(AddRequestHeaderGatewayFilterFactory.class).
140 apply(c -> c.setName(addRequestHeaderArgs[0].trim()).
141 setValue(addRequestHeaderArgs[1].trim()));
142 break;
143
144 case ADD_REQUEST_PARAMETER:
145 String[] addRequestParameterArgs = gwfilter.getArgs().split(",");
146 filter = ctx.getBean(AddRequestParameterGatewayFilterFactory.class).
147 apply(c -> c.setName(addRequestParameterArgs[0].trim()).
148 setValue(addRequestParameterArgs[1].trim()));
149 break;
150
151 case ADD_RESPONSE_HEADER:
152 String[] addResponseHeaderArgs = gwfilter.getArgs().split(",");
153 filter = ctx.getBean(AddResponseHeaderGatewayFilterFactory.class).
154 apply(c -> c.setName(addResponseHeaderArgs[0].trim()).
155 setValue(addResponseHeaderArgs[1].trim()));
156 break;
157
158 case DEDUPE_RESPONSE_HEADER:
159 String[] dedupeResponseHeaderArgs = gwfilter.getArgs().split(",");
160 filter = ctx.getBean(DedupeResponseHeaderGatewayFilterFactory.class).
161 apply(c -> {
162 c.setName(dedupeResponseHeaderArgs[0].trim());
163 if (dedupeResponseHeaderArgs.length > 1) {
164 c.setStrategy(DedupeResponseHeaderGatewayFilterFactory.Strategy.
165 valueOf(dedupeResponseHeaderArgs[1].trim()));
166 }
167 });
168 break;
169
170 case FALLBACK_HEADERS:
171 String[] fallbackHeadersArgs = gwfilter.getArgs().split(",");
172 filter = ctx.getBean(FallbackHeadersGatewayFilterFactory.class).
173 apply(c -> {
174 if (StringUtils.isNotBlank(fallbackHeadersArgs[0])) {
175 c.setExecutionExceptionTypeHeaderName(fallbackHeadersArgs[0].trim());
176 }
177 if (StringUtils.isNotBlank(fallbackHeadersArgs[1])) {
178 c.setExecutionExceptionMessageHeaderName(fallbackHeadersArgs[1].trim());
179 }
180 if (StringUtils.isNotBlank(fallbackHeadersArgs[2])) {
181 c.setRootCauseExceptionTypeHeaderName(fallbackHeadersArgs[2].trim());
182 }
183 if (StringUtils.isNotBlank(fallbackHeadersArgs[3])) {
184 c.setRootCauseExceptionMessageHeaderName(fallbackHeadersArgs[3].trim());
185 }
186 });
187 break;
188
189 case MAP_REQUEST_HEADER:
190 String[] mapRequestHeaderArgs = gwfilter.getArgs().split(",");
191 filter = ctx.getBean(MapRequestHeaderGatewayFilterFactory.class).
192 apply(c -> c.setFromHeader(mapRequestHeaderArgs[0].trim()).
193 setToHeader(mapRequestHeaderArgs[1].trim()));
194 break;
195
196 case PREFIX_PATH:
197 filter = ctx.getBean(PrefixPathGatewayFilterFactory.class).
198 apply(c -> c.setPrefix(gwfilter.getArgs().trim()));
199 break;
200
201 case PRESERVE_HOST_HEADER:
202 filter = ctx.getBean(PreserveHostHeaderGatewayFilterFactory.class).apply();
203 break;
204
205 case REDIRECT_TO:
206 String[] redirectArgs = gwfilter.getArgs().split(",");
207 filter = ctx.getBean(RedirectToGatewayFilterFactory.class).
208 apply(redirectArgs[0].trim(), redirectArgs[1].trim());
209 break;
210
211 case REMOVE_REQUEST_HEADER:
212 filter = ctx.getBean(RemoveRequestHeaderGatewayFilterFactory.class).
213 apply(c -> c.setName(gwfilter.getArgs().trim()));
214 break;
215
216 case REMOVE_RESPONSE_HEADER:
217 filter = ctx.getBean(RemoveResponseHeaderGatewayFilterFactory.class).
218 apply(c -> c.setName(gwfilter.getArgs().trim()));
219 break;
220
221 case REQUEST_RATE_LIMITER:
222 String[] requestRateLimiterArgs = gwfilter.getArgs().split(",");
223 filter = ctx.getBean(RequestRateLimiterGatewayFilterFactory.class).
224 apply(c -> {
225 if (StringUtils.isNotBlank(requestRateLimiterArgs[0])) {
226 c.setDenyEmptyKey(BooleanUtils.toBoolean(requestRateLimiterArgs[0].trim()));
227 }
228 if (StringUtils.isNotBlank(requestRateLimiterArgs[1])) {
229 c.setEmptyKeyStatus(requestRateLimiterArgs[1].trim());
230 }
231 if (StringUtils.isNotBlank(requestRateLimiterArgs[2])) {
232 c.setKeyResolver(ctx.getBean(requestRateLimiterArgs[2].trim(), KeyResolver.class));
233 }
234 if (StringUtils.isNotBlank(requestRateLimiterArgs[3])) {
235 c.setRateLimiter(ctx.getBean(requestRateLimiterArgs[3].trim(), RateLimiter.class));
236 }
237 if (StringUtils.isNotBlank(requestRateLimiterArgs[4])) {
238 c.setStatusCode(HttpStatus.valueOf(requestRateLimiterArgs[4].trim()));
239 }
240 });
241 break;
242
243 case REWRITE_PATH:
244 String[] rewritePathArgs = gwfilter.getArgs().split(",");
245 filter = ctx.getBean(RewritePathGatewayFilterFactory.class).
246 apply(c -> c.setRegexp(rewritePathArgs[0].trim()).
247 setReplacement(rewritePathArgs[1].trim()));
248 break;
249
250 case REWRITE_LOCATION:
251 String[] rewriteLocationArgs = gwfilter.getArgs().split(",");
252 filter = ctx.getBean(RewriteLocationResponseHeaderGatewayFilterFactory.class).
253 apply(c -> {
254 c.setStripVersion(RewriteLocationResponseHeaderGatewayFilterFactory.StripVersion.
255 valueOf(rewriteLocationArgs[0].trim()));
256 if (rewriteLocationArgs.length > 1) {
257 c.setLocationHeaderName(rewriteLocationArgs[1].trim());
258 }
259 if (rewriteLocationArgs.length > 2) {
260 c.setHostValue(rewriteLocationArgs[2].trim());
261 }
262 if (rewriteLocationArgs.length > 3) {
263 c.setProtocols(rewriteLocationArgs[3].trim());
264 }
265 });
266 break;
267
268 case REWRITE_RESPONSE_HEADER:
269 String[] rewriteResponseHeaderArgs = gwfilter.getArgs().split(",");
270 filter = ctx.getBean(RewriteResponseHeaderGatewayFilterFactory.class).
271 apply(c -> c.setReplacement(rewriteResponseHeaderArgs[2].trim()).
272 setRegexp(rewriteResponseHeaderArgs[1].trim()).
273 setName(rewriteResponseHeaderArgs[0].trim()));
274 break;
275
276 case RETRY:
277 AtomicInteger retries = new AtomicInteger();
278 try {
279 retries.set(Integer.valueOf(gwfilter.getArgs().trim()));
280 } catch (NumberFormatException e) {
281 LOG.error("Unexpected argument value: {}", gwfilter.getArgs().trim(), e);
282 retries.set(0);
283 }
284 filter = ctx.getBean(RetryGatewayFilterFactory.class).
285 apply(c -> c.setRetries(retries.get()));
286 break;
287
288 case SAVE_SESSION:
289 filter = ctx.getBean(SaveSessionGatewayFilterFactory.class).apply(c -> {
290 });
291 break;
292
293 case SECURE_HEADERS:
294 filter = ctx.getBean(SecureHeadersGatewayFilterFactory.class).apply(c -> {
295 });
296 break;
297
298 case SET_PATH:
299 filter = ctx.getBean(SetPathGatewayFilterFactory.class).
300 apply(c -> c.setTemplate(gwfilter.getArgs().trim()));
301 break;
302
303 case SET_REQUEST_HEADER:
304 String[] setRequestHeaderArgs = gwfilter.getArgs().split(",");
305 filter = ctx.getBean(SetRequestHeaderGatewayFilterFactory.class).
306 apply(c -> c.setName(setRequestHeaderArgs[0].trim()).
307 setValue(setRequestHeaderArgs[1].trim()));
308 break;
309
310 case SET_RESPONSE_HEADER:
311 String[] setResponseHeaderArgs = gwfilter.getArgs().split(",");
312 filter = ctx.getBean(SetResponseHeaderGatewayFilterFactory.class).
313 apply(c -> c.setName(setResponseHeaderArgs[0].trim()).
314 setValue(setResponseHeaderArgs[1].trim()));
315 break;
316
317 case SET_STATUS:
318 filter = ctx.getBean(SetStatusGatewayFilterFactory.class).
319 apply(c -> c.setStatus(gwfilter.getArgs().trim()));
320 break;
321
322 case STRIP_PREFIX:
323 AtomicInteger parts = new AtomicInteger();
324 try {
325 parts.set(Integer.valueOf(gwfilter.getArgs().trim()));
326 } catch (NumberFormatException e) {
327 LOG.error("Unexpected argument value: {}", gwfilter.getArgs().trim(), e);
328 parts.set(0);
329 }
330 filter = ctx.getBean(StripPrefixGatewayFilterFactory.class).
331 apply(c -> c.setParts(parts.get()));
332 break;
333
334 case REQUEST_HEADER_TO_REQUEST_URI:
335 filter = ctx.getBean(RequestHeaderToRequestUriGatewayFilterFactory.class).
336 apply(c -> c.setName(gwfilter.getArgs().trim()));
337 break;
338
339 case SET_REQUEST_SIZE:
340 filter = ctx.getBean(RequestSizeGatewayFilterFactory.class).
341 apply(c -> c.setMaxSize(DataSize.ofBytes(Long.valueOf(gwfilter.getArgs().trim()))));
342 break;
343
344 case SET_REQUEST_HOST:
345 filter = ctx.getBean(SetRequestHostHeaderGatewayFilterFactory.class).
346 apply(c -> c.setHost(gwfilter.getArgs().trim()));
347 break;
348
349 case LINK_REWRITE:
350 filter = ApplicationContextUtils.getOrCreateBean(
351 ctx,
352 LinkRewriteGatewayFilterFactory.class.getName(),
353 LinkRewriteGatewayFilterFactory.class).
354 apply(c -> c.setData(route.getTarget().toASCIIString() + "," + gwfilter.getArgs().trim()));
355 break;
356
357 case CLIENT_CERTS_TO_REQUEST_HEADER:
358 String header = StringUtils.isBlank(gwfilter.getArgs()) ? "X-Client-Certificate" : gwfilter.getArgs();
359 filter = ApplicationContextUtils.getOrCreateBean(
360 ctx,
361 ClientCertsToRequestHeaderFilterFactory.class.getName(),
362 ClientCertsToRequestHeaderFilterFactory.class).
363 apply(c -> c.setName(header.trim()));
364 break;
365
366 case QUERY_PARAM_TO_REQUEST_HEADER:
367 filter = ApplicationContextUtils.getOrCreateBean(
368 ctx,
369 QueryParamToRequestHeaderFilterFactory.class.getName(),
370 QueryParamToRequestHeaderFilterFactory.class).
371 apply(c -> c.setName(gwfilter.getArgs().trim()));
372 break;
373
374 case PRINCIPAL_TO_REQUEST_HEADER:
375 filter = ApplicationContextUtils.getOrCreateBean(
376 ctx,
377 PrincipalToRequestHeaderFilterFactory.class.getName(),
378 PrincipalToRequestHeaderFilterFactory.class).
379 apply(c -> c.setName(gwfilter.getArgs().trim()));
380 break;
381
382 case CUSTOM:
383 String[] customArgs = gwfilter.getArgs().split(";");
384 Consumer<CustomGatewayFilterFactory.Config> customConsumer = customArgs.length > 1
385 ? c -> c.setData(customArgs[1])
386 : c -> c.setData(null);
387 CustomGatewayFilterFactory factory = ApplicationContextUtils.getOrCreateBean(
388 ctx,
389 customArgs[0],
390 CustomGatewayFilterFactory.class);
391 filter = factory.getOrder().
392 map(order -> (GatewayFilter) new OrderedGatewayFilter(factory.apply(customConsumer), order)).
393 orElseGet(() -> factory.apply(customConsumer));
394 break;
395
396 default:
397 filter = null;
398 }
399
400 if (filter == null) {
401 throw new IllegalArgumentException("Could not translate " + gwfilter);
402 }
403
404 return filter instanceof Ordered ? filter : new OrderedGatewayFilter(filter, 0);
405 }
406
407 protected AsyncPredicate<ServerWebExchange> toPredicate(final SRARoutePredicate gwpredicate, final boolean negate)
408 throws ClassNotFoundException, NumberFormatException {
409
410 AsyncPredicate<ServerWebExchange> predicate;
411 switch (gwpredicate.getFactory()) {
412 case AFTER:
413 predicate = ctx.getBean(AfterRoutePredicateFactory.class).
414 applyAsync(c -> c.setDatetime(ZonedDateTime.parse(gwpredicate.getArgs().trim())));
415 break;
416
417 case BEFORE:
418 predicate = ctx.getBean(BeforeRoutePredicateFactory.class).
419 applyAsync(c -> c.setDatetime(ZonedDateTime.parse(gwpredicate.getArgs().trim())));
420 break;
421
422 case BETWEEN:
423 String[] betweenArgs = gwpredicate.getArgs().split(",");
424 predicate = ctx.getBean(BetweenRoutePredicateFactory.class).
425 applyAsync(c -> c.setDatetime1(ZonedDateTime.parse(betweenArgs[0].trim())).
426 setDatetime2(ZonedDateTime.parse(betweenArgs[1].trim())));
427 break;
428
429 case COOKIE:
430 String[] cookieArgs = gwpredicate.getArgs().split(",");
431 predicate = ctx.getBean(CookieRoutePredicateFactory.class).
432 applyAsync(c -> c.setName(cookieArgs[0].trim()).
433 setRegexp(cookieArgs[1].trim()));
434 break;
435
436 case HEADER:
437 String[] headerArgs = gwpredicate.getArgs().split(",");
438 predicate = ctx.getBean(HeaderRoutePredicateFactory.class).
439 applyAsync(c -> c.setHeader(headerArgs[0].trim()).
440 setRegexp(headerArgs[1].trim()));
441 break;
442
443 case HOST:
444 String[] hostArgs = gwpredicate.getArgs().split(",");
445 predicate = ctx.getBean(HostRoutePredicateFactory.class).
446 applyAsync(c -> c.setPatterns(List.of(hostArgs)));
447 break;
448
449 case METHOD:
450 String[] methodArgs = gwpredicate.getArgs().split(",");
451 predicate = ctx.getBean(MethodRoutePredicateFactory.class).
452 applyAsync(c -> c.setMethods(
453 Stream.of(methodArgs).map(arg -> HttpMethod.resolve(arg.trim())).toArray(HttpMethod[]::new)));
454 break;
455
456 case PATH:
457 String[] pathArgs = gwpredicate.getArgs().split(",");
458 predicate = ctx.getBean(PathRoutePredicateFactory.class).
459 applyAsync(c -> c.setPatterns(List.of(pathArgs)));
460 break;
461
462 case QUERY:
463 String[] queryArgs = gwpredicate.getArgs().split(",");
464 Consumer<QueryRoutePredicateFactory.Config> queryConsumer =
465 queryArgs.length > 1
466 ? c -> c.setParam(queryArgs[0].trim()).setRegexp(queryArgs[1].trim())
467 : c -> c.setParam(queryArgs[0].trim());
468 predicate = ctx.getBean(QueryRoutePredicateFactory.class).
469 applyAsync(queryConsumer);
470 break;
471
472 case REMOTE_ADDR:
473 String[] remoteAddrArgs = gwpredicate.getArgs().split(",");
474 predicate = ctx.getBean(RemoteAddrRoutePredicateFactory.class).
475 applyAsync(c -> c.setSources(List.of(remoteAddrArgs)));
476 break;
477
478 case WEIGHT:
479 String[] weigthArgs = gwpredicate.getArgs().split(",");
480 AtomicInteger weight = new AtomicInteger();
481 try {
482 weight.set(Integer.valueOf(weigthArgs[1].trim()));
483 } catch (NumberFormatException e) {
484 LOG.error("Unexpected argument value: {}", weigthArgs[1].trim(), e);
485 weight.set(0);
486 }
487 predicate = ctx.getBean(WeightRoutePredicateFactory.class).
488 applyAsync(c -> c.setGroup(weigthArgs[0].trim()).
489 setWeight(weight.get()));
490 break;
491
492 case CUSTOM:
493 String[] customArgs = gwpredicate.getArgs().split(";");
494 predicate = ApplicationContextUtils.getOrCreateBean(
495 ctx,
496 customArgs[0],
497 CustomRoutePredicateFactory.class).
498 applyAsync(c -> c.setData(customArgs[1]));
499 break;
500
501 default:
502 predicate = null;
503 }
504
505 if (predicate == null) {
506 throw new IllegalArgumentException("Could not translate predicate " + gwpredicate);
507 }
508
509 return negate ? predicate.negate() : predicate;
510 }
511
512 protected Route.AsyncBuilder toRoute(final SRARouteTO gwroute) {
513 Route.AsyncBuilder builder = new Route.AsyncBuilder().
514 id(gwroute.getKey()).order(gwroute.getOrder()).uri(gwroute.getTarget());
515
516 if (gwroute.getPredicates().isEmpty()) {
517 builder.predicate(exchange -> true);
518 } else {
519 gwroute.getPredicates().forEach(gwpredicate -> {
520 if (builder.getPredicate() == null) {
521 try {
522 builder.asyncPredicate(toPredicate(gwpredicate, gwpredicate.isNegate()));
523 } catch (Exception e) {
524 LOG.error("Could not translate {}, skipping", gwpredicate, e);
525 }
526 } else {
527 try {
528 switch (gwpredicate.getCond()) {
529 case OR:
530 builder.or(toPredicate(gwpredicate, gwpredicate.isNegate()));
531 break;
532
533 case AND:
534 default:
535 builder.and(toPredicate(gwpredicate, gwpredicate.isNegate()));
536 }
537 } catch (Exception e) {
538 LOG.error("Could not translate {}, skipping", gwpredicate, e);
539 }
540 }
541 });
542 }
543
544 if (!gwroute.getFilters().isEmpty()) {
545 builder.filters(gwroute.getFilters().stream().
546 map(gwfilter -> {
547 try {
548 return toFilter(gwroute, gwfilter);
549 } catch (Exception e) {
550 LOG.error("Could not translate {}, skipping", gwfilter, e);
551 return null;
552 }
553 }).
554 filter(Objects::nonNull).
555 collect(Collectors.toList()));
556 }
557
558 return builder;
559 }
560
561 public List<Route.AsyncBuilder> fetch() {
562 synchronized (this) {
563 if (client == null) {
564 try {
565 client = new SyncopeClientFactoryBean().
566 setAddress(serviceOps.get(NetworkService.Type.CORE).getAddress()).
567 setUseCompression(useGZIPCompression).
568 create(new AnonymousAuthenticationHandler(anonymousUser, anonymousKey));
569 } catch (Exception e) {
570 LOG.error("Could not init SyncopeClient", e);
571 return List.of();
572 }
573 }
574 }
575
576 synchronized (routeTOs) {
577 routeTOs.clear();
578 routeTOs.addAll(client.getService(SRARouteService.class).list());
579 }
580
581 return routeTOs.stream().map(this::toRoute).collect(Collectors.toList());
582 }
583
584 public List<SRARouteTO> getRouteTOs() {
585 return routeTOs;
586 }
587 }