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