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 }