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