001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.camel.impl; 018 019import java.util.ArrayList; 020import java.util.Collection; 021import java.util.Collections; 022import java.util.HashMap; 023import java.util.List; 024import java.util.Map; 025import java.util.Set; 026import java.util.StringJoiner; 027import java.util.concurrent.ConcurrentHashMap; 028import java.util.function.Function; 029 030import org.apache.camel.CamelContext; 031import org.apache.camel.Component; 032import org.apache.camel.Exchange; 033import org.apache.camel.Expression; 034import org.apache.camel.ExtendedCamelContext; 035import org.apache.camel.FailedToCreateRouteFromTemplateException; 036import org.apache.camel.NoSuchBeanException; 037import org.apache.camel.PropertyBindingException; 038import org.apache.camel.RouteTemplateContext; 039import org.apache.camel.model.DataFormatDefinition; 040import org.apache.camel.model.DefaultRouteTemplateContext; 041import org.apache.camel.model.FaultToleranceConfigurationDefinition; 042import org.apache.camel.model.HystrixConfigurationDefinition; 043import org.apache.camel.model.Model; 044import org.apache.camel.model.ModelCamelContext; 045import org.apache.camel.model.ModelLifecycleStrategy; 046import org.apache.camel.model.ProcessorDefinition; 047import org.apache.camel.model.ProcessorDefinitionHelper; 048import org.apache.camel.model.Resilience4jConfigurationDefinition; 049import org.apache.camel.model.RouteDefinition; 050import org.apache.camel.model.RouteDefinitionHelper; 051import org.apache.camel.model.RouteFilters; 052import org.apache.camel.model.RouteTemplateBeanDefinition; 053import org.apache.camel.model.RouteTemplateDefinition; 054import org.apache.camel.model.RouteTemplateParameterDefinition; 055import org.apache.camel.model.cloud.ServiceCallConfigurationDefinition; 056import org.apache.camel.model.rest.RestDefinition; 057import org.apache.camel.model.transformer.TransformerDefinition; 058import org.apache.camel.model.validator.ValidatorDefinition; 059import org.apache.camel.spi.ExchangeFactory; 060import org.apache.camel.spi.Language; 061import org.apache.camel.spi.ModelReifierFactory; 062import org.apache.camel.spi.PropertyConfigurer; 063import org.apache.camel.spi.RouteTemplateLoaderListener; 064import org.apache.camel.spi.RouteTemplateParameterSource; 065import org.apache.camel.spi.ScriptingLanguage; 066import org.apache.camel.support.CamelContextHelper; 067import org.apache.camel.support.PropertyBindingSupport; 068import org.apache.camel.support.RouteTemplateHelper; 069import org.apache.camel.support.ScriptHelper; 070import org.apache.camel.support.service.ServiceHelper; 071import org.apache.camel.util.AntPathMatcher; 072import org.apache.camel.util.ObjectHelper; 073import org.apache.camel.util.StringHelper; 074import org.apache.camel.util.function.Suppliers; 075 076public class DefaultModel implements Model { 077 078 private final CamelContext camelContext; 079 080 private ModelReifierFactory modelReifierFactory = new DefaultModelReifierFactory(); 081 private final List<ModelLifecycleStrategy> modelLifecycleStrategies = new ArrayList<>(); 082 private final List<RouteDefinition> routeDefinitions = new ArrayList<>(); 083 private final List<RouteTemplateDefinition> routeTemplateDefinitions = new ArrayList<>(); 084 private final List<RestDefinition> restDefinitions = new ArrayList<>(); 085 private final Map<String, RouteTemplateDefinition.Converter> routeTemplateConverters = new ConcurrentHashMap<>(); 086 private Map<String, DataFormatDefinition> dataFormats = new HashMap<>(); 087 private List<TransformerDefinition> transformers = new ArrayList<>(); 088 private List<ValidatorDefinition> validators = new ArrayList<>(); 089 private final Map<String, ServiceCallConfigurationDefinition> serviceCallConfigurations = new ConcurrentHashMap<>(); 090 private final Map<String, HystrixConfigurationDefinition> hystrixConfigurations = new ConcurrentHashMap<>(); 091 private final Map<String, Resilience4jConfigurationDefinition> resilience4jConfigurations = new ConcurrentHashMap<>(); 092 private final Map<String, FaultToleranceConfigurationDefinition> faultToleranceConfigurations = new ConcurrentHashMap<>(); 093 private Function<RouteDefinition, Boolean> routeFilter; 094 095 public DefaultModel(CamelContext camelContext) { 096 this.camelContext = camelContext; 097 } 098 099 public CamelContext getCamelContext() { 100 return camelContext; 101 } 102 103 @Override 104 public void addModelLifecycleStrategy(ModelLifecycleStrategy modelLifecycleStrategy) { 105 // avoid adding double which can happen with spring xml on spring boot 106 if (!this.modelLifecycleStrategies.contains(modelLifecycleStrategy)) { 107 this.modelLifecycleStrategies.add(modelLifecycleStrategy); 108 } 109 } 110 111 @Override 112 public List<ModelLifecycleStrategy> getModelLifecycleStrategies() { 113 return modelLifecycleStrategies; 114 } 115 116 @Override 117 public synchronized void addRouteDefinitions(Collection<RouteDefinition> routeDefinitions) throws Exception { 118 if (routeDefinitions == null || routeDefinitions.isEmpty()) { 119 return; 120 } 121 122 List<RouteDefinition> list; 123 if (routeFilter == null) { 124 list = new ArrayList<>(routeDefinitions); 125 } else { 126 list = new ArrayList<>(); 127 for (RouteDefinition r : routeDefinitions) { 128 if (routeFilter.apply(r)) { 129 list.add(r); 130 } 131 } 132 } 133 134 removeRouteDefinitions(list); 135 136 for (RouteDefinition r : list) { 137 for (ModelLifecycleStrategy s : modelLifecycleStrategies) { 138 s.onAddRouteDefinition(r); 139 } 140 this.routeDefinitions.add(r); 141 } 142 143 if (shouldStartRoutes()) { 144 getCamelContext().adapt(ModelCamelContext.class).startRouteDefinitions(list); 145 } 146 } 147 148 @Override 149 public void addRouteDefinition(RouteDefinition routeDefinition) throws Exception { 150 addRouteDefinitions(Collections.singletonList(routeDefinition)); 151 } 152 153 @Override 154 public synchronized void removeRouteDefinitions(Collection<RouteDefinition> routeDefinitions) throws Exception { 155 for (RouteDefinition routeDefinition : routeDefinitions) { 156 removeRouteDefinition(routeDefinition); 157 } 158 } 159 160 @Override 161 public synchronized void removeRouteDefinition(RouteDefinition routeDefinition) throws Exception { 162 RouteDefinition toBeRemoved = routeDefinition; 163 String id = routeDefinition.getId(); 164 if (id != null) { 165 // remove existing route 166 camelContext.getRouteController().stopRoute(id); 167 camelContext.removeRoute(id); 168 toBeRemoved = getRouteDefinition(id); 169 } 170 for (ModelLifecycleStrategy s : modelLifecycleStrategies) { 171 s.onRemoveRouteDefinition(toBeRemoved); 172 } 173 this.routeDefinitions.remove(toBeRemoved); 174 } 175 176 @Override 177 public synchronized List<RouteDefinition> getRouteDefinitions() { 178 return routeDefinitions; 179 } 180 181 @Override 182 public synchronized RouteDefinition getRouteDefinition(String id) { 183 for (RouteDefinition route : routeDefinitions) { 184 if (route.idOrCreate(camelContext.adapt(ExtendedCamelContext.class).getNodeIdFactory()).equals(id)) { 185 return route; 186 } 187 } 188 return null; 189 } 190 191 @Override 192 public List<RouteTemplateDefinition> getRouteTemplateDefinitions() { 193 return routeTemplateDefinitions; 194 } 195 196 @Override 197 public RouteTemplateDefinition getRouteTemplateDefinition(String id) { 198 for (RouteTemplateDefinition route : routeTemplateDefinitions) { 199 if (route.idOrCreate(camelContext.adapt(ExtendedCamelContext.class).getNodeIdFactory()).equals(id)) { 200 return route; 201 } 202 } 203 return null; 204 } 205 206 @Override 207 public void addRouteTemplateDefinitions(Collection<RouteTemplateDefinition> routeTemplateDefinitions) throws Exception { 208 if (routeTemplateDefinitions == null || routeTemplateDefinitions.isEmpty()) { 209 return; 210 } 211 212 for (RouteTemplateDefinition r : routeTemplateDefinitions) { 213 for (ModelLifecycleStrategy s : modelLifecycleStrategies) { 214 s.onAddRouteTemplateDefinition(r); 215 } 216 this.routeTemplateDefinitions.add(r); 217 } 218 } 219 220 @Override 221 public void addRouteTemplateDefinition(RouteTemplateDefinition routeTemplateDefinition) throws Exception { 222 addRouteTemplateDefinitions(Collections.singletonList(routeTemplateDefinition)); 223 } 224 225 @Override 226 public void removeRouteTemplateDefinitions(Collection<RouteTemplateDefinition> routeTemplateDefinitions) throws Exception { 227 for (RouteTemplateDefinition r : routeTemplateDefinitions) { 228 removeRouteTemplateDefinition(r); 229 } 230 } 231 232 @Override 233 public void removeRouteTemplateDefinition(RouteTemplateDefinition routeTemplateDefinition) throws Exception { 234 for (ModelLifecycleStrategy s : modelLifecycleStrategies) { 235 s.onRemoveRouteTemplateDefinition(routeTemplateDefinition); 236 } 237 routeTemplateDefinitions.remove(routeTemplateDefinition); 238 } 239 240 @Override 241 public void addRouteTemplateDefinitionConverter(String templateIdPattern, RouteTemplateDefinition.Converter converter) { 242 routeTemplateConverters.put(templateIdPattern, converter); 243 } 244 245 @Override 246 @Deprecated 247 public String addRouteFromTemplate(final String routeId, final String routeTemplateId, final Map<String, Object> parameters) 248 throws Exception { 249 RouteTemplateContext rtc = new DefaultRouteTemplateContext(camelContext); 250 if (parameters != null) { 251 parameters.forEach(rtc::setParameter); 252 } 253 return addRouteFromTemplate(routeId, routeTemplateId, rtc); 254 } 255 256 @Override 257 public String addRouteFromTemplate(String routeId, String routeTemplateId, RouteTemplateContext routeTemplateContext) 258 throws Exception { 259 RouteTemplateDefinition target = null; 260 for (RouteTemplateDefinition def : routeTemplateDefinitions) { 261 if (routeTemplateId.equals(def.getId())) { 262 target = def; 263 break; 264 } 265 } 266 if (target == null) { 267 // if the route template has a location parameter, then try to load route templates from the location 268 // and look up again 269 Object location = routeTemplateContext.getParameters().get(RouteTemplateParameterSource.LOCATION); 270 if (location != null) { 271 RouteTemplateLoaderListener listener 272 = CamelContextHelper.findByType(getCamelContext(), RouteTemplateLoaderListener.class); 273 RouteTemplateHelper.loadRouteTemplateFromLocation(getCamelContext(), listener, routeTemplateId, 274 location.toString()); 275 } 276 for (RouteTemplateDefinition def : routeTemplateDefinitions) { 277 if (routeTemplateId.equals(def.getId())) { 278 target = def; 279 break; 280 } 281 } 282 } 283 if (target == null) { 284 throw new IllegalArgumentException("Cannot find RouteTemplate with id " + routeTemplateId); 285 } 286 287 final Map<String, Object> prop = new HashMap<>(); 288 // include default values first from the template (and validate that we have inputs for all required parameters) 289 if (target.getTemplateParameters() != null) { 290 StringJoiner templatesBuilder = new StringJoiner(", "); 291 292 for (RouteTemplateParameterDefinition temp : target.getTemplateParameters()) { 293 if (temp.getDefaultValue() != null) { 294 prop.put(temp.getName(), temp.getDefaultValue()); 295 } else { 296 if (temp.isRequired() && !routeTemplateContext.getParameters().containsKey(temp.getName())) { 297 // this is a required parameter which is missing 298 templatesBuilder.add(temp.getName()); 299 } 300 } 301 } 302 if (templatesBuilder.length() > 0) { 303 throw new IllegalArgumentException( 304 "Route template " + routeTemplateId + " the following mandatory parameters must be provided: " 305 + templatesBuilder); 306 } 307 } 308 309 // then override with user parameters part 1 310 if (routeTemplateContext.getParameters() != null) { 311 prop.putAll(routeTemplateContext.getParameters()); 312 } 313 // route template context should include default template parameters from the target route template 314 // so it has all parameters available 315 if (target.getTemplateParameters() != null) { 316 for (RouteTemplateParameterDefinition temp : target.getTemplateParameters()) { 317 if (!routeTemplateContext.getParameters().containsKey(temp.getName()) && temp.getDefaultValue() != null) { 318 routeTemplateContext.setParameter(temp.getName(), temp.getDefaultValue()); 319 } 320 } 321 } 322 323 RouteTemplateDefinition.Converter converter = RouteTemplateDefinition.Converter.DEFAULT_CONVERTER; 324 325 for (Map.Entry<String, RouteTemplateDefinition.Converter> entry : routeTemplateConverters.entrySet()) { 326 final String key = entry.getKey(); 327 final String templateId = target.getId(); 328 329 if ("*".equals(key) || templateId.equals(key)) { 330 converter = entry.getValue(); 331 break; 332 } else if (AntPathMatcher.INSTANCE.match(key, templateId)) { 333 converter = entry.getValue(); 334 break; 335 } else if (templateId.matches(key)) { 336 converter = entry.getValue(); 337 break; 338 } 339 } 340 341 RouteDefinition def = converter.apply(target, prop); 342 if (routeId != null) { 343 def.setId(routeId); 344 } 345 def.setTemplateParameters(prop); 346 def.setRouteTemplateContext(routeTemplateContext); 347 348 // setup local beans 349 if (target.getTemplateBeans() != null) { 350 addTemplateBeans(routeTemplateContext, target); 351 } 352 353 if (target.getConfigurer() != null) { 354 routeTemplateContext.setConfigurer(target.getConfigurer()); 355 } 356 357 // assign ids to the routes and validate that the id's are all unique 358 String duplicate = RouteDefinitionHelper.validateUniqueIds(def, routeDefinitions); 359 if (duplicate != null) { 360 throw new FailedToCreateRouteFromTemplateException( 361 routeId, routeTemplateId, 362 "duplicate id detected: " + duplicate + ". Please correct ids to be unique among all your routes."); 363 } 364 addRouteDefinition(def); 365 return def.getId(); 366 } 367 368 private void addTemplateBeans(RouteTemplateContext routeTemplateContext, RouteTemplateDefinition target) throws Exception { 369 for (RouteTemplateBeanDefinition b : target.getTemplateBeans()) { 370 final Map<String, Object> props = new HashMap<>(); 371 if (b.getProperties() != null) { 372 b.getProperties().forEach(p -> props.put(p.getKey(), p.getValue())); 373 } 374 if (b.getBeanSupplier() != null) { 375 if (props.isEmpty()) { 376 // bean class is optional for supplier 377 if (b.getBeanClass() != null) { 378 routeTemplateContext.bind(b.getName(), b.getBeanClass(), b.getBeanSupplier()); 379 } else { 380 routeTemplateContext.bind(b.getName(), b.getBeanSupplier()); 381 } 382 } 383 } else if (b.getScript() != null) { 384 final String script = b.getScript().getScript(); 385 final Language lan = camelContext.resolveLanguage(b.getType()); 386 final Class<?> clazz = b.getBeanType() != null 387 ? camelContext.getClassResolver().resolveMandatoryClass(b.getBeanType()) 388 : b.getBeanClass() != null ? b.getBeanClass() : Object.class; 389 final ScriptingLanguage slan = lan instanceof ScriptingLanguage ? (ScriptingLanguage) lan : null; 390 if (slan != null) { 391 // scripting language should be evaluated with route template context as binding 392 // and memorize so the script is only evaluated once and the local bean is the same 393 // if a route template refers to the local bean multiple times 394 routeTemplateContext.bind(b.getName(), clazz, Suppliers.memorize(() -> { 395 Map<String, Object> bindings = new HashMap<>(); 396 // use rtx as the short-hand name, as context would imply its CamelContext 397 bindings.put("rtc", routeTemplateContext); 398 Object local = slan.evaluate(script, bindings, clazz); 399 if (!props.isEmpty()) { 400 setPropertiesOnTarget(camelContext, local, props); 401 } 402 return local; 403 })); 404 } else { 405 // exchange based languages needs a dummy exchange to be evaluated 406 // and memorize so the script is only evaluated once and the local bean is the same 407 // if a route template refers to the local bean multiple times 408 routeTemplateContext.bind(b.getName(), clazz, Suppliers.memorize(() -> { 409 ExchangeFactory ef = camelContext.adapt(ExtendedCamelContext.class).getExchangeFactory(); 410 Exchange dummy = ef.create(false); 411 try { 412 String text = ScriptHelper.resolveOptionalExternalScript(camelContext, dummy, script); 413 if (text != null) { 414 Expression exp = lan.createExpression(text); 415 Object local = exp.evaluate(dummy, clazz); 416 if (!props.isEmpty()) { 417 setPropertiesOnTarget(camelContext, local, props); 418 } 419 return local; 420 } else { 421 return null; 422 } 423 } finally { 424 ef.release(dummy); 425 } 426 })); 427 } 428 } else if (b.getBeanClass() != null || b.getType() != null && b.getType().startsWith("#class:")) { 429 // if there is a factory method then the class/bean should be created in a different way 430 String className = null; 431 String factoryMethod = null; 432 String parameters = null; 433 if (b.getType() != null) { 434 className = b.getType().substring(7); 435 if (className.endsWith(")") && className.indexOf('(') != -1) { 436 parameters = StringHelper.after(className, "("); 437 parameters = parameters.substring(0, parameters.length() - 1); // clip last ) 438 className = StringHelper.before(className, "("); 439 } 440 if (className != null && className.indexOf('#') != -1) { 441 factoryMethod = StringHelper.after(className, "#"); 442 className = StringHelper.before(className, "#"); 443 } 444 } 445 if (className != null && (factoryMethod != null || parameters != null)) { 446 final Class<?> clazz = camelContext.getClassResolver().resolveMandatoryClass(className); 447 final String fqn = className; 448 final String fm = factoryMethod; 449 final String fp = parameters; 450 routeTemplateContext.bind(b.getName(), Object.class, Suppliers.memorize(() -> { 451 try { 452 Object local; 453 if (fm != null) { 454 if (fp != null) { 455 // special to support factory method parameters 456 local = PropertyBindingSupport.newInstanceFactoryParameters(camelContext, clazz, fm, fp); 457 } else { 458 local = camelContext.getInjector().newInstance(clazz, fm); 459 } 460 if (local == null) { 461 throw new IllegalStateException( 462 "Cannot create bean instance using factory method: " + fqn + "#" + fm); 463 } 464 } else { 465 // special to support constructor parameters 466 local = PropertyBindingSupport.newInstanceConstructorParameters(camelContext, clazz, fp); 467 } 468 if (!props.isEmpty()) { 469 setPropertiesOnTarget(camelContext, local, props); 470 } 471 return local; 472 } catch (Exception e) { 473 throw new IllegalStateException( 474 "Cannot create bean: " + b.getType()); 475 } 476 })); 477 } else { 478 Class<?> clazz = b.getBeanClass() != null 479 ? b.getBeanClass() : camelContext.getClassResolver().resolveMandatoryClass(className); 480 // we only have the bean class so we use that to create a new bean via the injector 481 // and memorize so the bean is only created once and the local bean is the same 482 // if a route template refers to the local bean multiple times 483 routeTemplateContext.bind(b.getName(), clazz, 484 Suppliers.memorize(() -> { 485 Object local = camelContext.getInjector().newInstance(clazz); 486 if (!props.isEmpty()) { 487 setPropertiesOnTarget(camelContext, local, props); 488 } 489 return local; 490 })); 491 } 492 } else if (b.getType() != null && b.getType().startsWith("#type:")) { 493 Class<?> clazz = camelContext.getClassResolver().resolveMandatoryClass(b.getType().substring(6)); 494 Set<?> found = getCamelContext().getRegistry().findByType(clazz); 495 if (found == null || found.isEmpty()) { 496 throw new NoSuchBeanException(null, clazz.getName()); 497 } else if (found.size() > 1) { 498 throw new NoSuchBeanException( 499 "Found " + found.size() + " beans of type: " + clazz + ". Only one bean expected."); 500 } else { 501 // do not set properties when using #type as it uses an existing shared bean 502 routeTemplateContext.bind(b.getName(), clazz, found.iterator().next()); 503 } 504 } else { 505 // invalid syntax for the local bean, so lets report an exception 506 throw new IllegalArgumentException( 507 "Route template local bean: " + b.getName() + " has invalid type syntax: " + b.getType() 508 + ". To refer to a class then prefix the value with #class such as: #class:fullyQualifiedClassName"); 509 } 510 } 511 } 512 513 @Override 514 public synchronized List<RestDefinition> getRestDefinitions() { 515 return restDefinitions; 516 } 517 518 @Override 519 public synchronized void addRestDefinitions(Collection<RestDefinition> restDefinitions, boolean addToRoutes) 520 throws Exception { 521 if (restDefinitions == null || restDefinitions.isEmpty()) { 522 return; 523 } 524 525 this.restDefinitions.addAll(restDefinitions); 526 if (addToRoutes) { 527 // rests are also routes so need to add them there too 528 for (final RestDefinition restDefinition : restDefinitions) { 529 List<RouteDefinition> routeDefinitions = restDefinition.asRouteDefinition(camelContext); 530 addRouteDefinitions(routeDefinitions); 531 } 532 } 533 } 534 535 @Override 536 public ServiceCallConfigurationDefinition getServiceCallConfiguration(String serviceName) { 537 if (serviceName == null) { 538 serviceName = ""; 539 } 540 541 return serviceCallConfigurations.get(serviceName); 542 } 543 544 @Override 545 public void setServiceCallConfiguration(ServiceCallConfigurationDefinition configuration) { 546 serviceCallConfigurations.put("", configuration); 547 } 548 549 @Override 550 public void setServiceCallConfigurations(List<ServiceCallConfigurationDefinition> configurations) { 551 if (configurations != null) { 552 for (ServiceCallConfigurationDefinition configuration : configurations) { 553 serviceCallConfigurations.put(configuration.getId(), configuration); 554 } 555 } 556 } 557 558 @Override 559 public void addServiceCallConfiguration(String serviceName, ServiceCallConfigurationDefinition configuration) { 560 serviceCallConfigurations.put(serviceName, configuration); 561 } 562 563 @Override 564 public HystrixConfigurationDefinition getHystrixConfiguration(String id) { 565 if (id == null) { 566 id = ""; 567 } 568 569 return hystrixConfigurations.get(id); 570 } 571 572 @Override 573 public void setHystrixConfiguration(HystrixConfigurationDefinition configuration) { 574 hystrixConfigurations.put("", configuration); 575 } 576 577 @Override 578 public void setHystrixConfigurations(List<HystrixConfigurationDefinition> configurations) { 579 if (configurations != null) { 580 for (HystrixConfigurationDefinition configuration : configurations) { 581 hystrixConfigurations.put(configuration.getId(), configuration); 582 } 583 } 584 } 585 586 @Override 587 public void addHystrixConfiguration(String id, HystrixConfigurationDefinition configuration) { 588 hystrixConfigurations.put(id, configuration); 589 } 590 591 @Override 592 public Resilience4jConfigurationDefinition getResilience4jConfiguration(String id) { 593 if (id == null) { 594 id = ""; 595 } 596 597 return resilience4jConfigurations.get(id); 598 } 599 600 @Override 601 public void setResilience4jConfiguration(Resilience4jConfigurationDefinition configuration) { 602 resilience4jConfigurations.put("", configuration); 603 } 604 605 @Override 606 public void setResilience4jConfigurations(List<Resilience4jConfigurationDefinition> configurations) { 607 if (configurations != null) { 608 for (Resilience4jConfigurationDefinition configuration : configurations) { 609 resilience4jConfigurations.put(configuration.getId(), configuration); 610 } 611 } 612 } 613 614 @Override 615 public void addResilience4jConfiguration(String id, Resilience4jConfigurationDefinition configuration) { 616 resilience4jConfigurations.put(id, configuration); 617 } 618 619 @Override 620 public FaultToleranceConfigurationDefinition getFaultToleranceConfiguration(String id) { 621 if (id == null) { 622 id = ""; 623 } 624 625 return faultToleranceConfigurations.get(id); 626 } 627 628 @Override 629 public void setFaultToleranceConfiguration(FaultToleranceConfigurationDefinition configuration) { 630 faultToleranceConfigurations.put("", configuration); 631 } 632 633 @Override 634 public void setFaultToleranceConfigurations(List<FaultToleranceConfigurationDefinition> configurations) { 635 if (configurations != null) { 636 for (FaultToleranceConfigurationDefinition configuration : configurations) { 637 faultToleranceConfigurations.put(configuration.getId(), configuration); 638 } 639 } 640 } 641 642 @Override 643 public void addFaultToleranceConfiguration(String id, FaultToleranceConfigurationDefinition configuration) { 644 faultToleranceConfigurations.put(id, configuration); 645 } 646 647 @Override 648 public DataFormatDefinition resolveDataFormatDefinition(String name) { 649 // lookup type and create the data format from it 650 DataFormatDefinition type = lookup(camelContext, name, DataFormatDefinition.class); 651 if (type == null && getDataFormats() != null) { 652 type = getDataFormats().get(name); 653 } 654 return type; 655 } 656 657 @SuppressWarnings("rawtypes") 658 @Override 659 public ProcessorDefinition<?> getProcessorDefinition(String id) { 660 for (RouteDefinition route : getRouteDefinitions()) { 661 Collection<ProcessorDefinition> col 662 = ProcessorDefinitionHelper.filterTypeInOutputs(route.getOutputs(), ProcessorDefinition.class); 663 for (ProcessorDefinition proc : col) { 664 if (id.equals(proc.getId())) { 665 return proc; 666 } 667 } 668 } 669 return null; 670 } 671 672 @Override 673 public <T extends ProcessorDefinition<T>> T getProcessorDefinition(String id, Class<T> type) { 674 ProcessorDefinition<?> answer = getProcessorDefinition(id); 675 if (answer != null) { 676 return type.cast(answer); 677 } 678 return null; 679 } 680 681 @Override 682 public Map<String, DataFormatDefinition> getDataFormats() { 683 return dataFormats; 684 } 685 686 @Override 687 public void setDataFormats(Map<String, DataFormatDefinition> dataFormats) { 688 this.dataFormats = dataFormats; 689 } 690 691 @Override 692 public List<TransformerDefinition> getTransformers() { 693 return transformers; 694 } 695 696 @Override 697 public void setTransformers(List<TransformerDefinition> transformers) { 698 this.transformers = transformers; 699 } 700 701 @Override 702 public List<ValidatorDefinition> getValidators() { 703 return validators; 704 } 705 706 @Override 707 public void setValidators(List<ValidatorDefinition> validators) { 708 this.validators = validators; 709 } 710 711 @Override 712 public void setRouteFilterPattern(String include, String exclude) { 713 setRouteFilter(RouteFilters.filterByPattern(include, exclude)); 714 } 715 716 @Override 717 public Function<RouteDefinition, Boolean> getRouteFilter() { 718 return routeFilter; 719 } 720 721 @Override 722 public void setRouteFilter(Function<RouteDefinition, Boolean> routeFilter) { 723 this.routeFilter = routeFilter; 724 } 725 726 @Override 727 public ModelReifierFactory getModelReifierFactory() { 728 return modelReifierFactory; 729 } 730 731 @Override 732 public void setModelReifierFactory(ModelReifierFactory modelReifierFactory) { 733 this.modelReifierFactory = modelReifierFactory; 734 } 735 736 /** 737 * Should we start newly added routes? 738 */ 739 protected boolean shouldStartRoutes() { 740 return camelContext.isStarted() && !camelContext.isStarting(); 741 } 742 743 private static <T> T lookup(CamelContext context, String ref, Class<T> type) { 744 try { 745 return context.getRegistry().lookupByNameAndType(ref, type); 746 } catch (Exception e) { 747 // need to ignore not same type and return it as null 748 return null; 749 } 750 } 751 752 private static void setPropertiesOnTarget(CamelContext context, Object target, Map<String, Object> properties) { 753 ObjectHelper.notNull(context, "context"); 754 ObjectHelper.notNull(target, "target"); 755 ObjectHelper.notNull(properties, "properties"); 756 757 if (target instanceof CamelContext) { 758 throw new UnsupportedOperationException("Configuring the Camel Context is not supported"); 759 } 760 761 PropertyConfigurer configurer = null; 762 if (target instanceof Component) { 763 // the component needs to be initialized to have the configurer ready 764 ServiceHelper.initService(target); 765 configurer = ((Component) target).getComponentPropertyConfigurer(); 766 } 767 768 if (configurer == null) { 769 // see if there is a configurer for it 770 configurer = context.adapt(ExtendedCamelContext.class) 771 .getConfigurerResolver() 772 .resolvePropertyConfigurer(target.getClass().getSimpleName(), context); 773 } 774 775 try { 776 PropertyBindingSupport.build() 777 .withMandatory(true) 778 .withRemoveParameters(false) 779 .withConfigurer(configurer) 780 .withIgnoreCase(true) 781 .withFlattenProperties(true) 782 .bind(context, target, properties); 783 } catch (PropertyBindingException e) { 784 String key = e.getOptionKey(); 785 if (key == null) { 786 String prefix = e.getOptionPrefix(); 787 if (prefix != null && !prefix.endsWith(".")) { 788 prefix = "." + prefix; 789 } 790 791 key = prefix != null 792 ? prefix + "." + e.getPropertyName() 793 : e.getPropertyName(); 794 } 795 796 // enrich the error with more precise details with option prefix and key 797 throw new PropertyBindingException( 798 e.getTarget(), 799 e.getPropertyName(), 800 e.getValue(), 801 null, 802 key, 803 e.getCause()); 804 } 805 } 806 807}