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