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.net.URI; 022import java.util.ArrayList; 023import java.util.Arrays; 024import java.util.Collection; 025import java.util.Collections; 026import java.util.Comparator; 027import java.util.Date; 028import java.util.HashMap; 029import java.util.HashSet; 030import java.util.Iterator; 031import java.util.LinkedHashMap; 032import java.util.LinkedHashSet; 033import java.util.List; 034import java.util.Map; 035import java.util.Properties; 036import java.util.Set; 037import java.util.TreeMap; 038import java.util.concurrent.Callable; 039import java.util.concurrent.ConcurrentHashMap; 040import java.util.concurrent.CopyOnWriteArrayList; 041import java.util.concurrent.ScheduledExecutorService; 042import java.util.concurrent.TimeUnit; 043import java.util.concurrent.atomic.AtomicBoolean; 044import java.util.concurrent.atomic.AtomicInteger; 045import java.util.stream.Collectors; 046import javax.management.MalformedObjectNameException; 047import javax.management.ObjectName; 048import javax.naming.Context; 049import javax.xml.bind.JAXBContext; 050import javax.xml.bind.Unmarshaller; 051 052import org.apache.camel.CamelContext; 053import org.apache.camel.CamelContextAware; 054import org.apache.camel.Component; 055import org.apache.camel.Consumer; 056import org.apache.camel.ConsumerTemplate; 057import org.apache.camel.Endpoint; 058import org.apache.camel.ErrorHandlerFactory; 059import org.apache.camel.ExtendedStartupListener; 060import org.apache.camel.FailedToStartRouteException; 061import org.apache.camel.FluentProducerTemplate; 062import org.apache.camel.IsSingleton; 063import org.apache.camel.MultipleConsumersSupport; 064import org.apache.camel.NamedNode; 065import org.apache.camel.NoFactoryAvailableException; 066import org.apache.camel.NoSuchEndpointException; 067import org.apache.camel.PollingConsumer; 068import org.apache.camel.Processor; 069import org.apache.camel.Producer; 070import org.apache.camel.ProducerTemplate; 071import org.apache.camel.ResolveEndpointFailedException; 072import org.apache.camel.Route; 073import org.apache.camel.RoutesBuilder; 074import org.apache.camel.RuntimeCamelException; 075import org.apache.camel.Service; 076import org.apache.camel.ServiceStatus; 077import org.apache.camel.ShutdownRoute; 078import org.apache.camel.ShutdownRunningTask; 079import org.apache.camel.StartupListener; 080import org.apache.camel.StatefulService; 081import org.apache.camel.Suspendable; 082import org.apache.camel.SuspendableService; 083import org.apache.camel.TypeConverter; 084import org.apache.camel.VetoCamelContextStartException; 085import org.apache.camel.api.management.mbean.ManagedCamelContextMBean; 086import org.apache.camel.api.management.mbean.ManagedProcessorMBean; 087import org.apache.camel.api.management.mbean.ManagedRouteMBean; 088import org.apache.camel.builder.DefaultFluentProducerTemplate; 089import org.apache.camel.builder.ErrorHandlerBuilder; 090import org.apache.camel.builder.ErrorHandlerBuilderSupport; 091import org.apache.camel.component.properties.PropertiesComponent; 092import org.apache.camel.health.HealthCheckRegistry; 093import org.apache.camel.impl.converter.BaseTypeConverterRegistry; 094import org.apache.camel.impl.converter.DefaultTypeConverter; 095import org.apache.camel.impl.converter.LazyLoadingTypeConverter; 096import org.apache.camel.impl.health.DefaultHealthCheckRegistry; 097import org.apache.camel.impl.transformer.TransformerKey; 098import org.apache.camel.impl.validator.ValidatorKey; 099import org.apache.camel.management.DefaultManagementMBeanAssembler; 100import org.apache.camel.management.DefaultManagementStrategy; 101import org.apache.camel.management.JmxSystemPropertyKeys; 102import org.apache.camel.management.ManagementStrategyFactory; 103import org.apache.camel.model.DataFormatDefinition; 104import org.apache.camel.model.FromDefinition; 105import org.apache.camel.model.HystrixConfigurationDefinition; 106import org.apache.camel.model.ModelCamelContext; 107import org.apache.camel.model.ModelHelper; 108import org.apache.camel.model.ProcessorDefinition; 109import org.apache.camel.model.ProcessorDefinitionHelper; 110import org.apache.camel.model.RouteDefinition; 111import org.apache.camel.model.RouteDefinitionHelper; 112import org.apache.camel.model.RoutesDefinition; 113import org.apache.camel.model.cloud.ServiceCallConfigurationDefinition; 114import org.apache.camel.model.rest.RestDefinition; 115import org.apache.camel.model.rest.RestsDefinition; 116import org.apache.camel.model.transformer.TransformerDefinition; 117import org.apache.camel.model.validator.ValidatorDefinition; 118import org.apache.camel.processor.interceptor.BacklogDebugger; 119import org.apache.camel.processor.interceptor.BacklogTracer; 120import org.apache.camel.processor.interceptor.Debug; 121import org.apache.camel.processor.interceptor.Delayer; 122import org.apache.camel.processor.interceptor.HandleFault; 123import org.apache.camel.processor.interceptor.StreamCaching; 124import org.apache.camel.processor.interceptor.Tracer; 125import org.apache.camel.runtimecatalog.DefaultRuntimeCamelCatalog; 126import org.apache.camel.runtimecatalog.RuntimeCamelCatalog; 127import org.apache.camel.spi.AsyncProcessorAwaitManager; 128import org.apache.camel.spi.CamelContextNameStrategy; 129import org.apache.camel.spi.ClassResolver; 130import org.apache.camel.spi.ComponentResolver; 131import org.apache.camel.spi.Container; 132import org.apache.camel.spi.DataFormat; 133import org.apache.camel.spi.DataFormatResolver; 134import org.apache.camel.spi.DataType; 135import org.apache.camel.spi.Debugger; 136import org.apache.camel.spi.EndpointRegistry; 137import org.apache.camel.spi.EndpointStrategy; 138import org.apache.camel.spi.EventNotifier; 139import org.apache.camel.spi.ExecutorServiceManager; 140import org.apache.camel.spi.FactoryFinder; 141import org.apache.camel.spi.FactoryFinderResolver; 142import org.apache.camel.spi.HeadersMapFactory; 143import org.apache.camel.spi.InflightRepository; 144import org.apache.camel.spi.Injector; 145import org.apache.camel.spi.InterceptStrategy; 146import org.apache.camel.spi.Language; 147import org.apache.camel.spi.LanguageResolver; 148import org.apache.camel.spi.LifecycleStrategy; 149import org.apache.camel.spi.LogListener; 150import org.apache.camel.spi.ManagementMBeanAssembler; 151import org.apache.camel.spi.ManagementNameStrategy; 152import org.apache.camel.spi.ManagementStrategy; 153import org.apache.camel.spi.MessageHistoryFactory; 154import org.apache.camel.spi.ModelJAXBContextFactory; 155import org.apache.camel.spi.NodeIdFactory; 156import org.apache.camel.spi.PackageScanClassResolver; 157import org.apache.camel.spi.ProcessorFactory; 158import org.apache.camel.spi.Registry; 159import org.apache.camel.spi.ReloadStrategy; 160import org.apache.camel.spi.RestConfiguration; 161import org.apache.camel.spi.RestRegistry; 162import org.apache.camel.spi.RouteContext; 163import org.apache.camel.spi.RouteController; 164import org.apache.camel.spi.RouteError; 165import org.apache.camel.spi.RoutePolicyFactory; 166import org.apache.camel.spi.RouteStartupOrder; 167import org.apache.camel.spi.RuntimeEndpointRegistry; 168import org.apache.camel.spi.ServicePool; 169import org.apache.camel.spi.ShutdownStrategy; 170import org.apache.camel.spi.StreamCachingStrategy; 171import org.apache.camel.spi.Transformer; 172import org.apache.camel.spi.TransformerRegistry; 173import org.apache.camel.spi.TypeConverterRegistry; 174import org.apache.camel.spi.UnitOfWorkFactory; 175import org.apache.camel.spi.UuidGenerator; 176import org.apache.camel.spi.Validator; 177import org.apache.camel.spi.ValidatorRegistry; 178import org.apache.camel.support.ServiceSupport; 179import org.apache.camel.util.CamelContextHelper; 180import org.apache.camel.util.CollectionStringBuffer; 181import org.apache.camel.util.EndpointHelper; 182import org.apache.camel.util.EventHelper; 183import org.apache.camel.util.IOHelper; 184import org.apache.camel.util.IntrospectionSupport; 185import org.apache.camel.util.JsonSchemaHelper; 186import org.apache.camel.util.LRUCacheFactory; 187import org.apache.camel.util.LoadPropertiesException; 188import org.apache.camel.util.ObjectHelper; 189import org.apache.camel.util.OrderedComparator; 190import org.apache.camel.util.ServiceHelper; 191import org.apache.camel.util.StopWatch; 192import org.apache.camel.util.StringHelper; 193import org.apache.camel.util.StringQuoteHelper; 194import org.apache.camel.util.TimeUtils; 195import org.apache.camel.util.URISupport; 196import org.apache.camel.util.jsse.SSLContextParameters; 197import org.slf4j.Logger; 198import org.slf4j.LoggerFactory; 199import org.slf4j.MDC; 200 201import static org.apache.camel.impl.MDCUnitOfWork.MDC_CAMEL_CONTEXT_ID; 202 203/** 204 * Represents the context used to configure routes and the policies to use. 205 * 206 * @version 207 */ 208@SuppressWarnings("deprecation") 209public class DefaultCamelContext extends ServiceSupport implements ModelCamelContext, Suspendable { 210 private final Logger log = LoggerFactory.getLogger(getClass()); 211 private final AtomicBoolean vetoStated = new AtomicBoolean(); 212 private JAXBContext jaxbContext; 213 private CamelContextNameStrategy nameStrategy = new DefaultCamelContextNameStrategy(); 214 private ManagementNameStrategy managementNameStrategy = new DefaultManagementNameStrategy(this); 215 private String managementName; 216 private ClassLoader applicationContextClassLoader; 217 private EndpointRegistry<EndpointKey> endpoints; 218 private final AtomicInteger endpointKeyCounter = new AtomicInteger(); 219 private final List<EndpointStrategy> endpointStrategies = new ArrayList<EndpointStrategy>(); 220 private final Map<String, Component> components = new ConcurrentHashMap<String, Component>(); 221 private final Set<Route> routes = new LinkedHashSet<Route>(); 222 private final List<Service> servicesToStop = new CopyOnWriteArrayList<Service>(); 223 private final List<StartupListener> startupListeners = new CopyOnWriteArrayList<StartupListener>(); 224 private final DeferServiceStartupListener deferStartupListener = new DeferServiceStartupListener(); 225 private TypeConverter typeConverter; 226 private TypeConverterRegistry typeConverterRegistry; 227 private Injector injector; 228 private ComponentResolver componentResolver; 229 private boolean autoCreateComponents = true; 230 private LanguageResolver languageResolver = new DefaultLanguageResolver(); 231 private final Map<String, Language> languages = new HashMap<String, Language>(); 232 private Registry registry; 233 private List<LifecycleStrategy> lifecycleStrategies = new CopyOnWriteArrayList<LifecycleStrategy>(); 234 private ManagementStrategy managementStrategy; 235 private ManagementMBeanAssembler managementMBeanAssembler; 236 private final List<RouteDefinition> routeDefinitions = new ArrayList<RouteDefinition>(); 237 private final List<RestDefinition> restDefinitions = new ArrayList<RestDefinition>(); 238 private Map<String, RestConfiguration> restConfigurations = new ConcurrentHashMap<>(); 239 private Map<String, ServiceCallConfigurationDefinition> serviceCallConfigurations = new ConcurrentHashMap<>(); 240 private Map<String, HystrixConfigurationDefinition> hystrixConfigurations = new ConcurrentHashMap<>(); 241 private RestRegistry restRegistry = new DefaultRestRegistry(); 242 private List<InterceptStrategy> interceptStrategies = new ArrayList<InterceptStrategy>(); 243 private List<RoutePolicyFactory> routePolicyFactories = new ArrayList<RoutePolicyFactory>(); 244 private Set<LogListener> logListeners = new LinkedHashSet<>(); 245 private HeadersMapFactory headersMapFactory = new DefaultHeadersMapFactory(); 246 247 // special flags to control the first startup which can are special 248 private volatile boolean firstStartDone; 249 private volatile boolean doNotStartRoutesOnFirstStart; 250 private final ThreadLocal<Boolean> isStartingRoutes = new ThreadLocal<Boolean>(); 251 private final ThreadLocal<Boolean> isSetupRoutes = new ThreadLocal<Boolean>(); 252 private Boolean autoStartup = Boolean.TRUE; 253 private Boolean trace = Boolean.FALSE; 254 private Boolean messageHistory = Boolean.TRUE; 255 private Boolean logMask = Boolean.FALSE; 256 private Boolean logExhaustedMessageBody = Boolean.FALSE; 257 private Boolean streamCache = Boolean.FALSE; 258 private Boolean handleFault = Boolean.FALSE; 259 private Boolean disableJMX = Boolean.FALSE; 260 private Boolean lazyLoadTypeConverters = Boolean.FALSE; 261 private Boolean loadTypeConverters = Boolean.TRUE; 262 private Boolean typeConverterStatisticsEnabled = Boolean.FALSE; 263 private Boolean useMDCLogging = Boolean.FALSE; 264 private Boolean useDataType = Boolean.FALSE; 265 private Boolean useBreadcrumb = Boolean.TRUE; 266 private Boolean allowUseOriginalMessage = Boolean.FALSE; 267 private Long delay; 268 private ErrorHandlerFactory errorHandlerBuilder; 269 private final Object errorHandlerExecutorServiceLock = new Object(); 270 private ScheduledExecutorService errorHandlerExecutorService; 271 private Map<String, DataFormatDefinition> dataFormats = new HashMap<String, DataFormatDefinition>(); 272 private DataFormatResolver dataFormatResolver = new DefaultDataFormatResolver(); 273 private Map<String, String> globalOptions = new HashMap<String, String>(); 274 private FactoryFinderResolver factoryFinderResolver = new DefaultFactoryFinderResolver(); 275 private FactoryFinder defaultFactoryFinder; 276 private PropertiesComponent propertiesComponent; 277 private StreamCachingStrategy streamCachingStrategy; 278 private final Map<String, FactoryFinder> factories = new HashMap<String, FactoryFinder>(); 279 private final Map<String, RouteService> routeServices = new LinkedHashMap<String, RouteService>(); 280 private final Map<String, RouteService> suspendedRouteServices = new LinkedHashMap<String, RouteService>(); 281 private ClassResolver classResolver = new DefaultClassResolver(this); 282 private PackageScanClassResolver packageScanClassResolver; 283 // we use a capacity of 100 per endpoint, so for the same endpoint we have at most 100 producers in the pool 284 // so if we have 6 endpoints in the pool, we can have 6 x 100 producers in total 285 private ServicePool<Endpoint, Producer> producerServicePool = new SharedProducerServicePool(100); 286 private ServicePool<Endpoint, PollingConsumer> pollingConsumerServicePool = new SharedPollingConsumerServicePool(100); 287 private NodeIdFactory nodeIdFactory = new DefaultNodeIdFactory(); 288 private ProcessorFactory processorFactory = new DefaultProcessorFactory(); 289 private MessageHistoryFactory messageHistoryFactory = new DefaultMessageHistoryFactory(); 290 private InterceptStrategy defaultTracer; 291 private InterceptStrategy defaultBacklogTracer; 292 private InterceptStrategy defaultBacklogDebugger; 293 private InflightRepository inflightRepository = new DefaultInflightRepository(); 294 private AsyncProcessorAwaitManager asyncProcessorAwaitManager = new DefaultAsyncProcessorAwaitManager(); 295 private RuntimeEndpointRegistry runtimeEndpointRegistry; 296 private final List<RouteStartupOrder> routeStartupOrder = new ArrayList<RouteStartupOrder>(); 297 // start auto assigning route ids using numbering 1000 and upwards 298 private int defaultRouteStartupOrder = 1000; 299 private ShutdownStrategy shutdownStrategy = new DefaultShutdownStrategy(this); 300 private ShutdownRoute shutdownRoute = ShutdownRoute.Default; 301 private ShutdownRunningTask shutdownRunningTask = ShutdownRunningTask.CompleteCurrentTaskOnly; 302 private ExecutorServiceManager executorServiceManager; 303 private Debugger debugger; 304 private UuidGenerator uuidGenerator = createDefaultUuidGenerator(); 305 private UnitOfWorkFactory unitOfWorkFactory = new DefaultUnitOfWorkFactory(); 306 private final StopWatch stopWatch = new StopWatch(false); 307 private Date startDate; 308 private ModelJAXBContextFactory modelJAXBContextFactory; 309 private List<TransformerDefinition> transformers = new ArrayList<>(); 310 private TransformerRegistry<TransformerKey> transformerRegistry; 311 private List<ValidatorDefinition> validators = new ArrayList<>(); 312 private ValidatorRegistry<ValidatorKey> validatorRegistry; 313 private ReloadStrategy reloadStrategy; 314 private final RuntimeCamelCatalog runtimeCamelCatalog = new DefaultRuntimeCamelCatalog(this, true); 315 private SSLContextParameters sslContextParameters; 316 private final ThreadLocal<Set<String>> componentsInCreation = ThreadLocal.withInitial(HashSet::new); 317 private RouteController routeController = new DefaultRouteController(this); 318 private HealthCheckRegistry healthCheckRegistry = new DefaultHealthCheckRegistry(this); 319 320 /** 321 * Creates the {@link CamelContext} using {@link JndiRegistry} as registry, 322 * but will silently fallback and use {@link SimpleRegistry} if JNDI cannot be used. 323 * <p/> 324 * Use one of the other constructors to force use an explicit registry / JNDI. 325 */ 326 public DefaultCamelContext() { 327 boolean warmUp = "true".equalsIgnoreCase(System.getProperty("CamelWarmUpLRUCacheFactory", "true")); 328 if (warmUp) { 329 // warm-up LRUCache which happens in a background test, which can speedup starting Camel 330 // as the warm-up can run concurrently with starting up Camel and the runtime container Camel may be running inside 331 LRUCacheFactory.warmUp(); 332 } 333 334 this.executorServiceManager = new DefaultExecutorServiceManager(this); 335 336 // create a provisional (temporary) endpoint registry at first since end users may access endpoints before CamelContext is started 337 // we will later transfer the endpoints to the actual DefaultEndpointRegistry later, but we do this to starup Camel faster. 338 this.endpoints = new ProvisionalEndpointRegistry(); 339 340 // add the defer service startup listener 341 this.startupListeners.add(deferStartupListener); 342 343 // use WebSphere specific resolver if running on WebSphere 344 if (WebSpherePackageScanClassResolver.isWebSphereClassLoader(this.getClass().getClassLoader())) { 345 log.info("Using WebSphere specific PackageScanClassResolver"); 346 packageScanClassResolver = new WebSpherePackageScanClassResolver("META-INF/services/org/apache/camel/TypeConverter"); 347 } else { 348 packageScanClassResolver = new DefaultPackageScanClassResolver(); 349 } 350 351 // setup management strategy first since end users may use it to add event notifiers 352 // using the management strategy before the CamelContext has been started 353 this.managementStrategy = createManagementStrategy(); 354 this.managementMBeanAssembler = createManagementMBeanAssembler(); 355 356 // Call all registered trackers with this context 357 // Note, this may use a partially constructed object 358 CamelContextTrackerRegistry.INSTANCE.contextCreated(this); 359 } 360 361 /** 362 * Creates the {@link CamelContext} using the given JNDI context as the registry 363 * 364 * @param jndiContext the JNDI context 365 */ 366 public DefaultCamelContext(Context jndiContext) { 367 this(); 368 setJndiContext(jndiContext); 369 } 370 371 /** 372 * Creates the {@link CamelContext} using the given registry 373 * 374 * @param registry the registry 375 */ 376 public DefaultCamelContext(Registry registry) { 377 this(); 378 setRegistry(registry); 379 } 380 381 public <T extends CamelContext> T adapt(Class<T> type) { 382 return type.cast(this); 383 } 384 385 public boolean isVetoStarted() { 386 return vetoStated.get(); 387 } 388 389 public String getName() { 390 return getNameStrategy().getName(); 391 } 392 393 /** 394 * Sets the name of the this context. 395 * 396 * @param name the name 397 */ 398 public void setName(String name) { 399 // use an explicit name strategy since an explicit name was provided to be used 400 this.nameStrategy = new ExplicitCamelContextNameStrategy(name); 401 } 402 403 public CamelContextNameStrategy getNameStrategy() { 404 return nameStrategy; 405 } 406 407 public void setNameStrategy(CamelContextNameStrategy nameStrategy) { 408 this.nameStrategy = nameStrategy; 409 } 410 411 public ManagementNameStrategy getManagementNameStrategy() { 412 return managementNameStrategy; 413 } 414 415 public void setManagementNameStrategy(ManagementNameStrategy managementNameStrategy) { 416 this.managementNameStrategy = managementNameStrategy; 417 } 418 419 public String getManagementName() { 420 return managementName; 421 } 422 423 public void setManagementName(String managementName) { 424 this.managementName = managementName; 425 } 426 427 public Component hasComponent(String componentName) { 428 return components.get(componentName); 429 } 430 431 public void addComponent(String componentName, final Component component) { 432 ObjectHelper.notNull(component, "component"); 433 component.setCamelContext(this); 434 Component oldValue = components.putIfAbsent(componentName, component); 435 if (oldValue != null) { 436 throw new IllegalArgumentException("Cannot add component as its already previously added: " + componentName); 437 } 438 postInitComponent(componentName, component); 439 } 440 441 private void postInitComponent(String componentName, final Component component) { 442 for (LifecycleStrategy strategy : lifecycleStrategies) { 443 strategy.onComponentAdd(componentName, component); 444 } 445 446 // keep reference to properties component up to date 447 if (component instanceof PropertiesComponent && "properties".equals(componentName)) { 448 propertiesComponent = (PropertiesComponent) component; 449 } 450 } 451 452 public Component getComponent(String name) { 453 return getComponent(name, autoCreateComponents, true); 454 } 455 456 public Component getComponent(String name, boolean autoCreateComponents) { 457 return getComponent(name, autoCreateComponents, true); 458 } 459 460 public Component getComponent(String name, boolean autoCreateComponents, boolean autoStart) { 461 // Check if the named component is already being created, that would mean 462 // that the initComponent has triggered a new getComponent 463 if (componentsInCreation.get().contains(name)) { 464 throw new IllegalStateException("Circular dependency detected, the component " + name + " is already being created"); 465 } 466 467 try { 468 // Flag used to mark a component of being created. 469 final AtomicBoolean created = new AtomicBoolean(false); 470 471 // atomic operation to get/create a component. Avoid global locks. 472 final Component component = components.computeIfAbsent(name, comp -> { 473 created.set(true); 474 return initComponent(name, autoCreateComponents); 475 }); 476 477 // Start the component after its creation as if it is a component proxy 478 // that creates/start a delegated component, we may end up in a deadlock 479 if (component != null && created.get() && autoStart && (isStarted() || isStarting())) { 480 // If the component is looked up after the context is started, 481 // lets start it up. 482 if (component instanceof Service) { 483 startService((Service)component); 484 } 485 } 486 487 return component; 488 } catch (Exception e) { 489 throw new RuntimeCamelException("Cannot auto create component: " + name, e); 490 } finally { 491 // remove the reference to the component being created 492 componentsInCreation.get().remove(name); 493 } 494 } 495 496 /** 497 * Function to initialize a component and auto start. Returns null if the autoCreateComponents is disabled 498 */ 499 private Component initComponent(String name, boolean autoCreateComponents) { 500 Component component = null; 501 if (autoCreateComponents) { 502 try { 503 if (log.isDebugEnabled()) { 504 log.debug("Using ComponentResolver: {} to resolve component with name: {}", getComponentResolver(), name); 505 } 506 507 // Mark the component as being created so we can detect circular 508 // requests. 509 // 510 // In spring apps, the component resolver may trigger a new getComponent 511 // because of the underlying bean factory and as the endpoints are 512 // registered as singleton, the spring factory creates the bean 513 // and then check the type so the getComponent is always triggered. 514 // 515 // Simple circular dependency: 516 // 517 // <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring"> 518 // <route> 519 // <from id="twitter" uri="twitter://timeline/home?type=polling"/> 520 // <log message="Got ${body}"/> 521 // </route> 522 // </camelContext> 523 // 524 // Complex circular dependency: 525 // 526 // <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring"> 527 // <route> 528 // <from id="log" uri="seda:test"/> 529 // <to id="seda" uri="log:test"/> 530 // </route> 531 // </camelContext> 532 // 533 // This would freeze the app (lock or infinite loop). 534 // 535 // See https://issues.apache.org/jira/browse/CAMEL-11225 536 componentsInCreation.get().add(name); 537 538 component = getComponentResolver().resolveComponent(name, this); 539 if (component != null) { 540 component.setCamelContext(this); 541 postInitComponent(name, component); 542 } 543 } catch (Exception e) { 544 throw new RuntimeCamelException("Cannot auto create component: " + name, e); 545 } 546 } 547 return component; 548 } 549 550 public <T extends Component> T getComponent(String name, Class<T> componentType) { 551 Component component = getComponent(name); 552 if (componentType.isInstance(component)) { 553 return componentType.cast(component); 554 } else { 555 String message; 556 if (component == null) { 557 message = "Did not find component given by the name: " + name; 558 } else { 559 message = "Found component of type: " + component.getClass() + " instead of expected: " + componentType; 560 } 561 throw new IllegalArgumentException(message); 562 } 563 } 564 565 public Component resolveComponent(String name) { 566 Component answer = hasComponent(name); 567 if (answer == null) { 568 try { 569 answer = getComponentResolver().resolveComponent(name, this); 570 } catch (Exception e) { 571 throw new RuntimeCamelException("Cannot resolve component: " + name, e); 572 } 573 } 574 return answer; 575 } 576 577 public Component removeComponent(String componentName) { 578 Component oldComponent = components.remove(componentName); 579 if (oldComponent != null) { 580 try { 581 stopServices(oldComponent); 582 } catch (Exception e) { 583 log.warn("Error stopping component " + oldComponent + ". This exception will be ignored.", e); 584 } 585 for (LifecycleStrategy strategy : lifecycleStrategies) { 586 strategy.onComponentRemove(componentName, oldComponent); 587 } 588 } 589 // keep reference to properties component up to date 590 if (oldComponent != null && "properties".equals(componentName)) { 591 propertiesComponent = null; 592 } 593 return oldComponent; 594 } 595 596 // Endpoint Management Methods 597 // ----------------------------------------------------------------------- 598 599 public EndpointRegistry getEndpointRegistry() { 600 return endpoints; 601 } 602 603 public Collection<Endpoint> getEndpoints() { 604 return new ArrayList<Endpoint>(endpoints.values()); 605 } 606 607 public Map<String, Endpoint> getEndpointMap() { 608 Map<String, Endpoint> answer = new TreeMap<String, Endpoint>(); 609 for (Map.Entry<EndpointKey, Endpoint> entry : endpoints.entrySet()) { 610 answer.put(entry.getKey().get(), entry.getValue()); 611 } 612 return answer; 613 } 614 615 public Endpoint hasEndpoint(String uri) { 616 return endpoints.get(getEndpointKey(uri)); 617 } 618 619 public Endpoint addEndpoint(String uri, Endpoint endpoint) throws Exception { 620 Endpoint oldEndpoint; 621 622 startService(endpoint); 623 oldEndpoint = endpoints.remove(getEndpointKey(uri)); 624 for (LifecycleStrategy strategy : lifecycleStrategies) { 625 strategy.onEndpointAdd(endpoint); 626 } 627 addEndpointToRegistry(uri, endpoint); 628 if (oldEndpoint != null) { 629 stopServices(oldEndpoint); 630 } 631 632 return oldEndpoint; 633 } 634 635 public void removeEndpoint(Endpoint endpoint) throws Exception { 636 removeEndpoints(endpoint.getEndpointUri()); 637 } 638 639 public Collection<Endpoint> removeEndpoints(String uri) throws Exception { 640 Collection<Endpoint> answer = new ArrayList<Endpoint>(); 641 Endpoint oldEndpoint = endpoints.remove(getEndpointKey(uri)); 642 if (oldEndpoint != null) { 643 answer.add(oldEndpoint); 644 stopServices(oldEndpoint); 645 } else { 646 for (Map.Entry<EndpointKey, Endpoint> entry : endpoints.entrySet()) { 647 oldEndpoint = entry.getValue(); 648 if (EndpointHelper.matchEndpoint(this, oldEndpoint.getEndpointUri(), uri)) { 649 try { 650 stopServices(oldEndpoint); 651 } catch (Exception e) { 652 log.warn("Error stopping endpoint " + oldEndpoint + ". This exception will be ignored.", e); 653 } 654 answer.add(oldEndpoint); 655 endpoints.remove(entry.getKey()); 656 } 657 } 658 } 659 660 // notify lifecycle its being removed 661 for (Endpoint endpoint : answer) { 662 for (LifecycleStrategy strategy : lifecycleStrategies) { 663 strategy.onEndpointRemove(endpoint); 664 } 665 } 666 667 return answer; 668 } 669 670 public Endpoint getEndpoint(String uri) { 671 ObjectHelper.notEmpty(uri, "uri"); 672 673 log.trace("Getting endpoint with uri: {}", uri); 674 675 // in case path has property placeholders then try to let property component resolve those 676 try { 677 uri = resolvePropertyPlaceholders(uri); 678 } catch (Exception e) { 679 throw new ResolveEndpointFailedException(uri, e); 680 } 681 682 final String rawUri = uri; 683 684 // normalize uri so we can do endpoint hits with minor mistakes and parameters is not in the same order 685 uri = normalizeEndpointUri(uri); 686 687 log.trace("Getting endpoint with raw uri: {}, normalized uri: {}", rawUri, uri); 688 689 Endpoint answer; 690 String scheme = null; 691 // use optimized method to get the endpoint uri 692 EndpointKey key = getEndpointKeyPreNormalized(uri); 693 answer = endpoints.get(key); 694 if (answer == null) { 695 try { 696 // Use the URI prefix to find the component. 697 String splitURI[] = ObjectHelper.splitOnCharacter(uri, ":", 2); 698 if (splitURI[1] != null) { 699 scheme = splitURI[0]; 700 log.trace("Endpoint uri: {} is from component with name: {}", uri, scheme); 701 Component component = getComponent(scheme); 702 703 // Ask the component to resolve the endpoint. 704 if (component != null) { 705 log.trace("Creating endpoint from uri: {} using component: {}", uri, component); 706 707 // Have the component create the endpoint if it can. 708 if (component.useRawUri()) { 709 answer = component.createEndpoint(rawUri); 710 } else { 711 answer = component.createEndpoint(uri); 712 } 713 714 if (answer != null && log.isDebugEnabled()) { 715 log.debug("{} converted to endpoint: {} by component: {}", new Object[]{URISupport.sanitizeUri(uri), answer, component}); 716 } 717 } 718 } 719 720 if (answer == null) { 721 // no component then try in registry and elsewhere 722 answer = createEndpoint(uri); 723 log.trace("No component to create endpoint from uri: {} fallback lookup in registry -> {}", uri, answer); 724 } 725 726 if (answer == null && splitURI[1] == null) { 727 // the uri has no context-path which is rare and it was not referring to an endpoint in the registry 728 // so try to see if it can be created by a component 729 730 int pos = uri.indexOf('?'); 731 String componentName = pos > 0 ? uri.substring(0, pos) : uri; 732 733 Component component = getComponent(componentName); 734 735 // Ask the component to resolve the endpoint. 736 if (component != null) { 737 log.trace("Creating endpoint from uri: {} using component: {}", uri, component); 738 739 // Have the component create the endpoint if it can. 740 if (component.useRawUri()) { 741 answer = component.createEndpoint(rawUri); 742 } else { 743 answer = component.createEndpoint(uri); 744 } 745 746 if (answer != null && log.isDebugEnabled()) { 747 log.debug("{} converted to endpoint: {} by component: {}", new Object[]{URISupport.sanitizeUri(uri), answer, component}); 748 } 749 } 750 751 } 752 753 if (answer != null) { 754 addService(answer); 755 answer = addEndpointToRegistry(uri, answer); 756 } 757 } catch (Exception e) { 758 throw new ResolveEndpointFailedException(uri, e); 759 } 760 } 761 762 // unknown scheme 763 if (answer == null && scheme != null) { 764 throw new ResolveEndpointFailedException(uri, "No component found with scheme: " + scheme); 765 } 766 767 return answer; 768 } 769 770 public <T extends Endpoint> T getEndpoint(String name, Class<T> endpointType) { 771 Endpoint endpoint = getEndpoint(name); 772 if (endpoint == null) { 773 throw new NoSuchEndpointException(name); 774 } 775 if (endpoint instanceof InterceptSendToEndpoint) { 776 endpoint = ((InterceptSendToEndpoint) endpoint).getDelegate(); 777 } 778 if (endpointType.isInstance(endpoint)) { 779 return endpointType.cast(endpoint); 780 } else { 781 throw new IllegalArgumentException("The endpoint is not of type: " + endpointType 782 + " but is: " + endpoint.getClass().getCanonicalName()); 783 } 784 } 785 786 public void addRegisterEndpointCallback(EndpointStrategy strategy) { 787 if (!endpointStrategies.contains(strategy)) { 788 // let it be invoked for already registered endpoints so it can catch-up. 789 endpointStrategies.add(strategy); 790 for (Endpoint endpoint : getEndpoints()) { 791 Endpoint newEndpoint = strategy.registerEndpoint(endpoint.getEndpointUri(), endpoint); 792 if (newEndpoint != null) { 793 // put will replace existing endpoint with the new endpoint 794 endpoints.put(getEndpointKey(endpoint.getEndpointUri()), newEndpoint); 795 } 796 } 797 } 798 } 799 800 /** 801 * Strategy to add the given endpoint to the internal endpoint registry 802 * 803 * @param uri uri of the endpoint 804 * @param endpoint the endpoint to add 805 * @return the added endpoint 806 */ 807 protected Endpoint addEndpointToRegistry(String uri, Endpoint endpoint) { 808 ObjectHelper.notEmpty(uri, "uri"); 809 ObjectHelper.notNull(endpoint, "endpoint"); 810 811 // if there is endpoint strategies, then use the endpoints they return 812 // as this allows to intercept endpoints etc. 813 for (EndpointStrategy strategy : endpointStrategies) { 814 endpoint = strategy.registerEndpoint(uri, endpoint); 815 } 816 endpoints.put(getEndpointKey(uri, endpoint), endpoint); 817 return endpoint; 818 } 819 820 /** 821 * Normalize uri so we can do endpoint hits with minor mistakes and parameters is not in the same order. 822 * 823 * @param uri the uri 824 * @return normalized uri 825 * @throws ResolveEndpointFailedException if uri cannot be normalized 826 */ 827 protected static String normalizeEndpointUri(String uri) { 828 try { 829 uri = URISupport.normalizeUri(uri); 830 } catch (Exception e) { 831 throw new ResolveEndpointFailedException(uri, e); 832 } 833 return uri; 834 } 835 836 /** 837 * Gets the endpoint key to use for lookup or whe adding endpoints to the {@link DefaultEndpointRegistry} 838 * 839 * @param uri the endpoint uri 840 * @return the key 841 */ 842 protected EndpointKey getEndpointKey(String uri) { 843 return new EndpointKey(uri); 844 } 845 846 /** 847 * Gets the endpoint key to use for lookup or whe adding endpoints to the {@link DefaultEndpointRegistry} 848 * 849 * @param uri the endpoint uri which is pre normalized 850 * @return the key 851 */ 852 protected EndpointKey getEndpointKeyPreNormalized(String uri) { 853 return new EndpointKey(uri, true); 854 } 855 856 /** 857 * Gets the endpoint key to use for lookup or whe adding endpoints to the {@link DefaultEndpointRegistry} 858 * 859 * @param uri the endpoint uri 860 * @param endpoint the endpoint 861 * @return the key 862 */ 863 protected EndpointKey getEndpointKey(String uri, Endpoint endpoint) { 864 if (endpoint != null && !endpoint.isSingleton()) { 865 int counter = endpointKeyCounter.incrementAndGet(); 866 return new EndpointKey(uri + ":" + counter); 867 } else { 868 return new EndpointKey(uri); 869 } 870 } 871 872 // Route Management Methods 873 // ----------------------------------------------------------------------- 874 875 @Override 876 public void setRouteController(RouteController routeController) { 877 this.routeController = routeController; 878 this.routeController.setCamelContext(this); 879 } 880 881 @Override 882 public RouteController getRouteController() { 883 return routeController; 884 } 885 886 public List<RouteStartupOrder> getRouteStartupOrder() { 887 return routeStartupOrder; 888 } 889 890 public List<Route> getRoutes() { 891 // lets return a copy of the collection as objects are removed later when services are stopped 892 if (routes.isEmpty()) { 893 return Collections.emptyList(); 894 } else { 895 synchronized (routes) { 896 return new ArrayList<Route>(routes); 897 } 898 } 899 } 900 901 public Route getRoute(String id) { 902 for (Route route : getRoutes()) { 903 if (route.getId().equals(id)) { 904 return route; 905 } 906 } 907 return null; 908 } 909 910 public Processor getProcessor(String id) { 911 for (Route route : getRoutes()) { 912 List<Processor> list = route.filter(id); 913 if (list.size() == 1) { 914 return list.get(0); 915 } 916 } 917 return null; 918 } 919 920 public <T extends Processor> T getProcessor(String id, Class<T> type) { 921 Processor answer = getProcessor(id); 922 if (answer != null) { 923 return type.cast(answer); 924 } 925 return null; 926 } 927 928 public <T extends ManagedProcessorMBean> T getManagedProcessor(String id, Class<T> type) { 929 // jmx must be enabled 930 if (getManagementStrategy().getManagementAgent() == null) { 931 return null; 932 } 933 934 Processor processor = getProcessor(id); 935 ProcessorDefinition def = getProcessorDefinition(id); 936 937 // processor may be null if its anonymous inner class or as lambda 938 if (def != null) { 939 try { 940 ObjectName on = getManagementStrategy().getManagementNamingStrategy().getObjectNameForProcessor(this, processor, def); 941 return getManagementStrategy().getManagementAgent().newProxyClient(on, type); 942 } catch (MalformedObjectNameException e) { 943 throw ObjectHelper.wrapRuntimeCamelException(e); 944 } 945 } 946 947 return null; 948 } 949 950 public <T extends ManagedRouteMBean> T getManagedRoute(String routeId, Class<T> type) { 951 // jmx must be enabled 952 if (getManagementStrategy().getManagementAgent() == null) { 953 return null; 954 } 955 956 Route route = getRoute(routeId); 957 958 if (route != null) { 959 try { 960 ObjectName on = getManagementStrategy().getManagementNamingStrategy().getObjectNameForRoute(route); 961 return getManagementStrategy().getManagementAgent().newProxyClient(on, type); 962 } catch (MalformedObjectNameException e) { 963 throw ObjectHelper.wrapRuntimeCamelException(e); 964 } 965 } 966 967 return null; 968 } 969 970 public ManagedCamelContextMBean getManagedCamelContext() { 971 // jmx must be enabled 972 if (getManagementStrategy().getManagementAgent() == null) { 973 return null; 974 } 975 976 try { 977 ObjectName on = getManagementStrategy().getManagementNamingStrategy().getObjectNameForCamelContext(this); 978 return getManagementStrategy().getManagementAgent().newProxyClient(on, ManagedCamelContextMBean.class); 979 } catch (MalformedObjectNameException e) { 980 throw ObjectHelper.wrapRuntimeCamelException(e); 981 } 982 } 983 984 public ProcessorDefinition getProcessorDefinition(String id) { 985 for (RouteDefinition route : getRouteDefinitions()) { 986 Iterator<ProcessorDefinition> it = ProcessorDefinitionHelper.filterTypeInOutputs(route.getOutputs(), ProcessorDefinition.class); 987 while (it.hasNext()) { 988 ProcessorDefinition proc = it.next(); 989 if (id.equals(proc.getId())) { 990 return proc; 991 } 992 } 993 } 994 return null; 995 } 996 997 public <T extends ProcessorDefinition> T getProcessorDefinition(String id, Class<T> type) { 998 ProcessorDefinition answer = getProcessorDefinition(id); 999 if (answer != null) { 1000 return type.cast(answer); 1001 } 1002 return null; 1003 } 1004 1005 @Deprecated 1006 public void setRoutes(List<Route> routes) { 1007 throw new UnsupportedOperationException("Overriding existing routes is not supported yet, use addRouteCollection instead"); 1008 } 1009 1010 void removeRouteCollection(Collection<Route> routes) { 1011 synchronized (this.routes) { 1012 this.routes.removeAll(routes); 1013 } 1014 } 1015 1016 void addRouteCollection(Collection<Route> routes) throws Exception { 1017 synchronized (this.routes) { 1018 this.routes.addAll(routes); 1019 } 1020 } 1021 1022 public void addRoutes(final RoutesBuilder builder) throws Exception { 1023 log.debug("Adding routes from builder: {}", builder); 1024 doWithDefinedClassLoader(new Callable<Void>() { 1025 @Override 1026 public Void call() throws Exception { 1027 builder.addRoutesToCamelContext(DefaultCamelContext.this); 1028 return null; 1029 } 1030 }); 1031 } 1032 1033 public synchronized RoutesDefinition loadRoutesDefinition(InputStream is) throws Exception { 1034 return ModelHelper.loadRoutesDefinition(this, is); 1035 } 1036 1037 public synchronized RestsDefinition loadRestsDefinition(InputStream is) throws Exception { 1038 // load routes using JAXB 1039 if (jaxbContext == null) { 1040 // must use classloader from CamelContext to have JAXB working 1041 jaxbContext = getModelJAXBContextFactory().newJAXBContext(); 1042 } 1043 1044 Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); 1045 Object result = unmarshaller.unmarshal(is); 1046 1047 if (result == null) { 1048 throw new IOException("Cannot unmarshal to rests using JAXB from input stream: " + is); 1049 } 1050 1051 // can either be routes or a single route 1052 RestsDefinition answer; 1053 if (result instanceof RestDefinition) { 1054 RestDefinition rest = (RestDefinition) result; 1055 answer = new RestsDefinition(); 1056 answer.getRests().add(rest); 1057 } else if (result instanceof RestsDefinition) { 1058 answer = (RestsDefinition) result; 1059 } else { 1060 throw new IllegalArgumentException("Unmarshalled object is an unsupported type: " + ObjectHelper.className(result) + " -> " + result); 1061 } 1062 1063 return answer; 1064 } 1065 1066 public synchronized void addRouteDefinitions(Collection<RouteDefinition> routeDefinitions) throws Exception { 1067 if (routeDefinitions == null || routeDefinitions.isEmpty()) { 1068 return; 1069 } 1070 for (RouteDefinition routeDefinition : routeDefinitions) { 1071 removeRouteDefinition(routeDefinition); 1072 } 1073 this.routeDefinitions.addAll(routeDefinitions); 1074 if (shouldStartRoutes()) { 1075 startRouteDefinitions(routeDefinitions); 1076 } 1077 } 1078 1079 public void addRouteDefinition(RouteDefinition routeDefinition) throws Exception { 1080 addRouteDefinitions(Arrays.asList(routeDefinition)); 1081 } 1082 1083 /** 1084 * Removes the route definition with the given key. 1085 * 1086 * @return true if one or more routes was removed 1087 */ 1088 protected boolean removeRouteDefinition(String key) { 1089 boolean answer = false; 1090 Iterator<RouteDefinition> iter = routeDefinitions.iterator(); 1091 while (iter.hasNext()) { 1092 RouteDefinition route = iter.next(); 1093 if (route.idOrCreate(nodeIdFactory).equals(key)) { 1094 iter.remove(); 1095 answer = true; 1096 } 1097 } 1098 return answer; 1099 } 1100 1101 public synchronized void removeRouteDefinitions(Collection<RouteDefinition> routeDefinitions) throws Exception { 1102 for (RouteDefinition routeDefinition : routeDefinitions) { 1103 removeRouteDefinition(routeDefinition); 1104 } 1105 } 1106 1107 public synchronized void removeRouteDefinition(RouteDefinition routeDefinition) throws Exception { 1108 RouteDefinition toBeRemoved = routeDefinition; 1109 String id = routeDefinition.getId(); 1110 if (id != null) { 1111 // remove existing route 1112 stopRoute(id); 1113 removeRoute(id); 1114 toBeRemoved = getRouteDefinition(id); 1115 } 1116 this.routeDefinitions.remove(toBeRemoved); 1117 } 1118 1119 public ServiceStatus getRouteStatus(String key) { 1120 RouteService routeService = routeServices.get(key); 1121 if (routeService != null) { 1122 return routeService.getStatus(); 1123 } 1124 return null; 1125 } 1126 1127 public void startRoute(RouteDefinition route) throws Exception { 1128 // assign ids to the routes and validate that the id's is all unique 1129 RouteDefinitionHelper.forceAssignIds(this, routeDefinitions); 1130 String duplicate = RouteDefinitionHelper.validateUniqueIds(route, routeDefinitions); 1131 if (duplicate != null) { 1132 throw new FailedToStartRouteException(route.getId(), "duplicate id detected: " + duplicate + ". Please correct ids to be unique among all your routes."); 1133 } 1134 1135 // indicate we are staring the route using this thread so 1136 // we are able to query this if needed 1137 isStartingRoutes.set(true); 1138 try { 1139 // must ensure route is prepared, before we can start it 1140 route.prepare(this); 1141 1142 List<Route> routes = new ArrayList<Route>(); 1143 List<RouteContext> routeContexts = route.addRoutes(this, routes); 1144 RouteService routeService = new RouteService(this, route, routeContexts, routes); 1145 startRouteService(routeService, true); 1146 } finally { 1147 // we are done staring routes 1148 isStartingRoutes.remove(); 1149 } 1150 } 1151 1152 public boolean isStartingRoutes() { 1153 Boolean answer = isStartingRoutes.get(); 1154 return answer != null && answer; 1155 } 1156 1157 public boolean isSetupRoutes() { 1158 Boolean answer = isSetupRoutes.get(); 1159 return answer != null && answer; 1160 } 1161 1162 public void stopRoute(RouteDefinition route) throws Exception { 1163 stopRoute(route.idOrCreate(nodeIdFactory)); 1164 } 1165 1166 public void startAllRoutes() throws Exception { 1167 doStartOrResumeRoutes(routeServices, true, true, false, false); 1168 } 1169 1170 public synchronized void startRoute(String routeId) throws Exception { 1171 DefaultRouteError.reset(this, routeId); 1172 1173 RouteService routeService = routeServices.get(routeId); 1174 if (routeService != null) { 1175 try { 1176 startRouteService(routeService, false); 1177 } catch (Exception e) { 1178 DefaultRouteError.set(this, routeId, RouteError.Phase.START, e); 1179 throw e; 1180 } 1181 } 1182 } 1183 1184 public synchronized void resumeRoute(String routeId) throws Exception { 1185 DefaultRouteError.reset(this, routeId); 1186 1187 try { 1188 if (!routeSupportsSuspension(routeId)) { 1189 // start route if suspension is not supported 1190 startRoute(routeId); 1191 return; 1192 } 1193 1194 RouteService routeService = routeServices.get(routeId); 1195 if (routeService != null) { 1196 resumeRouteService(routeService); 1197 // must resume the route as well 1198 Route route = getRoute(routeId); 1199 ServiceHelper.resumeService(route); 1200 } 1201 } catch (Exception e) { 1202 DefaultRouteError.set(this, routeId, RouteError.Phase.RESUME, e); 1203 throw e; 1204 } 1205 } 1206 1207 public synchronized boolean stopRoute(String routeId, long timeout, TimeUnit timeUnit, boolean abortAfterTimeout) throws Exception { 1208 DefaultRouteError.reset(this, routeId); 1209 1210 RouteService routeService = routeServices.get(routeId); 1211 if (routeService != null) { 1212 try { 1213 RouteStartupOrder route = new DefaultRouteStartupOrder(1, routeService.getRoutes().iterator().next(), routeService); 1214 1215 boolean completed = getShutdownStrategy().shutdown(this, route, timeout, timeUnit, abortAfterTimeout); 1216 if (completed) { 1217 // must stop route service as well 1218 stopRouteService(routeService, false); 1219 } else { 1220 // shutdown was aborted, make sure route is re-started properly 1221 startRouteService(routeService, false); 1222 } 1223 return completed; 1224 } catch (Exception e) { 1225 DefaultRouteError.set(this, routeId, RouteError.Phase.STOP, e); 1226 throw e; 1227 } 1228 } 1229 1230 return false; 1231 } 1232 1233 public synchronized void stopRoute(String routeId) throws Exception { 1234 DefaultRouteError.reset(this, routeId); 1235 1236 RouteService routeService = routeServices.get(routeId); 1237 if (routeService != null) { 1238 try { 1239 List<RouteStartupOrder> routes = new ArrayList<RouteStartupOrder>(1); 1240 RouteStartupOrder order = new DefaultRouteStartupOrder(1, routeService.getRoutes().iterator().next(), routeService); 1241 routes.add(order); 1242 1243 getShutdownStrategy().shutdown(this, routes); 1244 // must stop route service as well 1245 stopRouteService(routeService, false); 1246 } catch (Exception e) { 1247 DefaultRouteError.set(this, routeId, RouteError.Phase.STOP, e); 1248 throw e; 1249 } 1250 } 1251 } 1252 1253 public synchronized void stopRoute(String routeId, long timeout, TimeUnit timeUnit) throws Exception { 1254 DefaultRouteError.reset(this, routeId); 1255 1256 RouteService routeService = routeServices.get(routeId); 1257 if (routeService != null) { 1258 try { 1259 List<RouteStartupOrder> routes = new ArrayList<RouteStartupOrder>(1); 1260 RouteStartupOrder order = new DefaultRouteStartupOrder(1, routeService.getRoutes().iterator().next(), routeService); 1261 routes.add(order); 1262 1263 getShutdownStrategy().shutdown(this, routes, timeout, timeUnit); 1264 // must stop route service as well 1265 stopRouteService(routeService, false); 1266 } catch (Exception e) { 1267 DefaultRouteError.set(this, routeId, RouteError.Phase.STOP, e); 1268 throw e; 1269 } 1270 } 1271 } 1272 1273 public synchronized void shutdownRoute(String routeId) throws Exception { 1274 DefaultRouteError.reset(this, routeId); 1275 1276 RouteService routeService = routeServices.get(routeId); 1277 if (routeService != null) { 1278 try { 1279 List<RouteStartupOrder> routes = new ArrayList<RouteStartupOrder>(1); 1280 RouteStartupOrder order = new DefaultRouteStartupOrder(1, routeService.getRoutes().iterator().next(), routeService); 1281 routes.add(order); 1282 1283 getShutdownStrategy().shutdown(this, routes); 1284 // must stop route service as well (and remove the routes from management) 1285 stopRouteService(routeService, true); 1286 } catch (Exception e) { 1287 DefaultRouteError.set(this, routeId, RouteError.Phase.SHUTDOWN, e); 1288 throw e; 1289 } 1290 } 1291 } 1292 1293 public synchronized void shutdownRoute(String routeId, long timeout, TimeUnit timeUnit) throws Exception { 1294 DefaultRouteError.reset(this, routeId); 1295 1296 RouteService routeService = routeServices.get(routeId); 1297 if (routeService != null) { 1298 try { 1299 List<RouteStartupOrder> routes = new ArrayList<RouteStartupOrder>(1); 1300 RouteStartupOrder order = new DefaultRouteStartupOrder(1, routeService.getRoutes().iterator().next(), routeService); 1301 routes.add(order); 1302 1303 getShutdownStrategy().shutdown(this, routes, timeout, timeUnit); 1304 // must stop route service as well (and remove the routes from management) 1305 stopRouteService(routeService, true); 1306 } catch (Exception e) { 1307 DefaultRouteError.set(this, routeId, RouteError.Phase.SHUTDOWN, e); 1308 throw e; 1309 } 1310 } 1311 } 1312 1313 public synchronized boolean removeRoute(String routeId) throws Exception { 1314 DefaultRouteError.reset(this, routeId); 1315 1316 // remove the route from ErrorHandlerBuilder if possible 1317 if (getErrorHandlerBuilder() instanceof ErrorHandlerBuilderSupport) { 1318 ErrorHandlerBuilderSupport builder = (ErrorHandlerBuilderSupport)getErrorHandlerBuilder(); 1319 builder.removeOnExceptionList(routeId); 1320 } 1321 1322 // gather a map of all the endpoints in use by the routes, so we can known if a given endpoints is in use 1323 // by one or more routes, when we remove the route 1324 Map<String, Set<Endpoint>> endpointsInUse = new HashMap<String, Set<Endpoint>>(); 1325 for (Map.Entry<String, RouteService> entry : routeServices.entrySet()) { 1326 endpointsInUse.put(entry.getKey(), entry.getValue().gatherEndpoints()); 1327 } 1328 1329 RouteService routeService = routeServices.get(routeId); 1330 if (routeService != null) { 1331 if (getRouteStatus(routeId).isStopped()) { 1332 try { 1333 routeService.setRemovingRoutes(true); 1334 shutdownRouteService(routeService); 1335 removeRouteDefinition(routeId); 1336 routeServices.remove(routeId); 1337 // remove route from startup order as well, as it was removed 1338 Iterator<RouteStartupOrder> it = routeStartupOrder.iterator(); 1339 while (it.hasNext()) { 1340 RouteStartupOrder order = it.next(); 1341 if (order.getRoute().getId().equals(routeId)) { 1342 it.remove(); 1343 } 1344 } 1345 1346 // from the route which we have removed, then remove all its private endpoints 1347 // (eg the endpoints which are not in use by other routes) 1348 Set<Endpoint> toRemove = new LinkedHashSet<Endpoint>(); 1349 for (Endpoint endpoint : endpointsInUse.get(routeId)) { 1350 // how many times is the endpoint in use 1351 int count = 0; 1352 for (Set<Endpoint> endpoints : endpointsInUse.values()) { 1353 if (endpoints.contains(endpoint)) { 1354 count++; 1355 } 1356 } 1357 // notice we will count ourselves so if there is only 1 then its safe to remove 1358 if (count <= 1) { 1359 toRemove.add(endpoint); 1360 } 1361 } 1362 for (Endpoint endpoint : toRemove) { 1363 log.debug("Removing: {} which was only in use by route: {}", endpoint, routeId); 1364 removeEndpoint(endpoint); 1365 } 1366 } catch (Exception e) { 1367 DefaultRouteError.set(this, routeId, RouteError.Phase.REMOVE, e); 1368 throw e; 1369 } 1370 1371 return true; 1372 } else { 1373 return false; 1374 } 1375 } 1376 return false; 1377 } 1378 1379 public synchronized void suspendRoute(String routeId) throws Exception { 1380 try { 1381 DefaultRouteError.reset(this, routeId); 1382 1383 if (!routeSupportsSuspension(routeId)) { 1384 // stop if we suspend is not supported 1385 stopRoute(routeId); 1386 return; 1387 } 1388 1389 RouteService routeService = routeServices.get(routeId); 1390 if (routeService != null) { 1391 List<RouteStartupOrder> routes = new ArrayList<RouteStartupOrder>(1); 1392 Route route = routeService.getRoutes().iterator().next(); 1393 RouteStartupOrder order = new DefaultRouteStartupOrder(1, route, routeService); 1394 routes.add(order); 1395 1396 getShutdownStrategy().suspend(this, routes); 1397 // must suspend route service as well 1398 suspendRouteService(routeService); 1399 // must suspend the route as well 1400 if (route instanceof SuspendableService) { 1401 ((SuspendableService) route).suspend(); 1402 } 1403 } 1404 } catch (Exception e) { 1405 DefaultRouteError.set(this, routeId, RouteError.Phase.SUSPEND, e); 1406 throw e; 1407 } 1408 } 1409 1410 public synchronized void suspendRoute(String routeId, long timeout, TimeUnit timeUnit) throws Exception { 1411 DefaultRouteError.reset(this, routeId); 1412 1413 try { 1414 if (!routeSupportsSuspension(routeId)) { 1415 stopRoute(routeId, timeout, timeUnit); 1416 return; 1417 } 1418 1419 RouteService routeService = routeServices.get(routeId); 1420 if (routeService != null) { 1421 List<RouteStartupOrder> routes = new ArrayList<RouteStartupOrder>(1); 1422 Route route = routeService.getRoutes().iterator().next(); 1423 RouteStartupOrder order = new DefaultRouteStartupOrder(1, route, routeService); 1424 routes.add(order); 1425 1426 getShutdownStrategy().suspend(this, routes, timeout, timeUnit); 1427 // must suspend route service as well 1428 suspendRouteService(routeService); 1429 // must suspend the route as well 1430 if (route instanceof SuspendableService) { 1431 ((SuspendableService) route).suspend(); 1432 } 1433 } 1434 } catch (Exception e) { 1435 DefaultRouteError.set(this, routeId, RouteError.Phase.SUSPEND, e); 1436 throw e; 1437 } 1438 } 1439 1440 public void addService(Object object) throws Exception { 1441 addService(object, true); 1442 } 1443 1444 public void addService(Object object, boolean stopOnShutdown) throws Exception { 1445 doAddService(object, stopOnShutdown, false); 1446 } 1447 1448 @Override 1449 public void addService(Object object, boolean stopOnShutdown, boolean forceStart) throws Exception { 1450 doAddService(object, stopOnShutdown, forceStart); 1451 } 1452 1453 private void doAddService(Object object, boolean stopOnShutdown, boolean forceStart) throws Exception { 1454 1455 // inject CamelContext 1456 if (object instanceof CamelContextAware) { 1457 CamelContextAware aware = (CamelContextAware) object; 1458 aware.setCamelContext(this); 1459 } 1460 1461 if (object instanceof Service) { 1462 Service service = (Service) object; 1463 1464 for (LifecycleStrategy strategy : lifecycleStrategies) { 1465 if (service instanceof Endpoint) { 1466 // use specialized endpoint add 1467 strategy.onEndpointAdd((Endpoint) service); 1468 } else { 1469 strategy.onServiceAdd(this, service, null); 1470 } 1471 } 1472 1473 if (!forceStart) { 1474 // now start the service (and defer starting if CamelContext is starting up itself) 1475 deferStartService(object, stopOnShutdown); 1476 } else { 1477 // only add to services to close if its a singleton 1478 // otherwise we could for example end up with a lot of prototype scope endpoints 1479 boolean singleton = true; // assume singleton by default 1480 if (object instanceof IsSingleton) { 1481 singleton = ((IsSingleton) service).isSingleton(); 1482 } 1483 // do not add endpoints as they have their own list 1484 if (singleton && !(service instanceof Endpoint)) { 1485 // only add to list of services to stop if its not already there 1486 if (stopOnShutdown && !hasService(service)) { 1487 servicesToStop.add(service); 1488 } 1489 } 1490 ServiceHelper.startService(service); 1491 } 1492 } 1493 } 1494 1495 public boolean removeService(Object object) throws Exception { 1496 if (object instanceof Endpoint) { 1497 removeEndpoint((Endpoint) object); 1498 return true; 1499 } 1500 if (object instanceof Service) { 1501 Service service = (Service) object; 1502 for (LifecycleStrategy strategy : lifecycleStrategies) { 1503 strategy.onServiceRemove(this, service, null); 1504 } 1505 return servicesToStop.remove(service); 1506 } 1507 return false; 1508 } 1509 1510 public boolean hasService(Object object) { 1511 if (object instanceof Service) { 1512 Service service = (Service) object; 1513 return servicesToStop.contains(service); 1514 } 1515 return false; 1516 } 1517 1518 @Override 1519 public <T> T hasService(Class<T> type) { 1520 for (Service service : servicesToStop) { 1521 if (type.isInstance(service)) { 1522 return type.cast(service); 1523 } 1524 } 1525 return null; 1526 } 1527 1528 @Override 1529 public <T> Set<T> hasServices(Class<T> type) { 1530 Set<T> set = new HashSet<>(); 1531 for (Service service : servicesToStop) { 1532 if (type.isInstance(service)) { 1533 set.add((T) service); 1534 } 1535 } 1536 return set; 1537 } 1538 1539 public void deferStartService(Object object, boolean stopOnShutdown) throws Exception { 1540 if (object instanceof Service) { 1541 Service service = (Service) object; 1542 1543 // only add to services to close if its a singleton 1544 // otherwise we could for example end up with a lot of prototype scope endpoints 1545 boolean singleton = true; // assume singleton by default 1546 if (object instanceof IsSingleton) { 1547 singleton = ((IsSingleton) service).isSingleton(); 1548 } 1549 // do not add endpoints as they have their own list 1550 if (singleton && !(service instanceof Endpoint)) { 1551 // only add to list of services to stop if its not already there 1552 if (stopOnShutdown && !hasService(service)) { 1553 servicesToStop.add(service); 1554 } 1555 } 1556 // are we already started? 1557 if (isStarted()) { 1558 ServiceHelper.startService(service); 1559 } else { 1560 deferStartupListener.addService(service); 1561 } 1562 } 1563 } 1564 1565 public void addStartupListener(StartupListener listener) throws Exception { 1566 // either add to listener so we can invoke then later when CamelContext has been started 1567 // or invoke the callback right now 1568 if (isStarted()) { 1569 listener.onCamelContextStarted(this, true); 1570 } else { 1571 startupListeners.add(listener); 1572 } 1573 } 1574 1575 public String resolveComponentDefaultName(String javaType) { 1576 // special for some components 1577 // TODO: ActiveMQ 5.11 will include this out of the box, so not needed when its released 1578 if ("org.apache.activemq.camel.component.ActiveMQComponent".equals(javaType)) { 1579 return "jms"; 1580 } 1581 1582 // try to find the component by its java type from the in-use components 1583 if (javaType != null) { 1584 // find all the components which will include the default component name 1585 try { 1586 Map<String, Properties> all = CamelContextHelper.findComponents(this); 1587 for (Map.Entry<String, Properties> entry : all.entrySet()) { 1588 String fqn = (String) entry.getValue().get("class"); 1589 if (javaType.equals(fqn)) { 1590 // is there component docs for that name? 1591 String name = entry.getKey(); 1592 String json = getComponentParameterJsonSchema(name); 1593 if (json != null) { 1594 return name; 1595 } 1596 } 1597 } 1598 } catch (Exception e) { 1599 // ignore 1600 return null; 1601 } 1602 } 1603 1604 // could not find a component with that name 1605 return null; 1606 } 1607 1608 public Map<String, Properties> findComponents() throws LoadPropertiesException, IOException { 1609 return CamelContextHelper.findComponents(this); 1610 } 1611 1612 public Map<String, Properties> findEips() throws LoadPropertiesException, IOException { 1613 return CamelContextHelper.findEips(this); 1614 } 1615 1616 public String getComponentDocumentation(String componentName) throws IOException { 1617 return null; 1618 } 1619 1620 public String getComponentParameterJsonSchema(String componentName) throws IOException { 1621 // use the component factory finder to find the package name of the component class, which is the location 1622 // where the documentation exists as well 1623 FactoryFinder finder = getFactoryFinder(DefaultComponentResolver.RESOURCE_PATH); 1624 try { 1625 Class<?> clazz = null; 1626 try { 1627 clazz = finder.findClass(componentName); 1628 } catch (NoFactoryAvailableException e) { 1629 // ignore, i.e. if a component is an auto-configured spring-boot 1630 // component 1631 } 1632 1633 if (clazz == null) { 1634 // fallback and find existing component 1635 Component existing = hasComponent(componentName); 1636 if (existing != null) { 1637 clazz = existing.getClass(); 1638 } else { 1639 return null; 1640 } 1641 } 1642 1643 String packageName = clazz.getPackage().getName(); 1644 packageName = packageName.replace('.', '/'); 1645 String path = packageName + "/" + componentName + ".json"; 1646 1647 ClassResolver resolver = getClassResolver(); 1648 InputStream inputStream = resolver.loadResourceAsStream(path); 1649 log.debug("Loading component JSON Schema for: {} using class resolver: {} -> {}", new Object[]{componentName, resolver, inputStream}); 1650 if (inputStream != null) { 1651 try { 1652 return IOHelper.loadText(inputStream); 1653 } finally { 1654 IOHelper.close(inputStream); 1655 } 1656 } 1657 // special for ActiveMQ as it is really just JMS 1658 if ("ActiveMQComponent".equals(clazz.getSimpleName())) { 1659 return getComponentParameterJsonSchema("jms"); 1660 } else { 1661 return null; 1662 } 1663 } catch (ClassNotFoundException e) { 1664 return null; 1665 } 1666 } 1667 1668 public String getDataFormatParameterJsonSchema(String dataFormatName) throws IOException { 1669 // use the dataformat factory finder to find the package name of the dataformat class, which is the location 1670 // where the documentation exists as well 1671 FactoryFinder finder = getFactoryFinder(DefaultDataFormatResolver.DATAFORMAT_RESOURCE_PATH); 1672 try { 1673 Class<?> clazz = null; 1674 try { 1675 clazz = finder.findClass(dataFormatName); 1676 } catch (NoFactoryAvailableException e) { 1677 // ignore, i.e. if a component is an auto-configured spring-boot 1678 // data-formats 1679 } 1680 1681 if (clazz == null) { 1682 return null; 1683 } 1684 1685 String packageName = clazz.getPackage().getName(); 1686 packageName = packageName.replace('.', '/'); 1687 String path = packageName + "/" + dataFormatName + ".json"; 1688 1689 ClassResolver resolver = getClassResolver(); 1690 InputStream inputStream = resolver.loadResourceAsStream(path); 1691 log.debug("Loading dataformat JSON Schema for: {} using class resolver: {} -> {}", new Object[]{dataFormatName, resolver, inputStream}); 1692 if (inputStream != null) { 1693 try { 1694 return IOHelper.loadText(inputStream); 1695 } finally { 1696 IOHelper.close(inputStream); 1697 } 1698 } 1699 return null; 1700 1701 } catch (ClassNotFoundException e) { 1702 return null; 1703 } 1704 } 1705 1706 public String getLanguageParameterJsonSchema(String languageName) throws IOException { 1707 // use the language factory finder to find the package name of the language class, which is the location 1708 // where the documentation exists as well 1709 FactoryFinder finder = getFactoryFinder(DefaultLanguageResolver.LANGUAGE_RESOURCE_PATH); 1710 try { 1711 Class<?> clazz = null; 1712 try { 1713 clazz = finder.findClass(languageName); 1714 } catch (NoFactoryAvailableException e) { 1715 // ignore, i.e. if a component is an auto-configured spring-boot 1716 // languages 1717 } 1718 1719 if (clazz == null) { 1720 return null; 1721 } 1722 1723 String packageName = clazz.getPackage().getName(); 1724 packageName = packageName.replace('.', '/'); 1725 String path = packageName + "/" + languageName + ".json"; 1726 1727 ClassResolver resolver = getClassResolver(); 1728 InputStream inputStream = resolver.loadResourceAsStream(path); 1729 log.debug("Loading language JSON Schema for: {} using class resolver: {} -> {}", new Object[]{languageName, resolver, inputStream}); 1730 if (inputStream != null) { 1731 try { 1732 return IOHelper.loadText(inputStream); 1733 } finally { 1734 IOHelper.close(inputStream); 1735 } 1736 } 1737 return null; 1738 1739 } catch (ClassNotFoundException e) { 1740 return null; 1741 } 1742 } 1743 1744 public String getEipParameterJsonSchema(String eipName) throws IOException { 1745 // the eip json schema may be in some of the sub-packages so look until we find it 1746 String[] subPackages = new String[]{"", "/config", "/dataformat", "/language", "/loadbalancer", "/rest"}; 1747 for (String sub : subPackages) { 1748 String path = CamelContextHelper.MODEL_DOCUMENTATION_PREFIX + sub + "/" + eipName + ".json"; 1749 ClassResolver resolver = getClassResolver(); 1750 InputStream inputStream = resolver.loadResourceAsStream(path); 1751 if (inputStream != null) { 1752 log.debug("Loading eip JSON Schema for: {} using class resolver: {} -> {}", new Object[]{eipName, resolver, inputStream}); 1753 try { 1754 return IOHelper.loadText(inputStream); 1755 } finally { 1756 IOHelper.close(inputStream); 1757 } 1758 } 1759 } 1760 return null; 1761 } 1762 1763 public String explainEipJson(String nameOrId, boolean includeAllOptions) { 1764 try { 1765 // try to find the id within all known routes and their eips 1766 String eipName = nameOrId; 1767 NamedNode target = null; 1768 for (RouteDefinition route : getRouteDefinitions()) { 1769 if (route.getId().equals(nameOrId)) { 1770 target = route; 1771 break; 1772 } 1773 for (FromDefinition from : route.getInputs()) { 1774 if (nameOrId.equals(from.getId())) { 1775 target = route; 1776 break; 1777 } 1778 } 1779 Iterator<ProcessorDefinition> it = ProcessorDefinitionHelper.filterTypeInOutputs(route.getOutputs(), ProcessorDefinition.class); 1780 while (it.hasNext()) { 1781 ProcessorDefinition def = it.next(); 1782 if (nameOrId.equals(def.getId())) { 1783 target = def; 1784 break; 1785 } 1786 } 1787 if (target != null) { 1788 break; 1789 } 1790 } 1791 1792 if (target != null) { 1793 eipName = target.getShortName(); 1794 } 1795 1796 String json = getEipParameterJsonSchema(eipName); 1797 if (json == null) { 1798 return null; 1799 } 1800 1801 // overlay with runtime parameters that id uses at runtime 1802 if (target != null) { 1803 List<Map<String, String>> rows = JsonSchemaHelper.parseJsonSchema("properties", json, true); 1804 1805 // selected rows to use for answer 1806 Map<String, String[]> selected = new LinkedHashMap<String, String[]>(); 1807 1808 // extract options from the node 1809 Map<String, Object> options = new LinkedHashMap<String, Object>(); 1810 IntrospectionSupport.getProperties(target, options, "", false); 1811 // remove outputs which we do not want to include 1812 options.remove("outputs"); 1813 1814 // include other rows 1815 for (Map<String, String> row : rows) { 1816 String name = row.get("name"); 1817 String kind = row.get("kind"); 1818 String label = row.get("label"); 1819 String required = row.get("required"); 1820 String value = row.get("value"); 1821 String defaultValue = row.get("defaultValue"); 1822 String type = row.get("type"); 1823 String javaType = row.get("javaType"); 1824 String deprecated = row.get("deprecated"); 1825 String description = row.get("description"); 1826 1827 // find the configured option 1828 Object o = options.get(name); 1829 if (o != null) { 1830 value = o.toString(); 1831 } 1832 1833 value = URISupport.sanitizePath(value); 1834 1835 if (includeAllOptions || o != null) { 1836 // add as selected row 1837 if (!selected.containsKey(name)) { 1838 selected.put(name, new String[]{name, kind, label, required, type, javaType, deprecated, value, defaultValue, description}); 1839 } 1840 } 1841 } 1842 1843 json = ObjectHelper.before(json, " \"properties\": {"); 1844 1845 StringBuilder buffer = new StringBuilder(" \"properties\": {"); 1846 1847 boolean first = true; 1848 for (String[] row : selected.values()) { 1849 if (first) { 1850 first = false; 1851 } else { 1852 buffer.append(","); 1853 } 1854 buffer.append("\n "); 1855 1856 String name = row[0]; 1857 String kind = row[1]; 1858 String label = row[2]; 1859 String required = row[3]; 1860 String type = row[4]; 1861 String javaType = row[5]; 1862 String deprecated = row[6]; 1863 String value = row[7]; 1864 String defaultValue = row[8]; 1865 String description = row[9]; 1866 1867 // add json of the option 1868 buffer.append(StringQuoteHelper.doubleQuote(name)).append(": { "); 1869 CollectionStringBuffer csb = new CollectionStringBuffer(); 1870 if (kind != null) { 1871 csb.append("\"kind\": \"" + kind + "\""); 1872 } 1873 if (label != null) { 1874 csb.append("\"label\": \"" + label + "\""); 1875 } 1876 if (required != null) { 1877 csb.append("\"required\": \"" + required + "\""); 1878 } 1879 if (type != null) { 1880 csb.append("\"type\": \"" + type + "\""); 1881 } 1882 if (javaType != null) { 1883 csb.append("\"javaType\": \"" + javaType + "\""); 1884 } 1885 if (deprecated != null) { 1886 csb.append("\"deprecated\": \"" + deprecated + "\""); 1887 } 1888 if (value != null) { 1889 csb.append("\"value\": \"" + value + "\""); 1890 } 1891 if (defaultValue != null) { 1892 csb.append("\"defaultValue\": \"" + defaultValue + "\""); 1893 } 1894 if (description != null) { 1895 csb.append("\"description\": \"" + description + "\""); 1896 } 1897 if (!csb.isEmpty()) { 1898 buffer.append(csb.toString()); 1899 } 1900 buffer.append(" }"); 1901 } 1902 1903 buffer.append("\n }\n}\n"); 1904 1905 // insert the original first part of the json into the start of the buffer 1906 buffer.insert(0, json); 1907 return buffer.toString(); 1908 } 1909 1910 return json; 1911 } catch (Exception e) { 1912 // ignore and return empty response 1913 return null; 1914 } 1915 } 1916 1917 public String explainDataFormatJson(String dataFormatName, DataFormat dataFormat, boolean includeAllOptions) { 1918 try { 1919 String json = getDataFormatParameterJsonSchema(dataFormatName); 1920 if (json == null) { 1921 // the model may be shared for multiple data formats such as bindy, json (xstream, jackson, gson) 1922 if (dataFormatName.contains("-")) { 1923 dataFormatName = ObjectHelper.before(dataFormatName, "-"); 1924 json = getDataFormatParameterJsonSchema(dataFormatName); 1925 } 1926 if (json == null) { 1927 return null; 1928 } 1929 } 1930 1931 List<Map<String, String>> rows = JsonSchemaHelper.parseJsonSchema("properties", json, true); 1932 1933 // selected rows to use for answer 1934 Map<String, String[]> selected = new LinkedHashMap<String, String[]>(); 1935 Map<String, String[]> dataFormatOptions = new LinkedHashMap<String, String[]>(); 1936 1937 // extract options from the data format 1938 Map<String, Object> options = new LinkedHashMap<String, Object>(); 1939 IntrospectionSupport.getProperties(dataFormat, options, "", false); 1940 1941 for (Map.Entry<String, Object> entry : options.entrySet()) { 1942 String name = entry.getKey(); 1943 String value = ""; 1944 if (entry.getValue() != null) { 1945 value = entry.getValue().toString(); 1946 } 1947 value = URISupport.sanitizePath(value); 1948 1949 // find type and description from the json schema 1950 String type = null; 1951 String kind = null; 1952 String label = null; 1953 String required = null; 1954 String javaType = null; 1955 String deprecated = null; 1956 String secret = null; 1957 String defaultValue = null; 1958 String description = null; 1959 for (Map<String, String> row : rows) { 1960 if (name.equals(row.get("name"))) { 1961 type = row.get("type"); 1962 kind = row.get("kind"); 1963 label = row.get("label"); 1964 required = row.get("required"); 1965 javaType = row.get("javaType"); 1966 deprecated = row.get("deprecated"); 1967 secret = row.get("secret"); 1968 defaultValue = row.get("defaultValue"); 1969 description = row.get("description"); 1970 break; 1971 } 1972 } 1973 1974 // remember this option from the uri 1975 dataFormatOptions.put(name, new String[]{name, kind, label, required, type, javaType, deprecated, secret, value, defaultValue, description}); 1976 } 1977 1978 // include other rows 1979 for (Map<String, String> row : rows) { 1980 String name = row.get("name"); 1981 String kind = row.get("kind"); 1982 String label = row.get("label"); 1983 String required = row.get("required"); 1984 String value = row.get("value"); 1985 String defaultValue = row.get("defaultValue"); 1986 String type = row.get("type"); 1987 String javaType = row.get("javaType"); 1988 String deprecated = row.get("deprecated"); 1989 String secret = row.get("secret"); 1990 value = URISupport.sanitizePath(value); 1991 String description = row.get("description"); 1992 1993 boolean isDataFormatOption = dataFormatOptions.containsKey(name); 1994 1995 // always include from uri or path options 1996 if (includeAllOptions || isDataFormatOption) { 1997 if (!selected.containsKey(name)) { 1998 // add as selected row, but take the value from uri options if it was from there 1999 if (isDataFormatOption) { 2000 selected.put(name, dataFormatOptions.get(name)); 2001 } else { 2002 selected.put(name, new String[]{name, kind, label, required, type, javaType, deprecated, secret, value, defaultValue, description}); 2003 } 2004 } 2005 } 2006 } 2007 2008 json = ObjectHelper.before(json, " \"properties\": {"); 2009 2010 StringBuilder buffer = new StringBuilder(" \"properties\": {"); 2011 2012 boolean first = true; 2013 for (String[] row : selected.values()) { 2014 if (first) { 2015 first = false; 2016 } else { 2017 buffer.append(","); 2018 } 2019 buffer.append("\n "); 2020 2021 String name = row[0]; 2022 String kind = row[1]; 2023 String label = row[2]; 2024 String required = row[3]; 2025 String type = row[4]; 2026 String javaType = row[5]; 2027 String deprecated = row[6]; 2028 String secret = row[7]; 2029 String value = row[8]; 2030 String defaultValue = row[9]; 2031 String description = row[10]; 2032 2033 // add json of the option 2034 buffer.append(StringQuoteHelper.doubleQuote(name)).append(": { "); 2035 CollectionStringBuffer csb = new CollectionStringBuffer(); 2036 if (kind != null) { 2037 csb.append("\"kind\": \"" + kind + "\""); 2038 } 2039 if (label != null) { 2040 csb.append("\"label\": \"" + label + "\""); 2041 } 2042 if (required != null) { 2043 csb.append("\"required\": \"" + required + "\""); 2044 } 2045 if (type != null) { 2046 csb.append("\"type\": \"" + type + "\""); 2047 } 2048 if (javaType != null) { 2049 csb.append("\"javaType\": \"" + javaType + "\""); 2050 } 2051 if (deprecated != null) { 2052 csb.append("\"deprecated\": \"" + deprecated + "\""); 2053 } 2054 if (secret != null) { 2055 csb.append("\"secret\": \"" + secret + "\""); 2056 } 2057 if (value != null) { 2058 csb.append("\"value\": \"" + value + "\""); 2059 } 2060 if (defaultValue != null) { 2061 csb.append("\"defaultValue\": \"" + defaultValue + "\""); 2062 } 2063 if (description != null) { 2064 csb.append("\"description\": \"" + description + "\""); 2065 } 2066 if (!csb.isEmpty()) { 2067 buffer.append(csb.toString()); 2068 } 2069 buffer.append(" }"); 2070 } 2071 2072 buffer.append("\n }\n}\n"); 2073 2074 // insert the original first part of the json into the start of the buffer 2075 buffer.insert(0, json); 2076 return buffer.toString(); 2077 2078 } catch (Exception e) { 2079 // ignore and return empty response 2080 return null; 2081 } 2082 } 2083 2084 public String explainComponentJson(String componentName, boolean includeAllOptions) { 2085 try { 2086 String json = getComponentParameterJsonSchema(componentName); 2087 if (json == null) { 2088 return null; 2089 } 2090 List<Map<String, String>> rows = JsonSchemaHelper.parseJsonSchema("componentProperties", json, true); 2091 2092 // selected rows to use for answer 2093 Map<String, String[]> selected = new LinkedHashMap<String, String[]>(); 2094 2095 // insert values from component 2096 Component component = getComponent(componentName); 2097 Map<String, Object> options = new HashMap<String, Object>(); 2098 IntrospectionSupport.getProperties(component, options, null); 2099 2100 for (Map.Entry<String, Object> entry : options.entrySet()) { 2101 String name = entry.getKey(); 2102 // skip unwanted options which is default inherited from DefaultComponent 2103 if ("camelContext".equals(name) || "endpointClass".equals(name)) { 2104 continue; 2105 } 2106 String value = ""; 2107 if (entry.getValue() != null) { 2108 value = entry.getValue().toString(); 2109 } 2110 value = URISupport.sanitizePath(value); 2111 2112 // find type and description from the json schema 2113 String type = null; 2114 String kind = null; 2115 String group = null; 2116 String label = null; 2117 String required = null; 2118 String javaType = null; 2119 String deprecated = null; 2120 String secret = null; 2121 String defaultValue = null; 2122 String description = null; 2123 for (Map<String, String> row : rows) { 2124 if (name.equals(row.get("name"))) { 2125 type = row.get("type"); 2126 kind = row.get("kind"); 2127 group = row.get("group"); 2128 label = row.get("label"); 2129 required = row.get("required"); 2130 javaType = row.get("javaType"); 2131 deprecated = row.get("deprecated"); 2132 secret = row.get("secret"); 2133 defaultValue = row.get("defaultValue"); 2134 description = row.get("description"); 2135 break; 2136 } 2137 } 2138 // add as selected row 2139 selected.put(name, new String[]{name, kind, group, label, required, type, javaType, deprecated, secret, value, defaultValue, description}); 2140 } 2141 2142 // include other rows 2143 for (Map<String, String> row : rows) { 2144 String name = row.get("name"); 2145 String kind = row.get("kind"); 2146 String group = row.get("group"); 2147 String label = row.get("label"); 2148 String required = row.get("required"); 2149 String value = row.get("value"); 2150 String defaultValue = row.get("defaultValue"); 2151 String type = row.get("type"); 2152 String javaType = row.get("javaType"); 2153 String deprecated = row.get("deprecated"); 2154 String secret = row.get("secret"); 2155 value = URISupport.sanitizePath(value); 2156 String description = row.get("description"); 2157 // always include path options 2158 if (includeAllOptions) { 2159 // add as selected row 2160 if (!selected.containsKey(name)) { 2161 selected.put(name, new String[]{name, kind, group, label, required, type, javaType, deprecated, secret, value, defaultValue, description}); 2162 } 2163 } 2164 } 2165 2166 json = ObjectHelper.before(json, " \"componentProperties\": {"); 2167 StringBuilder buffer = new StringBuilder(" \"componentProperties\": {"); 2168 2169 boolean first = true; 2170 for (String[] row : selected.values()) { 2171 if (first) { 2172 first = false; 2173 } else { 2174 buffer.append(","); 2175 } 2176 buffer.append("\n "); 2177 2178 String name = row[0]; 2179 String kind = row[1]; 2180 String group = row[2]; 2181 String label = row[3]; 2182 String required = row[4]; 2183 String type = row[5]; 2184 String javaType = row[6]; 2185 String deprecated = row[7]; 2186 String secret = row[8]; 2187 String value = row[9]; 2188 String defaultValue = row[10]; 2189 String description = row[11]; 2190 2191 // add json of the option 2192 buffer.append(StringQuoteHelper.doubleQuote(name)).append(": { "); 2193 CollectionStringBuffer csb = new CollectionStringBuffer(); 2194 if (kind != null) { 2195 csb.append("\"kind\": \"" + kind + "\""); 2196 } 2197 if (group != null) { 2198 csb.append("\"group\": \"" + group + "\""); 2199 } 2200 if (label != null) { 2201 csb.append("\"label\": \"" + label + "\""); 2202 } 2203 if (required != null) { 2204 csb.append("\"required\": \"" + required + "\""); 2205 } 2206 if (type != null) { 2207 csb.append("\"type\": \"" + type + "\""); 2208 } 2209 if (javaType != null) { 2210 csb.append("\"javaType\": \"" + javaType + "\""); 2211 } 2212 if (deprecated != null) { 2213 csb.append("\"deprecated\": \"" + deprecated + "\""); 2214 } 2215 if (secret != null) { 2216 csb.append("\"secret\": \"" + secret + "\""); 2217 } 2218 if (value != null) { 2219 csb.append("\"value\": \"" + value + "\""); 2220 } 2221 if (defaultValue != null) { 2222 csb.append("\"defaultValue\": \"" + defaultValue + "\""); 2223 } 2224 if (description != null) { 2225 csb.append("\"description\": \"" + description + "\""); 2226 } 2227 if (!csb.isEmpty()) { 2228 buffer.append(csb.toString()); 2229 } 2230 buffer.append(" }"); 2231 } 2232 buffer.append("\n }\n}\n"); 2233 // insert the original first part of the json into the start of the buffer 2234 buffer.insert(0, json); 2235 return buffer.toString(); 2236 } catch (Exception e) { 2237 // ignore and return empty response 2238 return null; 2239 } 2240 } 2241 2242 // CHECKSTYLE:OFF 2243 public String explainEndpointJson(String uri, boolean includeAllOptions) { 2244 try { 2245 URI u = new URI(uri); 2246 String json = getComponentParameterJsonSchema(u.getScheme()); 2247 if (json == null) { 2248 return null; 2249 } 2250 List<Map<String, String>> rows = JsonSchemaHelper.parseJsonSchema("properties", json, true); 2251 2252 // selected rows to use for answer 2253 Map<String, String[]> selected = new LinkedHashMap<String, String[]>(); 2254 Map<String, String[]> uriOptions = new LinkedHashMap<String, String[]>(); 2255 2256 // insert values from uri 2257 Map<String, Object> options = EndpointHelper.endpointProperties(this, uri); 2258 2259 // extract consumer. prefix options 2260 Map<String, Object> consumerOptions = IntrospectionSupport.extractProperties(options, "consumer."); 2261 // and add back again without the consumer. prefix as that json schema omits that 2262 options.putAll(consumerOptions); 2263 2264 for (Map.Entry<String, Object> entry : options.entrySet()) { 2265 String name = entry.getKey(); 2266 String value = ""; 2267 if (entry.getValue() != null) { 2268 value = entry.getValue().toString(); 2269 } 2270 value = URISupport.sanitizePath(value); 2271 // find type and description from the json schema 2272 String type = null; 2273 String kind = null; 2274 String group = null; 2275 String label = null; 2276 String required = null; 2277 String javaType = null; 2278 String deprecated = null; 2279 String secret = null; 2280 String defaultValue = null; 2281 String description = null; 2282 for (Map<String, String> row : rows) { 2283 if (name.equals(row.get("name"))) { 2284 type = row.get("type"); 2285 kind = row.get("kind"); 2286 group = row.get("group"); 2287 label = row.get("label"); 2288 required = row.get("required"); 2289 javaType = row.get("javaType"); 2290 deprecated = row.get("deprecated"); 2291 secret = row.get("secret"); 2292 defaultValue = row.get("defaultValue"); 2293 description = row.get("description"); 2294 break; 2295 } 2296 } 2297 // remember this option from the uri 2298 uriOptions.put(name, new String[]{name, kind, group, label, required, type, javaType, deprecated, secret, value, defaultValue, description}); 2299 } 2300 2301 // include other rows 2302 for (Map<String, String> row : rows) { 2303 String name = row.get("name"); 2304 String kind = row.get("kind"); 2305 String group = row.get("group"); 2306 String label = row.get("label"); 2307 String required = row.get("required"); 2308 String value = row.get("value"); 2309 String defaultValue = row.get("defaultValue"); 2310 String type = row.get("type"); 2311 String javaType = row.get("javaType"); 2312 String deprecated = row.get("deprecated"); 2313 String secret = row.get("secret"); 2314 value = URISupport.sanitizePath(value); 2315 String description = row.get("description"); 2316 boolean isUriOption = uriOptions.containsKey(name); 2317 // always include from uri or path options 2318 if (includeAllOptions || isUriOption || "path".equals(kind)) { 2319 if (!selected.containsKey(name)) { 2320 // add as selected row, but take the value from uri options if it was from there 2321 if (isUriOption) { 2322 selected.put(name, uriOptions.get(name)); 2323 } else { 2324 selected.put(name, new String[]{name, kind, group, label, required, type, javaType, deprecated, secret, value, defaultValue, description}); 2325 } 2326 } 2327 } 2328 } 2329 2330 // skip component properties 2331 json = ObjectHelper.before(json, " \"componentProperties\": {"); 2332 // and rewrite properties 2333 StringBuilder buffer = new StringBuilder(" \"properties\": {"); 2334 2335 boolean first = true; 2336 for (String[] row : selected.values()) { 2337 if (first) { 2338 first = false; 2339 } else { 2340 buffer.append(","); 2341 } 2342 buffer.append("\n "); 2343 2344 String name = row[0]; 2345 String kind = row[1]; 2346 String group = row[2]; 2347 String label = row[3]; 2348 String required = row[4]; 2349 String type = row[5]; 2350 String javaType = row[6]; 2351 String deprecated = row[7]; 2352 String secret = row[8]; 2353 String value = row[9]; 2354 String defaultValue = row[10]; 2355 String description = row[11]; 2356 2357 // add json of the option 2358 buffer.append(StringQuoteHelper.doubleQuote(name)).append(": { "); 2359 CollectionStringBuffer csb = new CollectionStringBuffer(); 2360 if (kind != null) { 2361 csb.append("\"kind\": \"" + kind + "\""); 2362 } 2363 if (group != null) { 2364 csb.append("\"group\": \"" + group + "\""); 2365 } 2366 if (label != null) { 2367 csb.append("\"label\": \"" + label + "\""); 2368 } 2369 if (required != null) { 2370 csb.append("\"required\": \"" + required + "\""); 2371 } 2372 if (type != null) { 2373 csb.append("\"type\": \"" + type + "\""); 2374 } 2375 if (javaType != null) { 2376 csb.append("\"javaType\": \"" + javaType + "\""); 2377 } 2378 if (deprecated != null) { 2379 csb.append("\"deprecated\": \"" + deprecated + "\""); 2380 } 2381 if (secret != null) { 2382 csb.append("\"secret\": \"" + secret + "\""); 2383 } 2384 if (value != null) { 2385 csb.append("\"value\": \"" + value + "\""); 2386 } 2387 if (defaultValue != null) { 2388 csb.append("\"defaultValue\": \"" + defaultValue + "\""); 2389 } 2390 if (description != null) { 2391 csb.append("\"description\": \"" + description + "\""); 2392 } 2393 if (!csb.isEmpty()) { 2394 buffer.append(csb.toString()); 2395 } 2396 buffer.append(" }"); 2397 } 2398 buffer.append("\n }\n}\n"); 2399 // insert the original first part of the json into the start of the buffer 2400 buffer.insert(0, json); 2401 return buffer.toString(); 2402 } catch (Exception e) { 2403 // ignore and return empty response 2404 return null; 2405 } 2406 } 2407 // CHECKSTYLE:ON 2408 2409 public String createRouteStaticEndpointJson(String routeId) { 2410 // lets include dynamic as well as we want as much data as possible 2411 return createRouteStaticEndpointJson(routeId, true); 2412 } 2413 2414 public String createRouteStaticEndpointJson(String routeId, boolean includeDynamic) { 2415 List<RouteDefinition> routes = new ArrayList<RouteDefinition>(); 2416 if (routeId != null) { 2417 RouteDefinition route = getRouteDefinition(routeId); 2418 if (route == null) { 2419 throw new IllegalArgumentException("Route with id " + routeId + " does not exist"); 2420 } 2421 routes.add(route); 2422 } else { 2423 routes.addAll(getRouteDefinitions()); 2424 } 2425 2426 StringBuilder buffer = new StringBuilder("{\n \"routes\": {"); 2427 boolean firstRoute = true; 2428 for (RouteDefinition route : routes) { 2429 if (!firstRoute) { 2430 buffer.append("\n },"); 2431 } else { 2432 firstRoute = false; 2433 } 2434 2435 String id = route.getId(); 2436 buffer.append("\n \"").append(id).append("\": {"); 2437 buffer.append("\n \"inputs\": ["); 2438 // for inputs we do not need to check dynamic as we have the data from the route definition 2439 Set<String> inputs = RouteDefinitionHelper.gatherAllStaticEndpointUris(this, route, true, false); 2440 boolean first = true; 2441 for (String input : inputs) { 2442 if (!first) { 2443 buffer.append(","); 2444 } else { 2445 first = false; 2446 } 2447 buffer.append("\n "); 2448 buffer.append(StringHelper.toJson("uri", input, true)); 2449 } 2450 buffer.append("\n ]"); 2451 2452 buffer.append(","); 2453 buffer.append("\n \"outputs\": ["); 2454 Set<String> outputs = RouteDefinitionHelper.gatherAllEndpointUris(this, route, false, true, includeDynamic); 2455 first = true; 2456 for (String output : outputs) { 2457 if (!first) { 2458 buffer.append(","); 2459 } else { 2460 first = false; 2461 } 2462 buffer.append("\n "); 2463 buffer.append(StringHelper.toJson("uri", output, true)); 2464 } 2465 buffer.append("\n ]"); 2466 } 2467 if (!firstRoute) { 2468 buffer.append("\n }"); 2469 } 2470 buffer.append("\n }\n}\n"); 2471 2472 return buffer.toString(); 2473 } 2474 2475 // Helper methods 2476 // ----------------------------------------------------------------------- 2477 2478 public Language resolveLanguage(String language) { 2479 Language answer; 2480 synchronized (languages) { 2481 answer = languages.get(language); 2482 2483 // check if the language is singleton, if so return the shared instance 2484 if (answer instanceof IsSingleton) { 2485 boolean singleton = ((IsSingleton) answer).isSingleton(); 2486 if (singleton) { 2487 return answer; 2488 } 2489 } 2490 2491 // language not known or not singleton, then use resolver 2492 answer = getLanguageResolver().resolveLanguage(language, this); 2493 2494 // inject CamelContext if aware 2495 if (answer != null) { 2496 if (answer instanceof CamelContextAware) { 2497 ((CamelContextAware) answer).setCamelContext(this); 2498 } 2499 if (answer instanceof Service) { 2500 try { 2501 startService((Service) answer); 2502 } catch (Exception e) { 2503 throw ObjectHelper.wrapRuntimeCamelException(e); 2504 } 2505 } 2506 2507 languages.put(language, answer); 2508 } 2509 } 2510 2511 return answer; 2512 } 2513 2514 public String getPropertyPrefixToken() { 2515 PropertiesComponent pc = getPropertiesComponent(); 2516 2517 if (pc != null) { 2518 return pc.getPrefixToken(); 2519 } else { 2520 return null; 2521 } 2522 } 2523 2524 public String getPropertySuffixToken() { 2525 PropertiesComponent pc = getPropertiesComponent(); 2526 2527 if (pc != null) { 2528 return pc.getSuffixToken(); 2529 } else { 2530 return null; 2531 } 2532 } 2533 2534 public String resolvePropertyPlaceholders(String text) throws Exception { 2535 // While it is more efficient to only do the lookup if we are sure we need the component, 2536 // with custom tokens, we cannot know if the URI contains a property or not without having 2537 // the component. We also lose fail-fast behavior for the missing component with this change. 2538 PropertiesComponent pc = getPropertiesComponent(); 2539 2540 // Do not parse uris that are designated for the properties component as it will handle that itself 2541 if (text != null && !text.startsWith("properties:")) { 2542 // No component, assume default tokens. 2543 if (pc == null && text.contains(PropertiesComponent.DEFAULT_PREFIX_TOKEN)) { 2544 // lookup existing properties component, or force create a new default component 2545 pc = (PropertiesComponent) CamelContextHelper.lookupPropertiesComponent(this, true); 2546 } 2547 2548 if (pc != null && text.contains(pc.getPrefixToken())) { 2549 // the parser will throw exception if property key was not found 2550 String answer = pc.parseUri(text); 2551 log.debug("Resolved text: {} -> {}", text, answer); 2552 return answer; 2553 } 2554 } 2555 2556 // return original text as is 2557 return text; 2558 } 2559 2560 // Properties 2561 // ----------------------------------------------------------------------- 2562 2563 public TypeConverter getTypeConverter() { 2564 if (typeConverter == null) { 2565 synchronized (this) { 2566 // we can synchronize on this as there is only one instance 2567 // of the camel context (its the container) 2568 typeConverter = createTypeConverter(); 2569 try { 2570 // must add service eager and force start it 2571 addService(typeConverter, true, true); 2572 } catch (Exception e) { 2573 throw ObjectHelper.wrapRuntimeCamelException(e); 2574 } 2575 } 2576 } 2577 return typeConverter; 2578 } 2579 2580 public void setTypeConverter(TypeConverter typeConverter) { 2581 this.typeConverter = typeConverter; 2582 try { 2583 // must add service eager and force start it 2584 addService(typeConverter, true, true); 2585 } catch (Exception e) { 2586 throw ObjectHelper.wrapRuntimeCamelException(e); 2587 } 2588 } 2589 2590 public TypeConverterRegistry getTypeConverterRegistry() { 2591 if (typeConverterRegistry == null) { 2592 // init type converter as its lazy 2593 if (typeConverter == null) { 2594 getTypeConverter(); 2595 } 2596 if (typeConverter instanceof TypeConverterRegistry) { 2597 typeConverterRegistry = (TypeConverterRegistry) typeConverter; 2598 } 2599 } 2600 return typeConverterRegistry; 2601 } 2602 2603 public void setTypeConverterRegistry(TypeConverterRegistry typeConverterRegistry) { 2604 this.typeConverterRegistry = typeConverterRegistry; 2605 } 2606 2607 public Injector getInjector() { 2608 if (injector == null) { 2609 injector = createInjector(); 2610 } 2611 return injector; 2612 } 2613 2614 public void setInjector(Injector injector) { 2615 this.injector = injector; 2616 } 2617 2618 public ManagementMBeanAssembler getManagementMBeanAssembler() { 2619 return managementMBeanAssembler; 2620 } 2621 2622 public void setManagementMBeanAssembler(ManagementMBeanAssembler managementMBeanAssembler) { 2623 this.managementMBeanAssembler = managementMBeanAssembler; 2624 } 2625 2626 public ComponentResolver getComponentResolver() { 2627 if (componentResolver == null) { 2628 componentResolver = createComponentResolver(); 2629 } 2630 return componentResolver; 2631 } 2632 2633 public void setComponentResolver(ComponentResolver componentResolver) { 2634 this.componentResolver = componentResolver; 2635 } 2636 2637 public LanguageResolver getLanguageResolver() { 2638 if (languageResolver == null) { 2639 languageResolver = new DefaultLanguageResolver(); 2640 } 2641 return languageResolver; 2642 } 2643 2644 public void setLanguageResolver(LanguageResolver languageResolver) { 2645 this.languageResolver = languageResolver; 2646 } 2647 2648 public boolean isAutoCreateComponents() { 2649 return autoCreateComponents; 2650 } 2651 2652 public void setAutoCreateComponents(boolean autoCreateComponents) { 2653 this.autoCreateComponents = autoCreateComponents; 2654 } 2655 2656 public Registry getRegistry() { 2657 if (registry == null) { 2658 registry = createRegistry(); 2659 setRegistry(registry); 2660 } 2661 return registry; 2662 } 2663 2664 public <T> T getRegistry(Class<T> type) { 2665 Registry reg = getRegistry(); 2666 2667 // unwrap the property placeholder delegate 2668 if (reg instanceof PropertyPlaceholderDelegateRegistry) { 2669 reg = ((PropertyPlaceholderDelegateRegistry) reg).getRegistry(); 2670 } 2671 2672 if (type.isAssignableFrom(reg.getClass())) { 2673 return type.cast(reg); 2674 } else if (reg instanceof CompositeRegistry) { 2675 List<Registry> list = ((CompositeRegistry) reg).getRegistryList(); 2676 for (Registry r : list) { 2677 if (type.isAssignableFrom(r.getClass())) { 2678 return type.cast(r); 2679 } 2680 } 2681 } 2682 return null; 2683 } 2684 2685 /** 2686 * Sets the registry to the given JNDI context 2687 * 2688 * @param jndiContext is the JNDI context to use as the registry 2689 * @see #setRegistry(org.apache.camel.spi.Registry) 2690 */ 2691 public void setJndiContext(Context jndiContext) { 2692 setRegistry(new JndiRegistry(jndiContext)); 2693 } 2694 2695 public void setRegistry(Registry registry) { 2696 // wrap the registry so we always do property placeholder lookups 2697 if (!(registry instanceof PropertyPlaceholderDelegateRegistry)) { 2698 registry = new PropertyPlaceholderDelegateRegistry(this, registry); 2699 } 2700 this.registry = registry; 2701 } 2702 2703 public List<LifecycleStrategy> getLifecycleStrategies() { 2704 return lifecycleStrategies; 2705 } 2706 2707 public void setLifecycleStrategies(List<LifecycleStrategy> lifecycleStrategies) { 2708 this.lifecycleStrategies = lifecycleStrategies; 2709 } 2710 2711 public void addLifecycleStrategy(LifecycleStrategy lifecycleStrategy) { 2712 this.lifecycleStrategies.add(lifecycleStrategy); 2713 } 2714 2715 public void setupRoutes(boolean done) { 2716 if (done) { 2717 isSetupRoutes.remove(); 2718 } else { 2719 isSetupRoutes.set(true); 2720 } 2721 } 2722 2723 public synchronized List<RouteDefinition> getRouteDefinitions() { 2724 return routeDefinitions; 2725 } 2726 2727 public synchronized RouteDefinition getRouteDefinition(String id) { 2728 for (RouteDefinition route : routeDefinitions) { 2729 if (route.idOrCreate(nodeIdFactory).equals(id)) { 2730 return route; 2731 } 2732 } 2733 return null; 2734 } 2735 2736 public synchronized List<RestDefinition> getRestDefinitions() { 2737 return restDefinitions; 2738 } 2739 2740 public void addRestDefinitions(Collection<RestDefinition> restDefinitions) throws Exception { 2741 if (restDefinitions == null || restDefinitions.isEmpty()) { 2742 return; 2743 } 2744 2745 this.restDefinitions.addAll(restDefinitions); 2746 } 2747 2748 public RestConfiguration getRestConfiguration() { 2749 return restConfigurations.get(""); 2750 } 2751 2752 public void setRestConfiguration(RestConfiguration restConfiguration) { 2753 restConfigurations.put("", restConfiguration); 2754 } 2755 2756 public Collection<RestConfiguration> getRestConfigurations() { 2757 return restConfigurations.values(); 2758 } 2759 2760 public void addRestConfiguration(RestConfiguration restConfiguration) { 2761 restConfigurations.put(restConfiguration.getComponent(), restConfiguration); 2762 } 2763 2764 public RestConfiguration getRestConfiguration(String component, boolean defaultIfNotExist) { 2765 if (component == null) { 2766 component = ""; 2767 } 2768 RestConfiguration config = restConfigurations.get(component); 2769 if (config == null && defaultIfNotExist) { 2770 // grab the default configuration 2771 config = getRestConfiguration(); 2772 if (config == null || (config.getComponent() != null && !config.getComponent().equals(component))) { 2773 config = new RestConfiguration(); 2774 restConfigurations.put(component, config); 2775 } 2776 } 2777 return config; 2778 } 2779 2780 @Override 2781 public ServiceCallConfigurationDefinition getServiceCallConfiguration(String serviceName) { 2782 if (serviceName == null) { 2783 serviceName = ""; 2784 } 2785 2786 return serviceCallConfigurations.get(serviceName); 2787 } 2788 2789 @Override 2790 public void setServiceCallConfiguration(ServiceCallConfigurationDefinition configuration) { 2791 serviceCallConfigurations.put("", configuration); 2792 } 2793 2794 @Override 2795 public void setServiceCallConfigurations(List<ServiceCallConfigurationDefinition> configurations) { 2796 if (configurations != null) { 2797 for (ServiceCallConfigurationDefinition configuration : configurations) { 2798 serviceCallConfigurations.put(configuration.getId(), configuration); 2799 } 2800 } 2801 } 2802 2803 @Override 2804 public void addServiceCallConfiguration(String serviceName, ServiceCallConfigurationDefinition configuration) { 2805 serviceCallConfigurations.put(serviceName, configuration); 2806 } 2807 2808 @Override 2809 public HystrixConfigurationDefinition getHystrixConfiguration(String id) { 2810 if (id == null) { 2811 id = ""; 2812 } 2813 2814 return hystrixConfigurations.get(id); 2815 } 2816 2817 @Override 2818 public void setHystrixConfiguration(HystrixConfigurationDefinition configuration) { 2819 hystrixConfigurations.put("", configuration); 2820 } 2821 2822 @Override 2823 public void setHystrixConfigurations(List<HystrixConfigurationDefinition> configurations) { 2824 if (configurations != null) { 2825 for (HystrixConfigurationDefinition configuration : configurations) { 2826 hystrixConfigurations.put(configuration.getId(), configuration); 2827 } 2828 } 2829 } 2830 2831 @Override 2832 public void addHystrixConfiguration(String id, HystrixConfigurationDefinition configuration) { 2833 hystrixConfigurations.put(id, configuration); 2834 } 2835 2836 public List<InterceptStrategy> getInterceptStrategies() { 2837 return interceptStrategies; 2838 } 2839 2840 public void setInterceptStrategies(List<InterceptStrategy> interceptStrategies) { 2841 this.interceptStrategies = interceptStrategies; 2842 } 2843 2844 public void addInterceptStrategy(InterceptStrategy interceptStrategy) { 2845 getInterceptStrategies().add(interceptStrategy); 2846 2847 // for backwards compatible or if user add them here instead of the setXXX methods 2848 2849 if (interceptStrategy instanceof Tracer) { 2850 setTracing(true); 2851 } else if (interceptStrategy instanceof HandleFault) { 2852 setHandleFault(true); 2853 } else if (interceptStrategy instanceof StreamCaching) { 2854 setStreamCaching(true); 2855 } else if (interceptStrategy instanceof Delayer) { 2856 setDelayer(((Delayer)interceptStrategy).getDelay()); 2857 } 2858 } 2859 2860 public List<RoutePolicyFactory> getRoutePolicyFactories() { 2861 return routePolicyFactories; 2862 } 2863 2864 public void setRoutePolicyFactories(List<RoutePolicyFactory> routePolicyFactories) { 2865 this.routePolicyFactories = routePolicyFactories; 2866 } 2867 2868 public void addRoutePolicyFactory(RoutePolicyFactory routePolicyFactory) { 2869 getRoutePolicyFactories().add(routePolicyFactory); 2870 } 2871 2872 public Set<LogListener> getLogListeners() { 2873 return logListeners; 2874 } 2875 2876 public void addLogListener(LogListener listener) { 2877 logListeners.add(listener); 2878 } 2879 2880 public void setStreamCaching(Boolean cache) { 2881 this.streamCache = cache; 2882 } 2883 2884 public Boolean isStreamCaching() { 2885 return streamCache; 2886 } 2887 2888 public void setTracing(Boolean tracing) { 2889 this.trace = tracing; 2890 } 2891 2892 public Boolean isTracing() { 2893 return trace; 2894 } 2895 2896 public Boolean isMessageHistory() { 2897 return messageHistory; 2898 } 2899 2900 public void setMessageHistory(Boolean messageHistory) { 2901 this.messageHistory = messageHistory; 2902 } 2903 2904 public void setLogMask(Boolean logMask) { 2905 this.logMask = logMask; 2906 } 2907 2908 public Boolean isLogMask() { 2909 return logMask != null && logMask; 2910 } 2911 2912 public Boolean isLogExhaustedMessageBody() { 2913 return logExhaustedMessageBody; 2914 } 2915 2916 public void setLogExhaustedMessageBody(Boolean logExhaustedMessageBody) { 2917 this.logExhaustedMessageBody = logExhaustedMessageBody; 2918 } 2919 2920 public Boolean isHandleFault() { 2921 return handleFault; 2922 } 2923 2924 public void setHandleFault(Boolean handleFault) { 2925 this.handleFault = handleFault; 2926 } 2927 2928 public Long getDelayer() { 2929 return delay; 2930 } 2931 2932 public void setDelayer(Long delay) { 2933 this.delay = delay; 2934 } 2935 2936 public ProducerTemplate createProducerTemplate() { 2937 int size = CamelContextHelper.getMaximumCachePoolSize(this); 2938 return createProducerTemplate(size); 2939 } 2940 2941 public ProducerTemplate createProducerTemplate(int maximumCacheSize) { 2942 DefaultProducerTemplate answer = new DefaultProducerTemplate(this); 2943 answer.setMaximumCacheSize(maximumCacheSize); 2944 // start it so its ready to use 2945 try { 2946 startService(answer); 2947 } catch (Exception e) { 2948 throw ObjectHelper.wrapRuntimeCamelException(e); 2949 } 2950 return answer; 2951 } 2952 2953 public FluentProducerTemplate createFluentProducerTemplate() { 2954 int size = CamelContextHelper.getMaximumCachePoolSize(this); 2955 return createFluentProducerTemplate(size); 2956 } 2957 2958 public FluentProducerTemplate createFluentProducerTemplate(int maximumCacheSize) { 2959 DefaultFluentProducerTemplate answer = new DefaultFluentProducerTemplate(this); 2960 answer.setMaximumCacheSize(maximumCacheSize); 2961 // start it so its ready to use 2962 try { 2963 startService(answer); 2964 } catch (Exception e) { 2965 throw ObjectHelper.wrapRuntimeCamelException(e); 2966 } 2967 return answer; 2968 } 2969 2970 public ConsumerTemplate createConsumerTemplate() { 2971 int size = CamelContextHelper.getMaximumCachePoolSize(this); 2972 return createConsumerTemplate(size); 2973 } 2974 2975 public ConsumerTemplate createConsumerTemplate(int maximumCacheSize) { 2976 DefaultConsumerTemplate answer = new DefaultConsumerTemplate(this); 2977 answer.setMaximumCacheSize(maximumCacheSize); 2978 // start it so its ready to use 2979 try { 2980 startService(answer); 2981 } catch (Exception e) { 2982 throw ObjectHelper.wrapRuntimeCamelException(e); 2983 } 2984 return answer; 2985 } 2986 2987 public ErrorHandlerBuilder getErrorHandlerBuilder() { 2988 return (ErrorHandlerBuilder)errorHandlerBuilder; 2989 } 2990 2991 public void setErrorHandlerBuilder(ErrorHandlerFactory errorHandlerBuilder) { 2992 this.errorHandlerBuilder = errorHandlerBuilder; 2993 } 2994 2995 public ScheduledExecutorService getErrorHandlerExecutorService() { 2996 synchronized (errorHandlerExecutorServiceLock) { 2997 if (errorHandlerExecutorService == null) { 2998 // setup default thread pool for error handler 2999 errorHandlerExecutorService = getExecutorServiceManager().newDefaultScheduledThreadPool("ErrorHandlerRedeliveryThreadPool", "ErrorHandlerRedeliveryTask"); 3000 } 3001 } 3002 return errorHandlerExecutorService; 3003 } 3004 3005 public void setProducerServicePool(ServicePool<Endpoint, Producer> producerServicePool) { 3006 this.producerServicePool = producerServicePool; 3007 } 3008 3009 public ServicePool<Endpoint, Producer> getProducerServicePool() { 3010 return producerServicePool; 3011 } 3012 3013 public ServicePool<Endpoint, PollingConsumer> getPollingConsumerServicePool() { 3014 return pollingConsumerServicePool; 3015 } 3016 3017 public void setPollingConsumerServicePool(ServicePool<Endpoint, PollingConsumer> pollingConsumerServicePool) { 3018 this.pollingConsumerServicePool = pollingConsumerServicePool; 3019 } 3020 3021 public UnitOfWorkFactory getUnitOfWorkFactory() { 3022 return unitOfWorkFactory; 3023 } 3024 3025 public void setUnitOfWorkFactory(UnitOfWorkFactory unitOfWorkFactory) { 3026 this.unitOfWorkFactory = unitOfWorkFactory; 3027 } 3028 3029 public RuntimeEndpointRegistry getRuntimeEndpointRegistry() { 3030 return runtimeEndpointRegistry; 3031 } 3032 3033 public void setRuntimeEndpointRegistry(RuntimeEndpointRegistry runtimeEndpointRegistry) { 3034 this.runtimeEndpointRegistry = runtimeEndpointRegistry; 3035 } 3036 3037 public String getUptime() { 3038 long delta = getUptimeMillis(); 3039 if (delta == 0) { 3040 return ""; 3041 } 3042 return TimeUtils.printDuration(delta); 3043 } 3044 3045 public long getUptimeMillis() { 3046 if (startDate == null) { 3047 return 0; 3048 } 3049 return new Date().getTime() - startDate.getTime(); 3050 } 3051 3052 @Override 3053 protected void doSuspend() throws Exception { 3054 EventHelper.notifyCamelContextSuspending(this); 3055 3056 log.info("Apache Camel {} (CamelContext: {}) is suspending", getVersion(), getName()); 3057 StopWatch watch = new StopWatch(); 3058 3059 // update list of started routes to be suspended 3060 // because we only want to suspend started routes 3061 // (so when we resume we only resume the routes which actually was suspended) 3062 for (Map.Entry<String, RouteService> entry : getRouteServices().entrySet()) { 3063 if (entry.getValue().getStatus().isStarted()) { 3064 suspendedRouteServices.put(entry.getKey(), entry.getValue()); 3065 } 3066 } 3067 3068 // assemble list of startup ordering so routes can be shutdown accordingly 3069 List<RouteStartupOrder> orders = new ArrayList<RouteStartupOrder>(); 3070 for (Map.Entry<String, RouteService> entry : suspendedRouteServices.entrySet()) { 3071 Route route = entry.getValue().getRoutes().iterator().next(); 3072 Integer order = entry.getValue().getRouteDefinition().getStartupOrder(); 3073 if (order == null) { 3074 order = defaultRouteStartupOrder++; 3075 } 3076 orders.add(new DefaultRouteStartupOrder(order, route, entry.getValue())); 3077 } 3078 3079 // suspend routes using the shutdown strategy so it can shutdown in correct order 3080 // routes which doesn't support suspension will be stopped instead 3081 getShutdownStrategy().suspend(this, orders); 3082 3083 // mark the route services as suspended or stopped 3084 for (RouteService service : suspendedRouteServices.values()) { 3085 if (routeSupportsSuspension(service.getId())) { 3086 service.suspend(); 3087 } else { 3088 service.stop(); 3089 } 3090 } 3091 3092 watch.stop(); 3093 if (log.isInfoEnabled()) { 3094 log.info("Apache Camel {} (CamelContext: {}) is suspended in {}", getVersion(), getName(), TimeUtils.printDuration(watch.taken())); 3095 } 3096 3097 EventHelper.notifyCamelContextSuspended(this); 3098 } 3099 3100 @Override 3101 protected void doResume() throws Exception { 3102 try { 3103 EventHelper.notifyCamelContextResuming(this); 3104 3105 log.info("Apache Camel {} (CamelContext: {}) is resuming", getVersion(), getName()); 3106 StopWatch watch = new StopWatch(); 3107 3108 // start the suspended routes (do not check for route clashes, and indicate) 3109 doStartOrResumeRoutes(suspendedRouteServices, false, true, true, false); 3110 3111 // mark the route services as resumed (will be marked as started) as well 3112 for (RouteService service : suspendedRouteServices.values()) { 3113 if (routeSupportsSuspension(service.getId())) { 3114 service.resume(); 3115 } else { 3116 service.start(); 3117 } 3118 } 3119 3120 if (log.isInfoEnabled()) { 3121 log.info("Resumed {} routes", suspendedRouteServices.size()); 3122 log.info("Apache Camel {} (CamelContext: {}) resumed in {}", getVersion(), getName(), TimeUtils.printDuration(watch.taken())); 3123 } 3124 3125 // and clear the list as they have been resumed 3126 suspendedRouteServices.clear(); 3127 3128 EventHelper.notifyCamelContextResumed(this); 3129 } catch (Exception e) { 3130 EventHelper.notifyCamelContextResumeFailed(this, e); 3131 throw e; 3132 } 3133 } 3134 3135 @Override 3136 public void start() throws Exception { 3137 try (MDCHelper mdcHelper = new MDCHelper()) { 3138 vetoStated.set(false); 3139 startDate = new Date(); 3140 stopWatch.restart(); 3141 log.info("Apache Camel {} (CamelContext: {}) is starting", getVersion(), getName()); 3142 3143 // Note: This is done on context start as we want to avoid doing it during object construction 3144 // where we could be dealing with CDI proxied camel contexts which may never be started (CAMEL-9657) 3145 // [TODO] Remove in 3.0 3146 Container.Instance.manage(this); 3147 3148 // Start the route controller 3149 ServiceHelper.startServices(this.routeController); 3150 3151 doNotStartRoutesOnFirstStart = !firstStartDone && !isAutoStartup(); 3152 3153 // if the context was configured with auto startup = false, and we are already started, 3154 // then we may need to start the routes on the 2nd start call 3155 if (firstStartDone && !isAutoStartup() && isStarted()) { 3156 // invoke this logic to warm up the routes and if possible also start the routes 3157 doStartOrResumeRoutes(routeServices, true, true, false, true); 3158 } 3159 3160 // super will invoke doStart which will prepare internal services and start routes etc. 3161 try { 3162 firstStartDone = true; 3163 super.start(); 3164 } catch (VetoCamelContextStartException e) { 3165 // mark we veto against starting Camel 3166 vetoStated.set(true); 3167 if (e.isRethrowException()) { 3168 throw e; 3169 } else { 3170 log.info("CamelContext ({}) vetoed to not start due {}", getName(), e.getMessage()); 3171 // swallow exception and change state of this camel context to stopped 3172 stop(); 3173 return; 3174 } 3175 } 3176 3177 if (log.isInfoEnabled()) { 3178 // count how many routes are actually started 3179 int started = 0; 3180 for (Route route : getRoutes()) { 3181 ServiceStatus status = getRouteStatus(route.getId()); 3182 if (status != null && status.isStarted()) { 3183 started++; 3184 } 3185 } 3186 3187 final Collection<Route> controlledRoutes = getRouteController().getControlledRoutes(); 3188 if (controlledRoutes.isEmpty()) { 3189 log.info("Total {} routes, of which {} are started", 3190 getRoutes().size(), 3191 started); 3192 } else { 3193 log.info("Total {} routes, of which {} are started, and {} are managed by RouteController: {}", 3194 getRoutes().size(), 3195 started, 3196 controlledRoutes.size(), 3197 getRouteController().getClass().getName() 3198 ); 3199 } 3200 log.info("Apache Camel {} (CamelContext: {}) started in {}", getVersion(), getName(), TimeUtils.printDuration(stopWatch.taken())); 3201 } 3202 3203 // okay the routes has been started so emit event that CamelContext has started (here at the end) 3204 EventHelper.notifyCamelContextStarted(this); 3205 3206 // now call the startup listeners where the routes has been started 3207 for (StartupListener startup : startupListeners) { 3208 if (startup instanceof ExtendedStartupListener) { 3209 ((ExtendedStartupListener) startup).onCamelContextFullyStarted(this, isStarted()); 3210 } 3211 } 3212 } 3213 } 3214 3215 @Override 3216 public void stop() throws Exception { 3217 try (MDCHelper mdcHelper = new MDCHelper()) { 3218 super.stop(); 3219 } 3220 } 3221 3222 @Override 3223 public void suspend() throws Exception { 3224 try (MDCHelper mdcHelper = new MDCHelper()) { 3225 super.suspend(); 3226 } 3227 } 3228 3229 @Override 3230 public void resume() throws Exception { 3231 try (MDCHelper mdcHelper = new MDCHelper()) { 3232 super.resume(); 3233 } 3234 } 3235 3236 @Override 3237 public void shutdown() throws Exception { 3238 try (MDCHelper mdcHelper = new MDCHelper()) { 3239 super.shutdown(); 3240 } 3241 } 3242 3243 // Implementation methods 3244 // ----------------------------------------------------------------------- 3245 3246 protected synchronized void doStart() throws Exception { 3247 doWithDefinedClassLoader(new Callable<Void>() { 3248 @Override 3249 public Void call() throws Exception { 3250 try { 3251 doStartCamel(); 3252 return null; 3253 } catch (Exception e) { 3254 // fire event that we failed to start 3255 EventHelper.notifyCamelContextStartupFailed(DefaultCamelContext.this, e); 3256 // rethrow cause 3257 throw e; 3258 } 3259 } 3260 }); 3261 } 3262 3263 private <T> T doWithDefinedClassLoader(Callable<T> callable) throws Exception { 3264 ClassLoader tccl = Thread.currentThread().getContextClassLoader(); 3265 try { 3266 // Using the ApplicationClassLoader as the default for TCCL 3267 if (applicationContextClassLoader != null) { 3268 Thread.currentThread().setContextClassLoader(applicationContextClassLoader); 3269 } 3270 return callable.call(); 3271 } finally { 3272 Thread.currentThread().setContextClassLoader(tccl); 3273 } 3274 } 3275 3276 private void doStartCamel() throws Exception { 3277 3278 // custom properties may use property placeholders so resolve those early on 3279 if (globalOptions != null && !globalOptions.isEmpty()) { 3280 for (Map.Entry<String, String> entry : globalOptions.entrySet()) { 3281 String key = entry.getKey(); 3282 String value = entry.getValue(); 3283 if (value != null) { 3284 String replaced = resolvePropertyPlaceholders(value); 3285 if (!value.equals(replaced)) { 3286 if (log.isDebugEnabled()) { 3287 log.debug("Camel property with key {} replaced value from {} -> {}", new Object[]{key, value, replaced}); 3288 } 3289 entry.setValue(replaced); 3290 } 3291 } 3292 } 3293 } 3294 3295 if (classResolver instanceof CamelContextAware) { 3296 ((CamelContextAware) classResolver).setCamelContext(this); 3297 } 3298 3299 if (log.isDebugEnabled()) { 3300 log.debug("Using ClassResolver={}, PackageScanClassResolver={}, ApplicationContextClassLoader={}, RouteController={}", 3301 getClassResolver(), getPackageScanClassResolver(), getApplicationContextClassLoader(), getRouteController()); 3302 } 3303 3304 if (isStreamCaching()) { 3305 log.info("StreamCaching is enabled on CamelContext: {}", getName()); 3306 } 3307 3308 if (isTracing()) { 3309 // tracing is added in the DefaultChannel so we can enable it on the fly 3310 log.info("Tracing is enabled on CamelContext: {}", getName()); 3311 } 3312 3313 if (isUseMDCLogging()) { 3314 // log if MDC has been enabled 3315 log.info("MDC logging is enabled on CamelContext: {}", getName()); 3316 } 3317 3318 if (isHandleFault()) { 3319 // only add a new handle fault if not already configured 3320 if (HandleFault.getHandleFault(this) == null) { 3321 log.info("HandleFault is enabled on CamelContext: {}", getName()); 3322 addInterceptStrategy(new HandleFault()); 3323 } 3324 } 3325 3326 if (getDelayer() != null && getDelayer() > 0) { 3327 log.info("Delayer is enabled with: {} ms. on CamelContext: {}", getDelayer(), getName()); 3328 } 3329 3330 // register debugger 3331 if (getDebugger() != null) { 3332 log.info("Debugger: {} is enabled on CamelContext: {}", getDebugger(), getName()); 3333 // register this camel context on the debugger 3334 getDebugger().setCamelContext(this); 3335 startService(getDebugger()); 3336 addInterceptStrategy(new Debug(getDebugger())); 3337 } 3338 3339 // start management strategy before lifecycles are started 3340 ManagementStrategy managementStrategy = getManagementStrategy(); 3341 // inject CamelContext if aware 3342 if (managementStrategy instanceof CamelContextAware) { 3343 ((CamelContextAware) managementStrategy).setCamelContext(this); 3344 } 3345 ServiceHelper.startService(managementStrategy); 3346 3347 // start lifecycle strategies 3348 ServiceHelper.startServices(lifecycleStrategies); 3349 Iterator<LifecycleStrategy> it = lifecycleStrategies.iterator(); 3350 while (it.hasNext()) { 3351 LifecycleStrategy strategy = it.next(); 3352 try { 3353 strategy.onContextStart(this); 3354 } catch (VetoCamelContextStartException e) { 3355 // okay we should not start Camel since it was vetoed 3356 log.warn("Lifecycle strategy vetoed starting CamelContext ({}) due: {}", getName(), e.getMessage()); 3357 throw e; 3358 } catch (Exception e) { 3359 log.warn("Lifecycle strategy " + strategy + " failed starting CamelContext ({}) due: {}", getName(), e.getMessage()); 3360 throw e; 3361 } 3362 } 3363 3364 // start notifiers as services 3365 for (EventNotifier notifier : getManagementStrategy().getEventNotifiers()) { 3366 if (notifier instanceof Service) { 3367 Service service = (Service) notifier; 3368 for (LifecycleStrategy strategy : lifecycleStrategies) { 3369 strategy.onServiceAdd(this, service, null); 3370 } 3371 } 3372 if (notifier instanceof Service) { 3373 startService((Service)notifier); 3374 } 3375 } 3376 3377 // must let some bootstrap service be started before we can notify the starting event 3378 EventHelper.notifyCamelContextStarting(this); 3379 3380 forceLazyInitialization(); 3381 3382 // re-create endpoint registry as the cache size limit may be set after the constructor of this instance was called. 3383 // and we needed to create endpoints up-front as it may be accessed before this context is started 3384 endpoints = new DefaultEndpointRegistry(this, endpoints); 3385 // add this as service and force pre-start them 3386 addService(endpoints, true, true); 3387 // special for executorServiceManager as want to stop it manually so false in stopOnShutdown 3388 addService(executorServiceManager, false, true); 3389 addService(producerServicePool, true, true); 3390 addService(pollingConsumerServicePool, true, true); 3391 addService(inflightRepository, true, true); 3392 addService(asyncProcessorAwaitManager, true, true); 3393 addService(shutdownStrategy, true, true); 3394 addService(packageScanClassResolver, true, true); 3395 addService(restRegistry, true, true); 3396 addService(messageHistoryFactory, true, true); 3397 addService(runtimeCamelCatalog, true, true); 3398 if (reloadStrategy != null) { 3399 log.info("Using ReloadStrategy: {}", reloadStrategy); 3400 addService(reloadStrategy, true, true); 3401 } 3402 3403 // Initialize declarative transformer/validator registry 3404 transformerRegistry = new DefaultTransformerRegistry(this, transformers); 3405 addService(transformerRegistry, true, true); 3406 validatorRegistry = new DefaultValidatorRegistry(this, validators); 3407 addService(validatorRegistry, true, true); 3408 3409 // optimised to not include runtimeEndpointRegistry unlesstartServices its enabled or JMX statistics is in extended mode 3410 if (runtimeEndpointRegistry == null && getManagementStrategy() != null && getManagementStrategy().getManagementAgent() != null) { 3411 Boolean isEnabled = getManagementStrategy().getManagementAgent().getEndpointRuntimeStatisticsEnabled(); 3412 boolean isExtended = getManagementStrategy().getManagementAgent().getStatisticsLevel().isExtended(); 3413 // extended mode is either if we use Extended statistics level or the option is explicit enabled 3414 boolean extended = isExtended || isEnabled != null && isEnabled; 3415 if (extended) { 3416 runtimeEndpointRegistry = new DefaultRuntimeEndpointRegistry(); 3417 } 3418 } 3419 if (runtimeEndpointRegistry != null) { 3420 if (runtimeEndpointRegistry instanceof EventNotifier) { 3421 getManagementStrategy().addEventNotifier((EventNotifier) runtimeEndpointRegistry); 3422 } 3423 addService(runtimeEndpointRegistry, true, true); 3424 } 3425 3426 // eager lookup any configured properties component to avoid subsequent lookup attempts which may impact performance 3427 // due we use properties component for property placeholder resolution at runtime 3428 Component existing = CamelContextHelper.lookupPropertiesComponent(this, false); 3429 if (existing != null) { 3430 // store reference to the existing properties component 3431 if (existing instanceof PropertiesComponent) { 3432 propertiesComponent = (PropertiesComponent) existing; 3433 } else { 3434 // properties component must be expected type 3435 throw new IllegalArgumentException("Found properties component of type: " + existing.getClass() + " instead of expected: " + PropertiesComponent.class); 3436 } 3437 } 3438 3439 // start components 3440 startServices(components.values()); 3441 3442 // start the route definitions before the routes is started 3443 startRouteDefinitions(routeDefinitions); 3444 3445 // 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 3446 boolean streamCachingInUse = isStreamCaching(); 3447 if (!streamCachingInUse) { 3448 for (RouteDefinition route : routeDefinitions) { 3449 Boolean routeCache = CamelContextHelper.parseBoolean(this, route.getStreamCache()); 3450 if (routeCache != null && routeCache) { 3451 streamCachingInUse = true; 3452 break; 3453 } 3454 } 3455 } 3456 3457 if (isUseDataType()) { 3458 // log if DataType has been enabled 3459 log.info("Message DataType is enabled on CamelContext: {}", getName()); 3460 } 3461 3462 if (streamCachingInUse) { 3463 // stream caching is in use so enable the strategy 3464 getStreamCachingStrategy().setEnabled(true); 3465 addService(getStreamCachingStrategy(), true, true); 3466 } else { 3467 // log if stream caching is not in use as this can help people to enable it if they use streams 3468 log.info("StreamCaching is not in use. If using streams then its recommended to enable stream caching." 3469 + " See more details at http://camel.apache.org/stream-caching.html"); 3470 } 3471 3472 if (isAllowUseOriginalMessage()) { 3473 log.debug("AllowUseOriginalMessage enabled because UseOriginalMessage is in use"); 3474 } 3475 3476 // use resolver to find the headers map factory to be used, if we are using the default 3477 if (headersMapFactory instanceof DefaultHeadersMapFactory) { 3478 headersMapFactory = new HeadersMapFactoryResolver().resolve(this); 3479 } 3480 3481 log.debug("Using HeadersMapFactory: {}", headersMapFactory); 3482 if (!headersMapFactory.isCaseInsensitive()) { 3483 log.info("HeadersMapFactory: {} is case-sensitive which can cause problems for protocols such as HTTP based, which rely on case-insensitive headers.", getHeadersMapFactory()); 3484 } 3485 3486 // start routes 3487 if (doNotStartRoutesOnFirstStart) { 3488 log.debug("Skip starting routes as CamelContext has been configured with autoStartup=false"); 3489 } 3490 3491 // invoke this logic to warmup the routes and if possible also start the routes 3492 doStartOrResumeRoutes(routeServices, true, !doNotStartRoutesOnFirstStart, false, true); 3493 3494 // starting will continue in the start method 3495 } 3496 3497 protected synchronized void doStop() throws Exception { 3498 stopWatch.restart(); 3499 log.info("Apache Camel {} (CamelContext: {}) is shutting down", getVersion(), getName()); 3500 EventHelper.notifyCamelContextStopping(this); 3501 3502 // Stop the route controller 3503 ServiceHelper.stopAndShutdownService(this.routeController); 3504 3505 // stop route inputs in the same order as they was started so we stop the very first inputs first 3506 try { 3507 // force shutting down routes as they may otherwise cause shutdown to hang 3508 shutdownStrategy.shutdownForced(this, getRouteStartupOrder()); 3509 } catch (Throwable e) { 3510 log.warn("Error occurred while shutting down routes. This exception will be ignored.", e); 3511 } 3512 3513 // shutdown await manager to trigger interrupt of blocked threads to attempt to free these threads graceful 3514 shutdownServices(asyncProcessorAwaitManager); 3515 3516 shutdownServices(getRouteStartupOrder().stream() 3517 .sorted(Comparator.comparing(RouteStartupOrder::getStartupOrder).reversed()) 3518 .map(DefaultRouteStartupOrder.class::cast) 3519 .map(DefaultRouteStartupOrder::getRouteService) 3520 .collect(Collectors.toList()), false); 3521 // do not clear route services or startup listeners as we can start Camel again and get the route back as before 3522 getRouteStartupOrder().clear(); 3523 3524 // but clear any suspend routes 3525 suspendedRouteServices.clear(); 3526 3527 // stop consumers from the services to close first, such as POJO consumer (eg @Consumer) 3528 // which we need to stop after the routes, as a POJO consumer is essentially a route also 3529 for (Service service : servicesToStop) { 3530 if (service instanceof Consumer) { 3531 shutdownServices(service); 3532 } 3533 } 3534 3535 // the stop order is important 3536 3537 // shutdown default error handler thread pool 3538 if (errorHandlerExecutorService != null) { 3539 // force shutting down the thread pool 3540 getExecutorServiceManager().shutdownNow(errorHandlerExecutorService); 3541 errorHandlerExecutorService = null; 3542 } 3543 3544 // shutdown debugger 3545 ServiceHelper.stopAndShutdownService(getDebugger()); 3546 3547 shutdownServices(endpoints.values()); 3548 endpoints.clear(); 3549 3550 shutdownServices(components.values()); 3551 components.clear(); 3552 3553 shutdownServices(languages.values()); 3554 languages.clear(); 3555 3556 try { 3557 for (LifecycleStrategy strategy : lifecycleStrategies) { 3558 strategy.onContextStop(this); 3559 } 3560 } catch (Throwable e) { 3561 log.warn("Error occurred while stopping lifecycle strategies. This exception will be ignored.", e); 3562 } 3563 3564 // shutdown services as late as possible 3565 shutdownServices(servicesToStop); 3566 servicesToStop.clear(); 3567 3568 // must notify that we are stopped before stopping the management strategy 3569 EventHelper.notifyCamelContextStopped(this); 3570 3571 // stop the notifier service 3572 for (EventNotifier notifier : getManagementStrategy().getEventNotifiers()) { 3573 shutdownServices(notifier); 3574 } 3575 3576 // shutdown executor service and management as the last one 3577 shutdownServices(executorServiceManager); 3578 shutdownServices(managementStrategy); 3579 shutdownServices(managementMBeanAssembler); 3580 shutdownServices(lifecycleStrategies); 3581 // do not clear lifecycleStrategies as we can start Camel again and get the route back as before 3582 3583 // stop the lazy created so they can be re-created on restart 3584 forceStopLazyInitialization(); 3585 3586 // stop to clear introspection cache 3587 IntrospectionSupport.stop(); 3588 3589 if (log.isInfoEnabled()) { 3590 log.info("Apache Camel " + getVersion() + " (CamelContext: " + getName() + ") uptime {}", getUptime()); 3591 log.info("Apache Camel {} (CamelContext: {}) is shutdown in {}", getVersion(), getName(), TimeUtils.printDuration(stopWatch.taken())); 3592 } 3593 3594 // and clear start date 3595 startDate = null; 3596 3597 // [TODO] Remove in 3.0 3598 Container.Instance.unmanage(this); 3599 } 3600 3601 /** 3602 * Starts or resumes the routes 3603 * 3604 * @param routeServices the routes to start (will only start a route if its not already started) 3605 * @param checkClash whether to check for startup ordering clash 3606 * @param startConsumer whether the route consumer should be started. Can be used to warmup the route without starting the consumer. 3607 * @param resumeConsumer whether the route consumer should be resumed. 3608 * @param addingRoutes whether we are adding new routes 3609 * @throws Exception is thrown if error starting routes 3610 */ 3611 protected void doStartOrResumeRoutes(Map<String, RouteService> routeServices, boolean checkClash, 3612 boolean startConsumer, boolean resumeConsumer, boolean addingRoutes) throws Exception { 3613 isStartingRoutes.set(true); 3614 try { 3615 // filter out already started routes 3616 Map<String, RouteService> filtered = new LinkedHashMap<String, RouteService>(); 3617 for (Map.Entry<String, RouteService> entry : routeServices.entrySet()) { 3618 boolean startable = false; 3619 3620 Consumer consumer = entry.getValue().getRoutes().iterator().next().getConsumer(); 3621 if (consumer instanceof SuspendableService) { 3622 // consumer could be suspended, which is not reflected in the RouteService status 3623 startable = ((SuspendableService) consumer).isSuspended(); 3624 } 3625 3626 if (!startable && consumer instanceof StatefulService) { 3627 // consumer could be stopped, which is not reflected in the RouteService status 3628 startable = ((StatefulService) consumer).getStatus().isStartable(); 3629 } else if (!startable) { 3630 // no consumer so use state from route service 3631 startable = entry.getValue().getStatus().isStartable(); 3632 } 3633 3634 if (startable) { 3635 filtered.put(entry.getKey(), entry.getValue()); 3636 } 3637 } 3638 3639 // the context is in last phase of staring, so lets start the routes 3640 safelyStartRouteServices(checkClash, startConsumer, resumeConsumer, addingRoutes, filtered.values()); 3641 3642 } finally { 3643 isStartingRoutes.remove(); 3644 } 3645 } 3646 3647 protected boolean routeSupportsSuspension(String routeId) { 3648 RouteService routeService = routeServices.get(routeId); 3649 if (routeService != null) { 3650 return routeService.getRoutes().iterator().next().supportsSuspension(); 3651 } 3652 return false; 3653 } 3654 3655 private void shutdownServices(Object service) { 3656 // do not rethrow exception as we want to keep shutting down in case of problems 3657 3658 // allow us to do custom work before delegating to service helper 3659 try { 3660 if (service instanceof Service) { 3661 ServiceHelper.stopAndShutdownService(service); 3662 } else if (service instanceof Collection) { 3663 ServiceHelper.stopAndShutdownServices((Collection<?>)service); 3664 } 3665 } catch (Throwable e) { 3666 log.warn("Error occurred while shutting down service: " + service + ". This exception will be ignored.", e); 3667 // fire event 3668 EventHelper.notifyServiceStopFailure(this, service, e); 3669 } 3670 } 3671 3672 private void shutdownServices(Collection<?> services) { 3673 // reverse stopping by default 3674 shutdownServices(services, true); 3675 } 3676 3677 private void shutdownServices(Collection<?> services, boolean reverse) { 3678 Collection<?> list = services; 3679 if (reverse) { 3680 List<Object> reverseList = new ArrayList<Object>(services); 3681 Collections.reverse(reverseList); 3682 list = reverseList; 3683 } 3684 3685 for (Object service : list) { 3686 shutdownServices(service); 3687 } 3688 } 3689 3690 private void startService(Service service) throws Exception { 3691 // and register startup aware so they can be notified when 3692 // camel context has been started 3693 if (service instanceof StartupListener) { 3694 StartupListener listener = (StartupListener) service; 3695 addStartupListener(listener); 3696 } 3697 3698 if (service instanceof CamelContextAware) { 3699 CamelContextAware aware = (CamelContextAware) service; 3700 aware.setCamelContext(this); 3701 } 3702 3703 service.start(); 3704 } 3705 3706 private void startServices(Collection<?> services) throws Exception { 3707 for (Object element : services) { 3708 if (element instanceof Service) { 3709 startService((Service)element); 3710 } 3711 } 3712 } 3713 3714 private void stopServices(Object service) throws Exception { 3715 // allow us to do custom work before delegating to service helper 3716 try { 3717 ServiceHelper.stopService(service); 3718 } catch (Exception e) { 3719 // fire event 3720 EventHelper.notifyServiceStopFailure(this, service, e); 3721 // rethrow to signal error with stopping 3722 throw e; 3723 } 3724 } 3725 3726 protected void startRouteDefinitions(Collection<RouteDefinition> list) throws Exception { 3727 if (list != null) { 3728 for (RouteDefinition route : list) { 3729 startRoute(route); 3730 } 3731 } 3732 } 3733 3734 /** 3735 * Starts the given route service 3736 */ 3737 protected synchronized void startRouteService(RouteService routeService, boolean addingRoutes) throws Exception { 3738 // we may already be starting routes so remember this, so we can unset accordingly in finally block 3739 boolean alreadyStartingRoutes = isStartingRoutes(); 3740 if (!alreadyStartingRoutes) { 3741 isStartingRoutes.set(true); 3742 } 3743 3744 try { 3745 // the route service could have been suspended, and if so then resume it instead 3746 if (routeService.getStatus().isSuspended()) { 3747 resumeRouteService(routeService); 3748 } else { 3749 // start the route service 3750 routeServices.put(routeService.getId(), routeService); 3751 if (shouldStartRoutes()) { 3752 // this method will log the routes being started 3753 safelyStartRouteServices(true, true, true, false, addingRoutes, routeService); 3754 // start route services if it was configured to auto startup and we are not adding routes 3755 boolean autoStartup = routeService.getRouteDefinition().isAutoStartup(this) && this.isAutoStartup(); 3756 if (!addingRoutes || autoStartup) { 3757 // start the route since auto start is enabled or we are starting a route (not adding new routes) 3758 routeService.start(); 3759 } 3760 } 3761 } 3762 } finally { 3763 if (!alreadyStartingRoutes) { 3764 isStartingRoutes.remove(); 3765 } 3766 } 3767 } 3768 3769 /** 3770 * Resumes the given route service 3771 */ 3772 protected synchronized void resumeRouteService(RouteService routeService) throws Exception { 3773 // the route service could have been stopped, and if so then start it instead 3774 if (!routeService.getStatus().isSuspended()) { 3775 startRouteService(routeService, false); 3776 } else { 3777 // resume the route service 3778 if (shouldStartRoutes()) { 3779 // this method will log the routes being started 3780 safelyStartRouteServices(true, false, true, true, false, routeService); 3781 // must resume route service as well 3782 routeService.resume(); 3783 } 3784 } 3785 } 3786 3787 protected synchronized void stopRouteService(RouteService routeService, boolean removingRoutes) throws Exception { 3788 routeService.setRemovingRoutes(removingRoutes); 3789 stopRouteService(routeService); 3790 } 3791 3792 protected void logRouteState(Route route, String state) { 3793 if (log.isInfoEnabled()) { 3794 if (route.getConsumer() != null) { 3795 log.info("Route: {} is {}, was consuming from: {}", new Object[]{route.getId(), state, route.getConsumer().getEndpoint()}); 3796 } else { 3797 log.info("Route: {} is {}.", route.getId(), state); 3798 } 3799 } 3800 } 3801 3802 protected synchronized void stopRouteService(RouteService routeService) throws Exception { 3803 routeService.stop(); 3804 for (Route route : routeService.getRoutes()) { 3805 logRouteState(route, "stopped"); 3806 } 3807 } 3808 3809 protected synchronized void shutdownRouteService(RouteService routeService) throws Exception { 3810 routeService.shutdown(); 3811 for (Route route : routeService.getRoutes()) { 3812 logRouteState(route, "shutdown and removed"); 3813 } 3814 } 3815 3816 protected synchronized void suspendRouteService(RouteService routeService) throws Exception { 3817 routeService.setRemovingRoutes(false); 3818 routeService.suspend(); 3819 for (Route route : routeService.getRoutes()) { 3820 logRouteState(route, "suspended"); 3821 } 3822 } 3823 3824 /** 3825 * Starts the routes services in a proper manner which ensures the routes will be started in correct order, 3826 * check for clash and that the routes will also be shutdown in correct order as well. 3827 * <p/> 3828 * This method <b>must</b> be used to start routes in a safe manner. 3829 * 3830 * @param checkClash whether to check for startup order clash 3831 * @param startConsumer whether the route consumer should be started. Can be used to warmup the route without starting the consumer. 3832 * @param resumeConsumer whether the route consumer should be resumed. 3833 * @param addingRoutes whether we are adding new routes 3834 * @param routeServices the routes 3835 * @throws Exception is thrown if error starting the routes 3836 */ 3837 protected synchronized void safelyStartRouteServices(boolean checkClash, boolean startConsumer, boolean resumeConsumer, 3838 boolean addingRoutes, Collection<RouteService> routeServices) throws Exception { 3839 // list of inputs to start when all the routes have been prepared for starting 3840 // we use a tree map so the routes will be ordered according to startup order defined on the route 3841 Map<Integer, DefaultRouteStartupOrder> inputs = new TreeMap<Integer, DefaultRouteStartupOrder>(); 3842 3843 // figure out the order in which the routes should be started 3844 for (RouteService routeService : routeServices) { 3845 DefaultRouteStartupOrder order = doPrepareRouteToBeStarted(routeService); 3846 // check for clash before we add it as input 3847 if (checkClash) { 3848 doCheckStartupOrderClash(order, inputs); 3849 } 3850 inputs.put(order.getStartupOrder(), order); 3851 } 3852 3853 // warm up routes before we start them 3854 doWarmUpRoutes(inputs, startConsumer); 3855 3856 // sort the startup listeners so they are started in the right order 3857 startupListeners.sort(OrderedComparator.get()); 3858 // now call the startup listeners where the routes has been warmed up 3859 // (only the actual route consumer has not yet been started) 3860 for (StartupListener startup : startupListeners) { 3861 startup.onCamelContextStarted(this, isStarted()); 3862 } 3863 // because the consumers may also register startup listeners we need to reset 3864 // the already started listeners 3865 List<StartupListener> backup = new ArrayList<>(startupListeners); 3866 startupListeners.clear(); 3867 3868 // now start the consumers 3869 if (startConsumer) { 3870 if (resumeConsumer) { 3871 // and now resume the routes 3872 doResumeRouteConsumers(inputs, addingRoutes); 3873 } else { 3874 // and now start the routes 3875 // and check for clash with multiple consumers of the same endpoints which is not allowed 3876 doStartRouteConsumers(inputs, addingRoutes); 3877 } 3878 } 3879 3880 // sort the startup listeners so they are started in the right order 3881 startupListeners.sort(OrderedComparator.get()); 3882 // now the consumers that was just started may also add new StartupListeners (such as timer) 3883 // so we need to ensure they get started as well 3884 for (StartupListener startup : startupListeners) { 3885 startup.onCamelContextStarted(this, isStarted()); 3886 } 3887 // and add the previous started startup listeners to the list so we have them all 3888 startupListeners.addAll(0, backup); 3889 3890 // inputs no longer needed 3891 inputs.clear(); 3892 } 3893 3894 /** 3895 * @see #safelyStartRouteServices(boolean,boolean,boolean,boolean,java.util.Collection) 3896 */ 3897 protected synchronized void safelyStartRouteServices(boolean forceAutoStart, boolean checkClash, boolean startConsumer, 3898 boolean resumeConsumer, boolean addingRoutes, RouteService... routeServices) throws Exception { 3899 safelyStartRouteServices(checkClash, startConsumer, resumeConsumer, addingRoutes, Arrays.asList(routeServices)); 3900 } 3901 3902 private DefaultRouteStartupOrder doPrepareRouteToBeStarted(RouteService routeService) { 3903 // add the inputs from this route service to the list to start afterwards 3904 // should be ordered according to the startup number 3905 Integer startupOrder = routeService.getRouteDefinition().getStartupOrder(); 3906 if (startupOrder == null) { 3907 // auto assign a default startup order 3908 startupOrder = defaultRouteStartupOrder++; 3909 } 3910 3911 // create holder object that contains information about this route to be started 3912 Route route = routeService.getRoutes().iterator().next(); 3913 return new DefaultRouteStartupOrder(startupOrder, route, routeService); 3914 } 3915 3916 private boolean doCheckStartupOrderClash(DefaultRouteStartupOrder answer, Map<Integer, DefaultRouteStartupOrder> inputs) throws FailedToStartRouteException { 3917 // check for clash by startupOrder id 3918 DefaultRouteStartupOrder other = inputs.get(answer.getStartupOrder()); 3919 if (other != null && answer != other) { 3920 String otherId = other.getRoute().getId(); 3921 throw new FailedToStartRouteException(answer.getRoute().getId(), "startupOrder clash. Route " + otherId + " already has startupOrder " 3922 + answer.getStartupOrder() + " configured which this route have as well. Please correct startupOrder to be unique among all your routes."); 3923 } 3924 // check in existing already started as well 3925 for (RouteStartupOrder order : routeStartupOrder) { 3926 String otherId = order.getRoute().getId(); 3927 if (answer.getRoute().getId().equals(otherId)) { 3928 // its the same route id so skip clash check as its the same route (can happen when using suspend/resume) 3929 } else if (answer.getStartupOrder() == order.getStartupOrder()) { 3930 throw new FailedToStartRouteException(answer.getRoute().getId(), "startupOrder clash. Route " + otherId + " already has startupOrder " 3931 + answer.getStartupOrder() + " configured which this route have as well. Please correct startupOrder to be unique among all your routes."); 3932 } 3933 } 3934 return true; 3935 } 3936 3937 private void doWarmUpRoutes(Map<Integer, DefaultRouteStartupOrder> inputs, boolean autoStartup) throws Exception { 3938 // now prepare the routes by starting its services before we start the input 3939 for (Map.Entry<Integer, DefaultRouteStartupOrder> entry : inputs.entrySet()) { 3940 // defer starting inputs till later as we want to prepare the routes by starting 3941 // all their processors and child services etc. 3942 // then later we open the floods to Camel by starting the inputs 3943 // what this does is to ensure Camel is more robust on starting routes as all routes 3944 // will then be prepared in time before we start inputs which will consume messages to be routed 3945 RouteService routeService = entry.getValue().getRouteService(); 3946 log.debug("Warming up route id: {} having autoStartup={}", routeService.getId(), autoStartup); 3947 routeService.warmUp(); 3948 } 3949 } 3950 3951 private void doResumeRouteConsumers(Map<Integer, DefaultRouteStartupOrder> inputs, boolean addingRoutes) throws Exception { 3952 doStartOrResumeRouteConsumers(inputs, true, addingRoutes); 3953 } 3954 3955 private void doStartRouteConsumers(Map<Integer, DefaultRouteStartupOrder> inputs, boolean addingRoutes) throws Exception { 3956 doStartOrResumeRouteConsumers(inputs, false, addingRoutes); 3957 } 3958 3959 private void doStartOrResumeRouteConsumers(Map<Integer, DefaultRouteStartupOrder> inputs, boolean resumeOnly, boolean addingRoute) throws Exception { 3960 List<Endpoint> routeInputs = new ArrayList<Endpoint>(); 3961 3962 for (Map.Entry<Integer, DefaultRouteStartupOrder> entry : inputs.entrySet()) { 3963 Integer order = entry.getKey(); 3964 Route route = entry.getValue().getRoute(); 3965 RouteService routeService = entry.getValue().getRouteService(); 3966 3967 // if we are starting camel, then skip routes which are configured to not be auto started 3968 boolean autoStartup = routeService.getRouteDefinition().isAutoStartup(this) && this.isAutoStartup(); 3969 if (addingRoute && !autoStartup) { 3970 log.info("Skipping starting of route {} as its configured with autoStartup=false", routeService.getId()); 3971 continue; 3972 } 3973 3974 // start the service 3975 for (Consumer consumer : routeService.getInputs().values()) { 3976 Endpoint endpoint = consumer.getEndpoint(); 3977 3978 // check multiple consumer violation, with the other routes to be started 3979 if (!doCheckMultipleConsumerSupportClash(endpoint, routeInputs)) { 3980 throw new FailedToStartRouteException(routeService.getId(), 3981 "Multiple consumers for the same endpoint is not allowed: " + endpoint); 3982 } 3983 3984 // check for multiple consumer violations with existing routes which 3985 // have already been started, or is currently starting 3986 List<Endpoint> existingEndpoints = new ArrayList<Endpoint>(); 3987 for (Route existingRoute : getRoutes()) { 3988 if (route.getId().equals(existingRoute.getId())) { 3989 // skip ourselves 3990 continue; 3991 } 3992 Endpoint existing = existingRoute.getEndpoint(); 3993 ServiceStatus status = getRouteStatus(existingRoute.getId()); 3994 if (status != null && (status.isStarted() || status.isStarting())) { 3995 existingEndpoints.add(existing); 3996 } 3997 } 3998 if (!doCheckMultipleConsumerSupportClash(endpoint, existingEndpoints)) { 3999 throw new FailedToStartRouteException(routeService.getId(), 4000 "Multiple consumers for the same endpoint is not allowed: " + endpoint); 4001 } 4002 4003 // start the consumer on the route 4004 log.debug("Route: {} >>> {}", route.getId(), route); 4005 if (resumeOnly) { 4006 log.debug("Resuming consumer (order: {}) on route: {}", order, route.getId()); 4007 } else { 4008 log.debug("Starting consumer (order: {}) on route: {}", order, route.getId()); 4009 } 4010 4011 if (resumeOnly && route.supportsSuspension()) { 4012 // if we are resuming and the route can be resumed 4013 ServiceHelper.resumeService(consumer); 4014 log.info("Route: {} resumed and consuming from: {}", route.getId(), endpoint); 4015 } else { 4016 // when starting we should invoke the lifecycle strategies 4017 for (LifecycleStrategy strategy : lifecycleStrategies) { 4018 strategy.onServiceAdd(this, consumer, route); 4019 } 4020 try { 4021 startService(consumer); 4022 route.getProperties().remove("route.start.exception"); 4023 } catch (Exception e) { 4024 route.getProperties().put("route.start.exception", e); 4025 throw e; 4026 } 4027 4028 log.info("Route: {} started and consuming from: {}", route.getId(), endpoint); 4029 } 4030 4031 routeInputs.add(endpoint); 4032 4033 // add to the order which they was started, so we know how to stop them in reverse order 4034 // but only add if we haven't already registered it before (we dont want to double add when restarting) 4035 boolean found = false; 4036 for (RouteStartupOrder other : routeStartupOrder) { 4037 if (other.getRoute().getId().equals(route.getId())) { 4038 found = true; 4039 break; 4040 } 4041 } 4042 if (!found) { 4043 routeStartupOrder.add(entry.getValue()); 4044 } 4045 } 4046 4047 if (resumeOnly) { 4048 routeService.resume(); 4049 } else { 4050 // and start the route service (no need to start children as they are already warmed up) 4051 try { 4052 routeService.start(false); 4053 route.getProperties().remove("route.start.exception"); 4054 } catch (Exception e) { 4055 route.getProperties().put("route.start.exception", e); 4056 throw e; 4057 } 4058 } 4059 } 4060 } 4061 4062 private boolean doCheckMultipleConsumerSupportClash(Endpoint endpoint, List<Endpoint> routeInputs) { 4063 // is multiple consumers supported 4064 boolean multipleConsumersSupported = false; 4065 if (endpoint instanceof MultipleConsumersSupport) { 4066 multipleConsumersSupported = ((MultipleConsumersSupport) endpoint).isMultipleConsumersSupported(); 4067 } 4068 4069 if (multipleConsumersSupported) { 4070 // multiple consumer allowed, so return true 4071 return true; 4072 } 4073 4074 // check in progress list 4075 if (routeInputs.contains(endpoint)) { 4076 return false; 4077 } 4078 4079 return true; 4080 } 4081 4082 /** 4083 * Force some lazy initialization to occur upfront before we start any 4084 * components and create routes 4085 */ 4086 protected void forceLazyInitialization() { 4087 getRegistry(); 4088 getInjector(); 4089 getLanguageResolver(); 4090 getTypeConverterRegistry(); 4091 getTypeConverter(); 4092 4093 if (isTypeConverterStatisticsEnabled() != null) { 4094 getTypeConverterRegistry().getStatistics().setStatisticsEnabled(isTypeConverterStatisticsEnabled()); 4095 } 4096 4097 // resolve simple language to initialize it 4098 resolveLanguage("simple"); 4099 } 4100 4101 /** 4102 * Force clear lazy initialization so they can be re-created on restart 4103 */ 4104 protected void forceStopLazyInitialization() { 4105 injector = null; 4106 languageResolver = null; 4107 typeConverterRegistry = null; 4108 typeConverter = null; 4109 } 4110 4111 /** 4112 * Lazily create a default implementation 4113 */ 4114 protected TypeConverter createTypeConverter() { 4115 BaseTypeConverterRegistry answer; 4116 if (isLazyLoadTypeConverters()) { 4117 answer = new LazyLoadingTypeConverter(packageScanClassResolver, getInjector(), getDefaultFactoryFinder()); 4118 } else { 4119 answer = new DefaultTypeConverter(packageScanClassResolver, getInjector(), getDefaultFactoryFinder(), isLoadTypeConverters()); 4120 } 4121 answer.setCamelContext(this); 4122 setTypeConverterRegistry(answer); 4123 return answer; 4124 } 4125 4126 /** 4127 * Lazily create a default implementation 4128 */ 4129 protected Injector createInjector() { 4130 FactoryFinder finder = getDefaultFactoryFinder(); 4131 try { 4132 return (Injector) finder.newInstance("Injector"); 4133 } catch (NoFactoryAvailableException e) { 4134 // lets use the default injector 4135 return new DefaultInjector(this); 4136 } 4137 } 4138 4139 /** 4140 * Lazily create a default implementation 4141 */ 4142 protected ManagementMBeanAssembler createManagementMBeanAssembler() { 4143 return new DefaultManagementMBeanAssembler(this); 4144 } 4145 4146 /** 4147 * Lazily create a default implementation 4148 */ 4149 protected ComponentResolver createComponentResolver() { 4150 return new DefaultComponentResolver(); 4151 } 4152 4153 /** 4154 * Lazily create a default implementation 4155 */ 4156 protected Registry createRegistry() { 4157 JndiRegistry jndi = new JndiRegistry(); 4158 try { 4159 // getContext() will force setting up JNDI 4160 jndi.getContext(); 4161 return jndi; 4162 } catch (Throwable e) { 4163 log.debug("Cannot create javax.naming.InitialContext due " + e.getMessage() + ". Will fallback and use SimpleRegistry instead. This exception is ignored.", e); 4164 return new SimpleRegistry(); 4165 } 4166 } 4167 4168 /** 4169 * A pluggable strategy to allow an endpoint to be created without requiring 4170 * a component to be its factory, such as for looking up the URI inside some 4171 * {@link Registry} 4172 * 4173 * @param uri the uri for the endpoint to be created 4174 * @return the newly created endpoint or null if it could not be resolved 4175 */ 4176 protected Endpoint createEndpoint(String uri) { 4177 Object value = getRegistry().lookupByName(uri); 4178 if (value instanceof Endpoint) { 4179 return (Endpoint) value; 4180 } else if (value instanceof Processor) { 4181 return new ProcessorEndpoint(uri, this, (Processor) value); 4182 } else if (value != null) { 4183 return convertBeanToEndpoint(uri, value); 4184 } 4185 return null; 4186 } 4187 4188 /** 4189 * Strategy method for attempting to convert the bean from a {@link Registry} to an endpoint using 4190 * some kind of transformation or wrapper 4191 * 4192 * @param uri the uri for the endpoint (and name in the registry) 4193 * @param bean the bean to be converted to an endpoint, which will be not null 4194 * @return a new endpoint 4195 */ 4196 protected Endpoint convertBeanToEndpoint(String uri, Object bean) { 4197 throw new IllegalArgumentException("uri: " + uri + " bean: " + bean 4198 + " could not be converted to an Endpoint"); 4199 } 4200 4201 /** 4202 * Should we start newly added routes? 4203 */ 4204 protected boolean shouldStartRoutes() { 4205 return isStarted() && !isStarting(); 4206 } 4207 4208 /** 4209 * Gets the properties component in use. 4210 * Returns {@code null} if no properties component is in use. 4211 */ 4212 protected PropertiesComponent getPropertiesComponent() { 4213 return propertiesComponent; 4214 } 4215 4216 public void setDataFormats(Map<String, DataFormatDefinition> dataFormats) { 4217 this.dataFormats = dataFormats; 4218 } 4219 4220 public Map<String, DataFormatDefinition> getDataFormats() { 4221 return dataFormats; 4222 } 4223 4224 @Deprecated 4225 public Map<String, String> getProperties() { 4226 return getGlobalOptions(); 4227 } 4228 4229 @Override 4230 public Map<String, String> getGlobalOptions() { 4231 return globalOptions; 4232 } 4233 4234 @Deprecated 4235 public void setProperties(Map<String, String> properties) { 4236 this.setGlobalOptions(properties); 4237 } 4238 4239 @Override 4240 public void setGlobalOptions(Map<String, String> globalOptions) { 4241 this.globalOptions = globalOptions; 4242 } 4243 4244 public FactoryFinder getDefaultFactoryFinder() { 4245 if (defaultFactoryFinder == null) { 4246 defaultFactoryFinder = factoryFinderResolver.resolveDefaultFactoryFinder(getClassResolver()); 4247 } 4248 return defaultFactoryFinder; 4249 } 4250 4251 public void setFactoryFinderResolver(FactoryFinderResolver resolver) { 4252 this.factoryFinderResolver = resolver; 4253 } 4254 4255 public FactoryFinder getFactoryFinder(String path) throws NoFactoryAvailableException { 4256 synchronized (factories) { 4257 FactoryFinder answer = factories.get(path); 4258 if (answer == null) { 4259 answer = factoryFinderResolver.resolveFactoryFinder(getClassResolver(), path); 4260 factories.put(path, answer); 4261 } 4262 return answer; 4263 } 4264 } 4265 4266 public ClassResolver getClassResolver() { 4267 return classResolver; 4268 } 4269 4270 public void setClassResolver(ClassResolver classResolver) { 4271 this.classResolver = classResolver; 4272 } 4273 4274 public PackageScanClassResolver getPackageScanClassResolver() { 4275 return packageScanClassResolver; 4276 } 4277 4278 public void setPackageScanClassResolver(PackageScanClassResolver packageScanClassResolver) { 4279 this.packageScanClassResolver = packageScanClassResolver; 4280 } 4281 4282 public List<String> getComponentNames() { 4283 List<String> answer = new ArrayList<String>(); 4284 for (String name : components.keySet()) { 4285 answer.add(name); 4286 } 4287 return answer; 4288 } 4289 4290 public List<String> getLanguageNames() { 4291 synchronized (languages) { 4292 List<String> answer = new ArrayList<String>(); 4293 for (String name : languages.keySet()) { 4294 answer.add(name); 4295 } 4296 return answer; 4297 } 4298 } 4299 4300 public ModelJAXBContextFactory getModelJAXBContextFactory() { 4301 if (modelJAXBContextFactory == null) { 4302 modelJAXBContextFactory = createModelJAXBContextFactory(); 4303 } 4304 return modelJAXBContextFactory; 4305 } 4306 4307 public void setModelJAXBContextFactory(final ModelJAXBContextFactory modelJAXBContextFactory) { 4308 this.modelJAXBContextFactory = modelJAXBContextFactory; 4309 } 4310 4311 public NodeIdFactory getNodeIdFactory() { 4312 return nodeIdFactory; 4313 } 4314 4315 public void setNodeIdFactory(NodeIdFactory idFactory) { 4316 this.nodeIdFactory = idFactory; 4317 } 4318 4319 public ManagementStrategy getManagementStrategy() { 4320 return managementStrategy; 4321 } 4322 4323 public void setManagementStrategy(ManagementStrategy managementStrategy) { 4324 this.managementStrategy = managementStrategy; 4325 } 4326 4327 public InterceptStrategy getDefaultTracer() { 4328 if (defaultTracer == null) { 4329 defaultTracer = new Tracer(); 4330 } 4331 return defaultTracer; 4332 } 4333 4334 public void setDefaultTracer(InterceptStrategy tracer) { 4335 this.defaultTracer = tracer; 4336 } 4337 4338 public InterceptStrategy getDefaultBacklogTracer() { 4339 if (defaultBacklogTracer == null) { 4340 defaultBacklogTracer = BacklogTracer.createTracer(this); 4341 } 4342 return defaultBacklogTracer; 4343 } 4344 4345 public void setDefaultBacklogTracer(InterceptStrategy backlogTracer) { 4346 this.defaultBacklogTracer = backlogTracer; 4347 } 4348 4349 public InterceptStrategy getDefaultBacklogDebugger() { 4350 if (defaultBacklogDebugger == null) { 4351 defaultBacklogDebugger = new BacklogDebugger(this); 4352 } 4353 return defaultBacklogDebugger; 4354 } 4355 4356 public void setDefaultBacklogDebugger(InterceptStrategy defaultBacklogDebugger) { 4357 this.defaultBacklogDebugger = defaultBacklogDebugger; 4358 } 4359 4360 public void disableJMX() { 4361 if (isStarting() || isStarted()) { 4362 throw new IllegalStateException("Disabling JMX can only be done when CamelContext has not been started"); 4363 } 4364 managementStrategy = new DefaultManagementStrategy(this); 4365 // must clear lifecycle strategies as we add DefaultManagementLifecycleStrategy by default for JMX support 4366 lifecycleStrategies.clear(); 4367 } 4368 4369 public InflightRepository getInflightRepository() { 4370 return inflightRepository; 4371 } 4372 4373 public void setInflightRepository(InflightRepository repository) { 4374 this.inflightRepository = repository; 4375 } 4376 4377 public AsyncProcessorAwaitManager getAsyncProcessorAwaitManager() { 4378 return asyncProcessorAwaitManager; 4379 } 4380 4381 public void setAsyncProcessorAwaitManager(AsyncProcessorAwaitManager asyncProcessorAwaitManager) { 4382 this.asyncProcessorAwaitManager = asyncProcessorAwaitManager; 4383 } 4384 4385 public void setAutoStartup(Boolean autoStartup) { 4386 this.autoStartup = autoStartup; 4387 } 4388 4389 public Boolean isAutoStartup() { 4390 return autoStartup != null && autoStartup; 4391 } 4392 4393 @Deprecated 4394 public Boolean isLazyLoadTypeConverters() { 4395 return lazyLoadTypeConverters != null && lazyLoadTypeConverters; 4396 } 4397 4398 @Deprecated 4399 public void setLazyLoadTypeConverters(Boolean lazyLoadTypeConverters) { 4400 this.lazyLoadTypeConverters = lazyLoadTypeConverters; 4401 } 4402 4403 public Boolean isLoadTypeConverters() { 4404 return loadTypeConverters != null && loadTypeConverters; 4405 } 4406 4407 public void setLoadTypeConverters(Boolean loadTypeConverters) { 4408 this.loadTypeConverters = loadTypeConverters; 4409 } 4410 4411 public Boolean isTypeConverterStatisticsEnabled() { 4412 return typeConverterStatisticsEnabled != null && typeConverterStatisticsEnabled; 4413 } 4414 4415 public void setTypeConverterStatisticsEnabled(Boolean typeConverterStatisticsEnabled) { 4416 this.typeConverterStatisticsEnabled = typeConverterStatisticsEnabled; 4417 } 4418 4419 public Boolean isUseMDCLogging() { 4420 return useMDCLogging != null && useMDCLogging; 4421 } 4422 4423 public void setUseMDCLogging(Boolean useMDCLogging) { 4424 this.useMDCLogging = useMDCLogging; 4425 } 4426 4427 public Boolean isUseDataType() { 4428 return useDataType; 4429 } 4430 4431 @Override 4432 public void setUseDataType(Boolean useDataType) { 4433 this.useDataType = useDataType; 4434 } 4435 4436 public Boolean isUseBreadcrumb() { 4437 return useBreadcrumb != null && useBreadcrumb; 4438 } 4439 4440 public void setUseBreadcrumb(Boolean useBreadcrumb) { 4441 this.useBreadcrumb = useBreadcrumb; 4442 } 4443 4444 public ClassLoader getApplicationContextClassLoader() { 4445 return applicationContextClassLoader; 4446 } 4447 4448 public void setApplicationContextClassLoader(ClassLoader classLoader) { 4449 applicationContextClassLoader = classLoader; 4450 } 4451 4452 public DataFormatResolver getDataFormatResolver() { 4453 return dataFormatResolver; 4454 } 4455 4456 public void setDataFormatResolver(DataFormatResolver dataFormatResolver) { 4457 this.dataFormatResolver = dataFormatResolver; 4458 } 4459 4460 public DataFormat resolveDataFormat(String name) { 4461 DataFormat answer = dataFormatResolver.resolveDataFormat(name, this); 4462 4463 // inject CamelContext if aware 4464 if (answer instanceof CamelContextAware) { 4465 ((CamelContextAware) answer).setCamelContext(this); 4466 } 4467 4468 return answer; 4469 } 4470 4471 public DataFormat createDataFormat(String name) { 4472 DataFormat answer = dataFormatResolver.createDataFormat(name, this); 4473 4474 // inject CamelContext if aware 4475 if (answer instanceof CamelContextAware) { 4476 ((CamelContextAware) answer).setCamelContext(this); 4477 } 4478 4479 return answer; 4480 } 4481 4482 public DataFormatDefinition resolveDataFormatDefinition(String name) { 4483 // lookup type and create the data format from it 4484 DataFormatDefinition type = lookup(this, name, DataFormatDefinition.class); 4485 if (type == null && getDataFormats() != null) { 4486 type = getDataFormats().get(name); 4487 } 4488 return type; 4489 } 4490 4491 private static <T> T lookup(CamelContext context, String ref, Class<T> type) { 4492 try { 4493 return context.getRegistry().lookupByNameAndType(ref, type); 4494 } catch (Exception e) { 4495 // need to ignore not same type and return it as null 4496 return null; 4497 } 4498 } 4499 4500 /** 4501 * @deprecated use {@link org.apache.camel.util.CamelContextHelper#lookupPropertiesComponent(org.apache.camel.CamelContext, boolean)} 4502 */ 4503 @Deprecated 4504 protected Component lookupPropertiesComponent() { 4505 return CamelContextHelper.lookupPropertiesComponent(this, false); 4506 } 4507 4508 public ShutdownStrategy getShutdownStrategy() { 4509 return shutdownStrategy; 4510 } 4511 4512 public void setShutdownStrategy(ShutdownStrategy shutdownStrategy) { 4513 this.shutdownStrategy = shutdownStrategy; 4514 } 4515 4516 public ShutdownRoute getShutdownRoute() { 4517 return shutdownRoute; 4518 } 4519 4520 public void setShutdownRoute(ShutdownRoute shutdownRoute) { 4521 this.shutdownRoute = shutdownRoute; 4522 } 4523 4524 public ShutdownRunningTask getShutdownRunningTask() { 4525 return shutdownRunningTask; 4526 } 4527 4528 public void setShutdownRunningTask(ShutdownRunningTask shutdownRunningTask) { 4529 this.shutdownRunningTask = shutdownRunningTask; 4530 } 4531 4532 public void setAllowUseOriginalMessage(Boolean allowUseOriginalMessage) { 4533 this.allowUseOriginalMessage = allowUseOriginalMessage; 4534 } 4535 4536 public Boolean isAllowUseOriginalMessage() { 4537 return allowUseOriginalMessage != null && allowUseOriginalMessage; 4538 } 4539 4540 public ExecutorServiceManager getExecutorServiceManager() { 4541 return this.executorServiceManager; 4542 } 4543 4544 @Deprecated 4545 public org.apache.camel.spi.ExecutorServiceStrategy getExecutorServiceStrategy() { 4546 // its okay to create a new instance as its stateless, and just delegate 4547 // ExecutorServiceManager which is the new API 4548 return new DefaultExecutorServiceStrategy(this); 4549 } 4550 4551 public void setExecutorServiceManager(ExecutorServiceManager executorServiceManager) { 4552 this.executorServiceManager = executorServiceManager; 4553 } 4554 4555 public ProcessorFactory getProcessorFactory() { 4556 return processorFactory; 4557 } 4558 4559 public void setProcessorFactory(ProcessorFactory processorFactory) { 4560 this.processorFactory = processorFactory; 4561 } 4562 4563 public MessageHistoryFactory getMessageHistoryFactory() { 4564 return messageHistoryFactory; 4565 } 4566 4567 public void setMessageHistoryFactory(MessageHistoryFactory messageHistoryFactory) { 4568 this.messageHistoryFactory = messageHistoryFactory; 4569 } 4570 4571 public Debugger getDebugger() { 4572 return debugger; 4573 } 4574 4575 public void setDebugger(Debugger debugger) { 4576 this.debugger = debugger; 4577 } 4578 4579 public UuidGenerator getUuidGenerator() { 4580 return uuidGenerator; 4581 } 4582 4583 public void setUuidGenerator(UuidGenerator uuidGenerator) { 4584 this.uuidGenerator = uuidGenerator; 4585 } 4586 4587 public StreamCachingStrategy getStreamCachingStrategy() { 4588 if (streamCachingStrategy == null) { 4589 streamCachingStrategy = new DefaultStreamCachingStrategy(); 4590 } 4591 return streamCachingStrategy; 4592 } 4593 4594 public void setStreamCachingStrategy(StreamCachingStrategy streamCachingStrategy) { 4595 this.streamCachingStrategy = streamCachingStrategy; 4596 } 4597 4598 public RestRegistry getRestRegistry() { 4599 return restRegistry; 4600 } 4601 4602 public void setRestRegistry(RestRegistry restRegistry) { 4603 this.restRegistry = restRegistry; 4604 } 4605 4606 @Deprecated 4607 @Override 4608 public String getProperty(String key) { 4609 return getGlobalOption(key); 4610 } 4611 4612 @Override 4613 public String getGlobalOption(String key) { 4614 String value = getGlobalOptions().get(key); 4615 if (ObjectHelper.isNotEmpty(value)) { 4616 try { 4617 value = resolvePropertyPlaceholders(value); 4618 } catch (Exception e) { 4619 throw new RuntimeCamelException("Error getting global option: " + key, e); 4620 } 4621 } 4622 return value; 4623 } 4624 4625 @Override 4626 public ReloadStrategy getReloadStrategy() { 4627 return reloadStrategy; 4628 } 4629 4630 @Override 4631 public void setReloadStrategy(ReloadStrategy reloadStrategy) { 4632 this.reloadStrategy = reloadStrategy; 4633 } 4634 4635 @Override 4636 public void setTransformers(List<TransformerDefinition> transformers) { 4637 this.transformers = transformers; 4638 } 4639 4640 @Override 4641 public List<TransformerDefinition> getTransformers() { 4642 return transformers; 4643 } 4644 4645 @Override 4646 public Transformer resolveTransformer(String scheme) { 4647 return transformerRegistry.resolveTransformer(new TransformerKey(scheme)); 4648 } 4649 4650 @Override 4651 public Transformer resolveTransformer(DataType from, DataType to) { 4652 return transformerRegistry.resolveTransformer(new TransformerKey(from, to)); 4653 } 4654 4655 @Override 4656 public TransformerRegistry getTransformerRegistry() { 4657 return transformerRegistry; 4658 } 4659 4660 @Override 4661 public void setValidators(List<ValidatorDefinition> validators) { 4662 this.validators = validators; 4663 } 4664 4665 @Override 4666 public List<ValidatorDefinition> getValidators() { 4667 return validators; 4668 } 4669 4670 @Override 4671 public Validator resolveValidator(DataType type) { 4672 return validatorRegistry.resolveValidator(new ValidatorKey(type)); 4673 } 4674 4675 @Override 4676 public ValidatorRegistry getValidatorRegistry() { 4677 return validatorRegistry; 4678 } 4679 4680 @Override 4681 public RuntimeCamelCatalog getRuntimeCamelCatalog() { 4682 return runtimeCamelCatalog; 4683 } 4684 4685 @Override 4686 public void setSSLContextParameters(SSLContextParameters sslContextParameters) { 4687 this.sslContextParameters = sslContextParameters; 4688 } 4689 4690 @Override 4691 public SSLContextParameters getSSLContextParameters() { 4692 return this.sslContextParameters; 4693 } 4694 4695 @Override 4696 public HeadersMapFactory getHeadersMapFactory() { 4697 return headersMapFactory; 4698 } 4699 4700 @Override 4701 public void setHeadersMapFactory(HeadersMapFactory headersMapFactory) { 4702 this.headersMapFactory = headersMapFactory; 4703 } 4704 4705 protected Map<String, RouteService> getRouteServices() { 4706 return routeServices; 4707 } 4708 4709 protected ManagementStrategy createManagementStrategy() { 4710 return new ManagementStrategyFactory().create(this, disableJMX || Boolean.getBoolean(JmxSystemPropertyKeys.DISABLED)); 4711 } 4712 4713 /** 4714 * Reset context counter to a preset value. Mostly used for tests to ensure a predictable getName() 4715 * 4716 * @param value new value for the context counter 4717 */ 4718 public static void setContextCounter(int value) { 4719 DefaultCamelContextNameStrategy.setCounter(value); 4720 DefaultManagementNameStrategy.setCounter(value); 4721 } 4722 4723 private static UuidGenerator createDefaultUuidGenerator() { 4724 if (System.getProperty("com.google.appengine.runtime.environment") != null) { 4725 // either "Production" or "Development" 4726 return new JavaUuidGenerator(); 4727 } else { 4728 return new DefaultUuidGenerator(); 4729 } 4730 } 4731 4732 protected ModelJAXBContextFactory createModelJAXBContextFactory() { 4733 return new DefaultModelJAXBContextFactory(); 4734 } 4735 4736 @Override 4737 public String toString() { 4738 return "CamelContext(" + getName() + ")"; 4739 } 4740 4741 class MDCHelper implements AutoCloseable { 4742 final Map<String, String> originalContextMap; 4743 4744 MDCHelper() { 4745 if (isUseMDCLogging()) { 4746 originalContextMap = MDC.getCopyOfContextMap(); 4747 MDC.put(MDC_CAMEL_CONTEXT_ID, getName()); 4748 } else { 4749 originalContextMap = null; 4750 } 4751 } 4752 4753 @Override 4754 public void close() { 4755 if (isUseMDCLogging()) { 4756 if (originalContextMap != null) { 4757 MDC.setContextMap(originalContextMap); 4758 } else { 4759 MDC.clear(); 4760 } 4761 } 4762 } 4763 } 4764 4765 @Override 4766 public HealthCheckRegistry getHealthCheckRegistry() { 4767 return healthCheckRegistry; 4768 } 4769 4770 /** 4771 * Sets a {@link HealthCheckRegistry}. 4772 */ 4773 public void setHealthCheckRegistry(HealthCheckRegistry healthCheckRegistry) { 4774 this.healthCheckRegistry = ObjectHelper.notNull(healthCheckRegistry, "HealthCheckRegistry"); 4775 } 4776}