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 */ 017 package org.apache.camel.impl; 018 019 import java.util.ArrayList; 020 import java.util.Collection; 021 import java.util.HashMap; 022 import java.util.Iterator; 023 import java.util.List; 024 import java.util.Map; 025 import java.util.TreeMap; 026 import java.util.concurrent.Callable; 027 028 import javax.naming.Context; 029 030 import org.apache.camel.CamelContext; 031 import org.apache.camel.Component; 032 import org.apache.camel.ConsumerTemplate; 033 import org.apache.camel.Endpoint; 034 import org.apache.camel.IsSingleton; 035 import org.apache.camel.NoFactoryAvailableException; 036 import org.apache.camel.Processor; 037 import org.apache.camel.Producer; 038 import org.apache.camel.ProducerTemplate; 039 import org.apache.camel.ResolveEndpointFailedException; 040 import org.apache.camel.Route; 041 import org.apache.camel.RoutesBuilder; 042 import org.apache.camel.RuntimeCamelException; 043 import org.apache.camel.Service; 044 import org.apache.camel.ServiceStatus; 045 import org.apache.camel.TypeConverter; 046 import org.apache.camel.builder.ErrorHandlerBuilder; 047 import org.apache.camel.impl.converter.DefaultTypeConverter; 048 import org.apache.camel.management.InstrumentationLifecycleStrategy; 049 import org.apache.camel.management.JmxSystemPropertyKeys; 050 import org.apache.camel.model.DataFormatDefinition; 051 import org.apache.camel.model.RouteDefinition; 052 import org.apache.camel.processor.interceptor.Delayer; 053 import org.apache.camel.processor.interceptor.HandleFault; 054 import org.apache.camel.processor.interceptor.StreamCaching; 055 import org.apache.camel.processor.interceptor.TraceFormatter; 056 import org.apache.camel.processor.interceptor.Tracer; 057 import org.apache.camel.spi.ClassResolver; 058 import org.apache.camel.spi.ComponentResolver; 059 import org.apache.camel.spi.EndpointStrategy; 060 import org.apache.camel.spi.ExchangeConverter; 061 import org.apache.camel.spi.FactoryFinder; 062 import org.apache.camel.spi.FactoryFinderResolver; 063 import org.apache.camel.spi.Injector; 064 import org.apache.camel.spi.InterceptStrategy; 065 import org.apache.camel.spi.Language; 066 import org.apache.camel.spi.LanguageResolver; 067 import org.apache.camel.spi.LifecycleStrategy; 068 import org.apache.camel.spi.PackageScanClassResolver; 069 import org.apache.camel.spi.Registry; 070 import org.apache.camel.spi.RouteContext; 071 import org.apache.camel.spi.ServicePool; 072 import org.apache.camel.spi.TypeConverterRegistry; 073 import org.apache.camel.util.LRUCache; 074 import org.apache.camel.util.ObjectHelper; 075 import org.apache.camel.util.ReflectionInjector; 076 import org.apache.camel.util.SystemHelper; 077 import org.apache.camel.util.URISupport; 078 import org.apache.commons.logging.Log; 079 import org.apache.commons.logging.LogFactory; 080 081 import static org.apache.camel.util.ServiceHelper.startServices; 082 import static org.apache.camel.util.ServiceHelper.stopServices; 083 084 /** 085 * Represents the context used to configure routes and the policies to use. 086 * 087 * @version $Revision: 795369 $ 088 */ 089 public class DefaultCamelContext extends ServiceSupport implements CamelContext { 090 private static final transient Log LOG = LogFactory.getLog(DefaultCamelContext.class); 091 private static final String NAME_PREFIX = "camel-"; 092 private static int nameSuffix; 093 private boolean routeDefinitionInitiated; 094 private String name; 095 private final Map<String, Endpoint> endpoints = new LRUCache<String, Endpoint>(1000); 096 private final List<EndpointStrategy> endpointStrategies = new ArrayList<EndpointStrategy>(); 097 private final Map<String, Component> components = new HashMap<String, Component>(); 098 private List<Route> routes; 099 private final List<Service> servicesToClose = new ArrayList<Service>(); 100 private TypeConverter typeConverter; 101 private TypeConverterRegistry typeConverterRegistry; 102 private ExchangeConverter exchangeConverter; 103 private Injector injector; 104 private ComponentResolver componentResolver; 105 private boolean autoCreateComponents = true; 106 private LanguageResolver languageResolver = new DefaultLanguageResolver(); 107 private final Map<String, Language> languages = new HashMap<String, Language>(); 108 private Registry registry; 109 private LifecycleStrategy lifecycleStrategy; 110 private final List<RouteDefinition> routeDefinitions = new ArrayList<RouteDefinition>(); 111 private List<InterceptStrategy> interceptStrategies = new ArrayList<InterceptStrategy>(); 112 private Boolean trace; 113 private Boolean streamCache = Boolean.FALSE; 114 private Boolean handleFault = Boolean.FALSE; 115 private Long delay; 116 private ErrorHandlerBuilder errorHandlerBuilder; 117 private Map<String, DataFormatDefinition> dataFormats = new HashMap<String, DataFormatDefinition>(); 118 private Map<String, String> properties = new HashMap<String, String>(); 119 private FactoryFinderResolver factoryFinderResolver = new DefaultFactoryFinderResolver(); 120 private FactoryFinder defaultFactoryFinder; 121 private final Map<String, FactoryFinder> factories = new HashMap<String, FactoryFinder>(); 122 private final Map<String, RouteService> routeServices = new HashMap<String, RouteService>(); 123 private ClassResolver classResolver = new DefaultClassResolver(); 124 private PackageScanClassResolver packageScanClassResolver; 125 // we use a capacity of 100 per endpoint, so for the same endpoint we have at most 100 producers in the pool 126 // so if we have 6 endpoints in the pool, we have 6 x 100 producers in total 127 private ServicePool<Endpoint, Producer> producerServicePool = new DefaultProducerServicePool(100); 128 129 public DefaultCamelContext() { 130 super(); 131 name = NAME_PREFIX + ++nameSuffix; 132 133 if (Boolean.getBoolean(JmxSystemPropertyKeys.DISABLED)) { 134 LOG.info("JMX is disabled. Using DefaultLifecycleStrategy."); 135 lifecycleStrategy = new DefaultLifecycleStrategy(); 136 } else { 137 try { 138 LOG.info("JMX enabled. Using InstrumentationLifecycleStrategy."); 139 lifecycleStrategy = new InstrumentationLifecycleStrategy(); 140 } catch (NoClassDefFoundError e) { 141 // if we can't instantiate the JMX enabled strategy then fallback to default 142 // could be because of missing .jars on the classpath 143 LOG.warn("Could not find needed classes for JMX lifecycle strategy." 144 + " Needed class is in spring-context.jar using Spring 2.5 or newer (" 145 + " spring-jmx.jar using Spring 2.0.x)." 146 + " NoClassDefFoundError: " + e.getMessage()); 147 } catch (Exception e) { 148 LOG.warn("Could not create JMX lifecycle strategy, caused by: " + e.getMessage()); 149 } 150 // if not created then fallback to default 151 if (lifecycleStrategy == null) { 152 LOG.warn("Cannot use JMX lifecycle strategy. Using DefaultLifecycleStrategy instead."); 153 lifecycleStrategy = new DefaultLifecycleStrategy(); 154 } 155 } 156 157 // use WebSphere specific resolver if running on WebSphere 158 if (WebSpherePacakageScanClassResolver.isWebSphereClassLoader(this.getClass().getClassLoader())) { 159 LOG.info("Using WebSphere specific PackageScanClassResolver"); 160 packageScanClassResolver = new WebSpherePacakageScanClassResolver("META-INF/services/org/apache/camel/TypeConverter"); 161 } else { 162 packageScanClassResolver = new DefaultPackageScanClassResolver(); 163 } 164 165 } 166 167 /** 168 * Creates the {@link CamelContext} using the given JNDI context as the 169 * registry 170 */ 171 public DefaultCamelContext(Context jndiContext) { 172 this(); 173 setJndiContext(jndiContext); 174 } 175 176 /** 177 * Creates the {@link CamelContext} using the given registry 178 */ 179 public DefaultCamelContext(Registry registry) { 180 this(); 181 this.registry = registry; 182 } 183 184 public String getName() { 185 return name; 186 } 187 188 /** 189 * Sets the name of the this context. 190 */ 191 public void setName(String name) { 192 this.name = name; 193 } 194 195 public void addComponent(String componentName, final Component component) { 196 ObjectHelper.notNull(component, "component"); 197 synchronized (components) { 198 if (components.containsKey(componentName)) { 199 throw new IllegalArgumentException("Cannot add component as its already previously added: " + componentName); 200 } 201 component.setCamelContext(this); 202 components.put(componentName, component); 203 } 204 } 205 206 public Component getComponent(String name) { 207 // synchronize the look up and auto create so that 2 threads can't 208 // concurrently auto create the same component. 209 synchronized (components) { 210 Component component = components.get(name); 211 if (component == null && autoCreateComponents) { 212 try { 213 component = getComponentResolver().resolveComponent(name, this); 214 if (component != null) { 215 addComponent(name, component); 216 if (isStarted() || isStarting()) { 217 // If the component is looked up after the context is started, 218 // lets start it up. 219 startServices(component); 220 } 221 } 222 } catch (Exception e) { 223 throw new RuntimeCamelException("Could not auto create component: " + name, e); 224 } 225 } 226 return component; 227 } 228 } 229 230 public <T extends Component> T getComponent(String name, Class<T> componentType) { 231 Component component = getComponent(name); 232 if (componentType.isInstance(component)) { 233 return componentType.cast(component); 234 } else { 235 throw new IllegalArgumentException("The component is not of type: " + componentType + " but is: " 236 + component); 237 } 238 } 239 240 public Component removeComponent(String componentName) { 241 synchronized (components) { 242 return components.remove(componentName); 243 } 244 } 245 246 public Component getOrCreateComponent(String componentName, Callable<Component> factory) { 247 synchronized (components) { 248 Component component = components.get(componentName); 249 if (component == null) { 250 try { 251 component = factory.call(); 252 if (component == null) { 253 throw new RuntimeCamelException("Factory failed to create the " + componentName 254 + " component, it returned null."); 255 } 256 components.put(componentName, component); 257 component.setCamelContext(this); 258 } catch (Exception e) { 259 throw new RuntimeCamelException("Factory failed to create the " + componentName 260 + " component", e); 261 } 262 } 263 return component; 264 } 265 } 266 267 // Endpoint Management Methods 268 // ----------------------------------------------------------------------- 269 270 public Collection<Endpoint> getEndpoints() { 271 synchronized (endpoints) { 272 return new ArrayList<Endpoint>(endpoints.values()); 273 } 274 } 275 276 public Map<String, Endpoint> getEndpointMap() { 277 synchronized (endpoints) { 278 return new TreeMap<String, Endpoint>(endpoints); 279 } 280 } 281 282 public Collection<Endpoint> getEndpoints(String uri) { 283 Collection<Endpoint> answer = new ArrayList<Endpoint>(); 284 Collection<Endpoint> coll; 285 synchronized (endpoints) { 286 Endpoint ep = endpoints.get(uri); 287 if (ep != null) { 288 answer.add(ep); 289 return answer; 290 } 291 coll = new ArrayList<Endpoint>(endpoints.values()); 292 } 293 for (Endpoint ep : coll) { 294 if (!ep.isSingleton() && uri.equals(ep.getEndpointUri())) { 295 answer.add(ep); 296 } 297 } 298 return answer; 299 } 300 301 public Collection<Endpoint> getSingletonEndpoints() { 302 Collection<Endpoint> answer = new ArrayList<Endpoint>(); 303 Collection<Endpoint> coll = getEndpoints(); 304 for (Endpoint ep : coll) { 305 if (ep.isSingleton()) { 306 answer.add(ep); 307 } 308 } 309 return answer; 310 } 311 312 public Endpoint addEndpoint(String uri, Endpoint endpoint) throws Exception { 313 Endpoint oldEndpoint; 314 synchronized (endpoints) { 315 startServices(endpoint); 316 oldEndpoint = endpoints.remove(uri); 317 addEndpointToRegistry(uri, endpoint); 318 if (oldEndpoint != null) { 319 stopServices(oldEndpoint); 320 } 321 } 322 return oldEndpoint; 323 } 324 325 public Collection<Endpoint> removeEndpoints(String uri) throws Exception { 326 Collection<Endpoint> answer = new ArrayList<Endpoint>(); 327 synchronized (endpoints) { 328 Endpoint oldEndpoint = endpoints.remove(uri); 329 if (oldEndpoint != null) { 330 answer.add(oldEndpoint); 331 stopServices(oldEndpoint); 332 } else { 333 for (Map.Entry entry : endpoints.entrySet()) { 334 oldEndpoint = (Endpoint) entry.getValue(); 335 if (!oldEndpoint.isSingleton() && uri.equals(oldEndpoint.getEndpointUri())) { 336 answer.add(oldEndpoint); 337 stopServices(oldEndpoint); 338 endpoints.remove(entry.getKey()); 339 } 340 } 341 } 342 } 343 return answer; 344 } 345 346 public Endpoint addSingletonEndpoint(String uri, Endpoint endpoint) throws Exception { 347 return addEndpoint(uri, endpoint); 348 } 349 350 public Endpoint removeSingletonEndpoint(String uri) throws Exception { 351 Collection<Endpoint> answer = removeEndpoints(uri); 352 return (Endpoint) (answer.size() > 0 ? answer.toArray()[0] : null); 353 } 354 355 public Endpoint getEndpoint(String uri) { 356 ObjectHelper.notEmpty(uri, "uri"); 357 358 // normalize uri so we can do endpoint hits with minor mistakes and parameters is not in the same order 359 try { 360 uri = URISupport.normalizeUri(uri); 361 } catch (Exception e) { 362 throw new ResolveEndpointFailedException(uri, e); 363 } 364 365 if (LOG.isTraceEnabled()) { 366 LOG.trace("Getting endpoint with uri: " + uri); 367 } 368 369 Endpoint answer; 370 String scheme = null; 371 synchronized (endpoints) { 372 answer = endpoints.get(uri); 373 if (answer == null) { 374 try { 375 // Use the URI prefix to find the component. 376 String splitURI[] = ObjectHelper.splitOnCharacter(uri, ":", 2); 377 if (splitURI[1] != null) { 378 scheme = splitURI[0]; 379 Component component = getComponent(scheme); 380 381 // Ask the component to resolve the endpoint. 382 if (component != null) { 383 // Have the component create the endpoint if it can. 384 answer = component.createEndpoint(uri); 385 386 if (answer != null && LOG.isDebugEnabled()) { 387 LOG.debug(uri + " converted to endpoint: " + answer + " by component: " + component); 388 } 389 } 390 } 391 392 if (answer == null) { 393 // no component then try in registry and elsewhere 394 answer = createEndpoint(uri); 395 } 396 397 if (answer != null) { 398 addService(answer); 399 Endpoint newAnswer = addEndpointToRegistry(uri, answer); 400 lifecycleStrategy.onEndpointAdd(answer); 401 answer = newAnswer; 402 } 403 } catch (Exception e) { 404 throw new ResolveEndpointFailedException(uri, e); 405 } 406 } 407 } 408 409 // unknown scheme 410 if (answer == null && scheme != null) { 411 throw new ResolveEndpointFailedException(uri, "No component found with scheme: " + scheme); 412 } 413 414 return answer; 415 } 416 417 public <T extends Endpoint> T getEndpoint(String name, Class<T> endpointType) { 418 Endpoint endpoint = getEndpoint(name); 419 420 if (endpoint instanceof InterceptSendToEndpoint) { 421 endpoint = ((InterceptSendToEndpoint) endpoint).getDelegate(); 422 } 423 if (endpointType.isInstance(endpoint)) { 424 return endpointType.cast(endpoint); 425 } else { 426 throw new IllegalArgumentException("The endpoint is not of type: " + endpointType + " but is: " 427 + endpoint.getClass().getCanonicalName()); 428 } 429 } 430 431 public void addRegisterEndpointCallback(EndpointStrategy strategy) { 432 if (!endpointStrategies.contains(strategy)) { 433 // let it be invoked for already registered endpoints so it can catch-up. 434 endpointStrategies.add(strategy); 435 for (Endpoint endpoint : getEndpoints()) { 436 Endpoint newEndpoint = strategy.registerEndpoint(endpoint.getEndpointUri(), endpoint); 437 if (newEndpoint != endpoint) { 438 endpoints.put(getEndpointKey(newEndpoint.getEndpointUri(), newEndpoint), newEndpoint); 439 } 440 } 441 } 442 } 443 444 /** 445 * Strategy to add the given endpoint to the internal endpoint registry 446 * 447 * @param uri uri of endpoint 448 * @param endpoint the endpoint to add 449 * @return the added endpoint 450 */ 451 protected Endpoint addEndpointToRegistry(String uri, Endpoint endpoint) { 452 for (EndpointStrategy strategy : endpointStrategies) { 453 endpoint = strategy.registerEndpoint(uri, endpoint); 454 } 455 endpoints.put(getEndpointKey(uri, endpoint), endpoint); 456 return endpoint; 457 } 458 459 // Route Management Methods 460 // ----------------------------------------------------------------------- 461 public synchronized List<Route> getRoutes() { 462 if (routes == null) { 463 routes = new ArrayList<Route>(); 464 } 465 466 // lets return a copy of the collection as objects are removed later 467 // when services are stopped 468 return new ArrayList<Route>(routes); 469 } 470 471 public void setRoutes(List<Route> routes) { 472 this.routes = routes; 473 throw new UnsupportedOperationException("Overriding existing routes is not supported yet, use addRoutes instead"); 474 } 475 476 synchronized void removeRouteCollection(Collection<Route> routes) { 477 if (this.routes != null) { 478 this.routes.removeAll(routes); 479 } 480 } 481 482 synchronized void addRouteCollection(Collection<Route> routes) throws Exception { 483 if (this.routes == null) { 484 this.routes = new ArrayList<Route>(); 485 } 486 487 if (routes != null) { 488 this.routes.addAll(routes); 489 } 490 } 491 492 public void addRoutes(RoutesBuilder builder) throws Exception { 493 if (LOG.isDebugEnabled()) { 494 LOG.debug("Adding routes from builder: " + builder); 495 } 496 // lets now add the routes from the builder 497 builder.addRoutesToCamelContext(this); 498 } 499 500 public void addRouteDefinitions(Collection<RouteDefinition> routeDefinitions) throws Exception { 501 for (RouteDefinition routeDefinition : routeDefinitions) { 502 routeDefinition.setCamelContext(this); 503 removeRouteDefinition(routeDefinition); 504 } 505 this.routeDefinitions.addAll(routeDefinitions); 506 if (shouldStartRoutes()) { 507 startRouteDefinitions(routeDefinitions); 508 } 509 } 510 511 /** 512 * Removes the route definition with the given key. 513 * 514 * @return true if one or more routes was removed 515 */ 516 public boolean removeRouteDefinition(String key) { 517 boolean answer = false; 518 Iterator<RouteDefinition> iter = routeDefinitions.iterator(); 519 while (iter.hasNext()) { 520 RouteDefinition route = iter.next(); 521 if (route.idOrCreate().equals(key)) { 522 iter.remove(); 523 answer = true; 524 } 525 } 526 return answer; 527 } 528 529 public void removeRouteDefinitions(Collection<RouteDefinition> routeDefinitions) throws Exception { 530 this.routeDefinitions.removeAll(routeDefinitions); 531 for (RouteDefinition routeDefinition : routeDefinitions) { 532 removeRouteDefinition(routeDefinition); 533 } 534 } 535 536 public void removeRouteDefinition(RouteDefinition routeDefinition) throws Exception { 537 String key = routeDefinition.idOrCreate(); 538 stopRoute(key); 539 removeRouteDefinition(key); 540 } 541 542 public ServiceStatus getRouteStatus(RouteDefinition route) { 543 return getRouteStatus(route.idOrCreate()); 544 } 545 546 /** 547 * Returns the status of the service of the given ID or null if there is no service created yet 548 */ 549 public ServiceStatus getRouteStatus(String key) { 550 RouteService routeService = routeServices.get(key); 551 if (routeService != null) { 552 return routeService.getStatus(); 553 } 554 return null; 555 } 556 557 public void startRoute(RouteDefinition route) throws Exception { 558 Collection<Route> routes = new ArrayList<Route>(); 559 List<RouteContext> routeContexts = route.addRoutes(this, routes); 560 RouteService routeService = new RouteService(this, route, routeContexts, routes); 561 startRouteService(routeService); 562 } 563 564 565 public void stopRoute(RouteDefinition route) throws Exception { 566 stopRoute(route.idOrCreate()); 567 } 568 569 /** 570 * Stops the route denoted by the given RouteType id 571 */ 572 public synchronized void stopRoute(String key) throws Exception { 573 RouteService routeService = routeServices.remove(key); 574 if (routeService != null) { 575 routeService.stop(); 576 } 577 } 578 579 580 /** 581 * Adds a service, starting it so that it will be stopped with this context 582 */ 583 public void addService(Object object) throws Exception { 584 if (object instanceof Service) { 585 Service service = (Service) object; 586 getLifecycleStrategy().onServiceAdd(this, service); 587 service.start(); 588 servicesToClose.add(service); 589 } 590 } 591 592 // Helper methods 593 // ----------------------------------------------------------------------- 594 595 public Language resolveLanguage(String language) { 596 Language answer; 597 synchronized (languages) { 598 answer = languages.get(language); 599 600 // check if the language is singleton, if so return the shared instance 601 if (answer instanceof IsSingleton) { 602 boolean singleton = ((IsSingleton) answer).isSingleton(); 603 if (singleton) { 604 return answer; 605 } 606 } 607 608 // language not known or not singleton, then use resolver 609 answer = getLanguageResolver().resolveLanguage(language, this); 610 if (answer != null) { 611 languages.put(language, answer); 612 } 613 } 614 615 // no language resolved 616 return answer; 617 } 618 619 // Properties 620 // ----------------------------------------------------------------------- 621 public ExchangeConverter getExchangeConverter() { 622 if (exchangeConverter == null) { 623 exchangeConverter = createExchangeConverter(); 624 } 625 return exchangeConverter; 626 } 627 628 public void setExchangeConverter(ExchangeConverter exchangeConverter) { 629 this.exchangeConverter = exchangeConverter; 630 } 631 632 public TypeConverter getTypeConverter() { 633 if (typeConverter == null) { 634 typeConverter = createTypeConverter(); 635 } 636 return typeConverter; 637 } 638 639 public void setTypeConverter(TypeConverter typeConverter) { 640 this.typeConverter = typeConverter; 641 } 642 643 public TypeConverterRegistry getTypeConverterRegistry() { 644 if (typeConverterRegistry == null) { 645 // init type converter as its lazy 646 if (typeConverter == null) { 647 getTypeConverter(); 648 } 649 // type converter is usually the default one that also is the registry 650 if (typeConverter instanceof DefaultTypeConverter) { 651 typeConverterRegistry = (DefaultTypeConverter) typeConverter; 652 } 653 } 654 return typeConverterRegistry; 655 } 656 657 public void setTypeConverterRegistry(TypeConverterRegistry typeConverterRegistry) { 658 this.typeConverterRegistry = typeConverterRegistry; 659 } 660 661 public Injector getInjector() { 662 if (injector == null) { 663 injector = createInjector(); 664 } 665 return injector; 666 } 667 668 public void setInjector(Injector injector) { 669 this.injector = injector; 670 } 671 672 public ComponentResolver getComponentResolver() { 673 if (componentResolver == null) { 674 componentResolver = createComponentResolver(); 675 } 676 return componentResolver; 677 } 678 679 public void setComponentResolver(ComponentResolver componentResolver) { 680 this.componentResolver = componentResolver; 681 } 682 683 public LanguageResolver getLanguageResolver() { 684 return languageResolver; 685 } 686 687 public void setLanguageResolver(LanguageResolver languageResolver) { 688 this.languageResolver = languageResolver; 689 } 690 691 public boolean isAutoCreateComponents() { 692 return autoCreateComponents; 693 } 694 695 public void setAutoCreateComponents(boolean autoCreateComponents) { 696 this.autoCreateComponents = autoCreateComponents; 697 } 698 699 public Registry getRegistry() { 700 if (registry == null) { 701 registry = createRegistry(); 702 } 703 return registry; 704 } 705 706 /** 707 * Sets the registry to the given JNDI context 708 * 709 * @param jndiContext is the JNDI context to use as the registry 710 * @see #setRegistry(org.apache.camel.spi.Registry) 711 */ 712 public void setJndiContext(Context jndiContext) { 713 setRegistry(new JndiRegistry(jndiContext)); 714 } 715 716 public void setRegistry(Registry registry) { 717 this.registry = registry; 718 } 719 720 public LifecycleStrategy getLifecycleStrategy() { 721 return lifecycleStrategy; 722 } 723 724 public void setLifecycleStrategy(LifecycleStrategy lifecycleStrategy) { 725 this.lifecycleStrategy = lifecycleStrategy; 726 } 727 728 public List<RouteDefinition> getRouteDefinitions() { 729 return routeDefinitions; 730 } 731 732 public List<InterceptStrategy> getInterceptStrategies() { 733 return interceptStrategies; 734 } 735 736 public void setInterceptStrategies(List<InterceptStrategy> interceptStrategies) { 737 this.interceptStrategies = interceptStrategies; 738 } 739 740 public void addInterceptStrategy(InterceptStrategy interceptStrategy) { 741 getInterceptStrategies().add(interceptStrategy); 742 } 743 744 /** 745 * Returns true if tracing has been enabled or disabled via the {@link #setTrace(Boolean)} method 746 * or it has not been specified then default to the <b>camel.streamCache</b> system property 747 */ 748 public boolean isStreamCacheEnabled() { 749 final Boolean value = getStreamCaching(); 750 if (value != null) { 751 return value; 752 } else { 753 return SystemHelper.isSystemProperty("camel.streamCache"); 754 } 755 } 756 757 public Boolean getStreamCaching() { 758 return streamCache; 759 } 760 761 public void setStreamCaching(Boolean cache) { 762 this.streamCache = cache; 763 } 764 765 public void setTracing(Boolean tracing) { 766 // look if alredy enabled 767 Tracer tracer = Tracer.getTracer(this); 768 if (tracing && tracer == null) { 769 // not already enabled 770 addInterceptStrategy(new Tracer()); 771 } else if (tracer != null) { 772 // disable existing tracer 773 for (InterceptStrategy strategy : interceptStrategies) { 774 if (strategy instanceof Tracer) { 775 interceptStrategies.remove(strategy); 776 } 777 } 778 } 779 } 780 781 /** 782 * Returns true if handle fault has been enabled 783 */ 784 public boolean isHandleFaultEnabled() { 785 final Boolean value = getHandleFault(); 786 if (value != null) { 787 return value; 788 } else { 789 return SystemHelper.isSystemProperty("camel.handleFault"); 790 } 791 } 792 793 public Boolean getHandleFault() { 794 return handleFault; 795 } 796 797 public void setHandleFault(Boolean handleFault) { 798 this.handleFault = handleFault; 799 } 800 801 /** 802 * Returns true if tracing has been enabled 803 */ 804 public boolean isTraceEnabled() { 805 final Boolean value = getTrace(); 806 if (value != null) { 807 return value; 808 } else { 809 return SystemHelper.isSystemProperty("camel.trace"); 810 } 811 } 812 813 public Boolean getTrace() { 814 return trace; 815 } 816 817 public void setTrace(Boolean trace) { 818 this.trace = trace; 819 } 820 821 /** 822 * Returns the delay in millis if delaying has been enabled. Returns 0 if not enabled. 823 */ 824 public long isDelayEnabled() { 825 final Long value = getDelay(); 826 if (value != null) { 827 return value; 828 } else { 829 String prop = SystemHelper.getSystemProperty("camel.delay"); 830 return prop != null ? Long.getLong(prop) : 0; 831 } 832 } 833 834 public Long getDelay() { 835 return delay; 836 } 837 838 public void setDelay(Long delay) { 839 this.delay = delay; 840 } 841 842 public ProducerTemplate createProducerTemplate() { 843 return new DefaultProducerTemplate(this); 844 } 845 846 public ConsumerTemplate createConsumerTemplate() { 847 return new DefaultConsumerTemplate(this); 848 } 849 850 public ErrorHandlerBuilder getErrorHandlerBuilder() { 851 return errorHandlerBuilder; 852 } 853 854 /** 855 * Sets the default error handler builder which is inherited by the routes 856 */ 857 public void setErrorHandlerBuilder(ErrorHandlerBuilder errorHandlerBuilder) { 858 this.errorHandlerBuilder = errorHandlerBuilder; 859 } 860 861 public void setProducerServicePool(ServicePool<Endpoint, Producer> producerServicePool) { 862 this.producerServicePool = producerServicePool; 863 } 864 865 public ServicePool<Endpoint, Producer> getProducerServicePool() { 866 return producerServicePool; 867 } 868 869 public void start() throws Exception { 870 super.start(); 871 872 if (LOG.isDebugEnabled()) { 873 LOG.debug("Starting routes"); 874 } 875 // the context is now considered started (i.e. isStarted() == true)) 876 // starting routes is done after, not during context startup 877 synchronized (this) { 878 for (RouteService routeService : routeServices.values()) { 879 routeService.start(); 880 } 881 } 882 if (LOG.isDebugEnabled()) { 883 for (int i = 0; i < getRoutes().size(); i++) { 884 LOG.debug("Route " + i + ": " + getRoutes().get(i)); 885 } 886 LOG.debug("Started routes"); 887 } 888 889 LOG.info("Apache Camel " + getVersion() + " (CamelContext:" + getName() + ") started"); 890 } 891 892 // Implementation methods 893 // ----------------------------------------------------------------------- 894 895 protected void doStart() throws Exception { 896 LOG.info("Apache Camel " + getVersion() + " (CamelContext:" + getName() + ") is starting"); 897 898 startServices(producerServicePool); 899 900 if (isStreamCacheEnabled()) { 901 // only add a new stream cache if not already configured 902 if (StreamCaching.getStreamCaching(this) == null) { 903 LOG.debug("StreamCaching is enabled"); 904 addInterceptStrategy(new StreamCaching()); 905 } 906 } 907 908 if (isTraceEnabled()) { 909 // only add a new tracer if not already configured 910 if (Tracer.getTracer(this) == null) { 911 Tracer tracer = new Tracer(); 912 // lets see if we have a formatter if so use it 913 TraceFormatter formatter = this.getRegistry().lookup("traceFormatter", TraceFormatter.class); 914 if (formatter != null) { 915 tracer.setFormatter(formatter); 916 } 917 LOG.debug("Tracing is enabled"); 918 addInterceptStrategy(tracer); 919 } 920 } 921 922 long delayInMillis = isDelayEnabled(); 923 if (delayInMillis > 0) { 924 // only add a new delayer if not already configured 925 if (Delayer.getDelayer(this) == null) { 926 LOG.debug("Delayer is enabled with: " + delayInMillis + " ms."); 927 addInterceptStrategy(new Delayer(delayInMillis)); 928 } 929 } 930 931 if (isHandleFaultEnabled()) { 932 // only add a new handle fault if not already configured 933 if (HandleFault.getHandleFault(this) == null) { 934 LOG.debug("HandleFault is enabled"); 935 addInterceptStrategy(new HandleFault()); 936 } 937 } 938 939 try { 940 lifecycleStrategy.onContextStart(this); 941 } catch (Exception e) { 942 // not all containers allow access to its MBeanServer (such as OC4j) 943 LOG.warn("Cannot start lifecycleStrategy: " + lifecycleStrategy + ". Cause: " + e.getMessage()); 944 if (lifecycleStrategy instanceof InstrumentationLifecycleStrategy) { 945 // fallback to non JMX lifecycle to allow Camel to startup 946 LOG.warn("Will fallback to use default (non JMX) lifecycle strategy"); 947 lifecycleStrategy = new DefaultLifecycleStrategy(); 948 lifecycleStrategy.onContextStart(this); 949 } 950 } 951 952 forceLazyInitialization(); 953 if (components != null) { 954 for (Component component : components.values()) { 955 startServices(component); 956 } 957 } 958 // To avoid initiating the routeDefinitions after stopping the camel context 959 if (!routeDefinitionInitiated) { 960 startRouteDefinitions(routeDefinitions); 961 routeDefinitionInitiated = true; 962 } 963 } 964 965 protected synchronized void doStop() throws Exception { 966 LOG.info("Apache Camel " + getVersion() + " (CamelContext:" + getName() + ") is stopping"); 967 stopServices(routeServices.values()); 968 stopServices(servicesToClose); 969 if (components != null) { 970 for (Component component : components.values()) { 971 stopServices(component); 972 } 973 } 974 servicesToClose.clear(); 975 stopServices(producerServicePool); 976 977 LOG.info("Apache Camel " + getVersion() + " (CamelContext:" + getName() + ") stopped"); 978 } 979 980 protected void startRouteDefinitions(Collection<RouteDefinition> list) throws Exception { 981 if (list != null) { 982 for (RouteDefinition route : list) { 983 startRoute(route); 984 } 985 } 986 } 987 988 /** 989 * Starts the given route service 990 */ 991 protected synchronized void startRouteService(RouteService routeService) throws Exception { 992 String key = routeService.getId(); 993 stopRoute(key); 994 routeServices.put(key, routeService); 995 if (shouldStartRoutes()) { 996 routeService.start(); 997 } 998 } 999 1000 /** 1001 * Lets force some lazy initialization to occur upfront before we start any 1002 * components and create routes 1003 */ 1004 protected void forceLazyInitialization() { 1005 getExchangeConverter(); 1006 getInjector(); 1007 getLanguageResolver(); 1008 getTypeConverter(); 1009 } 1010 1011 /** 1012 * Lazily create a default implementation 1013 */ 1014 protected ExchangeConverter createExchangeConverter() { 1015 return new DefaultExchangeConverter(); 1016 } 1017 1018 /** 1019 * Lazily create a default implementation 1020 */ 1021 protected TypeConverter createTypeConverter() { 1022 DefaultTypeConverter answer = new DefaultTypeConverter(packageScanClassResolver, getInjector(), getDefaultFactoryFinder()); 1023 typeConverterRegistry = answer; 1024 return answer; 1025 } 1026 1027 /** 1028 * Lazily create a default implementation 1029 */ 1030 protected Injector createInjector() { 1031 FactoryFinder finder = getDefaultFactoryFinder(); 1032 try { 1033 return (Injector) finder.newInstance("Injector"); 1034 } catch (NoFactoryAvailableException e) { 1035 // lets use the default 1036 return new ReflectionInjector(); 1037 } 1038 } 1039 1040 /** 1041 * Lazily create a default implementation 1042 */ 1043 protected ComponentResolver createComponentResolver() { 1044 return new DefaultComponentResolver(); 1045 } 1046 1047 /** 1048 * Lazily create a default implementation 1049 */ 1050 protected Registry createRegistry() { 1051 return new JndiRegistry(); 1052 } 1053 1054 /** 1055 * A pluggable strategy to allow an endpoint to be created without requiring 1056 * a component to be its factory, such as for looking up the URI inside some 1057 * {@link Registry} 1058 * 1059 * @param uri the uri for the endpoint to be created 1060 * @return the newly created endpoint or null if it could not be resolved 1061 */ 1062 protected Endpoint createEndpoint(String uri) { 1063 Object value = getRegistry().lookup(uri); 1064 if (value instanceof Endpoint) { 1065 return (Endpoint) value; 1066 } else if (value instanceof Processor) { 1067 return new ProcessorEndpoint(uri, this, (Processor) value); 1068 } else if (value != null) { 1069 return convertBeanToEndpoint(uri, value); 1070 } 1071 return null; 1072 } 1073 1074 /** 1075 * Strategy method for attempting to convert the bean from a {@link Registry} to an endpoint using 1076 * some kind of transformation or wrapper 1077 * 1078 * @param uri the uri for the endpoint (and name in the registry) 1079 * @param bean the bean to be converted to an endpoint, which will be not null 1080 * @return a new endpoint 1081 */ 1082 protected Endpoint convertBeanToEndpoint(String uri, Object bean) { 1083 throw new IllegalArgumentException("uri: " + uri + " bean: " + bean 1084 + " could not be converted to an Endpoint"); 1085 } 1086 1087 /** 1088 * Should we start newly added routes? 1089 */ 1090 protected boolean shouldStartRoutes() { 1091 return isStarted() && !isStarting(); 1092 } 1093 1094 public void setDataFormats(Map<String, DataFormatDefinition> dataFormats) { 1095 this.dataFormats = dataFormats; 1096 } 1097 1098 public Map<String, DataFormatDefinition> getDataFormats() { 1099 return dataFormats; 1100 } 1101 1102 public Map<String, String> getProperties() { 1103 return properties; 1104 } 1105 1106 public void setProperties(Map<String, String> properties) { 1107 this.properties = properties; 1108 } 1109 1110 public FactoryFinder getDefaultFactoryFinder() { 1111 if (defaultFactoryFinder == null) { 1112 defaultFactoryFinder = factoryFinderResolver.resolveDefaultFactoryFinder(getClassResolver()); 1113 } 1114 return defaultFactoryFinder; 1115 } 1116 1117 public void setFactoryFinderResolver(FactoryFinderResolver resolver) { 1118 this.factoryFinderResolver = resolver; 1119 } 1120 1121 public FactoryFinder getFactoryFinder(String path) throws NoFactoryAvailableException { 1122 synchronized (factories) { 1123 FactoryFinder answer = factories.get(path); 1124 if (answer == null) { 1125 answer = factoryFinderResolver.resolveFactoryFinder(getClassResolver(), path); 1126 factories.put(path, answer); 1127 } 1128 return answer; 1129 } 1130 } 1131 1132 public ClassResolver getClassResolver() { 1133 return classResolver; 1134 } 1135 1136 public void setClassResolver(ClassResolver classResolver) { 1137 this.classResolver = classResolver; 1138 } 1139 1140 public PackageScanClassResolver getPackageScanClassResolver() { 1141 return packageScanClassResolver; 1142 } 1143 1144 public void setPackageScanClassResolver(PackageScanClassResolver packageScanClassResolver) { 1145 this.packageScanClassResolver = packageScanClassResolver; 1146 } 1147 1148 public List<String> getComponentNames() { 1149 synchronized (components) { 1150 List<String> answer = new ArrayList<String>(); 1151 for (String name : components.keySet()) { 1152 answer.add(name); 1153 } 1154 return answer; 1155 } 1156 } 1157 1158 public List<String> getLanguageNames() { 1159 synchronized (languages) { 1160 List<String> answer = new ArrayList<String>(); 1161 for (String name : languages.keySet()) { 1162 answer.add(name); 1163 } 1164 return answer; 1165 } 1166 } 1167 1168 protected synchronized String getEndpointKey(String uri, Endpoint endpoint) { 1169 if (endpoint.isSingleton()) { 1170 return uri; 1171 } else { 1172 // lets try find the first endpoint key which is free 1173 for (int counter = 0; true; counter++) { 1174 String key = (counter > 0) ? uri + ":" + counter : uri; 1175 if (!endpoints.containsKey(key)) { 1176 return key; 1177 } 1178 } 1179 } 1180 } 1181 1182 protected Map<String, RouteService> getRouteServices() { 1183 return routeServices; 1184 } 1185 1186 @Override 1187 public String toString() { 1188 return "DefaultCamelContext(" + getName() + ")"; 1189 } 1190 1191 }