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 */ 017 package org.apache.camel.impl; 018 019 import java.io.IOException; 020 import java.io.InputStream; 021 import java.util.ArrayList; 022 import java.util.Arrays; 023 import java.util.Collection; 024 import java.util.Collections; 025 import java.util.Date; 026 import java.util.HashMap; 027 import java.util.Iterator; 028 import java.util.LinkedHashMap; 029 import java.util.LinkedHashSet; 030 import java.util.List; 031 import java.util.Map; 032 import java.util.Properties; 033 import java.util.Set; 034 import java.util.TreeMap; 035 import java.util.concurrent.ScheduledExecutorService; 036 import java.util.concurrent.TimeUnit; 037 import java.util.concurrent.atomic.AtomicInteger; 038 import javax.naming.Context; 039 import javax.xml.bind.JAXBContext; 040 import javax.xml.bind.Unmarshaller; 041 042 import org.apache.camel.CamelContext; 043 import org.apache.camel.CamelContextAware; 044 import org.apache.camel.Component; 045 import org.apache.camel.Consumer; 046 import org.apache.camel.ConsumerTemplate; 047 import org.apache.camel.Endpoint; 048 import org.apache.camel.ErrorHandlerFactory; 049 import org.apache.camel.FailedToStartRouteException; 050 import org.apache.camel.IsSingleton; 051 import org.apache.camel.MultipleConsumersSupport; 052 import org.apache.camel.NoFactoryAvailableException; 053 import org.apache.camel.NoSuchEndpointException; 054 import org.apache.camel.Processor; 055 import org.apache.camel.Producer; 056 import org.apache.camel.ProducerTemplate; 057 import org.apache.camel.ResolveEndpointFailedException; 058 import org.apache.camel.Route; 059 import org.apache.camel.RoutesBuilder; 060 import org.apache.camel.RuntimeCamelException; 061 import org.apache.camel.Service; 062 import org.apache.camel.ServiceStatus; 063 import org.apache.camel.ShutdownRoute; 064 import org.apache.camel.ShutdownRunningTask; 065 import org.apache.camel.StartupListener; 066 import org.apache.camel.StatefulService; 067 import org.apache.camel.SuspendableService; 068 import org.apache.camel.TypeConverter; 069 import org.apache.camel.VetoCamelContextStartException; 070 import org.apache.camel.builder.ErrorHandlerBuilder; 071 import org.apache.camel.component.properties.PropertiesComponent; 072 import org.apache.camel.impl.converter.BaseTypeConverterRegistry; 073 import org.apache.camel.impl.converter.DefaultTypeConverter; 074 import org.apache.camel.impl.converter.LazyLoadingTypeConverter; 075 import org.apache.camel.management.DefaultManagementMBeanAssembler; 076 import org.apache.camel.management.DefaultManagementStrategy; 077 import org.apache.camel.management.JmxSystemPropertyKeys; 078 import org.apache.camel.management.ManagementStrategyFactory; 079 import org.apache.camel.model.Constants; 080 import org.apache.camel.model.DataFormatDefinition; 081 import org.apache.camel.model.ModelCamelContext; 082 import org.apache.camel.model.RouteDefinition; 083 import org.apache.camel.model.RouteDefinitionHelper; 084 import org.apache.camel.model.RoutesDefinition; 085 import org.apache.camel.processor.interceptor.BacklogDebugger; 086 import org.apache.camel.processor.interceptor.BacklogTracer; 087 import org.apache.camel.processor.interceptor.Debug; 088 import org.apache.camel.processor.interceptor.Delayer; 089 import org.apache.camel.processor.interceptor.HandleFault; 090 import org.apache.camel.processor.interceptor.StreamCaching; 091 import org.apache.camel.processor.interceptor.Tracer; 092 import org.apache.camel.spi.CamelContextNameStrategy; 093 import org.apache.camel.spi.ClassResolver; 094 import org.apache.camel.spi.ComponentResolver; 095 import org.apache.camel.spi.Container; 096 import org.apache.camel.spi.DataFormat; 097 import org.apache.camel.spi.DataFormatResolver; 098 import org.apache.camel.spi.Debugger; 099 import org.apache.camel.spi.EndpointStrategy; 100 import org.apache.camel.spi.EventNotifier; 101 import org.apache.camel.spi.ExecutorServiceManager; 102 import org.apache.camel.spi.FactoryFinder; 103 import org.apache.camel.spi.FactoryFinderResolver; 104 import org.apache.camel.spi.InflightRepository; 105 import org.apache.camel.spi.Injector; 106 import org.apache.camel.spi.InterceptStrategy; 107 import org.apache.camel.spi.Language; 108 import org.apache.camel.spi.LanguageResolver; 109 import org.apache.camel.spi.LifecycleStrategy; 110 import org.apache.camel.spi.ManagementMBeanAssembler; 111 import org.apache.camel.spi.ManagementNameStrategy; 112 import org.apache.camel.spi.ManagementStrategy; 113 import org.apache.camel.spi.NodeIdFactory; 114 import org.apache.camel.spi.PackageScanClassResolver; 115 import org.apache.camel.spi.ProcessorFactory; 116 import org.apache.camel.spi.Registry; 117 import org.apache.camel.spi.RouteContext; 118 import org.apache.camel.spi.RouteStartupOrder; 119 import org.apache.camel.spi.ServicePool; 120 import org.apache.camel.spi.ShutdownStrategy; 121 import org.apache.camel.spi.StreamCachingStrategy; 122 import org.apache.camel.spi.TypeConverterRegistry; 123 import org.apache.camel.spi.UnitOfWorkFactory; 124 import org.apache.camel.spi.UuidGenerator; 125 import org.apache.camel.support.ServiceSupport; 126 import org.apache.camel.util.CamelContextHelper; 127 import org.apache.camel.util.EndpointHelper; 128 import org.apache.camel.util.EventHelper; 129 import org.apache.camel.util.IOHelper; 130 import org.apache.camel.util.IntrospectionSupport; 131 import org.apache.camel.util.LoadPropertiesException; 132 import org.apache.camel.util.ObjectHelper; 133 import org.apache.camel.util.ServiceHelper; 134 import org.apache.camel.util.StopWatch; 135 import org.apache.camel.util.StringHelper; 136 import org.apache.camel.util.TimeUtils; 137 import org.apache.camel.util.URISupport; 138 import org.slf4j.Logger; 139 import org.slf4j.LoggerFactory; 140 141 /** 142 * Represents the context used to configure routes and the policies to use. 143 * 144 * @version 145 */ 146 @SuppressWarnings("deprecation") 147 public class DefaultCamelContext extends ServiceSupport implements ModelCamelContext, SuspendableService { 148 private final Logger log = LoggerFactory.getLogger(getClass()); 149 private JAXBContext jaxbContext; 150 private CamelContextNameStrategy nameStrategy = new DefaultCamelContextNameStrategy(); 151 private ManagementNameStrategy managementNameStrategy = new DefaultManagementNameStrategy(this); 152 private String managementName; 153 private ClassLoader applicationContextClassLoader; 154 private Map<EndpointKey, Endpoint> endpoints; 155 private final AtomicInteger endpointKeyCounter = new AtomicInteger(); 156 private final List<EndpointStrategy> endpointStrategies = new ArrayList<EndpointStrategy>(); 157 private final Map<String, Component> components = new HashMap<String, Component>(); 158 private final Set<Route> routes = new LinkedHashSet<Route>(); 159 private final List<Service> servicesToClose = new ArrayList<Service>(); 160 private final Set<StartupListener> startupListeners = new LinkedHashSet<StartupListener>(); 161 private TypeConverter typeConverter; 162 private TypeConverterRegistry typeConverterRegistry; 163 private Injector injector; 164 private ComponentResolver componentResolver; 165 private boolean autoCreateComponents = true; 166 private LanguageResolver languageResolver = new DefaultLanguageResolver(); 167 private final Map<String, Language> languages = new HashMap<String, Language>(); 168 private Registry registry; 169 private List<LifecycleStrategy> lifecycleStrategies = new ArrayList<LifecycleStrategy>(); 170 private ManagementStrategy managementStrategy; 171 private ManagementMBeanAssembler managementMBeanAssembler; 172 private final List<RouteDefinition> routeDefinitions = new ArrayList<RouteDefinition>(); 173 private List<InterceptStrategy> interceptStrategies = new ArrayList<InterceptStrategy>(); 174 175 // special flags to control the first startup which can are special 176 private volatile boolean firstStartDone; 177 private volatile boolean doNotStartRoutesOnFirstStart; 178 private final ThreadLocal<Boolean> isStartingRoutes = new ThreadLocal<Boolean>(); 179 private Boolean autoStartup = Boolean.TRUE; 180 private Boolean trace = Boolean.FALSE; 181 private Boolean messageHistory = Boolean.TRUE; 182 private Boolean streamCache = Boolean.FALSE; 183 private Boolean handleFault = Boolean.FALSE; 184 private Boolean disableJMX = Boolean.FALSE; 185 private Boolean lazyLoadTypeConverters = Boolean.FALSE; 186 private Boolean typeConverterStatisticsEnabled = Boolean.FALSE; 187 private Boolean useMDCLogging = Boolean.FALSE; 188 private Boolean useBreadcrumb = Boolean.TRUE; 189 private Boolean allowUseOriginalMessage = Boolean.TRUE; 190 private Long delay; 191 private ErrorHandlerFactory errorHandlerBuilder; 192 private final Object errorHandlerExecutorServiceLock = new Object(); 193 private ScheduledExecutorService errorHandlerExecutorService; 194 private Map<String, DataFormatDefinition> dataFormats = new HashMap<String, DataFormatDefinition>(); 195 private DataFormatResolver dataFormatResolver = new DefaultDataFormatResolver(); 196 private Map<String, String> properties = new HashMap<String, String>(); 197 private FactoryFinderResolver factoryFinderResolver = new DefaultFactoryFinderResolver(); 198 private FactoryFinder defaultFactoryFinder; 199 private PropertiesComponent propertiesComponent; 200 private StreamCachingStrategy streamCachingStrategy; 201 private final Map<String, FactoryFinder> factories = new HashMap<String, FactoryFinder>(); 202 private final Map<String, RouteService> routeServices = new LinkedHashMap<String, RouteService>(); 203 private final Map<String, RouteService> suspendedRouteServices = new LinkedHashMap<String, RouteService>(); 204 private ClassResolver classResolver = new DefaultClassResolver(); 205 private PackageScanClassResolver packageScanClassResolver; 206 // we use a capacity of 100 per endpoint, so for the same endpoint we have at most 100 producers in the pool 207 // so if we have 6 endpoints in the pool, we can have 6 x 100 producers in total 208 private ServicePool<Endpoint, Producer> producerServicePool = new SharedProducerServicePool(100); 209 private NodeIdFactory nodeIdFactory = new DefaultNodeIdFactory(); 210 private ProcessorFactory processorFactory; 211 private InterceptStrategy defaultTracer; 212 private InterceptStrategy defaultBacklogTracer; 213 private InterceptStrategy defaultBacklogDebugger; 214 private InflightRepository inflightRepository = new DefaultInflightRepository(); 215 private final List<RouteStartupOrder> routeStartupOrder = new ArrayList<RouteStartupOrder>(); 216 // start auto assigning route ids using numbering 1000 and upwards 217 private int defaultRouteStartupOrder = 1000; 218 private ShutdownStrategy shutdownStrategy = new DefaultShutdownStrategy(this); 219 private ShutdownRoute shutdownRoute = ShutdownRoute.Default; 220 private ShutdownRunningTask shutdownRunningTask = ShutdownRunningTask.CompleteCurrentTaskOnly; 221 private ExecutorServiceManager executorServiceManager; 222 private Debugger debugger; 223 private UuidGenerator uuidGenerator = createDefaultUuidGenerator(); 224 private UnitOfWorkFactory unitOfWorkFactory = new DefaultUnitOfWorkFactory(); 225 private final StopWatch stopWatch = new StopWatch(false); 226 private Date startDate; 227 228 /** 229 * Creates the {@link CamelContext} using {@link JndiRegistry} as registry, 230 * but will silently fallback and use {@link SimpleRegistry} if JNDI cannot be used. 231 * <p/> 232 * Use one of the other constructors to force use an explicit registry / JNDI. 233 */ 234 public DefaultCamelContext() { 235 this.executorServiceManager = new DefaultExecutorServiceManager(this); 236 237 // create endpoint registry at first since end users may access endpoints before CamelContext is started 238 this.endpoints = new EndpointRegistry(this); 239 240 // use WebSphere specific resolver if running on WebSphere 241 if (WebSpherePackageScanClassResolver.isWebSphereClassLoader(this.getClass().getClassLoader())) { 242 log.info("Using WebSphere specific PackageScanClassResolver"); 243 packageScanClassResolver = new WebSpherePackageScanClassResolver("META-INF/services/org/apache/camel/TypeConverter"); 244 } else { 245 packageScanClassResolver = new DefaultPackageScanClassResolver(); 246 } 247 248 // setup management strategy first since end users may use it to add event notifiers 249 // using the management strategy before the CamelContext has been started 250 this.managementStrategy = createManagementStrategy(); 251 this.managementMBeanAssembler = createManagementMBeanAssembler(); 252 253 Container.Instance.manage(this); 254 } 255 256 /** 257 * Creates the {@link CamelContext} using the given JNDI context as the registry 258 * 259 * @param jndiContext the JNDI context 260 */ 261 public DefaultCamelContext(Context jndiContext) { 262 this(); 263 setJndiContext(jndiContext); 264 } 265 266 /** 267 * Creates the {@link CamelContext} using the given registry 268 * 269 * @param registry the registry 270 */ 271 public DefaultCamelContext(Registry registry) { 272 this(); 273 setRegistry(registry); 274 } 275 276 public String getName() { 277 return getNameStrategy().getName(); 278 } 279 280 /** 281 * Sets the name of the this context. 282 * 283 * @param name the name 284 */ 285 public void setName(String name) { 286 // use an explicit name strategy since an explicit name was provided to be used 287 this.nameStrategy = new ExplicitCamelContextNameStrategy(name); 288 } 289 290 public CamelContextNameStrategy getNameStrategy() { 291 return nameStrategy; 292 } 293 294 public void setNameStrategy(CamelContextNameStrategy nameStrategy) { 295 this.nameStrategy = nameStrategy; 296 } 297 298 public ManagementNameStrategy getManagementNameStrategy() { 299 return managementNameStrategy; 300 } 301 302 public void setManagementNameStrategy(ManagementNameStrategy managementNameStrategy) { 303 this.managementNameStrategy = managementNameStrategy; 304 } 305 306 public String getManagementName() { 307 return managementName; 308 } 309 310 public void setManagementName(String managementName) { 311 this.managementName = managementName; 312 } 313 314 public Component hasComponent(String componentName) { 315 return components.get(componentName); 316 } 317 318 public void addComponent(String componentName, final Component component) { 319 ObjectHelper.notNull(component, "component"); 320 synchronized (components) { 321 if (components.containsKey(componentName)) { 322 throw new IllegalArgumentException("Cannot add component as its already previously added: " + componentName); 323 } 324 component.setCamelContext(this); 325 components.put(componentName, component); 326 for (LifecycleStrategy strategy : lifecycleStrategies) { 327 strategy.onComponentAdd(componentName, component); 328 } 329 330 // keep reference to properties component up to date 331 if (component instanceof PropertiesComponent && "properties".equals(componentName)) { 332 propertiesComponent = (PropertiesComponent) component; 333 } 334 } 335 } 336 337 public Component getComponent(String name) { 338 return getComponent(name, autoCreateComponents); 339 } 340 341 public Component getComponent(String name, boolean autoCreateComponents) { 342 // synchronize the look up and auto create so that 2 threads can't 343 // concurrently auto create the same component. 344 synchronized (components) { 345 Component component = components.get(name); 346 if (component == null && autoCreateComponents) { 347 try { 348 if (log.isDebugEnabled()) { 349 log.debug("Using ComponentResolver: {} to resolve component with name: {}", getComponentResolver(), name); 350 } 351 component = getComponentResolver().resolveComponent(name, this); 352 if (component != null) { 353 addComponent(name, component); 354 if (isStarted() || isStarting()) { 355 // If the component is looked up after the context is started, lets start it up. 356 if (component instanceof Service) { 357 startService((Service)component); 358 } 359 } 360 } 361 } catch (Exception e) { 362 throw new RuntimeCamelException("Cannot auto create component: " + name, e); 363 } 364 } 365 log.trace("getComponent({}) -> {}", name, component); 366 return component; 367 } 368 } 369 370 public <T extends Component> T getComponent(String name, Class<T> componentType) { 371 Component component = getComponent(name); 372 if (componentType.isInstance(component)) { 373 return componentType.cast(component); 374 } else { 375 String message; 376 if (component == null) { 377 message = "Did not find component given by the name: " + name; 378 } else { 379 message = "Found component of type: " + component.getClass() + " instead of expected: " + componentType; 380 } 381 throw new IllegalArgumentException(message); 382 } 383 } 384 385 public Component removeComponent(String componentName) { 386 synchronized (components) { 387 Component oldComponent = components.remove(componentName); 388 if (oldComponent != null) { 389 try { 390 stopServices(oldComponent); 391 } catch (Exception e) { 392 log.warn("Error stopping component " + oldComponent + ". This exception will be ignored.", e); 393 } 394 for (LifecycleStrategy strategy : lifecycleStrategies) { 395 strategy.onComponentRemove(componentName, oldComponent); 396 } 397 } 398 // keep reference to properties component up to date 399 if (oldComponent != null && "properties".equals(componentName)) { 400 propertiesComponent = null; 401 } 402 return oldComponent; 403 } 404 } 405 406 // Endpoint Management Methods 407 // ----------------------------------------------------------------------- 408 409 public Collection<Endpoint> getEndpoints() { 410 return new ArrayList<Endpoint>(endpoints.values()); 411 } 412 413 public Map<String, Endpoint> getEndpointMap() { 414 Map<String, Endpoint> answer = new TreeMap<String, Endpoint>(); 415 for (Map.Entry<EndpointKey, Endpoint> entry : endpoints.entrySet()) { 416 answer.put(entry.getKey().get(), entry.getValue()); 417 } 418 return answer; 419 } 420 421 public Endpoint hasEndpoint(String uri) { 422 return endpoints.get(getEndpointKey(uri)); 423 } 424 425 public Endpoint addEndpoint(String uri, Endpoint endpoint) throws Exception { 426 Endpoint oldEndpoint; 427 428 startService(endpoint); 429 oldEndpoint = endpoints.remove(getEndpointKey(uri)); 430 for (LifecycleStrategy strategy : lifecycleStrategies) { 431 strategy.onEndpointAdd(endpoint); 432 } 433 addEndpointToRegistry(uri, endpoint); 434 if (oldEndpoint != null) { 435 stopServices(oldEndpoint); 436 } 437 438 return oldEndpoint; 439 } 440 441 public Collection<Endpoint> removeEndpoints(String uri) throws Exception { 442 Collection<Endpoint> answer = new ArrayList<Endpoint>(); 443 Endpoint oldEndpoint = endpoints.remove(getEndpointKey(uri)); 444 if (oldEndpoint != null) { 445 answer.add(oldEndpoint); 446 stopServices(oldEndpoint); 447 } else { 448 for (Map.Entry<EndpointKey, Endpoint> entry : endpoints.entrySet()) { 449 oldEndpoint = entry.getValue(); 450 if (EndpointHelper.matchEndpoint(this, oldEndpoint.getEndpointUri(), uri)) { 451 try { 452 stopServices(oldEndpoint); 453 } catch (Exception e) { 454 log.warn("Error stopping endpoint " + oldEndpoint + ". This exception will be ignored.", e); 455 } 456 answer.add(oldEndpoint); 457 endpoints.remove(entry.getKey()); 458 } 459 } 460 } 461 462 // notify lifecycle its being removed 463 for (Endpoint endpoint : answer) { 464 for (LifecycleStrategy strategy : lifecycleStrategies) { 465 strategy.onEndpointRemove(endpoint); 466 } 467 } 468 469 return answer; 470 } 471 472 public Endpoint getEndpoint(String uri) { 473 ObjectHelper.notEmpty(uri, "uri"); 474 475 log.trace("Getting endpoint with uri: {}", uri); 476 477 // in case path has property placeholders then try to let property component resolve those 478 try { 479 uri = resolvePropertyPlaceholders(uri); 480 } catch (Exception e) { 481 throw new ResolveEndpointFailedException(uri, e); 482 } 483 484 final String rawUri = uri; 485 486 // normalize uri so we can do endpoint hits with minor mistakes and parameters is not in the same order 487 uri = normalizeEndpointUri(uri); 488 489 log.trace("Getting endpoint with raw uri: {}, normalized uri: {}", rawUri, uri); 490 491 Endpoint answer; 492 String scheme = null; 493 EndpointKey key = getEndpointKey(uri); 494 answer = endpoints.get(key); 495 if (answer == null) { 496 try { 497 // Use the URI prefix to find the component. 498 String splitURI[] = ObjectHelper.splitOnCharacter(uri, ":", 2); 499 if (splitURI[1] != null) { 500 scheme = splitURI[0]; 501 log.trace("Endpoint uri: {} is from component with name: {}", uri, scheme); 502 Component component = getComponent(scheme); 503 504 // Ask the component to resolve the endpoint. 505 if (component != null) { 506 log.trace("Creating endpoint from uri: {} using component: {}", uri, component); 507 508 // Have the component create the endpoint if it can. 509 if (component.useRawUri()) { 510 answer = component.createEndpoint(rawUri); 511 } else { 512 answer = component.createEndpoint(uri); 513 } 514 515 if (answer != null && log.isDebugEnabled()) { 516 log.debug("{} converted to endpoint: {} by component: {}", new Object[]{URISupport.sanitizeUri(uri), answer, component}); 517 } 518 } 519 } 520 521 if (answer == null) { 522 // no component then try in registry and elsewhere 523 answer = createEndpoint(uri); 524 log.trace("No component to create endpoint from uri: {} fallback lookup in registry -> {}", uri, answer); 525 } 526 527 if (answer != null) { 528 addService(answer); 529 answer = addEndpointToRegistry(uri, answer); 530 } 531 } catch (Exception e) { 532 throw new ResolveEndpointFailedException(uri, e); 533 } 534 } 535 536 // unknown scheme 537 if (answer == null && scheme != null) { 538 throw new ResolveEndpointFailedException(uri, "No component found with scheme: " + scheme); 539 } 540 541 return answer; 542 } 543 544 public <T extends Endpoint> T getEndpoint(String name, Class<T> endpointType) { 545 Endpoint endpoint = getEndpoint(name); 546 if (endpoint == null) { 547 throw new NoSuchEndpointException(name); 548 } 549 if (endpoint instanceof InterceptSendToEndpoint) { 550 endpoint = ((InterceptSendToEndpoint) endpoint).getDelegate(); 551 } 552 if (endpointType.isInstance(endpoint)) { 553 return endpointType.cast(endpoint); 554 } else { 555 throw new IllegalArgumentException("The endpoint is not of type: " + endpointType 556 + " but is: " + endpoint.getClass().getCanonicalName()); 557 } 558 } 559 560 public void addRegisterEndpointCallback(EndpointStrategy strategy) { 561 if (!endpointStrategies.contains(strategy)) { 562 // let it be invoked for already registered endpoints so it can catch-up. 563 endpointStrategies.add(strategy); 564 for (Endpoint endpoint : getEndpoints()) { 565 Endpoint newEndpoint = strategy.registerEndpoint(endpoint.getEndpointUri(), endpoint); 566 if (newEndpoint != null) { 567 // put will replace existing endpoint with the new endpoint 568 endpoints.put(getEndpointKey(endpoint.getEndpointUri()), newEndpoint); 569 } 570 } 571 } 572 } 573 574 /** 575 * Strategy to add the given endpoint to the internal endpoint registry 576 * 577 * @param uri uri of the endpoint 578 * @param endpoint the endpoint to add 579 * @return the added endpoint 580 */ 581 protected Endpoint addEndpointToRegistry(String uri, Endpoint endpoint) { 582 ObjectHelper.notEmpty(uri, "uri"); 583 ObjectHelper.notNull(endpoint, "endpoint"); 584 585 // if there is endpoint strategies, then use the endpoints they return 586 // as this allows to intercept endpoints etc. 587 for (EndpointStrategy strategy : endpointStrategies) { 588 endpoint = strategy.registerEndpoint(uri, endpoint); 589 } 590 endpoints.put(getEndpointKey(uri, endpoint), endpoint); 591 return endpoint; 592 } 593 594 /** 595 * Normalize uri so we can do endpoint hits with minor mistakes and parameters is not in the same order. 596 * 597 * @param uri the uri 598 * @return normalized uri 599 * @throws ResolveEndpointFailedException if uri cannot be normalized 600 */ 601 protected static String normalizeEndpointUri(String uri) { 602 try { 603 uri = URISupport.normalizeUri(uri); 604 } catch (Exception e) { 605 throw new ResolveEndpointFailedException(uri, e); 606 } 607 return uri; 608 } 609 610 /** 611 * Gets the endpoint key to use for lookup or whe adding endpoints to the {@link EndpointRegistry} 612 * 613 * @param uri the endpoint uri 614 * @return the key 615 */ 616 protected EndpointKey getEndpointKey(String uri) { 617 return new EndpointKey(uri); 618 } 619 620 /** 621 * Gets the endpoint key to use for lookup or whe adding endpoints to the {@link EndpointRegistry} 622 * 623 * @param uri the endpoint uri 624 * @param endpoint the endpoint 625 * @return the key 626 */ 627 protected EndpointKey getEndpointKey(String uri, Endpoint endpoint) { 628 if (endpoint != null && !endpoint.isSingleton()) { 629 int counter = endpointKeyCounter.incrementAndGet(); 630 return new EndpointKey(uri + ":" + counter); 631 } else { 632 return new EndpointKey(uri); 633 } 634 } 635 636 // Route Management Methods 637 // ----------------------------------------------------------------------- 638 639 public List<RouteStartupOrder> getRouteStartupOrder() { 640 return routeStartupOrder; 641 } 642 643 public List<Route> getRoutes() { 644 // lets return a copy of the collection as objects are removed later when services are stopped 645 if (routes.isEmpty()) { 646 return Collections.emptyList(); 647 } else { 648 return new ArrayList<Route>(routes); 649 } 650 } 651 652 public Route getRoute(String id) { 653 for (Route route : getRoutes()) { 654 if (route.getId().equals(id)) { 655 return route; 656 } 657 } 658 return null; 659 } 660 661 @Deprecated 662 public void setRoutes(List<Route> routes) { 663 throw new UnsupportedOperationException("Overriding existing routes is not supported yet, use addRouteCollection instead"); 664 } 665 666 synchronized void removeRouteCollection(Collection<Route> routes) { 667 this.routes.removeAll(routes); 668 } 669 670 synchronized void addRouteCollection(Collection<Route> routes) throws Exception { 671 this.routes.addAll(routes); 672 } 673 674 public void addRoutes(RoutesBuilder builder) throws Exception { 675 log.debug("Adding routes from builder: {}", builder); 676 // lets now add the routes from the builder 677 builder.addRoutesToCamelContext(this); 678 } 679 680 public synchronized RoutesDefinition loadRoutesDefinition(InputStream is) throws Exception { 681 // load routes using JAXB 682 if (jaxbContext == null) { 683 // must use classloader from CamelContext to have JAXB working 684 jaxbContext = JAXBContext.newInstance(Constants.JAXB_CONTEXT_PACKAGES, CamelContext.class.getClassLoader()); 685 } 686 687 Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); 688 Object result = unmarshaller.unmarshal(is); 689 690 if (result == null) { 691 throw new IOException("Cannot unmarshal to routes using JAXB from input stream: " + is); 692 } 693 694 // can either be routes or a single route 695 RoutesDefinition answer = null; 696 if (result instanceof RouteDefinition) { 697 RouteDefinition route = (RouteDefinition) result; 698 answer = new RoutesDefinition(); 699 answer.getRoutes().add(route); 700 } else if (result instanceof RoutesDefinition) { 701 answer = (RoutesDefinition) result; 702 } else { 703 throw new IllegalArgumentException("Unmarshalled object is an unsupported type: " + ObjectHelper.className(result) + " -> " + result); 704 } 705 706 return answer; 707 } 708 709 public synchronized void addRouteDefinitions(Collection<RouteDefinition> routeDefinitions) throws Exception { 710 for (RouteDefinition routeDefinition : routeDefinitions) { 711 removeRouteDefinition(routeDefinition); 712 } 713 this.routeDefinitions.addAll(routeDefinitions); 714 if (shouldStartRoutes()) { 715 startRouteDefinitions(routeDefinitions); 716 } 717 } 718 719 public void addRouteDefinition(RouteDefinition routeDefinition) throws Exception { 720 addRouteDefinitions(Arrays.asList(routeDefinition)); 721 } 722 723 /** 724 * Removes the route definition with the given key. 725 * 726 * @return true if one or more routes was removed 727 */ 728 protected boolean removeRouteDefinition(String key) { 729 boolean answer = false; 730 Iterator<RouteDefinition> iter = routeDefinitions.iterator(); 731 while (iter.hasNext()) { 732 RouteDefinition route = iter.next(); 733 if (route.idOrCreate(nodeIdFactory).equals(key)) { 734 iter.remove(); 735 answer = true; 736 } 737 } 738 return answer; 739 } 740 741 public synchronized void removeRouteDefinitions(Collection<RouteDefinition> routeDefinitions) throws Exception { 742 for (RouteDefinition routeDefinition : routeDefinitions) { 743 removeRouteDefinition(routeDefinition); 744 } 745 } 746 747 public synchronized void removeRouteDefinition(RouteDefinition routeDefinition) throws Exception { 748 String id = routeDefinition.idOrCreate(nodeIdFactory); 749 stopRoute(id); 750 removeRoute(id); 751 this.routeDefinitions.remove(routeDefinition); 752 } 753 754 public ServiceStatus getRouteStatus(String key) { 755 RouteService routeService = routeServices.get(key); 756 if (routeService != null) { 757 return routeService.getStatus(); 758 } 759 return null; 760 } 761 762 public void startRoute(RouteDefinition route) throws Exception { 763 // assign ids to the routes and validate that the id's is all unique 764 RouteDefinitionHelper.forceAssignIds(this, routeDefinitions); 765 String duplicate = RouteDefinitionHelper.validateUniqueIds(route, routeDefinitions); 766 if (duplicate != null) { 767 throw new FailedToStartRouteException(route.getId(), "duplicate id detected: " + duplicate + ". Please correct ids to be unique among all your routes."); 768 } 769 770 // indicate we are staring the route using this thread so 771 // we are able to query this if needed 772 isStartingRoutes.set(true); 773 try { 774 // must ensure route is prepared, before we can start it 775 route.prepare(this); 776 777 List<Route> routes = new ArrayList<Route>(); 778 List<RouteContext> routeContexts = route.addRoutes(this, routes); 779 RouteService routeService = new RouteService(this, route, routeContexts, routes); 780 startRouteService(routeService, true); 781 } finally { 782 // we are done staring routes 783 isStartingRoutes.remove(); 784 } 785 } 786 787 public boolean isStartingRoutes() { 788 Boolean answer = isStartingRoutes.get(); 789 return answer != null && answer; 790 } 791 792 public void stopRoute(RouteDefinition route) throws Exception { 793 stopRoute(route.idOrCreate(nodeIdFactory)); 794 } 795 796 public synchronized void startRoute(String routeId) throws Exception { 797 RouteService routeService = routeServices.get(routeId); 798 if (routeService != null) { 799 startRouteService(routeService, false); 800 } 801 } 802 803 public synchronized void resumeRoute(String routeId) throws Exception { 804 if (!routeSupportsSuspension(routeId)) { 805 // start route if suspension is not supported 806 startRoute(routeId); 807 return; 808 } 809 810 RouteService routeService = routeServices.get(routeId); 811 if (routeService != null) { 812 resumeRouteService(routeService); 813 } 814 } 815 816 public synchronized boolean stopRoute(String routeId, long timeout, TimeUnit timeUnit, boolean abortAfterTimeout) throws Exception { 817 RouteService routeService = routeServices.get(routeId); 818 if (routeService != null) { 819 RouteStartupOrder route = new DefaultRouteStartupOrder(1, routeService.getRoutes().iterator().next(), routeService); 820 821 boolean completed = getShutdownStrategy().shutdown(this, route, timeout, timeUnit, abortAfterTimeout); 822 if (completed) { 823 // must stop route service as well 824 stopRouteService(routeService, false); 825 } else { 826 // shutdown was aborted, make sure route is re-started properly 827 startRouteService(routeService, false); 828 } 829 return completed; 830 } 831 return false; 832 } 833 834 public synchronized void stopRoute(String routeId) throws Exception { 835 RouteService routeService = routeServices.get(routeId); 836 if (routeService != null) { 837 List<RouteStartupOrder> routes = new ArrayList<RouteStartupOrder>(1); 838 RouteStartupOrder order = new DefaultRouteStartupOrder(1, routeService.getRoutes().iterator().next(), routeService); 839 routes.add(order); 840 841 getShutdownStrategy().shutdown(this, routes); 842 // must stop route service as well 843 stopRouteService(routeService, false); 844 } 845 } 846 847 public synchronized void stopRoute(String routeId, long timeout, TimeUnit timeUnit) throws Exception { 848 RouteService routeService = routeServices.get(routeId); 849 if (routeService != null) { 850 List<RouteStartupOrder> routes = new ArrayList<RouteStartupOrder>(1); 851 RouteStartupOrder order = new DefaultRouteStartupOrder(1, routeService.getRoutes().iterator().next(), routeService); 852 routes.add(order); 853 854 getShutdownStrategy().shutdown(this, routes, timeout, timeUnit); 855 // must stop route service as well 856 stopRouteService(routeService, false); 857 } 858 } 859 860 public synchronized void shutdownRoute(String routeId) throws Exception { 861 RouteService routeService = routeServices.get(routeId); 862 if (routeService != null) { 863 List<RouteStartupOrder> routes = new ArrayList<RouteStartupOrder>(1); 864 RouteStartupOrder order = new DefaultRouteStartupOrder(1, routeService.getRoutes().iterator().next(), routeService); 865 routes.add(order); 866 867 getShutdownStrategy().shutdown(this, routes); 868 // must stop route service as well (and remove the routes from management) 869 stopRouteService(routeService, true); 870 } 871 } 872 873 public synchronized void shutdownRoute(String routeId, long timeout, TimeUnit timeUnit) throws Exception { 874 RouteService routeService = routeServices.get(routeId); 875 if (routeService != null) { 876 List<RouteStartupOrder> routes = new ArrayList<RouteStartupOrder>(1); 877 RouteStartupOrder order = new DefaultRouteStartupOrder(1, routeService.getRoutes().iterator().next(), routeService); 878 routes.add(order); 879 880 getShutdownStrategy().shutdown(this, routes, timeout, timeUnit); 881 // must stop route service as well (and remove the routes from management) 882 stopRouteService(routeService, true); 883 } 884 } 885 886 public synchronized boolean removeRoute(String routeId) throws Exception { 887 RouteService routeService = routeServices.get(routeId); 888 if (routeService != null) { 889 if (getRouteStatus(routeId).isStopped()) { 890 routeService.setRemovingRoutes(true); 891 shutdownRouteService(routeService); 892 removeRouteDefinition(routeId); 893 routeServices.remove(routeId); 894 // remove route from startup order as well, as it was removed 895 Iterator<RouteStartupOrder> it = routeStartupOrder.iterator(); 896 while (it.hasNext()) { 897 RouteStartupOrder order = it.next(); 898 if (order.getRoute().getId().equals(routeId)) { 899 it.remove(); 900 } 901 } 902 return true; 903 } else { 904 return false; 905 } 906 } 907 return false; 908 } 909 910 public synchronized void suspendRoute(String routeId) throws Exception { 911 if (!routeSupportsSuspension(routeId)) { 912 // stop if we suspend is not supported 913 stopRoute(routeId); 914 return; 915 } 916 917 RouteService routeService = routeServices.get(routeId); 918 if (routeService != null) { 919 List<RouteStartupOrder> routes = new ArrayList<RouteStartupOrder>(1); 920 RouteStartupOrder order = new DefaultRouteStartupOrder(1, routeService.getRoutes().iterator().next(), routeService); 921 routes.add(order); 922 923 getShutdownStrategy().suspend(this, routes); 924 // must suspend route service as well 925 suspendRouteService(routeService); 926 } 927 } 928 929 public synchronized void suspendRoute(String routeId, long timeout, TimeUnit timeUnit) throws Exception { 930 if (!routeSupportsSuspension(routeId)) { 931 stopRoute(routeId, timeout, timeUnit); 932 return; 933 } 934 935 RouteService routeService = routeServices.get(routeId); 936 if (routeService != null) { 937 List<RouteStartupOrder> routes = new ArrayList<RouteStartupOrder>(1); 938 RouteStartupOrder order = new DefaultRouteStartupOrder(1, routeService.getRoutes().iterator().next(), routeService); 939 routes.add(order); 940 941 getShutdownStrategy().suspend(this, routes, timeout, timeUnit); 942 // must suspend route service as well 943 suspendRouteService(routeService); 944 } 945 } 946 947 public void addService(Object object) throws Exception { 948 doAddService(object, true); 949 } 950 951 private void doAddService(Object object, boolean closeOnShutdown) throws Exception { 952 // inject CamelContext 953 if (object instanceof CamelContextAware) { 954 CamelContextAware aware = (CamelContextAware) object; 955 aware.setCamelContext(this); 956 } 957 958 if (object instanceof Service) { 959 Service service = (Service) object; 960 961 for (LifecycleStrategy strategy : lifecycleStrategies) { 962 if (service instanceof Endpoint) { 963 // use specialized endpoint add 964 strategy.onEndpointAdd((Endpoint) service); 965 } else { 966 strategy.onServiceAdd(this, service, null); 967 } 968 } 969 970 // only add to services to close if its a singleton 971 // otherwise we could for example end up with a lot of prototype scope endpoints 972 boolean singleton = true; // assume singleton by default 973 if (service instanceof IsSingleton) { 974 singleton = ((IsSingleton) service).isSingleton(); 975 } 976 // do not add endpoints as they have their own list 977 if (singleton && !(service instanceof Endpoint)) { 978 // only add to list of services to close if its not already there 979 if (closeOnShutdown && !hasService(service)) { 980 servicesToClose.add(service); 981 } 982 } 983 } 984 985 // and then ensure service is started (as stated in the javadoc) 986 if (object instanceof Service) { 987 startService((Service)object); 988 } else if (object instanceof Collection<?>) { 989 startServices((Collection<?>)object); 990 } 991 } 992 993 public boolean removeService(Object object) throws Exception { 994 if (object instanceof Service) { 995 Service service = (Service) object; 996 997 for (LifecycleStrategy strategy : lifecycleStrategies) { 998 if (service instanceof Endpoint) { 999 // use specialized endpoint remove 1000 strategy.onEndpointRemove((Endpoint) service); 1001 } else { 1002 strategy.onServiceRemove(this, service, null); 1003 } 1004 } 1005 return servicesToClose.remove(service); 1006 } 1007 return false; 1008 } 1009 1010 public boolean hasService(Object object) { 1011 if (object instanceof Service) { 1012 Service service = (Service) object; 1013 return servicesToClose.contains(service); 1014 } 1015 return false; 1016 } 1017 1018 public void addStartupListener(StartupListener listener) throws Exception { 1019 // either add to listener so we can invoke then later when CamelContext has been started 1020 // or invoke the callback right now 1021 if (isStarted()) { 1022 listener.onCamelContextStarted(this, true); 1023 } else { 1024 startupListeners.add(listener); 1025 } 1026 } 1027 1028 public Map<String, Properties> findComponents() throws LoadPropertiesException, IOException { 1029 return CamelContextHelper.findComponents(this); 1030 } 1031 1032 public String getComponentDocumentation(String componentName) throws IOException { 1033 String packageName = sanitizeComponentName(componentName); 1034 String path = CamelContextHelper.COMPONENT_DOCUMENTATION_PREFIX + packageName + "/" + componentName + ".html"; 1035 ClassResolver resolver = getClassResolver(); 1036 InputStream inputStream = resolver.loadResourceAsStream(path); 1037 log.debug("Loading component documentation for: {} using class resolver: {} -> {}", new Object[]{componentName, resolver, inputStream}); 1038 if (inputStream != null) { 1039 try { 1040 return IOHelper.loadText(inputStream); 1041 } finally { 1042 IOHelper.close(inputStream); 1043 } 1044 } 1045 return null; 1046 } 1047 1048 /** 1049 * Sanitizes the component name by removing dash (-) in the name, when using the component name to load 1050 * resources from the classpath. 1051 */ 1052 private static String sanitizeComponentName(String componentName) { 1053 // the ftp components are in a special package 1054 if ("ftp".equals(componentName) || "ftps".equals(componentName) || "sftp".equals(componentName)) { 1055 return "file/remote"; 1056 } 1057 return componentName.replaceAll("-", ""); 1058 } 1059 1060 public String createRouteStaticEndpointJson(String routeId) { 1061 List<RouteDefinition> routes = new ArrayList<RouteDefinition>(); 1062 if (routeId != null) { 1063 RouteDefinition route = getRouteDefinition(routeId); 1064 if (route == null) { 1065 throw new IllegalArgumentException("Route with id " + routeId + " does not exist"); 1066 } 1067 routes.add(route); 1068 } else { 1069 routes.addAll(getRouteDefinitions()); 1070 } 1071 1072 StringBuilder buffer = new StringBuilder("{\n \"routes\": {"); 1073 boolean firstRoute = true; 1074 for (RouteDefinition route : routes) { 1075 if (!firstRoute) { 1076 buffer.append("\n },"); 1077 } else { 1078 firstRoute = false; 1079 } 1080 1081 String id = route.getId(); 1082 buffer.append("\n \"" + id + "\": {"); 1083 buffer.append("\n \"inputs\": ["); 1084 Set<String> inputs = RouteDefinitionHelper.gatherAllStaticEndpointUris(route, true, false); 1085 boolean first = true; 1086 for (String input : inputs) { 1087 if (!first) { 1088 buffer.append(","); 1089 } else { 1090 first = false; 1091 } 1092 buffer.append("\n "); 1093 buffer.append(StringHelper.toJson("uri", input, true)); 1094 } 1095 buffer.append("\n ]"); 1096 1097 buffer.append(","); 1098 buffer.append("\n \"outputs\": ["); 1099 Set<String> outputs = RouteDefinitionHelper.gatherAllStaticEndpointUris(route, false, true); 1100 first = true; 1101 for (String output : outputs) { 1102 if (!first) { 1103 buffer.append(","); 1104 } else { 1105 first = false; 1106 } 1107 buffer.append("\n "); 1108 buffer.append(StringHelper.toJson("uri", output, true)); 1109 } 1110 buffer.append("\n ]"); 1111 } 1112 buffer.append("\n }"); 1113 buffer.append("\n }\n}\n"); 1114 1115 return buffer.toString(); 1116 } 1117 1118 // Helper methods 1119 // ----------------------------------------------------------------------- 1120 1121 public Language resolveLanguage(String language) { 1122 Language answer; 1123 synchronized (languages) { 1124 answer = languages.get(language); 1125 1126 // check if the language is singleton, if so return the shared instance 1127 if (answer instanceof IsSingleton) { 1128 boolean singleton = ((IsSingleton) answer).isSingleton(); 1129 if (singleton) { 1130 return answer; 1131 } 1132 } 1133 1134 // language not known or not singleton, then use resolver 1135 answer = getLanguageResolver().resolveLanguage(language, this); 1136 1137 // inject CamelContext if aware 1138 if (answer != null) { 1139 if (answer instanceof CamelContextAware) { 1140 ((CamelContextAware) answer).setCamelContext(this); 1141 } 1142 if (answer instanceof Service) { 1143 try { 1144 startService((Service) answer); 1145 } catch (Exception e) { 1146 throw ObjectHelper.wrapRuntimeCamelException(e); 1147 } 1148 } 1149 1150 languages.put(language, answer); 1151 } 1152 } 1153 1154 // no language resolved 1155 return answer; 1156 } 1157 1158 public String getPropertyPrefixToken() { 1159 PropertiesComponent pc = getPropertiesComponent(); 1160 1161 if (pc != null) { 1162 return pc.getPrefixToken(); 1163 } else { 1164 return null; 1165 } 1166 } 1167 1168 public String getPropertySuffixToken() { 1169 PropertiesComponent pc = getPropertiesComponent(); 1170 1171 if (pc != null) { 1172 return pc.getSuffixToken(); 1173 } else { 1174 return null; 1175 } 1176 } 1177 1178 public String resolvePropertyPlaceholders(String text) throws Exception { 1179 // While it is more efficient to only do the lookup if we are sure we need the component, 1180 // with custom tokens, we cannot know if the URI contains a property or not without having 1181 // the component. We also lose fail-fast behavior for the missing component with this change. 1182 PropertiesComponent pc = getPropertiesComponent(); 1183 1184 // Do not parse uris that are designated for the properties component as it will handle that itself 1185 if (text != null && !text.startsWith("properties:")) { 1186 // No component, assume default tokens. 1187 if (pc == null && text.contains(PropertiesComponent.DEFAULT_PREFIX_TOKEN)) { 1188 1189 // try to lookup component, as we may be initializing CamelContext itself 1190 Component existing = lookupPropertiesComponent(); 1191 if (existing != null) { 1192 if (existing instanceof PropertiesComponent) { 1193 pc = (PropertiesComponent) existing; 1194 } else { 1195 // properties component must be expected type 1196 throw new IllegalArgumentException("Found properties component of type: " + existing.getClass() + " instead of expected: " + PropertiesComponent.class); 1197 } 1198 } 1199 1200 if (pc != null) { 1201 // the parser will throw exception if property key was not found 1202 String answer = pc.parseUri(text); 1203 log.debug("Resolved text: {} -> {}", text, answer); 1204 return answer; 1205 } else { 1206 throw new IllegalArgumentException("PropertiesComponent with name properties must be defined" 1207 + " in CamelContext to support property placeholders."); 1208 } 1209 1210 // Component available, use actual tokens 1211 } else if (pc != null && text.contains(pc.getPrefixToken())) { 1212 // the parser will throw exception if property key was not found 1213 String answer = pc.parseUri(text); 1214 log.debug("Resolved text: {} -> {}", text, answer); 1215 return answer; 1216 } 1217 } 1218 1219 // return original text as is 1220 return text; 1221 } 1222 1223 // Properties 1224 // ----------------------------------------------------------------------- 1225 1226 public TypeConverter getTypeConverter() { 1227 if (typeConverter == null) { 1228 synchronized (this) { 1229 // we can synchronize on this as there is only one instance 1230 // of the camel context (its the container) 1231 typeConverter = createTypeConverter(); 1232 try { 1233 // must add service eager 1234 addService(typeConverter); 1235 } catch (Exception e) { 1236 throw ObjectHelper.wrapRuntimeCamelException(e); 1237 } 1238 } 1239 } 1240 return typeConverter; 1241 } 1242 1243 public void setTypeConverter(TypeConverter typeConverter) { 1244 this.typeConverter = typeConverter; 1245 try { 1246 // must add service eager 1247 addService(typeConverter); 1248 } catch (Exception e) { 1249 throw ObjectHelper.wrapRuntimeCamelException(e); 1250 } 1251 } 1252 1253 public TypeConverterRegistry getTypeConverterRegistry() { 1254 if (typeConverterRegistry == null) { 1255 // init type converter as its lazy 1256 if (typeConverter == null) { 1257 getTypeConverter(); 1258 } 1259 if (typeConverter instanceof TypeConverterRegistry) { 1260 typeConverterRegistry = (TypeConverterRegistry) typeConverter; 1261 } 1262 } 1263 return typeConverterRegistry; 1264 } 1265 1266 public void setTypeConverterRegistry(TypeConverterRegistry typeConverterRegistry) { 1267 this.typeConverterRegistry = typeConverterRegistry; 1268 } 1269 1270 public Injector getInjector() { 1271 if (injector == null) { 1272 injector = createInjector(); 1273 } 1274 return injector; 1275 } 1276 1277 public void setInjector(Injector injector) { 1278 this.injector = injector; 1279 } 1280 1281 public ManagementMBeanAssembler getManagementMBeanAssembler() { 1282 return managementMBeanAssembler; 1283 } 1284 1285 public void setManagementMBeanAssembler(ManagementMBeanAssembler managementMBeanAssembler) { 1286 this.managementMBeanAssembler = managementMBeanAssembler; 1287 } 1288 1289 public ComponentResolver getComponentResolver() { 1290 if (componentResolver == null) { 1291 componentResolver = createComponentResolver(); 1292 } 1293 return componentResolver; 1294 } 1295 1296 public void setComponentResolver(ComponentResolver componentResolver) { 1297 this.componentResolver = componentResolver; 1298 } 1299 1300 public LanguageResolver getLanguageResolver() { 1301 if (languageResolver == null) { 1302 languageResolver = new DefaultLanguageResolver(); 1303 } 1304 return languageResolver; 1305 } 1306 1307 public void setLanguageResolver(LanguageResolver languageResolver) { 1308 this.languageResolver = languageResolver; 1309 } 1310 1311 public boolean isAutoCreateComponents() { 1312 return autoCreateComponents; 1313 } 1314 1315 public void setAutoCreateComponents(boolean autoCreateComponents) { 1316 this.autoCreateComponents = autoCreateComponents; 1317 } 1318 1319 public Registry getRegistry() { 1320 if (registry == null) { 1321 registry = createRegistry(); 1322 setRegistry(registry); 1323 } 1324 return registry; 1325 } 1326 1327 public <T> T getRegistry(Class<T> type) { 1328 Registry reg = getRegistry(); 1329 1330 // unwrap the property placeholder delegate 1331 if (reg instanceof PropertyPlaceholderDelegateRegistry) { 1332 reg = ((PropertyPlaceholderDelegateRegistry) reg).getRegistry(); 1333 } 1334 1335 if (type.isAssignableFrom(reg.getClass())) { 1336 return type.cast(reg); 1337 } else if (reg instanceof CompositeRegistry) { 1338 List<Registry> list = ((CompositeRegistry) reg).getRegistryList(); 1339 for (Registry r : list) { 1340 if (type.isAssignableFrom(r.getClass())) { 1341 return type.cast(r); 1342 } 1343 } 1344 } 1345 return null; 1346 } 1347 1348 /** 1349 * Sets the registry to the given JNDI context 1350 * 1351 * @param jndiContext is the JNDI context to use as the registry 1352 * @see #setRegistry(org.apache.camel.spi.Registry) 1353 */ 1354 public void setJndiContext(Context jndiContext) { 1355 setRegistry(new JndiRegistry(jndiContext)); 1356 } 1357 1358 public void setRegistry(Registry registry) { 1359 // wrap the registry so we always do property placeholder lookups 1360 if (!(registry instanceof PropertyPlaceholderDelegateRegistry)) { 1361 registry = new PropertyPlaceholderDelegateRegistry(this, registry); 1362 } 1363 this.registry = registry; 1364 } 1365 1366 public List<LifecycleStrategy> getLifecycleStrategies() { 1367 return lifecycleStrategies; 1368 } 1369 1370 public void setLifecycleStrategies(List<LifecycleStrategy> lifecycleStrategies) { 1371 this.lifecycleStrategies = lifecycleStrategies; 1372 } 1373 1374 public void addLifecycleStrategy(LifecycleStrategy lifecycleStrategy) { 1375 this.lifecycleStrategies.add(lifecycleStrategy); 1376 } 1377 1378 public synchronized List<RouteDefinition> getRouteDefinitions() { 1379 return routeDefinitions; 1380 } 1381 1382 public synchronized RouteDefinition getRouteDefinition(String id) { 1383 for (RouteDefinition route : routeDefinitions) { 1384 if (route.getId().equals(id)) { 1385 return route; 1386 } 1387 } 1388 return null; 1389 } 1390 1391 public List<InterceptStrategy> getInterceptStrategies() { 1392 return interceptStrategies; 1393 } 1394 1395 public void setInterceptStrategies(List<InterceptStrategy> interceptStrategies) { 1396 this.interceptStrategies = interceptStrategies; 1397 } 1398 1399 public void addInterceptStrategy(InterceptStrategy interceptStrategy) { 1400 getInterceptStrategies().add(interceptStrategy); 1401 1402 // for backwards compatible or if user add them here instead of the setXXX methods 1403 1404 if (interceptStrategy instanceof Tracer) { 1405 setTracing(true); 1406 } else if (interceptStrategy instanceof HandleFault) { 1407 setHandleFault(true); 1408 } else if (interceptStrategy instanceof StreamCaching) { 1409 setStreamCaching(true); 1410 } else if (interceptStrategy instanceof Delayer) { 1411 setDelayer(((Delayer)interceptStrategy).getDelay()); 1412 } 1413 } 1414 1415 public void setStreamCaching(Boolean cache) { 1416 this.streamCache = cache; 1417 } 1418 1419 public Boolean isStreamCaching() { 1420 return streamCache; 1421 } 1422 1423 public void setTracing(Boolean tracing) { 1424 this.trace = tracing; 1425 } 1426 1427 public Boolean isTracing() { 1428 return trace; 1429 } 1430 1431 public Boolean isMessageHistory() { 1432 return messageHistory; 1433 } 1434 1435 public void setMessageHistory(Boolean messageHistory) { 1436 this.messageHistory = messageHistory; 1437 } 1438 1439 public Boolean isHandleFault() { 1440 return handleFault; 1441 } 1442 1443 public void setHandleFault(Boolean handleFault) { 1444 this.handleFault = handleFault; 1445 } 1446 1447 public Long getDelayer() { 1448 return delay; 1449 } 1450 1451 public void setDelayer(Long delay) { 1452 this.delay = delay; 1453 } 1454 1455 public ProducerTemplate createProducerTemplate() { 1456 int size = CamelContextHelper.getMaximumCachePoolSize(this); 1457 return createProducerTemplate(size); 1458 } 1459 1460 public ProducerTemplate createProducerTemplate(int maximumCacheSize) { 1461 DefaultProducerTemplate answer = new DefaultProducerTemplate(this); 1462 answer.setMaximumCacheSize(maximumCacheSize); 1463 // start it so its ready to use 1464 try { 1465 startService(answer); 1466 } catch (Exception e) { 1467 throw ObjectHelper.wrapRuntimeCamelException(e); 1468 } 1469 return answer; 1470 } 1471 1472 public ConsumerTemplate createConsumerTemplate() { 1473 int size = CamelContextHelper.getMaximumCachePoolSize(this); 1474 return createConsumerTemplate(size); 1475 } 1476 1477 public ConsumerTemplate createConsumerTemplate(int maximumCacheSize) { 1478 DefaultConsumerTemplate answer = new DefaultConsumerTemplate(this); 1479 answer.setMaximumCacheSize(maximumCacheSize); 1480 // start it so its ready to use 1481 try { 1482 startService(answer); 1483 } catch (Exception e) { 1484 throw ObjectHelper.wrapRuntimeCamelException(e); 1485 } 1486 return answer; 1487 } 1488 1489 public ErrorHandlerBuilder getErrorHandlerBuilder() { 1490 return (ErrorHandlerBuilder)errorHandlerBuilder; 1491 } 1492 1493 public void setErrorHandlerBuilder(ErrorHandlerFactory errorHandlerBuilder) { 1494 this.errorHandlerBuilder = errorHandlerBuilder; 1495 } 1496 1497 public ScheduledExecutorService getErrorHandlerExecutorService() { 1498 synchronized (errorHandlerExecutorServiceLock) { 1499 if (errorHandlerExecutorService == null) { 1500 // setup default thread pool for error handler 1501 errorHandlerExecutorService = getExecutorServiceManager().newDefaultScheduledThreadPool("ErrorHandlerRedeliveryThreadPool", "ErrorHandlerRedeliveryTask"); 1502 } 1503 } 1504 return errorHandlerExecutorService; 1505 } 1506 1507 public void setProducerServicePool(ServicePool<Endpoint, Producer> producerServicePool) { 1508 this.producerServicePool = producerServicePool; 1509 } 1510 1511 public ServicePool<Endpoint, Producer> getProducerServicePool() { 1512 return producerServicePool; 1513 } 1514 1515 public UnitOfWorkFactory getUnitOfWorkFactory() { 1516 return unitOfWorkFactory; 1517 } 1518 1519 public void setUnitOfWorkFactory(UnitOfWorkFactory unitOfWorkFactory) { 1520 this.unitOfWorkFactory = unitOfWorkFactory; 1521 } 1522 1523 public String getUptime() { 1524 // compute and log uptime 1525 if (startDate == null) { 1526 return "not started"; 1527 } 1528 long delta = new Date().getTime() - startDate.getTime(); 1529 return TimeUtils.printDuration(delta); 1530 } 1531 1532 @Override 1533 protected void doSuspend() throws Exception { 1534 EventHelper.notifyCamelContextSuspending(this); 1535 1536 log.info("Apache Camel " + getVersion() + " (CamelContext: " + getName() + ") is suspending"); 1537 StopWatch watch = new StopWatch(); 1538 1539 // update list of started routes to be suspended 1540 // because we only want to suspend started routes 1541 // (so when we resume we only resume the routes which actually was suspended) 1542 for (Map.Entry<String, RouteService> entry : getRouteServices().entrySet()) { 1543 if (entry.getValue().getStatus().isStarted()) { 1544 suspendedRouteServices.put(entry.getKey(), entry.getValue()); 1545 } 1546 } 1547 1548 // assemble list of startup ordering so routes can be shutdown accordingly 1549 List<RouteStartupOrder> orders = new ArrayList<RouteStartupOrder>(); 1550 for (Map.Entry<String, RouteService> entry : suspendedRouteServices.entrySet()) { 1551 Route route = entry.getValue().getRoutes().iterator().next(); 1552 Integer order = entry.getValue().getRouteDefinition().getStartupOrder(); 1553 if (order == null) { 1554 order = defaultRouteStartupOrder++; 1555 } 1556 orders.add(new DefaultRouteStartupOrder(order, route, entry.getValue())); 1557 } 1558 1559 // suspend routes using the shutdown strategy so it can shutdown in correct order 1560 // routes which doesn't support suspension will be stopped instead 1561 getShutdownStrategy().suspend(this, orders); 1562 1563 // mark the route services as suspended or stopped 1564 for (RouteService service : suspendedRouteServices.values()) { 1565 if (routeSupportsSuspension(service.getId())) { 1566 service.suspend(); 1567 } else { 1568 service.stop(); 1569 } 1570 } 1571 1572 watch.stop(); 1573 if (log.isInfoEnabled()) { 1574 log.info("Apache Camel " + getVersion() + " (CamelContext: " + getName() + ") is suspended in " + TimeUtils.printDuration(watch.taken())); 1575 } 1576 1577 EventHelper.notifyCamelContextSuspended(this); 1578 } 1579 1580 @Override 1581 protected void doResume() throws Exception { 1582 try { 1583 EventHelper.notifyCamelContextResuming(this); 1584 1585 log.info("Apache Camel " + getVersion() + " (CamelContext: " + getName() + ") is resuming"); 1586 StopWatch watch = new StopWatch(); 1587 1588 // start the suspended routes (do not check for route clashes, and indicate) 1589 doStartOrResumeRoutes(suspendedRouteServices, false, true, true, false); 1590 1591 // mark the route services as resumed (will be marked as started) as well 1592 for (RouteService service : suspendedRouteServices.values()) { 1593 if (routeSupportsSuspension(service.getId())) { 1594 service.resume(); 1595 } else { 1596 service.start(); 1597 } 1598 } 1599 1600 watch.stop(); 1601 if (log.isInfoEnabled()) { 1602 log.info("Resumed " + suspendedRouteServices.size() + " routes"); 1603 log.info("Apache Camel " + getVersion() + " (CamelContext: " + getName() + ") resumed in " + TimeUtils.printDuration(watch.taken())); 1604 } 1605 1606 // and clear the list as they have been resumed 1607 suspendedRouteServices.clear(); 1608 1609 EventHelper.notifyCamelContextResumed(this); 1610 } catch (Exception e) { 1611 EventHelper.notifyCamelContextResumeFailed(this, e); 1612 throw e; 1613 } 1614 } 1615 1616 public void start() throws Exception { 1617 startDate = new Date(); 1618 stopWatch.restart(); 1619 log.info("Apache Camel " + getVersion() + " (CamelContext: " + getName() + ") is starting"); 1620 1621 doNotStartRoutesOnFirstStart = !firstStartDone && !isAutoStartup(); 1622 1623 // if the context was configured with auto startup = false, and we are already started, 1624 // then we may need to start the routes on the 2nd start call 1625 if (firstStartDone && !isAutoStartup() && isStarted()) { 1626 // invoke this logic to warm up the routes and if possible also start the routes 1627 doStartOrResumeRoutes(routeServices, true, true, false, true); 1628 } 1629 1630 // super will invoke doStart which will prepare internal services and start routes etc. 1631 try { 1632 firstStartDone = true; 1633 super.start(); 1634 } catch (VetoCamelContextStartException e) { 1635 if (e.isRethrowException()) { 1636 throw e; 1637 } else { 1638 log.info("CamelContext ({}) vetoed to not start due {}", getName(), e.getMessage()); 1639 // swallow exception and change state of this camel context to stopped 1640 stop(); 1641 return; 1642 } 1643 } 1644 1645 stopWatch.stop(); 1646 if (log.isInfoEnabled()) { 1647 // count how many routes are actually started 1648 int started = 0; 1649 for (Route route : getRoutes()) { 1650 if (getRouteStatus(route.getId()).isStarted()) { 1651 started++; 1652 } 1653 } 1654 log.info("Total " + getRoutes().size() + " routes, of which " + started + " is started."); 1655 log.info("Apache Camel " + getVersion() + " (CamelContext: " + getName() + ") started in " + TimeUtils.printDuration(stopWatch.taken())); 1656 } 1657 EventHelper.notifyCamelContextStarted(this); 1658 } 1659 1660 // Implementation methods 1661 // ----------------------------------------------------------------------- 1662 1663 protected synchronized void doStart() throws Exception { 1664 try { 1665 doStartCamel(); 1666 } catch (Exception e) { 1667 // fire event that we failed to start 1668 EventHelper.notifyCamelContextStartupFailed(this, e); 1669 // rethrow cause 1670 throw e; 1671 } 1672 } 1673 1674 private void doStartCamel() throws Exception { 1675 if (applicationContextClassLoader == null) { 1676 // use the classloader that loaded this class 1677 setApplicationContextClassLoader(this.getClass().getClassLoader()); 1678 } 1679 1680 if (log.isDebugEnabled()) { 1681 log.debug("Using ClassResolver={}, PackageScanClassResolver={}, ApplicationContextClassLoader={}", 1682 new Object[]{getClassResolver(), getPackageScanClassResolver(), getApplicationContextClassLoader()}); 1683 } 1684 1685 if (isStreamCaching()) { 1686 log.info("StreamCaching is enabled on CamelContext: {}", getName()); 1687 } 1688 1689 if (isTracing()) { 1690 // tracing is added in the DefaultChannel so we can enable it on the fly 1691 log.info("Tracing is enabled on CamelContext: {}", getName()); 1692 } 1693 1694 if (isUseMDCLogging()) { 1695 // log if MDC has been enabled 1696 log.info("MDC logging is enabled on CamelContext: {}", getName()); 1697 } 1698 1699 if (isHandleFault()) { 1700 // only add a new handle fault if not already configured 1701 if (HandleFault.getHandleFault(this) == null) { 1702 log.info("HandleFault is enabled on CamelContext: {}", getName()); 1703 addInterceptStrategy(new HandleFault()); 1704 } 1705 } 1706 1707 if (getDelayer() != null && getDelayer() > 0) { 1708 log.info("Delayer is enabled with: {} ms. on CamelContext: {}", getDelayer(), getName()); 1709 } 1710 1711 // register debugger 1712 if (getDebugger() != null) { 1713 log.info("Debugger: {} is enabled on CamelContext: {}", getDebugger(), getName()); 1714 // register this camel context on the debugger 1715 getDebugger().setCamelContext(this); 1716 startService(getDebugger()); 1717 addInterceptStrategy(new Debug(getDebugger())); 1718 } 1719 1720 // start management strategy before lifecycles are started 1721 ManagementStrategy managementStrategy = getManagementStrategy(); 1722 // inject CamelContext if aware 1723 if (managementStrategy instanceof CamelContextAware) { 1724 ((CamelContextAware) managementStrategy).setCamelContext(this); 1725 } 1726 ServiceHelper.startService(managementStrategy); 1727 1728 // start lifecycle strategies 1729 ServiceHelper.startServices(lifecycleStrategies); 1730 Iterator<LifecycleStrategy> it = lifecycleStrategies.iterator(); 1731 while (it.hasNext()) { 1732 LifecycleStrategy strategy = it.next(); 1733 try { 1734 strategy.onContextStart(this); 1735 } catch (VetoCamelContextStartException e) { 1736 // okay we should not start Camel since it was vetoed 1737 log.warn("Lifecycle strategy vetoed starting CamelContext ({}) due {}", getName(), e.getMessage()); 1738 throw e; 1739 } catch (Exception e) { 1740 log.warn("Lifecycle strategy " + strategy + " failed starting CamelContext ({}) due {}", getName(), e.getMessage()); 1741 throw e; 1742 } 1743 } 1744 1745 // start notifiers as services 1746 for (EventNotifier notifier : getManagementStrategy().getEventNotifiers()) { 1747 if (notifier instanceof Service) { 1748 Service service = (Service) notifier; 1749 for (LifecycleStrategy strategy : lifecycleStrategies) { 1750 strategy.onServiceAdd(this, service, null); 1751 } 1752 } 1753 if (notifier instanceof Service) { 1754 startService((Service)notifier); 1755 } 1756 } 1757 1758 // must let some bootstrap service be started before we can notify the starting event 1759 EventHelper.notifyCamelContextStarting(this); 1760 1761 forceLazyInitialization(); 1762 1763 // re-create endpoint registry as the cache size limit may be set after the constructor of this instance was called. 1764 // and we needed to create endpoints up-front as it may be accessed before this context is started 1765 endpoints = new EndpointRegistry(this, endpoints); 1766 addService(endpoints); 1767 // special for executorServiceManager as want to stop it manually 1768 doAddService(executorServiceManager, false); 1769 addService(producerServicePool); 1770 addService(inflightRepository); 1771 addService(shutdownStrategy); 1772 addService(packageScanClassResolver); 1773 1774 // eager lookup any configured properties component to avoid subsequent lookup attempts which may impact performance 1775 // due we use properties component for property placeholder resolution at runtime 1776 Component existing = lookupPropertiesComponent(); 1777 if (existing != null) { 1778 // store reference to the existing properties component 1779 if (existing instanceof PropertiesComponent) { 1780 propertiesComponent = (PropertiesComponent) existing; 1781 } else { 1782 // properties component must be expected type 1783 throw new IllegalArgumentException("Found properties component of type: " + existing.getClass() + " instead of expected: " + PropertiesComponent.class); 1784 } 1785 } 1786 1787 // start components 1788 startServices(components.values()); 1789 1790 // start the route definitions before the routes is started 1791 startRouteDefinitions(routeDefinitions); 1792 1793 // is there any stream caching enabled then log an info about this and its limit of spooling to disk, so people is aware of this 1794 boolean streamCachingInUse = isStreamCaching(); 1795 if (!streamCachingInUse) { 1796 for (RouteDefinition route : routeDefinitions) { 1797 Boolean routeCache = CamelContextHelper.parseBoolean(this, route.getStreamCache()); 1798 if (routeCache != null && routeCache) { 1799 streamCachingInUse = true; 1800 break; 1801 } 1802 } 1803 } 1804 1805 if (isAllowUseOriginalMessage()) { 1806 log.info("AllowUseOriginalMessage is enabled. If access to the original message is not needed," 1807 + " then its recommended to turn this option off as it may improve performance."); 1808 } 1809 1810 if (streamCachingInUse) { 1811 // stream caching is in use so enable the strategy 1812 getStreamCachingStrategy().setEnabled(true); 1813 addService(getStreamCachingStrategy()); 1814 } else { 1815 // log if stream caching is not in use as this can help people to enable it if they use streams 1816 log.info("StreamCaching is not in use. If using streams then its recommended to enable stream caching." 1817 + " See more details at http://camel.apache.org/stream-caching.html"); 1818 } 1819 1820 // start routes 1821 if (doNotStartRoutesOnFirstStart) { 1822 log.debug("Skip starting of routes as CamelContext has been configured with autoStartup=false"); 1823 } 1824 1825 // invoke this logic to warmup the routes and if possible also start the routes 1826 doStartOrResumeRoutes(routeServices, true, !doNotStartRoutesOnFirstStart, false, true); 1827 1828 // starting will continue in the start method 1829 } 1830 1831 protected synchronized void doStop() throws Exception { 1832 stopWatch.restart(); 1833 log.info("Apache Camel " + getVersion() + " (CamelContext: " + getName() + ") is shutting down"); 1834 EventHelper.notifyCamelContextStopping(this); 1835 1836 // stop route inputs in the same order as they was started so we stop the very first inputs first 1837 try { 1838 // force shutting down routes as they may otherwise cause shutdown to hang 1839 shutdownStrategy.shutdownForced(this, getRouteStartupOrder()); 1840 } catch (Throwable e) { 1841 log.warn("Error occurred while shutting down routes. This exception will be ignored.", e); 1842 } 1843 getRouteStartupOrder().clear(); 1844 1845 shutdownServices(routeServices.values()); 1846 // do not clear route services or startup listeners as we can start Camel again and get the route back as before 1847 1848 // but clear any suspend routes 1849 suspendedRouteServices.clear(); 1850 1851 // the stop order is important 1852 1853 // shutdown default error handler thread pool 1854 if (errorHandlerExecutorService != null) { 1855 // force shutting down the thread pool 1856 getExecutorServiceManager().shutdownNow(errorHandlerExecutorService); 1857 errorHandlerExecutorService = null; 1858 } 1859 1860 // shutdown debugger 1861 ServiceHelper.stopAndShutdownService(getDebugger()); 1862 1863 shutdownServices(endpoints.values()); 1864 endpoints.clear(); 1865 1866 shutdownServices(components.values()); 1867 components.clear(); 1868 1869 shutdownServices(languages.values()); 1870 languages.clear(); 1871 1872 try { 1873 for (LifecycleStrategy strategy : lifecycleStrategies) { 1874 strategy.onContextStop(this); 1875 } 1876 } catch (Throwable e) { 1877 log.warn("Error occurred while stopping lifecycle strategies. This exception will be ignored.", e); 1878 } 1879 1880 // shutdown services as late as possible 1881 shutdownServices(servicesToClose); 1882 servicesToClose.clear(); 1883 1884 // must notify that we are stopped before stopping the management strategy 1885 EventHelper.notifyCamelContextStopped(this); 1886 1887 // stop the notifier service 1888 for (EventNotifier notifier : getManagementStrategy().getEventNotifiers()) { 1889 shutdownServices(notifier); 1890 } 1891 1892 // shutdown executor service and management as the last one 1893 shutdownServices(executorServiceManager); 1894 shutdownServices(managementStrategy); 1895 shutdownServices(managementMBeanAssembler); 1896 shutdownServices(lifecycleStrategies); 1897 // do not clear lifecycleStrategies as we can start Camel again and get the route back as before 1898 1899 // stop the lazy created so they can be re-created on restart 1900 forceStopLazyInitialization(); 1901 1902 // stop to clear introspection cache 1903 IntrospectionSupport.stop(); 1904 1905 stopWatch.stop(); 1906 if (log.isInfoEnabled()) { 1907 log.info("Apache Camel " + getVersion() + " (CamelContext: " + getName() + ") uptime {}", getUptime()); 1908 log.info("Apache Camel " + getVersion() + " (CamelContext: " + getName() + ") is shutdown in " + TimeUtils.printDuration(stopWatch.taken())); 1909 } 1910 1911 // and clear start date 1912 startDate = null; 1913 } 1914 1915 /** 1916 * Starts or resumes the routes 1917 * 1918 * @param routeServices the routes to start (will only start a route if its not already started) 1919 * @param checkClash whether to check for startup ordering clash 1920 * @param startConsumer whether the route consumer should be started. Can be used to warmup the route without starting the consumer. 1921 * @param resumeConsumer whether the route consumer should be resumed. 1922 * @param addingRoutes whether we are adding new routes 1923 * @throws Exception is thrown if error starting routes 1924 */ 1925 protected void doStartOrResumeRoutes(Map<String, RouteService> routeServices, boolean checkClash, 1926 boolean startConsumer, boolean resumeConsumer, boolean addingRoutes) throws Exception { 1927 // filter out already started routes 1928 Map<String, RouteService> filtered = new LinkedHashMap<String, RouteService>(); 1929 for (Map.Entry<String, RouteService> entry : routeServices.entrySet()) { 1930 boolean startable = false; 1931 1932 Consumer consumer = entry.getValue().getRoutes().iterator().next().getConsumer(); 1933 if (consumer instanceof SuspendableService) { 1934 // consumer could be suspended, which is not reflected in the RouteService status 1935 startable = ((SuspendableService) consumer).isSuspended(); 1936 } 1937 1938 if (!startable && consumer instanceof StatefulService) { 1939 // consumer could be stopped, which is not reflected in the RouteService status 1940 startable = ((StatefulService) consumer).getStatus().isStartable(); 1941 } else if (!startable) { 1942 // no consumer so use state from route service 1943 startable = entry.getValue().getStatus().isStartable(); 1944 } 1945 1946 if (startable) { 1947 filtered.put(entry.getKey(), entry.getValue()); 1948 } 1949 } 1950 1951 if (!filtered.isEmpty()) { 1952 // the context is now considered started (i.e. isStarted() == true)) 1953 // starting routes is done after, not during context startup 1954 safelyStartRouteServices(checkClash, startConsumer, resumeConsumer, addingRoutes, filtered.values()); 1955 } 1956 1957 // now notify any startup aware listeners as all the routes etc has been started, 1958 // allowing the listeners to do custom work after routes has been started 1959 for (StartupListener startup : startupListeners) { 1960 startup.onCamelContextStarted(this, isStarted()); 1961 } 1962 } 1963 1964 protected boolean routeSupportsSuspension(String routeId) { 1965 RouteService routeService = routeServices.get(routeId); 1966 if (routeService != null) { 1967 return routeService.getRoutes().iterator().next().supportsSuspension(); 1968 } 1969 return false; 1970 } 1971 1972 private void shutdownServices(Object service) { 1973 // do not rethrow exception as we want to keep shutting down in case of problems 1974 1975 // allow us to do custom work before delegating to service helper 1976 try { 1977 if (service instanceof Service) { 1978 ServiceHelper.stopAndShutdownService(service); 1979 } else if (service instanceof Collection) { 1980 ServiceHelper.stopAndShutdownServices((Collection<?>)service); 1981 } 1982 } catch (Throwable e) { 1983 log.warn("Error occurred while shutting down service: " + service + ". This exception will be ignored.", e); 1984 // fire event 1985 EventHelper.notifyServiceStopFailure(this, service, e); 1986 } 1987 } 1988 1989 private void shutdownServices(Collection<?> services) { 1990 // reverse stopping by default 1991 shutdownServices(services, true); 1992 } 1993 1994 private void shutdownServices(Collection<?> services, boolean reverse) { 1995 Collection<?> list = services; 1996 if (reverse) { 1997 List<Object> reverseList = new ArrayList<Object>(services); 1998 Collections.reverse(reverseList); 1999 list = reverseList; 2000 } 2001 2002 for (Object service : list) { 2003 shutdownServices(service); 2004 } 2005 } 2006 2007 private void startService(Service service) throws Exception { 2008 // and register startup aware so they can be notified when 2009 // camel context has been started 2010 if (service instanceof StartupListener) { 2011 StartupListener listener = (StartupListener) service; 2012 addStartupListener(listener); 2013 } 2014 2015 service.start(); 2016 } 2017 2018 private void startServices(Collection<?> services) throws Exception { 2019 for (Object element : services) { 2020 if (element instanceof Service) { 2021 startService((Service)element); 2022 } 2023 } 2024 } 2025 2026 private void stopServices(Object service) throws Exception { 2027 // allow us to do custom work before delegating to service helper 2028 try { 2029 ServiceHelper.stopService(service); 2030 } catch (Exception e) { 2031 // fire event 2032 EventHelper.notifyServiceStopFailure(this, service, e); 2033 // rethrow to signal error with stopping 2034 throw e; 2035 } 2036 } 2037 2038 protected void startRouteDefinitions(Collection<RouteDefinition> list) throws Exception { 2039 if (list != null) { 2040 for (RouteDefinition route : list) { 2041 startRoute(route); 2042 } 2043 } 2044 } 2045 2046 /** 2047 * Starts the given route service 2048 */ 2049 protected synchronized void startRouteService(RouteService routeService, boolean addingRoutes) throws Exception { 2050 // we may already be starting routes so remember this, so we can unset accordingly in finally block 2051 boolean alreadyStartingRoutes = isStartingRoutes(); 2052 if (!alreadyStartingRoutes) { 2053 isStartingRoutes.set(true); 2054 } 2055 2056 try { 2057 // the route service could have been suspended, and if so then resume it instead 2058 if (routeService.getStatus().isSuspended()) { 2059 resumeRouteService(routeService); 2060 } else { 2061 // start the route service 2062 routeServices.put(routeService.getId(), routeService); 2063 if (shouldStartRoutes()) { 2064 // this method will log the routes being started 2065 safelyStartRouteServices(true, true, true, false, addingRoutes, routeService); 2066 // start route services if it was configured to auto startup and we are not adding routes 2067 boolean autoStartup = routeService.getRouteDefinition().isAutoStartup(this); 2068 if (!addingRoutes || autoStartup) { 2069 // start the route since auto start is enabled or we are starting a route (not adding new routes) 2070 routeService.start(); 2071 } 2072 } 2073 } 2074 } finally { 2075 if (!alreadyStartingRoutes) { 2076 isStartingRoutes.remove(); 2077 } 2078 } 2079 } 2080 2081 /** 2082 * Resumes the given route service 2083 */ 2084 protected synchronized void resumeRouteService(RouteService routeService) throws Exception { 2085 // the route service could have been stopped, and if so then start it instead 2086 if (!routeService.getStatus().isSuspended()) { 2087 startRouteService(routeService, false); 2088 } else { 2089 // resume the route service 2090 if (shouldStartRoutes()) { 2091 // this method will log the routes being started 2092 safelyStartRouteServices(true, false, true, true, false, routeService); 2093 // must resume route service as well 2094 routeService.resume(); 2095 } 2096 } 2097 } 2098 2099 protected synchronized void stopRouteService(RouteService routeService, boolean removingRoutes) throws Exception { 2100 routeService.setRemovingRoutes(removingRoutes); 2101 stopRouteService(routeService); 2102 } 2103 2104 protected void logRouteState(Route route, String state) { 2105 if (log.isInfoEnabled()) { 2106 if (route.getConsumer() != null) { 2107 log.info("Route: {} is {}, was consuming from: {}", new Object[]{route.getId(), state, route.getConsumer().getEndpoint()}); 2108 } else { 2109 log.info("Route: {} is {}.", route.getId(), state); 2110 } 2111 } 2112 } 2113 2114 protected synchronized void stopRouteService(RouteService routeService) throws Exception { 2115 routeService.stop(); 2116 for (Route route : routeService.getRoutes()) { 2117 logRouteState(route, "stopped"); 2118 } 2119 } 2120 2121 protected synchronized void shutdownRouteService(RouteService routeService) throws Exception { 2122 routeService.shutdown(); 2123 for (Route route : routeService.getRoutes()) { 2124 logRouteState(route, "shutdown and removed"); 2125 } 2126 } 2127 2128 protected synchronized void suspendRouteService(RouteService routeService) throws Exception { 2129 routeService.setRemovingRoutes(false); 2130 routeService.suspend(); 2131 for (Route route : routeService.getRoutes()) { 2132 logRouteState(route, "suspended"); 2133 } 2134 } 2135 2136 /** 2137 * Starts the routes services in a proper manner which ensures the routes will be started in correct order, 2138 * check for clash and that the routes will also be shutdown in correct order as well. 2139 * <p/> 2140 * This method <b>must</b> be used to start routes in a safe manner. 2141 * 2142 * @param checkClash whether to check for startup order clash 2143 * @param startConsumer whether the route consumer should be started. Can be used to warmup the route without starting the consumer. 2144 * @param resumeConsumer whether the route consumer should be resumed. 2145 * @param addingRoutes whether we are adding new routes 2146 * @param routeServices the routes 2147 * @throws Exception is thrown if error starting the routes 2148 */ 2149 protected synchronized void safelyStartRouteServices(boolean checkClash, boolean startConsumer, boolean resumeConsumer, 2150 boolean addingRoutes, Collection<RouteService> routeServices) throws Exception { 2151 // list of inputs to start when all the routes have been prepared for starting 2152 // we use a tree map so the routes will be ordered according to startup order defined on the route 2153 Map<Integer, DefaultRouteStartupOrder> inputs = new TreeMap<Integer, DefaultRouteStartupOrder>(); 2154 2155 // figure out the order in which the routes should be started 2156 for (RouteService routeService : routeServices) { 2157 DefaultRouteStartupOrder order = doPrepareRouteToBeStarted(routeService); 2158 // check for clash before we add it as input 2159 if (checkClash) { 2160 doCheckStartupOrderClash(order, inputs); 2161 } 2162 inputs.put(order.getStartupOrder(), order); 2163 } 2164 2165 // warm up routes before we start them 2166 doWarmUpRoutes(inputs, startConsumer); 2167 2168 if (startConsumer) { 2169 if (resumeConsumer) { 2170 // and now resume the routes 2171 doResumeRouteConsumers(inputs, addingRoutes); 2172 } else { 2173 // and now start the routes 2174 // and check for clash with multiple consumers of the same endpoints which is not allowed 2175 doStartRouteConsumers(inputs, addingRoutes); 2176 } 2177 } 2178 2179 // inputs no longer needed 2180 inputs.clear(); 2181 } 2182 2183 /** 2184 * @see #safelyStartRouteServices(boolean,boolean,boolean,boolean,java.util.Collection) 2185 */ 2186 protected synchronized void safelyStartRouteServices(boolean forceAutoStart, boolean checkClash, boolean startConsumer, 2187 boolean resumeConsumer, boolean addingRoutes, RouteService... routeServices) throws Exception { 2188 safelyStartRouteServices(checkClash, startConsumer, resumeConsumer, addingRoutes, Arrays.asList(routeServices)); 2189 } 2190 2191 private DefaultRouteStartupOrder doPrepareRouteToBeStarted(RouteService routeService) { 2192 // add the inputs from this route service to the list to start afterwards 2193 // should be ordered according to the startup number 2194 Integer startupOrder = routeService.getRouteDefinition().getStartupOrder(); 2195 if (startupOrder == null) { 2196 // auto assign a default startup order 2197 startupOrder = defaultRouteStartupOrder++; 2198 } 2199 2200 // create holder object that contains information about this route to be started 2201 Route route = routeService.getRoutes().iterator().next(); 2202 return new DefaultRouteStartupOrder(startupOrder, route, routeService); 2203 } 2204 2205 private boolean doCheckStartupOrderClash(DefaultRouteStartupOrder answer, Map<Integer, DefaultRouteStartupOrder> inputs) throws FailedToStartRouteException { 2206 // check for clash by startupOrder id 2207 DefaultRouteStartupOrder other = inputs.get(answer.getStartupOrder()); 2208 if (other != null && answer != other) { 2209 String otherId = other.getRoute().getId(); 2210 throw new FailedToStartRouteException(answer.getRoute().getId(), "startupOrder clash. Route " + otherId + " already has startupOrder " 2211 + answer.getStartupOrder() + " configured which this route have as well. Please correct startupOrder to be unique among all your routes."); 2212 } 2213 // check in existing already started as well 2214 for (RouteStartupOrder order : routeStartupOrder) { 2215 String otherId = order.getRoute().getId(); 2216 if (answer.getRoute().getId().equals(otherId)) { 2217 // its the same route id so skip clash check as its the same route (can happen when using suspend/resume) 2218 } else if (answer.getStartupOrder() == order.getStartupOrder()) { 2219 throw new FailedToStartRouteException(answer.getRoute().getId(), "startupOrder clash. Route " + otherId + " already has startupOrder " 2220 + answer.getStartupOrder() + " configured which this route have as well. Please correct startupOrder to be unique among all your routes."); 2221 } 2222 } 2223 return true; 2224 } 2225 2226 private void doWarmUpRoutes(Map<Integer, DefaultRouteStartupOrder> inputs, boolean autoStartup) throws Exception { 2227 // now prepare the routes by starting its services before we start the input 2228 for (Map.Entry<Integer, DefaultRouteStartupOrder> entry : inputs.entrySet()) { 2229 // defer starting inputs till later as we want to prepare the routes by starting 2230 // all their processors and child services etc. 2231 // then later we open the floods to Camel by starting the inputs 2232 // what this does is to ensure Camel is more robust on starting routes as all routes 2233 // will then be prepared in time before we start inputs which will consume messages to be routed 2234 RouteService routeService = entry.getValue().getRouteService(); 2235 log.debug("Warming up route id: {} having autoStartup={}", routeService.getId(), autoStartup); 2236 routeService.warmUp(); 2237 } 2238 } 2239 2240 private void doResumeRouteConsumers(Map<Integer, DefaultRouteStartupOrder> inputs, boolean addingRoutes) throws Exception { 2241 doStartOrResumeRouteConsumers(inputs, true, addingRoutes); 2242 } 2243 2244 private void doStartRouteConsumers(Map<Integer, DefaultRouteStartupOrder> inputs, boolean addingRoutes) throws Exception { 2245 doStartOrResumeRouteConsumers(inputs, false, addingRoutes); 2246 } 2247 2248 private void doStartOrResumeRouteConsumers(Map<Integer, DefaultRouteStartupOrder> inputs, boolean resumeOnly, boolean addingRoute) throws Exception { 2249 List<Endpoint> routeInputs = new ArrayList<Endpoint>(); 2250 2251 for (Map.Entry<Integer, DefaultRouteStartupOrder> entry : inputs.entrySet()) { 2252 Integer order = entry.getKey(); 2253 Route route = entry.getValue().getRoute(); 2254 RouteService routeService = entry.getValue().getRouteService(); 2255 2256 // if we are starting camel, then skip routes which are configured to not be auto started 2257 boolean autoStartup = routeService.getRouteDefinition().isAutoStartup(this); 2258 if (addingRoute && !autoStartup) { 2259 log.info("Skipping starting of route " + routeService.getId() + " as its configured with autoStartup=false"); 2260 continue; 2261 } 2262 2263 // start the service 2264 for (Consumer consumer : routeService.getInputs().values()) { 2265 Endpoint endpoint = consumer.getEndpoint(); 2266 2267 // check multiple consumer violation, with the other routes to be started 2268 if (!doCheckMultipleConsumerSupportClash(endpoint, routeInputs)) { 2269 throw new FailedToStartRouteException(routeService.getId(), 2270 "Multiple consumers for the same endpoint is not allowed: " + endpoint); 2271 } 2272 2273 // check for multiple consumer violations with existing routes which 2274 // have already been started, or is currently starting 2275 List<Endpoint> existingEndpoints = new ArrayList<Endpoint>(); 2276 for (Route existingRoute : getRoutes()) { 2277 if (route.getId().equals(existingRoute.getId())) { 2278 // skip ourselves 2279 continue; 2280 } 2281 Endpoint existing = existingRoute.getEndpoint(); 2282 ServiceStatus status = getRouteStatus(existingRoute.getId()); 2283 if (status != null && (status.isStarted() || status.isStarting())) { 2284 existingEndpoints.add(existing); 2285 } 2286 } 2287 if (!doCheckMultipleConsumerSupportClash(endpoint, existingEndpoints)) { 2288 throw new FailedToStartRouteException(routeService.getId(), 2289 "Multiple consumers for the same endpoint is not allowed: " + endpoint); 2290 } 2291 2292 // start the consumer on the route 2293 log.debug("Route: {} >>> {}", route.getId(), route); 2294 if (resumeOnly) { 2295 log.debug("Resuming consumer (order: {}) on route: {}", order, route.getId()); 2296 } else { 2297 log.debug("Starting consumer (order: {}) on route: {}", order, route.getId()); 2298 } 2299 2300 if (resumeOnly && route.supportsSuspension()) { 2301 // if we are resuming and the route can be resumed 2302 ServiceHelper.resumeService(consumer); 2303 log.info("Route: " + route.getId() + " resumed and consuming from: " + endpoint); 2304 } else { 2305 // when starting we should invoke the lifecycle strategies 2306 for (LifecycleStrategy strategy : lifecycleStrategies) { 2307 strategy.onServiceAdd(this, consumer, route); 2308 } 2309 startService(consumer); 2310 log.info("Route: " + route.getId() + " started and consuming from: " + endpoint); 2311 } 2312 2313 routeInputs.add(endpoint); 2314 2315 // add to the order which they was started, so we know how to stop them in reverse order 2316 // but only add if we haven't already registered it before (we dont want to double add when restarting) 2317 boolean found = false; 2318 for (RouteStartupOrder other : routeStartupOrder) { 2319 if (other.getRoute().getId().equals(route.getId())) { 2320 found = true; 2321 break; 2322 } 2323 } 2324 if (!found) { 2325 routeStartupOrder.add(entry.getValue()); 2326 } 2327 } 2328 2329 if (resumeOnly) { 2330 routeService.resume(); 2331 } else { 2332 // and start the route service (no need to start children as they are already warmed up) 2333 routeService.start(false); 2334 } 2335 } 2336 } 2337 2338 private boolean doCheckMultipleConsumerSupportClash(Endpoint endpoint, List<Endpoint> routeInputs) { 2339 // is multiple consumers supported 2340 boolean multipleConsumersSupported = false; 2341 if (endpoint instanceof MultipleConsumersSupport) { 2342 multipleConsumersSupported = ((MultipleConsumersSupport) endpoint).isMultipleConsumersSupported(); 2343 } 2344 2345 if (multipleConsumersSupported) { 2346 // multiple consumer allowed, so return true 2347 return true; 2348 } 2349 2350 // check in progress list 2351 if (routeInputs.contains(endpoint)) { 2352 return false; 2353 } 2354 2355 return true; 2356 } 2357 2358 /** 2359 * Force some lazy initialization to occur upfront before we start any 2360 * components and create routes 2361 */ 2362 protected void forceLazyInitialization() { 2363 getRegistry(); 2364 getInjector(); 2365 getLanguageResolver(); 2366 getTypeConverterRegistry(); 2367 getTypeConverter(); 2368 2369 if (isTypeConverterStatisticsEnabled() != null) { 2370 getTypeConverterRegistry().getStatistics().setStatisticsEnabled(isTypeConverterStatisticsEnabled()); 2371 } 2372 } 2373 2374 /** 2375 * Force clear lazy initialization so they can be re-created on restart 2376 */ 2377 protected void forceStopLazyInitialization() { 2378 injector = null; 2379 languageResolver = null; 2380 typeConverterRegistry = null; 2381 typeConverter = null; 2382 } 2383 2384 /** 2385 * Lazily create a default implementation 2386 */ 2387 protected TypeConverter createTypeConverter() { 2388 BaseTypeConverterRegistry answer; 2389 if (isLazyLoadTypeConverters()) { 2390 answer = new LazyLoadingTypeConverter(packageScanClassResolver, getInjector(), getDefaultFactoryFinder()); 2391 } else { 2392 answer = new DefaultTypeConverter(packageScanClassResolver, getInjector(), getDefaultFactoryFinder()); 2393 } 2394 setTypeConverterRegistry(answer); 2395 return answer; 2396 } 2397 2398 /** 2399 * Lazily create a default implementation 2400 */ 2401 protected Injector createInjector() { 2402 FactoryFinder finder = getDefaultFactoryFinder(); 2403 try { 2404 return (Injector) finder.newInstance("Injector"); 2405 } catch (NoFactoryAvailableException e) { 2406 // lets use the default injector 2407 return new DefaultInjector(this); 2408 } 2409 } 2410 2411 /** 2412 * Lazily create a default implementation 2413 */ 2414 protected ManagementMBeanAssembler createManagementMBeanAssembler() { 2415 return new DefaultManagementMBeanAssembler(this); 2416 } 2417 2418 /** 2419 * Lazily create a default implementation 2420 */ 2421 protected ComponentResolver createComponentResolver() { 2422 return new DefaultComponentResolver(); 2423 } 2424 2425 /** 2426 * Lazily create a default implementation 2427 */ 2428 protected Registry createRegistry() { 2429 JndiRegistry jndi = new JndiRegistry(); 2430 try { 2431 // getContext() will force setting up JNDI 2432 jndi.getContext(); 2433 return jndi; 2434 } catch (Throwable e) { 2435 log.debug("Cannot create javax.naming.InitialContext due " + e.getMessage() + ". Will fallback and use SimpleRegistry instead. This exception is ignored.", e); 2436 return new SimpleRegistry(); 2437 } 2438 } 2439 2440 /** 2441 * A pluggable strategy to allow an endpoint to be created without requiring 2442 * a component to be its factory, such as for looking up the URI inside some 2443 * {@link Registry} 2444 * 2445 * @param uri the uri for the endpoint to be created 2446 * @return the newly created endpoint or null if it could not be resolved 2447 */ 2448 protected Endpoint createEndpoint(String uri) { 2449 Object value = getRegistry().lookupByName(uri); 2450 if (value instanceof Endpoint) { 2451 return (Endpoint) value; 2452 } else if (value instanceof Processor) { 2453 return new ProcessorEndpoint(uri, this, (Processor) value); 2454 } else if (value != null) { 2455 return convertBeanToEndpoint(uri, value); 2456 } 2457 return null; 2458 } 2459 2460 /** 2461 * Strategy method for attempting to convert the bean from a {@link Registry} to an endpoint using 2462 * some kind of transformation or wrapper 2463 * 2464 * @param uri the uri for the endpoint (and name in the registry) 2465 * @param bean the bean to be converted to an endpoint, which will be not null 2466 * @return a new endpoint 2467 */ 2468 protected Endpoint convertBeanToEndpoint(String uri, Object bean) { 2469 throw new IllegalArgumentException("uri: " + uri + " bean: " + bean 2470 + " could not be converted to an Endpoint"); 2471 } 2472 2473 /** 2474 * Should we start newly added routes? 2475 */ 2476 protected boolean shouldStartRoutes() { 2477 return isStarted() && !isStarting(); 2478 } 2479 2480 /** 2481 * Gets the properties component in use. 2482 * Returns {@code null} if no properties component is in use. 2483 */ 2484 protected PropertiesComponent getPropertiesComponent() { 2485 return propertiesComponent; 2486 } 2487 2488 public void setDataFormats(Map<String, DataFormatDefinition> dataFormats) { 2489 this.dataFormats = dataFormats; 2490 } 2491 2492 public Map<String, DataFormatDefinition> getDataFormats() { 2493 return dataFormats; 2494 } 2495 2496 public Map<String, String> getProperties() { 2497 return properties; 2498 } 2499 2500 public void setProperties(Map<String, String> properties) { 2501 this.properties = properties; 2502 } 2503 2504 public FactoryFinder getDefaultFactoryFinder() { 2505 if (defaultFactoryFinder == null) { 2506 defaultFactoryFinder = factoryFinderResolver.resolveDefaultFactoryFinder(getClassResolver()); 2507 } 2508 return defaultFactoryFinder; 2509 } 2510 2511 public void setFactoryFinderResolver(FactoryFinderResolver resolver) { 2512 this.factoryFinderResolver = resolver; 2513 } 2514 2515 public FactoryFinder getFactoryFinder(String path) throws NoFactoryAvailableException { 2516 synchronized (factories) { 2517 FactoryFinder answer = factories.get(path); 2518 if (answer == null) { 2519 answer = factoryFinderResolver.resolveFactoryFinder(getClassResolver(), path); 2520 factories.put(path, answer); 2521 } 2522 return answer; 2523 } 2524 } 2525 2526 public ClassResolver getClassResolver() { 2527 return classResolver; 2528 } 2529 2530 public void setClassResolver(ClassResolver classResolver) { 2531 this.classResolver = classResolver; 2532 } 2533 2534 public PackageScanClassResolver getPackageScanClassResolver() { 2535 return packageScanClassResolver; 2536 } 2537 2538 public void setPackageScanClassResolver(PackageScanClassResolver packageScanClassResolver) { 2539 this.packageScanClassResolver = packageScanClassResolver; 2540 } 2541 2542 public List<String> getComponentNames() { 2543 synchronized (components) { 2544 List<String> answer = new ArrayList<String>(); 2545 for (String name : components.keySet()) { 2546 answer.add(name); 2547 } 2548 return answer; 2549 } 2550 } 2551 2552 public List<String> getLanguageNames() { 2553 synchronized (languages) { 2554 List<String> answer = new ArrayList<String>(); 2555 for (String name : languages.keySet()) { 2556 answer.add(name); 2557 } 2558 return answer; 2559 } 2560 } 2561 2562 public NodeIdFactory getNodeIdFactory() { 2563 return nodeIdFactory; 2564 } 2565 2566 public void setNodeIdFactory(NodeIdFactory idFactory) { 2567 this.nodeIdFactory = idFactory; 2568 } 2569 2570 public ManagementStrategy getManagementStrategy() { 2571 return managementStrategy; 2572 } 2573 2574 public void setManagementStrategy(ManagementStrategy managementStrategy) { 2575 this.managementStrategy = managementStrategy; 2576 } 2577 2578 public InterceptStrategy getDefaultTracer() { 2579 if (defaultTracer == null) { 2580 defaultTracer = new Tracer(); 2581 } 2582 return defaultTracer; 2583 } 2584 2585 public void setDefaultTracer(InterceptStrategy tracer) { 2586 this.defaultTracer = tracer; 2587 } 2588 2589 public InterceptStrategy getDefaultBacklogTracer() { 2590 if (defaultBacklogTracer == null) { 2591 defaultBacklogTracer = new BacklogTracer(this); 2592 } 2593 return defaultBacklogTracer; 2594 } 2595 2596 public void setDefaultBacklogTracer(InterceptStrategy backlogTracer) { 2597 this.defaultBacklogTracer = backlogTracer; 2598 } 2599 2600 public InterceptStrategy getDefaultBacklogDebugger() { 2601 if (defaultBacklogDebugger == null) { 2602 defaultBacklogDebugger = new BacklogDebugger(this); 2603 } 2604 return defaultBacklogDebugger; 2605 } 2606 2607 public void setDefaultBacklogDebugger(InterceptStrategy defaultBacklogDebugger) { 2608 this.defaultBacklogDebugger = defaultBacklogDebugger; 2609 } 2610 2611 public void disableJMX() { 2612 if (isStarting() || isStarted()) { 2613 throw new IllegalStateException("Disabling JMX can only be done when CamelContext has not been started"); 2614 } 2615 managementStrategy = new DefaultManagementStrategy(this); 2616 // must clear lifecycle strategies as we add DefaultManagementLifecycleStrategy by default for JMX support 2617 lifecycleStrategies.clear(); 2618 } 2619 2620 public InflightRepository getInflightRepository() { 2621 return inflightRepository; 2622 } 2623 2624 public void setInflightRepository(InflightRepository repository) { 2625 this.inflightRepository = repository; 2626 } 2627 2628 public void setAutoStartup(Boolean autoStartup) { 2629 this.autoStartup = autoStartup; 2630 } 2631 2632 public Boolean isAutoStartup() { 2633 return autoStartup != null && autoStartup; 2634 } 2635 2636 @Deprecated 2637 public Boolean isLazyLoadTypeConverters() { 2638 return lazyLoadTypeConverters != null && lazyLoadTypeConverters; 2639 } 2640 2641 @Deprecated 2642 public void setLazyLoadTypeConverters(Boolean lazyLoadTypeConverters) { 2643 this.lazyLoadTypeConverters = lazyLoadTypeConverters; 2644 } 2645 2646 public Boolean isTypeConverterStatisticsEnabled() { 2647 return typeConverterStatisticsEnabled != null && typeConverterStatisticsEnabled; 2648 } 2649 2650 public void setTypeConverterStatisticsEnabled(Boolean typeConverterStatisticsEnabled) { 2651 this.typeConverterStatisticsEnabled = typeConverterStatisticsEnabled; 2652 } 2653 2654 public Boolean isUseMDCLogging() { 2655 return useMDCLogging != null && useMDCLogging; 2656 } 2657 2658 public void setUseMDCLogging(Boolean useMDCLogging) { 2659 this.useMDCLogging = useMDCLogging; 2660 } 2661 2662 public Boolean isUseBreadcrumb() { 2663 return useBreadcrumb != null && useBreadcrumb; 2664 } 2665 2666 public void setUseBreadcrumb(Boolean useBreadcrumb) { 2667 this.useBreadcrumb = useBreadcrumb; 2668 } 2669 2670 public ClassLoader getApplicationContextClassLoader() { 2671 return applicationContextClassLoader; 2672 } 2673 2674 public void setApplicationContextClassLoader(ClassLoader classLoader) { 2675 applicationContextClassLoader = classLoader; 2676 } 2677 2678 public DataFormatResolver getDataFormatResolver() { 2679 return dataFormatResolver; 2680 } 2681 2682 public void setDataFormatResolver(DataFormatResolver dataFormatResolver) { 2683 this.dataFormatResolver = dataFormatResolver; 2684 } 2685 2686 public DataFormat resolveDataFormat(String name) { 2687 DataFormat answer = dataFormatResolver.resolveDataFormat(name, this); 2688 2689 // inject CamelContext if aware 2690 if (answer != null && answer instanceof CamelContextAware) { 2691 ((CamelContextAware) answer).setCamelContext(this); 2692 } 2693 2694 return answer; 2695 } 2696 2697 public DataFormatDefinition resolveDataFormatDefinition(String name) { 2698 // lookup type and create the data format from it 2699 DataFormatDefinition type = lookup(this, name, DataFormatDefinition.class); 2700 if (type == null && getDataFormats() != null) { 2701 type = getDataFormats().get(name); 2702 } 2703 return type; 2704 } 2705 2706 private static <T> T lookup(CamelContext context, String ref, Class<T> type) { 2707 try { 2708 return context.getRegistry().lookupByNameAndType(ref, type); 2709 } catch (Exception e) { 2710 // need to ignore not same type and return it as null 2711 return null; 2712 } 2713 } 2714 2715 protected Component lookupPropertiesComponent() { 2716 // no existing properties component so lookup and add as component if possible 2717 PropertiesComponent answer = (PropertiesComponent) hasComponent("properties"); 2718 if (answer == null) { 2719 answer = getRegistry().lookupByNameAndType("properties", PropertiesComponent.class); 2720 if (answer != null) { 2721 addComponent("properties", answer); 2722 } 2723 } 2724 return answer; 2725 } 2726 2727 public ShutdownStrategy getShutdownStrategy() { 2728 return shutdownStrategy; 2729 } 2730 2731 public void setShutdownStrategy(ShutdownStrategy shutdownStrategy) { 2732 this.shutdownStrategy = shutdownStrategy; 2733 } 2734 2735 public ShutdownRoute getShutdownRoute() { 2736 return shutdownRoute; 2737 } 2738 2739 public void setShutdownRoute(ShutdownRoute shutdownRoute) { 2740 this.shutdownRoute = shutdownRoute; 2741 } 2742 2743 public ShutdownRunningTask getShutdownRunningTask() { 2744 return shutdownRunningTask; 2745 } 2746 2747 public void setShutdownRunningTask(ShutdownRunningTask shutdownRunningTask) { 2748 this.shutdownRunningTask = shutdownRunningTask; 2749 } 2750 2751 public void setAllowUseOriginalMessage(Boolean allowUseOriginalMessage) { 2752 this.allowUseOriginalMessage = allowUseOriginalMessage; 2753 } 2754 2755 public Boolean isAllowUseOriginalMessage() { 2756 return allowUseOriginalMessage != null && allowUseOriginalMessage; 2757 } 2758 2759 public ExecutorServiceManager getExecutorServiceManager() { 2760 return this.executorServiceManager; 2761 } 2762 2763 @Deprecated 2764 public org.apache.camel.spi.ExecutorServiceStrategy getExecutorServiceStrategy() { 2765 // its okay to create a new instance as its stateless, and just delegate 2766 // ExecutorServiceManager which is the new API 2767 return new DefaultExecutorServiceStrategy(this); 2768 } 2769 2770 public void setExecutorServiceManager(ExecutorServiceManager executorServiceManager) { 2771 this.executorServiceManager = executorServiceManager; 2772 } 2773 2774 public ProcessorFactory getProcessorFactory() { 2775 return processorFactory; 2776 } 2777 2778 public void setProcessorFactory(ProcessorFactory processorFactory) { 2779 this.processorFactory = processorFactory; 2780 } 2781 2782 public Debugger getDebugger() { 2783 return debugger; 2784 } 2785 2786 public void setDebugger(Debugger debugger) { 2787 this.debugger = debugger; 2788 } 2789 2790 public UuidGenerator getUuidGenerator() { 2791 return uuidGenerator; 2792 } 2793 2794 public void setUuidGenerator(UuidGenerator uuidGenerator) { 2795 this.uuidGenerator = uuidGenerator; 2796 } 2797 2798 public StreamCachingStrategy getStreamCachingStrategy() { 2799 if (streamCachingStrategy == null) { 2800 streamCachingStrategy = new DefaultStreamCachingStrategy(); 2801 } 2802 return streamCachingStrategy; 2803 } 2804 2805 public void setStreamCachingStrategy(StreamCachingStrategy streamCachingStrategy) { 2806 this.streamCachingStrategy = streamCachingStrategy; 2807 } 2808 2809 @Override 2810 public String getProperty(String name) { 2811 String value = getProperties().get(name); 2812 if (ObjectHelper.isNotEmpty(value)) { 2813 try { 2814 value = resolvePropertyPlaceholders(value); 2815 } catch (Exception e) { 2816 throw new RuntimeCamelException("Error getting property: " + name, e); 2817 } 2818 } 2819 return value; 2820 } 2821 2822 protected Map<String, RouteService> getRouteServices() { 2823 return routeServices; 2824 } 2825 2826 protected ManagementStrategy createManagementStrategy() { 2827 return new ManagementStrategyFactory().create(this, disableJMX || Boolean.getBoolean(JmxSystemPropertyKeys.DISABLED)); 2828 } 2829 2830 /** 2831 * Reset context counter to a preset value. Mostly used for tests to ensure a predictable getName() 2832 * 2833 * @param value new value for the context counter 2834 */ 2835 public static void setContextCounter(int value) { 2836 DefaultCamelContextNameStrategy.setCounter(value); 2837 DefaultManagementNameStrategy.setCounter(value); 2838 } 2839 2840 private static UuidGenerator createDefaultUuidGenerator() { 2841 if (System.getProperty("com.google.appengine.runtime.environment") != null) { 2842 // either "Production" or "Development" 2843 return new JavaUuidGenerator(); 2844 } else { 2845 return new ActiveMQUuidGenerator(); 2846 } 2847 } 2848 2849 @Override 2850 public String toString() { 2851 return "CamelContext(" + getName() + ")"; 2852 } 2853 }