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.Collection; 020import java.util.HashMap; 021import java.util.HashSet; 022import java.util.List; 023import java.util.Map; 024import java.util.Properties; 025import java.util.Set; 026import java.util.function.Function; 027 028import org.apache.camel.CamelContext; 029import org.apache.camel.Expression; 030import org.apache.camel.ExtendedCamelContext; 031import org.apache.camel.FailedToStartRouteException; 032import org.apache.camel.Predicate; 033import org.apache.camel.Processor; 034import org.apache.camel.Route; 035import org.apache.camel.RouteTemplateContext; 036import org.apache.camel.StartupStep; 037import org.apache.camel.ValueHolder; 038import org.apache.camel.api.management.JmxSystemPropertyKeys; 039import org.apache.camel.builder.AdviceWith; 040import org.apache.camel.builder.AdviceWithRouteBuilder; 041import org.apache.camel.impl.engine.DefaultExecutorServiceManager; 042import org.apache.camel.impl.engine.RouteService; 043import org.apache.camel.impl.engine.SimpleCamelContext; 044import org.apache.camel.impl.engine.TransformerKey; 045import org.apache.camel.impl.engine.ValidatorKey; 046import org.apache.camel.impl.scan.AssignableToPackageScanFilter; 047import org.apache.camel.impl.scan.InvertingPackageScanFilter; 048import org.apache.camel.model.DataFormatDefinition; 049import org.apache.camel.model.FaultToleranceConfigurationDefinition; 050import org.apache.camel.model.HystrixConfigurationDefinition; 051import org.apache.camel.model.Model; 052import org.apache.camel.model.ModelCamelContext; 053import org.apache.camel.model.ModelLifecycleStrategy; 054import org.apache.camel.model.ProcessorDefinition; 055import org.apache.camel.model.ProcessorDefinitionHelper; 056import org.apache.camel.model.Resilience4jConfigurationDefinition; 057import org.apache.camel.model.RouteDefinition; 058import org.apache.camel.model.RouteDefinitionHelper; 059import org.apache.camel.model.RouteTemplateDefinition; 060import org.apache.camel.model.RouteTemplatesDefinition; 061import org.apache.camel.model.RoutesDefinition; 062import org.apache.camel.model.cloud.ServiceCallConfigurationDefinition; 063import org.apache.camel.model.language.ExpressionDefinition; 064import org.apache.camel.model.rest.RestDefinition; 065import org.apache.camel.model.rest.RestsDefinition; 066import org.apache.camel.model.transformer.TransformerDefinition; 067import org.apache.camel.model.validator.ValidatorDefinition; 068import org.apache.camel.spi.BeanRepository; 069import org.apache.camel.spi.DataFormat; 070import org.apache.camel.spi.DataType; 071import org.apache.camel.spi.ExecutorServiceManager; 072import org.apache.camel.spi.LocalBeanRepositoryAware; 073import org.apache.camel.spi.ModelReifierFactory; 074import org.apache.camel.spi.ModelToXMLDumper; 075import org.apache.camel.spi.PackageScanClassResolver; 076import org.apache.camel.spi.PropertiesComponent; 077import org.apache.camel.spi.Registry; 078import org.apache.camel.spi.StartupStepRecorder; 079import org.apache.camel.spi.Transformer; 080import org.apache.camel.spi.UuidGenerator; 081import org.apache.camel.spi.Validator; 082import org.apache.camel.support.CamelContextHelper; 083import org.apache.camel.support.DefaultRegistry; 084import org.apache.camel.support.LocalBeanRegistry; 085import org.apache.camel.support.SimpleUuidGenerator; 086import org.apache.camel.util.ObjectHelper; 087import org.apache.camel.util.StopWatch; 088import org.apache.camel.util.StringHelper; 089import org.slf4j.Logger; 090import org.slf4j.LoggerFactory; 091 092/** 093 * Represents the context used to configure routes and the policies to use. 094 */ 095public class DefaultCamelContext extends SimpleCamelContext implements ModelCamelContext { 096 097 protected static final ThreadLocal<OptionHolder> OPTIONS = ThreadLocal.withInitial(OptionHolder::new); 098 private static final Logger LOG = LoggerFactory.getLogger(DefaultCamelContext.class); 099 private static final UuidGenerator UUID = new SimpleUuidGenerator(); 100 101 private Model model = new DefaultModel(this); 102 103 /** 104 * Creates the {@link ModelCamelContext} using {@link org.apache.camel.support.DefaultRegistry} as registry. 105 * <p/> 106 * Use one of the other constructors to force use an explicit registry. 107 */ 108 public DefaultCamelContext() { 109 this(true); 110 } 111 112 /** 113 * Creates the {@link CamelContext} using the given {@link BeanRepository} as first-choice repository, and the 114 * {@link org.apache.camel.support.SimpleRegistry} as fallback, via the {@link DefaultRegistry} implementation. 115 * 116 * @param repository the bean repository. 117 */ 118 public DefaultCamelContext(BeanRepository repository) { 119 this(new DefaultRegistry(repository)); 120 } 121 122 /** 123 * Creates the {@link ModelCamelContext} using the given registry 124 * 125 * @param registry the registry 126 */ 127 public DefaultCamelContext(Registry registry) { 128 this(); 129 setRegistry(registry); 130 } 131 132 public DefaultCamelContext(boolean init) { 133 super(init); 134 if (isDisableJmx()) { 135 disableJMX(); 136 } 137 } 138 139 @Override 140 protected void doDumpRoutes() { 141 ModelToXMLDumper dumper = getModelToXMLDumper(); 142 143 int size = getRouteDefinitions().size(); 144 if (size > 0) { 145 LOG.info("Dumping {} routes as XML", size); 146 // for XML to output nicely all routes in one XML then lets put them into <routes> 147 RoutesDefinition def = new RoutesDefinition(); 148 def.setRoutes(getRouteDefinitions()); 149 try { 150 String xml = dumper.dumpModelAsXml(this, def, true, true); 151 // lets separate routes with empty line 152 xml = StringHelper.replaceFirst(xml, "xmlns=\"http://camel.apache.org/schema/spring\">", 153 "xmlns=\"http://camel.apache.org/schema/spring\">\n"); 154 xml = StringHelper.replaceAll(xml, "</route>", "</route>\n"); 155 LOG.info("\n\n{}\n", xml); 156 } catch (Exception e) { 157 LOG.warn("Error dumping routes to XML due to {}. This exception is ignored.", e.getMessage(), e); 158 } 159 } 160 161 size = getRestDefinitions().size(); 162 if (size > 0) { 163 LOG.info("Dumping {} rests as XML", size); 164 // for XML to output nicely all routes in one XML then lets put them into <routes> 165 RestsDefinition def = new RestsDefinition(); 166 def.setRests(getRestDefinitions()); 167 try { 168 String xml = dumper.dumpModelAsXml(this, def, true, true); 169 // lets separate rests with empty line 170 xml = StringHelper.replaceFirst(xml, "xmlns=\"http://camel.apache.org/schema/spring\">", 171 "xmlns=\"http://camel.apache.org/schema/spring\">\n"); 172 xml = StringHelper.replaceAll(xml, "</rest>", "</rest>\n"); 173 LOG.info("\n\n{}\n", xml); 174 } catch (Exception e) { 175 LOG.warn("Error dumping rests to XML due to {}. This exception is ignored.", e.getMessage(), e); 176 } 177 } 178 179 size = getRouteTemplateDefinitions().size(); 180 if (size > 0) { 181 LOG.info("Dumping {} route templates as XML", size); 182 // for XML to output nicely all routes in one XML then lets put them into <routes> 183 RouteTemplatesDefinition def = new RouteTemplatesDefinition(); 184 def.setRouteTemplates(getRouteTemplateDefinitions()); 185 try { 186 String xml = dumper.dumpModelAsXml(this, def, true, true); 187 // lets separate rests with empty line 188 xml = StringHelper.replaceFirst(xml, "xmlns=\"http://camel.apache.org/schema/spring\">", 189 "xmlns=\"http://camel.apache.org/schema/spring\">\n"); 190 xml = StringHelper.replaceAll(xml, "</routeTemplate>", "</routeTemplate>\n"); 191 LOG.info("\n\n{}\n", xml); 192 } catch (Exception e) { 193 LOG.warn("Error dumping route-templates to XML due to {}. This exception is ignored.", e.getMessage(), e); 194 } 195 } 196 } 197 198 public static void setNoStart(boolean b) { 199 getOptions().noStart = b; 200 } 201 202 public static boolean isNoStart() { 203 return getOptions().noStart; 204 } 205 206 public static void setDisableJmx(boolean b) { 207 getOptions().disableJmx = b; 208 } 209 210 public static boolean isDisableJmx() { 211 return getOptions().disableJmx; 212 } 213 214 @Override 215 public String getTestExcludeRoutes() { 216 return getExcludeRoutes(); 217 } 218 219 public static String getExcludeRoutes() { 220 return getOptions().excludeRoutes; 221 } 222 223 public static void setExcludeRoutes(String s) { 224 getOptions().excludeRoutes = s; 225 } 226 227 public static void clearOptions() { 228 OPTIONS.set(new OptionHolder()); 229 } 230 231 private static OptionHolder getOptions() { 232 return OPTIONS.get(); 233 } 234 235 @Override 236 public void start() { 237 // for example from unit testing we want to start Camel later (manually) 238 if (isNoStart()) { 239 LOG.trace("Ignoring start() as NO_START is true"); 240 return; 241 } 242 243 if (!isStarted() && !isStarting()) { 244 StopWatch watch = new StopWatch(); 245 super.start(); 246 LOG.debug("start() took {} millis", watch.taken()); 247 } else { 248 // ignore as Camel is already started 249 LOG.trace("Ignoring start() as Camel is already started"); 250 } 251 } 252 253 @Override 254 protected PackageScanClassResolver createPackageScanClassResolver() { 255 PackageScanClassResolver resolver = super.createPackageScanClassResolver(); 256 String excluded = getExcludeRoutes(); 257 if (ObjectHelper.isNotEmpty(excluded)) { 258 Set<Class<?>> excludedClasses = new HashSet<>(); 259 for (String str : excluded.split(",")) { 260 excludedClasses.add(getClassResolver().resolveClass(str)); 261 } 262 resolver.addFilter(new InvertingPackageScanFilter(new AssignableToPackageScanFilter(excludedClasses))); 263 } 264 return resolver; 265 } 266 267 @Override 268 public void disposeModel() { 269 LOG.debug("Disposing Model on CamelContext"); 270 model = null; 271 } 272 273 @Override 274 public void addModelLifecycleStrategy(ModelLifecycleStrategy modelLifecycleStrategy) { 275 if (model == null && isLightweight()) { 276 throw new IllegalStateException("Access to model not supported in lightweight mode"); 277 } 278 model.addModelLifecycleStrategy(modelLifecycleStrategy); 279 } 280 281 @Override 282 public List<ModelLifecycleStrategy> getModelLifecycleStrategies() { 283 if (model == null && isLightweight()) { 284 throw new IllegalStateException("Access to model not supported in lightweight mode"); 285 } 286 return model.getModelLifecycleStrategies(); 287 } 288 289 @Override 290 public List<RouteDefinition> getRouteDefinitions() { 291 if (model == null && isLightweight()) { 292 throw new IllegalStateException("Access to model not supported in lightweight mode"); 293 } 294 return model.getRouteDefinitions(); 295 } 296 297 @Override 298 public RouteDefinition getRouteDefinition(String id) { 299 if (model == null && isLightweight()) { 300 throw new IllegalStateException("Access to model not supported in lightweight mode"); 301 } 302 return model.getRouteDefinition(id); 303 } 304 305 @Override 306 public void addRouteDefinitions(Collection<RouteDefinition> routeDefinitions) throws Exception { 307 if (model == null && isLightweight()) { 308 throw new IllegalStateException("Access to model not supported in lightweight mode"); 309 } 310 model.addRouteDefinitions(routeDefinitions); 311 } 312 313 @Override 314 public void addRouteDefinition(RouteDefinition routeDefinition) throws Exception { 315 if (model == null && isLightweight()) { 316 throw new IllegalStateException("Access to model not supported in lightweight mode"); 317 } 318 model.addRouteDefinition(routeDefinition); 319 } 320 321 @Override 322 public void removeRouteDefinitions(Collection<RouteDefinition> routeDefinitions) throws Exception { 323 if (model == null && isLightweight()) { 324 throw new IllegalStateException("Access to model not supported in lightweight mode"); 325 } 326 model.removeRouteDefinitions(routeDefinitions); 327 } 328 329 @Override 330 public void removeRouteDefinition(RouteDefinition routeDefinition) throws Exception { 331 if (model == null && isLightweight()) { 332 throw new IllegalStateException("Access to model not supported in lightweight mode"); 333 } 334 model.removeRouteDefinition(routeDefinition); 335 } 336 337 @Override 338 public List<RouteTemplateDefinition> getRouteTemplateDefinitions() { 339 if (model == null && isLightweight()) { 340 throw new IllegalStateException("Access to model not supported in lightweight mode"); 341 } 342 return model.getRouteTemplateDefinitions(); 343 } 344 345 @Override 346 public RouteTemplateDefinition getRouteTemplateDefinition(String id) { 347 if (model == null && isLightweight()) { 348 throw new IllegalStateException("Access to model not supported in lightweight mode"); 349 } 350 return model.getRouteTemplateDefinition(id); 351 } 352 353 @Override 354 public void addRouteTemplateDefinitions(Collection<RouteTemplateDefinition> routeTemplateDefinitions) throws Exception { 355 if (model == null && isLightweight()) { 356 throw new IllegalStateException("Access to model not supported in lightweight mode"); 357 } 358 model.addRouteTemplateDefinitions(routeTemplateDefinitions); 359 } 360 361 @Override 362 public void addRouteTemplateDefinition(RouteTemplateDefinition routeTemplateDefinition) throws Exception { 363 if (model == null && isLightweight()) { 364 throw new IllegalStateException("Access to model not supported in lightweight mode"); 365 } 366 model.addRouteTemplateDefinition(routeTemplateDefinition); 367 } 368 369 @Override 370 public void removeRouteTemplateDefinitions(Collection<RouteTemplateDefinition> routeTemplateDefinitions) throws Exception { 371 if (model == null && isLightweight()) { 372 throw new IllegalStateException("Access to model not supported in lightweight mode"); 373 } 374 model.removeRouteTemplateDefinitions(routeTemplateDefinitions); 375 } 376 377 @Override 378 public void removeRouteTemplateDefinition(RouteTemplateDefinition routeTemplateDefinition) throws Exception { 379 if (model == null && isLightweight()) { 380 throw new IllegalStateException("Access to model not supported in lightweight mode"); 381 } 382 model.removeRouteTemplateDefinition(routeTemplateDefinition); 383 } 384 385 @Override 386 public void addRouteTemplateDefinitionConverter(String templateIdPattern, RouteTemplateDefinition.Converter converter) { 387 if (model == null && isLightweight()) { 388 throw new IllegalStateException("Access to model not supported in lightweight mode"); 389 } 390 model.addRouteTemplateDefinitionConverter(templateIdPattern, converter); 391 } 392 393 @Override 394 public String addRouteFromTemplate(String routeId, String routeTemplateId, Map<String, Object> parameters) 395 throws Exception { 396 if (model == null && isLightweight()) { 397 throw new IllegalStateException("Access to model not supported in lightweight mode"); 398 } 399 return model.addRouteFromTemplate(routeId, routeTemplateId, parameters); 400 } 401 402 @Override 403 public String addRouteFromTemplate(String routeId, String routeTemplateId, RouteTemplateContext routeTemplateContext) 404 throws Exception { 405 if (model == null && isLightweight()) { 406 throw new IllegalStateException("Access to model not supported in lightweight mode"); 407 } 408 return model.addRouteFromTemplate(routeId, routeTemplateId, routeTemplateContext); 409 } 410 411 @Override 412 public List<RestDefinition> getRestDefinitions() { 413 if (model == null && isLightweight()) { 414 throw new IllegalStateException("Access to model not supported in lightweight mode"); 415 } 416 return model.getRestDefinitions(); 417 } 418 419 @Override 420 public void addRestDefinitions(Collection<RestDefinition> restDefinitions, boolean addToRoutes) throws Exception { 421 if (model == null && isLightweight()) { 422 throw new IllegalStateException("Access to model not supported in lightweight mode"); 423 } 424 model.addRestDefinitions(restDefinitions, addToRoutes); 425 } 426 427 @Override 428 public void setDataFormats(Map<String, DataFormatDefinition> dataFormats) { 429 if (model == null && isLightweight()) { 430 throw new IllegalStateException("Access to model not supported in lightweight mode"); 431 } 432 model.setDataFormats(dataFormats); 433 } 434 435 @Override 436 public Map<String, DataFormatDefinition> getDataFormats() { 437 if (model == null && isLightweight()) { 438 throw new IllegalStateException("Access to model not supported in lightweight mode"); 439 } 440 return model.getDataFormats(); 441 } 442 443 @Override 444 public DataFormatDefinition resolveDataFormatDefinition(String name) { 445 if (model == null && isLightweight()) { 446 throw new IllegalStateException("Access to model not supported in lightweight mode"); 447 } 448 return model.resolveDataFormatDefinition(name); 449 } 450 451 @Override 452 public ProcessorDefinition<?> getProcessorDefinition(String id) { 453 if (model == null && isLightweight()) { 454 throw new IllegalStateException("Access to model not supported in lightweight mode"); 455 } 456 return model.getProcessorDefinition(id); 457 } 458 459 @Override 460 public <T extends ProcessorDefinition<T>> T getProcessorDefinition(String id, Class<T> type) { 461 if (model == null && isLightweight()) { 462 throw new IllegalStateException("Access to model not supported in lightweight mode"); 463 } 464 return model.getProcessorDefinition(id, type); 465 } 466 467 @Override 468 public void setValidators(List<ValidatorDefinition> validators) { 469 if (model == null && isLightweight()) { 470 throw new IllegalStateException("Access to model not supported in lightweight mode"); 471 } 472 model.setValidators(validators); 473 } 474 475 @Override 476 public HystrixConfigurationDefinition getHystrixConfiguration(String id) { 477 if (model == null && isLightweight()) { 478 throw new IllegalStateException("Access to model not supported in lightweight mode"); 479 } 480 return model.getHystrixConfiguration(id); 481 } 482 483 @Override 484 public void setHystrixConfiguration(HystrixConfigurationDefinition configuration) { 485 if (model == null && isLightweight()) { 486 throw new IllegalStateException("Access to model not supported in lightweight mode"); 487 } 488 model.setHystrixConfiguration(configuration); 489 } 490 491 @Override 492 public void setHystrixConfigurations(List<HystrixConfigurationDefinition> configurations) { 493 if (model == null && isLightweight()) { 494 throw new IllegalStateException("Access to model not supported in lightweight mode"); 495 } 496 model.setHystrixConfigurations(configurations); 497 } 498 499 @Override 500 public void addHystrixConfiguration(String id, HystrixConfigurationDefinition configuration) { 501 if (model == null && isLightweight()) { 502 throw new IllegalStateException("Access to model not supported in lightweight mode"); 503 } 504 model.addHystrixConfiguration(id, configuration); 505 } 506 507 @Override 508 public Resilience4jConfigurationDefinition getResilience4jConfiguration(String id) { 509 if (model == null && isLightweight()) { 510 throw new IllegalStateException("Access to model not supported in lightweight mode"); 511 } 512 return model.getResilience4jConfiguration(id); 513 } 514 515 @Override 516 public void setResilience4jConfiguration(Resilience4jConfigurationDefinition configuration) { 517 if (model == null && isLightweight()) { 518 throw new IllegalStateException("Access to model not supported in lightweight mode"); 519 } 520 model.setResilience4jConfiguration(configuration); 521 } 522 523 @Override 524 public void setResilience4jConfigurations(List<Resilience4jConfigurationDefinition> configurations) { 525 if (model == null && isLightweight()) { 526 throw new IllegalStateException("Access to model not supported in lightweight mode"); 527 } 528 model.setResilience4jConfigurations(configurations); 529 } 530 531 @Override 532 public void addResilience4jConfiguration(String id, Resilience4jConfigurationDefinition configuration) { 533 if (model == null && isLightweight()) { 534 throw new IllegalStateException("Access to model not supported in lightweight mode"); 535 } 536 model.addResilience4jConfiguration(id, configuration); 537 } 538 539 @Override 540 public FaultToleranceConfigurationDefinition getFaultToleranceConfiguration(String id) { 541 if (model == null && isLightweight()) { 542 throw new IllegalStateException("Access to model not supported in lightweight mode"); 543 } 544 return model.getFaultToleranceConfiguration(id); 545 } 546 547 @Override 548 public void setFaultToleranceConfiguration(FaultToleranceConfigurationDefinition configuration) { 549 if (model == null && isLightweight()) { 550 throw new IllegalStateException("Access to model not supported in lightweight mode"); 551 } 552 model.setFaultToleranceConfiguration(configuration); 553 } 554 555 @Override 556 public void setFaultToleranceConfigurations(List<FaultToleranceConfigurationDefinition> configurations) { 557 if (model == null && isLightweight()) { 558 throw new IllegalStateException("Access to model not supported in lightweight mode"); 559 } 560 model.setFaultToleranceConfigurations(configurations); 561 } 562 563 @Override 564 public void addFaultToleranceConfiguration(String id, FaultToleranceConfigurationDefinition configuration) { 565 if (model == null && isLightweight()) { 566 throw new IllegalStateException("Access to model not supported in lightweight mode"); 567 } 568 model.addFaultToleranceConfiguration(id, configuration); 569 } 570 571 @Override 572 public List<ValidatorDefinition> getValidators() { 573 if (model == null && isLightweight()) { 574 throw new IllegalStateException("Access to model not supported in lightweight mode"); 575 } 576 return model.getValidators(); 577 } 578 579 @Override 580 public void setTransformers(List<TransformerDefinition> transformers) { 581 if (model == null && isLightweight()) { 582 throw new IllegalStateException("Access to model not supported in lightweight mode"); 583 } 584 model.setTransformers(transformers); 585 } 586 587 @Override 588 public List<TransformerDefinition> getTransformers() { 589 if (model == null && isLightweight()) { 590 throw new IllegalStateException("Access to model not supported in lightweight mode"); 591 } 592 return model.getTransformers(); 593 } 594 595 @Override 596 public ServiceCallConfigurationDefinition getServiceCallConfiguration(String serviceName) { 597 if (model == null && isLightweight()) { 598 throw new IllegalStateException("Access to model not supported in lightweight mode"); 599 } 600 return model.getServiceCallConfiguration(serviceName); 601 } 602 603 @Override 604 public void setServiceCallConfiguration(ServiceCallConfigurationDefinition configuration) { 605 if (model == null && isLightweight()) { 606 throw new IllegalStateException("Access to model not supported in lightweight mode"); 607 } 608 model.setServiceCallConfiguration(configuration); 609 } 610 611 @Override 612 public void setServiceCallConfigurations(List<ServiceCallConfigurationDefinition> configurations) { 613 if (model == null && isLightweight()) { 614 throw new IllegalStateException("Access to model not supported in lightweight mode"); 615 } 616 model.setServiceCallConfigurations(configurations); 617 } 618 619 @Override 620 public void addServiceCallConfiguration(String serviceName, ServiceCallConfigurationDefinition configuration) { 621 if (model == null && isLightweight()) { 622 throw new IllegalStateException("Access to model not supported in lightweight mode"); 623 } 624 model.addServiceCallConfiguration(serviceName, configuration); 625 } 626 627 @Override 628 public void setRouteFilterPattern(String include, String exclude) { 629 if (model == null && isLightweight()) { 630 throw new IllegalStateException("Access to model not supported in lightweight mode"); 631 } 632 model.setRouteFilterPattern(include, exclude); 633 } 634 635 @Override 636 public void setRouteFilter(Function<RouteDefinition, Boolean> filter) { 637 if (model == null && isLightweight()) { 638 throw new IllegalStateException("Access to model not supported in lightweight mode"); 639 } 640 model.setRouteFilter(filter); 641 } 642 643 @Override 644 public Function<RouteDefinition, Boolean> getRouteFilter() { 645 if (model == null && isLightweight()) { 646 throw new IllegalStateException("Access to model not supported in lightweight mode"); 647 } 648 return model.getRouteFilter(); 649 } 650 651 @Override 652 public ModelReifierFactory getModelReifierFactory() { 653 if (model == null && isLightweight()) { 654 throw new IllegalStateException("Access to model not supported in lightweight mode"); 655 } 656 return model.getModelReifierFactory(); 657 } 658 659 @Override 660 public void setModelReifierFactory(ModelReifierFactory modelReifierFactory) { 661 if (model == null && isLightweight()) { 662 throw new IllegalStateException("Access to model not supported in lightweight mode"); 663 } 664 model.setModelReifierFactory(modelReifierFactory); 665 } 666 667 @Override 668 protected void bindDataFormats() throws Exception { 669 // eager lookup data formats and bind to registry so the dataformats can 670 // be looked up and used 671 if (model != null) { 672 for (Map.Entry<String, DataFormatDefinition> e : model.getDataFormats().entrySet()) { 673 String id = e.getKey(); 674 DataFormatDefinition def = e.getValue(); 675 LOG.debug("Creating Dataformat with id: {} and definition: {}", id, def); 676 DataFormat df = model.getModelReifierFactory().createDataFormat(this, def); 677 addService(df, true); 678 getRegistry().bind(id, df); 679 } 680 } 681 } 682 683 @Override 684 protected synchronized void shutdownRouteService(RouteService routeService) throws Exception { 685 if (model != null) { 686 RouteDefinition rd = model.getRouteDefinition(routeService.getId()); 687 if (rd != null) { 688 model.getRouteDefinitions().remove(rd); 689 } 690 } 691 super.shutdownRouteService(routeService); 692 } 693 694 @Override 695 protected boolean isStreamCachingInUse() throws Exception { 696 boolean streamCachingInUse = super.isStreamCachingInUse(); 697 if (!streamCachingInUse) { 698 for (RouteDefinition route : model.getRouteDefinitions()) { 699 Boolean routeCache = CamelContextHelper.parseBoolean(this, route.getStreamCache()); 700 if (routeCache != null && routeCache) { 701 streamCachingInUse = true; 702 break; 703 } 704 } 705 } 706 return streamCachingInUse; 707 } 708 709 @Override 710 public void startRouteDefinitions() throws Exception { 711 if (model == null && isLightweight()) { 712 throw new IllegalStateException("Access to model not supported in lightweight mode"); 713 } 714 List<RouteDefinition> routeDefinitions = model.getRouteDefinitions(); 715 if (routeDefinitions != null) { 716 startRouteDefinitions(routeDefinitions); 717 } 718 } 719 720 public void startRouteDefinitions(List<RouteDefinition> routeDefinitions) throws Exception { 721 if (model == null && isLightweight()) { 722 throw new IllegalStateException("Access to model not supported in lightweight mode"); 723 } 724 725 // indicate we are staring the route using this thread so 726 // we are able to query this if needed 727 boolean alreadyStartingRoutes = isStartingRoutes(); 728 if (!alreadyStartingRoutes) { 729 setStartingRoutes(true); 730 } 731 732 PropertiesComponent pc = getCamelContextReference().getPropertiesComponent(); 733 // route templates supports binding beans that are local for the template only 734 // in this local mode then we need to check for side-effects (see further) 735 LocalBeanRepositoryAware localBeans = null; 736 if (getCamelContextReference().getRegistry() instanceof LocalBeanRepositoryAware) { 737 localBeans = (LocalBeanRepositoryAware) getCamelContextReference().getRegistry(); 738 } 739 try { 740 RouteDefinitionHelper.forceAssignIds(getCamelContextReference(), routeDefinitions); 741 for (RouteDefinition routeDefinition : routeDefinitions) { 742 // assign ids to the routes and validate that the id's is all unique 743 String duplicate = RouteDefinitionHelper.validateUniqueIds(routeDefinition, routeDefinitions); 744 if (duplicate != null) { 745 throw new FailedToStartRouteException( 746 routeDefinition.getId(), 747 "duplicate id detected: " + duplicate + ". Please correct ids to be unique among all your routes."); 748 } 749 750 // if the route definition was created via a route template then we need to prepare its parameters when the route is being created and started 751 if (routeDefinition.isTemplate() != null && routeDefinition.isTemplate() 752 && routeDefinition.getTemplateParameters() != null) { 753 754 // apply configurer if any present 755 if (routeDefinition.getRouteTemplateContext().getConfigurer() != null) { 756 routeDefinition.getRouteTemplateContext().getConfigurer() 757 .accept(routeDefinition.getRouteTemplateContext()); 758 } 759 760 // copy parameters/bean repository to not cause side-effect 761 Map<String, Object> params = new HashMap<>(routeDefinition.getTemplateParameters()); 762 LocalBeanRegistry bbr 763 = (LocalBeanRegistry) routeDefinition.getRouteTemplateContext().getLocalBeanRepository(); 764 LocalBeanRegistry bbrCopy = new LocalBeanRegistry(); 765 766 // make all bean in the bean repository use unique keys (need to add uuid counter) 767 // so when the route template is used again to create another route, then there is 768 // no side-effect from previously used values that Camel may use in its endpoint 769 // registry and elsewhere 770 if (bbr != null && !bbr.isEmpty()) { 771 for (Map.Entry<String, Object> param : params.entrySet()) { 772 Object value = param.getValue(); 773 if (value instanceof String) { 774 String oldKey = (String) value; 775 boolean clash = bbr.keys().stream().anyMatch(k -> k.equals(oldKey)); 776 if (clash) { 777 String newKey = oldKey + "-" + UUID.generateUuid(); 778 LOG.debug( 779 "Route: {} re-assigning local-bean id: {} to: {} to ensure ids are globally unique", 780 routeDefinition.getId(), oldKey, newKey); 781 bbrCopy.put(newKey, bbr.remove(oldKey)); 782 param.setValue(newKey); 783 } 784 } 785 } 786 // the remainder of the local beans must also have their ids made global unique 787 for (String oldKey : bbr.keySet()) { 788 String newKey = oldKey + "-" + UUID.generateUuid(); 789 LOG.debug( 790 "Route: {} re-assigning local-bean id: {} to: {} to ensure ids are globally unique", 791 routeDefinition.getId(), oldKey, newKey); 792 bbrCopy.put(newKey, bbr.get(oldKey)); 793 if (!params.containsKey(oldKey)) { 794 // if a bean was bound as local bean with a key and it was not defined as template parameter 795 // then store it as if it was a template parameter with same key=value which allows us 796 // to use this local bean in the route without any problem such as: 797 // to("bean:{{myBean}}") 798 // and myBean is the local bean id. 799 params.put(oldKey, newKey); 800 } 801 } 802 } 803 804 Properties prop = new Properties(); 805 prop.putAll(params); 806 pc.setLocalProperties(prop); 807 808 // we need to shadow the bean registry on the CamelContext with the local beans from the route template context 809 if (localBeans != null && bbrCopy != null) { 810 localBeans.setLocalBeanRepository(bbrCopy); 811 } 812 813 // need to reset auto assigned ids, so there is no clash when creating routes 814 ProcessorDefinitionHelper.resetAllAutoAssignedNodeIds(routeDefinition); 815 } 816 817 // must ensure route is prepared, before we can start it 818 if (!routeDefinition.isPrepared()) { 819 RouteDefinitionHelper.prepareRoute(getCamelContextReference(), routeDefinition); 820 routeDefinition.markPrepared(); 821 } 822 823 StartupStepRecorder recorder 824 = getCamelContextReference().adapt(ExtendedCamelContext.class).getStartupStepRecorder(); 825 StartupStep step = recorder.beginStep(Route.class, routeDefinition.getRouteId(), "Create Route"); 826 Route route = model.getModelReifierFactory().createRoute(this, routeDefinition); 827 recorder.endStep(step); 828 829 RouteService routeService = new RouteService(route); 830 startRouteService(routeService, true); 831 832 // clear local after the route is created via the reifier 833 pc.setLocalProperties(null); 834 if (localBeans != null) { 835 localBeans.setLocalBeanRepository(null); 836 } 837 } 838 } finally { 839 if (!alreadyStartingRoutes) { 840 setStartingRoutes(false); 841 } 842 pc.setLocalProperties(null); 843 if (localBeans != null) { 844 localBeans.setLocalBeanRepository(null); 845 } 846 } 847 } 848 849 @Override 850 protected ExecutorServiceManager createExecutorServiceManager() { 851 return new DefaultExecutorServiceManager(this); 852 } 853 854 @Override 855 public Processor createErrorHandler(Route route, Processor processor) throws Exception { 856 if (model == null && isLightweight()) { 857 throw new IllegalStateException("Access to model not supported in lightweight mode"); 858 } 859 return model.getModelReifierFactory().createErrorHandler(route, processor); 860 } 861 862 @Override 863 public Expression createExpression(ExpressionDefinition definition) { 864 if (model == null && isLightweight()) { 865 throw new IllegalStateException("Access to model not supported in lightweight mode"); 866 } 867 return model.getModelReifierFactory().createExpression(this, definition); 868 } 869 870 @Override 871 public Predicate createPredicate(ExpressionDefinition definition) { 872 if (model == null && isLightweight()) { 873 throw new IllegalStateException("Access to model not supported in lightweight mode"); 874 } 875 return model.getModelReifierFactory().createPredicate(this, definition); 876 } 877 878 @Override 879 public RouteDefinition adviceWith(RouteDefinition definition, AdviceWithRouteBuilder builder) throws Exception { 880 return AdviceWith.adviceWith(definition, this, builder); 881 } 882 883 @Override 884 public void registerValidator(ValidatorDefinition def) { 885 if (model == null && isLightweight()) { 886 throw new IllegalStateException("Access to model not supported in lightweight mode"); 887 } 888 model.getValidators().add(def); 889 Validator validator = model.getModelReifierFactory().createValidator(this, def); 890 getValidatorRegistry().put(createValidatorKey(def), validator); 891 } 892 893 private static ValueHolder<String> createValidatorKey(ValidatorDefinition def) { 894 return new ValidatorKey(new DataType(def.getType())); 895 } 896 897 @Override 898 public void registerTransformer(TransformerDefinition def) { 899 if (model == null && isLightweight()) { 900 throw new IllegalStateException("Access to model not supported in lightweight mode"); 901 } 902 model.getTransformers().add(def); 903 Transformer transformer = model.getModelReifierFactory().createTransformer(this, def); 904 getTransformerRegistry().put(createTransformerKey(def), transformer); 905 } 906 907 private static ValueHolder<String> createTransformerKey(TransformerDefinition def) { 908 return ObjectHelper.isNotEmpty(def.getScheme()) 909 ? new TransformerKey(def.getScheme()) 910 : new TransformerKey(new DataType(def.getFromType()), new DataType(def.getToType())); 911 } 912 913 protected static class OptionHolder { 914 public boolean noStart; 915 public boolean disableJmx = Boolean.getBoolean(JmxSystemPropertyKeys.DISABLED); 916 public String excludeRoutes; 917 } 918}