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