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