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