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