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