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