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