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