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 }