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