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.Collections;
022    import java.util.HashMap;
023    import java.util.Iterator;
024    import java.util.LinkedHashMap;
025    import java.util.List;
026    import java.util.Map;
027    import java.util.TreeMap;
028    import java.util.concurrent.Callable;
029    import java.util.concurrent.atomic.AtomicBoolean;
030    import java.util.concurrent.atomic.AtomicInteger;
031    
032    import javax.naming.Context;
033    
034    import org.apache.camel.CamelContext;
035    import org.apache.camel.Component;
036    import org.apache.camel.Consumer;
037    import org.apache.camel.ConsumerTemplate;
038    import org.apache.camel.Endpoint;
039    import org.apache.camel.FailedToStartRouteException;
040    import org.apache.camel.IsSingleton;
041    import org.apache.camel.MultipleConsumersSupport;
042    import org.apache.camel.NoFactoryAvailableException;
043    import org.apache.camel.Processor;
044    import org.apache.camel.Producer;
045    import org.apache.camel.ProducerTemplate;
046    import org.apache.camel.ResolveEndpointFailedException;
047    import org.apache.camel.Route;
048    import org.apache.camel.RoutesBuilder;
049    import org.apache.camel.RuntimeCamelException;
050    import org.apache.camel.Service;
051    import org.apache.camel.ServiceStatus;
052    import org.apache.camel.ShutdownRoute;
053    import org.apache.camel.ShutdownRunningTask;
054    import org.apache.camel.TypeConverter;
055    import org.apache.camel.builder.ErrorHandlerBuilder;
056    import org.apache.camel.impl.converter.DefaultTypeConverter;
057    import org.apache.camel.management.DefaultManagementAgent;
058    import org.apache.camel.management.DefaultManagementLifecycleStrategy;
059    import org.apache.camel.management.DefaultManagementStrategy;
060    import org.apache.camel.management.JmxSystemPropertyKeys;
061    import org.apache.camel.management.ManagedManagementStrategy;
062    import org.apache.camel.model.DataFormatDefinition;
063    import org.apache.camel.model.RouteDefinition;
064    import org.apache.camel.processor.interceptor.Delayer;
065    import org.apache.camel.processor.interceptor.HandleFault;
066    import org.apache.camel.processor.interceptor.StreamCaching;
067    import org.apache.camel.processor.interceptor.Tracer;
068    import org.apache.camel.spi.ClassResolver;
069    import org.apache.camel.spi.ComponentResolver;
070    import org.apache.camel.spi.DataFormat;
071    import org.apache.camel.spi.DataFormatResolver;
072    import org.apache.camel.spi.EndpointStrategy;
073    import org.apache.camel.spi.FactoryFinder;
074    import org.apache.camel.spi.FactoryFinderResolver;
075    import org.apache.camel.spi.InflightRepository;
076    import org.apache.camel.spi.Injector;
077    import org.apache.camel.spi.InterceptStrategy;
078    import org.apache.camel.spi.Language;
079    import org.apache.camel.spi.LanguageResolver;
080    import org.apache.camel.spi.LifecycleStrategy;
081    import org.apache.camel.spi.ManagementStrategy;
082    import org.apache.camel.spi.NodeIdFactory;
083    import org.apache.camel.spi.PackageScanClassResolver;
084    import org.apache.camel.spi.Registry;
085    import org.apache.camel.spi.RouteContext;
086    import org.apache.camel.spi.RouteStartupOrder;
087    import org.apache.camel.spi.ServicePool;
088    import org.apache.camel.spi.ShutdownStrategy;
089    import org.apache.camel.spi.TypeConverterRegistry;
090    import org.apache.camel.util.CastUtils;
091    import org.apache.camel.util.EventHelper;
092    import org.apache.camel.util.LRUCache;
093    import org.apache.camel.util.ObjectHelper;
094    import org.apache.camel.util.ReflectionInjector;
095    import org.apache.camel.util.ServiceHelper;
096    import org.apache.camel.util.URISupport;
097    import org.apache.commons.logging.Log;
098    import org.apache.commons.logging.LogFactory;
099    
100    /**
101     * Represents the context used to configure routes and the policies to use.
102     *
103     * @version $Revision: 905995 $
104     */
105    public class DefaultCamelContext extends ServiceSupport implements CamelContext {
106        private static final transient Log LOG = LogFactory.getLog(DefaultCamelContext.class);
107        private static final String NAME_PREFIX = "camel-";
108        private static int nameSuffix;
109        private ClassLoader applicationContextClassLoader;
110        private boolean routeDefinitionInitiated;
111        private String name;
112        private final Map<String, Endpoint> endpoints = new LRUCache<String, Endpoint>(1000);
113        private final AtomicInteger endpointKeyCounter = new AtomicInteger();
114        private final List<EndpointStrategy> endpointStrategies = new ArrayList<EndpointStrategy>();
115        private final Map<String, Component> components = new HashMap<String, Component>();
116        private List<Route> routes;
117        private final List<Service> servicesToClose = new ArrayList<Service>();
118        private TypeConverter typeConverter;
119        private TypeConverterRegistry typeConverterRegistry;
120        private Injector injector;
121        private ComponentResolver componentResolver;
122        private boolean autoCreateComponents = true;
123        private LanguageResolver languageResolver = new DefaultLanguageResolver();
124        private final Map<String, Language> languages = new HashMap<String, Language>();
125        private Registry registry;
126        private List<LifecycleStrategy> lifecycleStrategies = new ArrayList<LifecycleStrategy>();
127        private ManagementStrategy managementStrategy;
128        private AtomicBoolean managementStrategyInitialized = new AtomicBoolean(false);
129        private final List<RouteDefinition> routeDefinitions = new ArrayList<RouteDefinition>();
130        private List<InterceptStrategy> interceptStrategies = new ArrayList<InterceptStrategy>();
131        private boolean firstStartDone;
132        private Boolean autoStartup = Boolean.TRUE;
133        private Boolean trace = Boolean.FALSE;
134        private Boolean streamCache = Boolean.FALSE;
135        private Boolean handleFault = Boolean.FALSE;
136        private Boolean disableJMX = Boolean.FALSE;
137        private Long delay;
138        private ErrorHandlerBuilder errorHandlerBuilder;
139        private Map<String, DataFormatDefinition> dataFormats = new HashMap<String, DataFormatDefinition>();
140        private DataFormatResolver dataFormatResolver = new DefaultDataFormatResolver();
141        private Map<String, String> properties = new HashMap<String, String>();
142        private FactoryFinderResolver factoryFinderResolver = new DefaultFactoryFinderResolver();
143        private FactoryFinder defaultFactoryFinder;
144        private final Map<String, FactoryFinder> factories = new HashMap<String, FactoryFinder>();
145        private final Map<String, RouteService> routeServices = new LinkedHashMap<String, RouteService>();
146        private ClassResolver classResolver = new DefaultClassResolver();
147        private PackageScanClassResolver packageScanClassResolver;
148        // we use a capacity of 100 per endpoint, so for the same endpoint we have at most 100 producers in the pool
149        // so if we have 6 endpoints in the pool, we have 6 x 100 producers in total
150        private ServicePool<Endpoint, Producer> producerServicePool = new SharedProducerServicePool(100);
151        private NodeIdFactory nodeIdFactory = new DefaultNodeIdFactory();
152        private Tracer defaultTracer;
153        private InflightRepository inflightRepository = new DefaultInflightRepository();
154        private final List<RouteStartupOrder> routeStartupOrder = new ArrayList<RouteStartupOrder>();
155        private int defaultRouteStartupOrder = 1000;
156        private ShutdownStrategy shutdownStrategy = new DefaultShutdownStrategy();
157        private ShutdownRoute shutdownRoute = ShutdownRoute.Default;
158        private ShutdownRunningTask shutdownRunningTask = ShutdownRunningTask.CompleteCurrentTaskOnly;
159    
160        public DefaultCamelContext() {
161            super();
162            name = NAME_PREFIX + ++nameSuffix;
163    
164            // use WebSphere specific resolver if running on WebSphere
165            if (WebSpherePackageScanClassResolver.isWebSphereClassLoader(this.getClass().getClassLoader())) {
166                LOG.info("Using WebSphere specific PackageScanClassResolver");
167                packageScanClassResolver = new WebSpherePackageScanClassResolver("META-INF/services/org/apache/camel/TypeConverter");
168            } else {
169                packageScanClassResolver = new DefaultPackageScanClassResolver();
170            }
171        }
172    
173        /**
174         * Creates the {@link CamelContext} using the given JNDI context as the
175         * registry
176         */
177        public DefaultCamelContext(Context jndiContext) {
178            this();
179            setJndiContext(jndiContext);
180        }
181    
182        /**
183         * Creates the {@link CamelContext} using the given registry
184         */
185        public DefaultCamelContext(Registry registry) {
186            this();
187            this.registry = registry;
188        }
189    
190        public String getName() {
191            return name;
192        }
193    
194        /**
195         * Sets the name of the this context.
196         */
197        public void setName(String name) {
198            this.name = name;
199        }
200    
201        public Component hasComponent(String componentName) {
202            return components.get(componentName);
203        }
204    
205        public void addComponent(String componentName, final Component component) {
206            ObjectHelper.notNull(component, "component");
207            synchronized (components) {
208                if (components.containsKey(componentName)) {
209                    throw new IllegalArgumentException("Cannot add component as its already previously added: " + componentName);
210                }
211                component.setCamelContext(this);
212                components.put(componentName, component);
213                for (LifecycleStrategy strategy : lifecycleStrategies) {
214                    strategy.onComponentAdd(componentName, component);
215                }
216            }
217        }
218    
219        public Component getComponent(String name) {
220            // synchronize the look up and auto create so that 2 threads can't
221            // concurrently auto create the same component.
222            synchronized (components) {
223                Component component = components.get(name);
224                if (component == null && autoCreateComponents) {
225                    try {
226                        component = getComponentResolver().resolveComponent(name, this);
227                        if (component != null) {
228                            addComponent(name, component);
229                            if (isStarted() || isStarting()) {
230                                // If the component is looked up after the context is started, lets start it up.
231                                startServices(component);
232                            }
233                        }
234                    } catch (Exception e) {
235                        throw new RuntimeCamelException("Could not auto create component: " + name, e);
236                    }
237                }
238                return component;
239            }
240        }
241    
242        public <T extends Component> T getComponent(String name, Class<T> componentType) {
243            Component component = getComponent(name);
244            if (componentType.isInstance(component)) {
245                return componentType.cast(component);
246            } else {
247                throw new IllegalArgumentException("The component is not of type: " + componentType + " but is: "
248                        + component);
249            }
250        }
251    
252        @Deprecated
253        public Component removeComponent(String componentName) {
254            synchronized (components) {
255                Component answer = components.remove(componentName);
256                if (answer != null) {
257                    for (LifecycleStrategy strategy : lifecycleStrategies) {
258                        strategy.onComponentRemove(componentName, answer);
259                    }
260                }
261                return answer;
262            }
263        }
264    
265        public Component getOrCreateComponent(String componentName, Callable<Component> factory) {
266            synchronized (components) {
267                Component component = components.get(componentName);
268                if (component == null) {
269                    try {
270                        component = factory.call();
271                        if (component == null) {
272                            throw new RuntimeCamelException("Factory failed to create the " + componentName
273                                    + " component, it returned null.");
274                        }
275                        components.put(componentName, component);
276                        component.setCamelContext(this);
277                        for (LifecycleStrategy strategy : lifecycleStrategies) {
278                            strategy.onComponentAdd(componentName, component);
279                        }
280                    } catch (Exception e) {
281                        throw new RuntimeCamelException("Factory failed to create the " + componentName
282                                + " component", e);
283                    }
284                }
285                return component;
286            }
287        }
288    
289        // Endpoint Management Methods
290        // -----------------------------------------------------------------------
291    
292        public Collection<Endpoint> getEndpoints() {
293            synchronized (endpoints) {
294                return new ArrayList<Endpoint>(endpoints.values());
295            }
296        }
297    
298        public Map<String, Endpoint> getEndpointMap() {
299            synchronized (endpoints) {
300                return new TreeMap<String, Endpoint>(endpoints);
301            }
302        }
303    
304        public Endpoint hasEndpoint(String uri) {
305            // normalize uri so we can do endpoint hits with minor mistakes and parameters is not in the same order
306            try {
307                uri = URISupport.normalizeUri(uri);
308            } catch (Exception e) {
309                throw new ResolveEndpointFailedException(uri, e);
310            }
311            synchronized (endpoints) {
312                return endpoints.get(uri);
313            }
314        }
315    
316        public Collection<Endpoint> getEndpoints(String uri) {
317            Collection<Endpoint> answer = new ArrayList<Endpoint>();
318            Collection<Endpoint> coll;
319            synchronized (endpoints) {
320                Endpoint ep = endpoints.get(uri);
321                if (ep != null) {
322                    answer.add(ep);
323                    return answer;
324                }
325                coll = new ArrayList<Endpoint>(endpoints.values());
326            }
327            for (Endpoint ep : coll) {
328                if (!ep.isSingleton() && uri.equals(ep.getEndpointUri())) {
329                    answer.add(ep);
330                }
331            }
332            return answer;
333        }
334    
335        public Collection<Endpoint> getSingletonEndpoints() {
336            Collection<Endpoint> answer = new ArrayList<Endpoint>();
337            Collection<Endpoint> coll = getEndpoints();
338            for (Endpoint ep : coll) {
339                if (ep.isSingleton()) {
340                    answer.add(ep);
341                }
342            }
343            return answer;
344        }
345    
346        public Endpoint addEndpoint(String uri, Endpoint endpoint) throws Exception {
347            Endpoint oldEndpoint;
348            synchronized (endpoints) {
349                startServices(endpoint);
350                oldEndpoint = endpoints.remove(uri);
351                for (LifecycleStrategy strategy : lifecycleStrategies) {
352                    strategy.onEndpointAdd(endpoint);
353                }
354                addEndpointToRegistry(uri, endpoint);
355                if (oldEndpoint != null) {
356                    stopServices(oldEndpoint);
357                }
358            }
359            return oldEndpoint;
360        }
361    
362        public Collection<Endpoint> removeEndpoints(String uri) throws Exception {
363            Collection<Endpoint> answer = new ArrayList<Endpoint>();
364            synchronized (endpoints) {
365                Endpoint oldEndpoint = endpoints.remove(uri);
366                if (oldEndpoint != null) {
367                    answer.add(oldEndpoint);
368                    stopServices(oldEndpoint);
369                    for (LifecycleStrategy strategy : lifecycleStrategies) {
370                        strategy.onEndpointRemove(oldEndpoint);
371                    }
372                } else {
373                    Collection<Map.Entry<String, Endpoint>> worklist = new ArrayList<Map.Entry<String, Endpoint>>();
374                    for (Map.Entry<String, Endpoint> entry : endpoints.entrySet()) {
375                        oldEndpoint = entry.getValue();
376                        if (!oldEndpoint.isSingleton() && uri.equals(oldEndpoint.getEndpointUri())) {
377                            // add to worklist to avoid concurrent modification exception
378                            worklist.add(entry);
379                        }
380                    }
381                    for (Map.Entry<String, Endpoint> entry : worklist) {
382                        oldEndpoint = entry.getValue();
383                        answer.add(oldEndpoint);
384                        stopServices(oldEndpoint);
385                        endpoints.remove(entry.getKey());
386                        for (LifecycleStrategy strategy : lifecycleStrategies) {
387                            strategy.onEndpointRemove(oldEndpoint);
388                        }
389                    }
390    
391                }
392            }
393            return answer;
394        }
395    
396        public Endpoint getEndpoint(String uri) {
397            ObjectHelper.notEmpty(uri, "uri");
398    
399            // normalize uri so we can do endpoint hits with minor mistakes and parameters is not in the same order
400            try {
401                uri = URISupport.normalizeUri(uri);
402            } catch (Exception e) {
403                throw new ResolveEndpointFailedException(uri, e);
404            }
405    
406            if (LOG.isTraceEnabled()) {
407                LOG.trace("Getting endpoint with uri: " + uri);
408            }
409    
410            Endpoint answer;
411            String scheme = null;
412            synchronized (endpoints) {
413                answer = endpoints.get(uri);
414                if (answer == null) {
415                    try {
416                        // Use the URI prefix to find the component.
417                        String splitURI[] = ObjectHelper.splitOnCharacter(uri, ":", 2);
418                        if (splitURI[1] != null) {
419                            scheme = splitURI[0];
420                            Component component = getComponent(scheme);
421    
422                            // Ask the component to resolve the endpoint.
423                            if (component != null) {
424                                // Have the component create the endpoint if it can.
425                                answer = component.createEndpoint(uri);
426    
427                                if (answer != null && LOG.isDebugEnabled()) {
428                                    LOG.debug(uri + " converted to endpoint: " + answer + " by component: " + component);
429                                }
430                            }
431                        }
432    
433                        if (answer == null) {
434                            // no component then try in registry and elsewhere
435                            answer = createEndpoint(uri);
436                        }
437    
438                        if (answer != null) {
439                            addService(answer);
440                            for (LifecycleStrategy strategy : lifecycleStrategies) {
441                                strategy.onEndpointAdd(answer);
442                            }
443                            answer = addEndpointToRegistry(uri, answer);
444                        }
445                    } catch (Exception e) {
446                        throw new ResolveEndpointFailedException(uri, e);
447                    }
448                }
449            }
450    
451            // unknown scheme
452            if (answer == null && scheme != null) {
453                throw new ResolveEndpointFailedException(uri, "No component found with scheme: " + scheme);
454            }
455    
456            return answer;
457        }
458    
459        public <T extends Endpoint> T getEndpoint(String name, Class<T> endpointType) {
460            Endpoint endpoint = getEndpoint(name);
461    
462            if (endpoint instanceof InterceptSendToEndpoint) {
463                endpoint = ((InterceptSendToEndpoint) endpoint).getDelegate();
464            }
465            if (endpointType.isInstance(endpoint)) {
466                return endpointType.cast(endpoint);
467            } else {
468                throw new IllegalArgumentException("The endpoint is not of type: " + endpointType + " but is: "
469                        + endpoint.getClass().getCanonicalName());
470            }
471        }
472    
473        public void addRegisterEndpointCallback(EndpointStrategy strategy) {
474            if (!endpointStrategies.contains(strategy)) {
475                // let it be invoked for already registered endpoints so it can catch-up.
476                endpointStrategies.add(strategy);
477                for (Endpoint endpoint : getEndpoints()) {
478                    Endpoint newEndpoint = strategy.registerEndpoint(endpoint.getEndpointUri(), endpoint);
479                    if (newEndpoint != endpoint) {
480                        endpoints.put(getEndpointKey(newEndpoint.getEndpointUri(), newEndpoint), newEndpoint);
481                    }
482                }
483            }
484        }
485    
486        /**
487         * Strategy to add the given endpoint to the internal endpoint registry
488         *
489         * @param uri  uri of endpoint
490         * @param endpoint the endpoint to add
491         * @return the added endpoint
492         */
493        protected Endpoint addEndpointToRegistry(String uri, Endpoint endpoint) {
494            for (EndpointStrategy strategy : endpointStrategies) {
495                endpoint = strategy.registerEndpoint(uri, endpoint);
496            }
497            endpoints.put(getEndpointKey(uri, endpoint), endpoint);
498            return endpoint;
499        }
500    
501        // Route Management Methods
502        // -----------------------------------------------------------------------
503    
504        /**
505         * Returns the order in which the route inputs was started.
506         *
507         * @return a list ordered by the starting order of the route inputs
508         */
509        public List<RouteStartupOrder> getRouteStartupOrder() {
510            return routeStartupOrder;
511        }
512    
513        public synchronized List<Route> getRoutes() {
514            if (routes == null) {
515                routes = new ArrayList<Route>();
516            }
517    
518            // lets return a copy of the collection as objects are removed later
519            // when services are stopped
520            return new ArrayList<Route>(routes);
521        }
522    
523        public void setRoutes(List<Route> routes) {
524            this.routes = routes;
525            throw new UnsupportedOperationException("Overriding existing routes is not supported yet, use addRoutes instead");
526        }
527    
528        synchronized void removeRouteCollection(Collection<Route> routes) {
529            if (this.routes != null) {
530                this.routes.removeAll(routes);
531            }
532        }
533    
534        synchronized void addRouteCollection(Collection<Route> routes) throws Exception {
535            if (this.routes == null) {
536                this.routes = new ArrayList<Route>();
537            }
538    
539            if (routes != null) {
540                this.routes.addAll(routes);
541            }
542        }
543    
544        public void addRoutes(RoutesBuilder builder) throws Exception {
545            if (LOG.isDebugEnabled()) {
546                LOG.debug("Adding routes from builder: " + builder);
547            }
548            // lets now add the routes from the builder
549            builder.addRoutesToCamelContext(this);
550        }
551    
552        public void addRouteDefinitions(Collection<RouteDefinition> routeDefinitions) throws Exception {
553            for (RouteDefinition routeDefinition : routeDefinitions) {
554                routeDefinition.setCamelContext(this);
555                removeRouteDefinition(routeDefinition);
556            }
557            this.routeDefinitions.addAll(routeDefinitions);
558            if (shouldStartRoutes()) {
559                startRouteDefinitions(routeDefinitions);
560            }
561        }
562    
563        /**
564         * Removes the route definition with the given key.
565         *
566         * @return true if one or more routes was removed
567         */
568        public boolean removeRouteDefinition(String key) {
569            boolean answer = false;
570            Iterator<RouteDefinition> iter = routeDefinitions.iterator();
571            while (iter.hasNext()) {
572                RouteDefinition route = iter.next();
573                if (route.idOrCreate(nodeIdFactory).equals(key)) {
574                    iter.remove();
575                    answer = true;
576                }
577            }
578            return answer;
579        }
580    
581        public void removeRouteDefinitions(Collection<RouteDefinition> routeDefinitions) throws Exception {
582            this.routeDefinitions.removeAll(routeDefinitions);
583            for (RouteDefinition routeDefinition : routeDefinitions) {
584                removeRouteDefinition(routeDefinition);
585            }
586        }
587    
588        public void removeRouteDefinition(RouteDefinition routeDefinition) throws Exception {
589            String key = routeDefinition.idOrCreate(nodeIdFactory);
590            // stop and remove the route
591            stopRoute(key);
592            this.routeServices.remove(key);
593            removeRouteDefinition(key);
594        }
595    
596        public ServiceStatus getRouteStatus(RouteDefinition route) {
597            return getRouteStatus(route.idOrCreate(nodeIdFactory));
598        }
599    
600        public ServiceStatus getRouteStatus(String key) {
601            RouteService routeService = routeServices.get(key);
602            if (routeService != null) {
603                return routeService.getStatus();
604            }
605            return null;
606        }
607    
608        public void startRoute(RouteDefinition route) throws Exception {
609            List<Route> routes = new ArrayList<Route>();
610            List<RouteContext> routeContexts = route.addRoutes(this, routes);
611            RouteService routeService = new RouteService(this, route, routeContexts, routes);
612            startRouteService(routeService);
613        }
614    
615        public synchronized void startRoute(String routeId) throws Exception {
616            RouteService routeService = routeServices.get(routeId);
617            if (routeService != null) {
618                routeService.start();
619            }
620        }
621    
622        public void stopRoute(RouteDefinition route) throws Exception {
623            stopRoute(route.idOrCreate(nodeIdFactory));
624        }
625    
626        /**
627         * Stops the route denoted by the given RouteType id
628         */
629        public synchronized void stopRoute(String key) throws Exception {
630            RouteService routeService = routeServices.get(key);
631            if (routeService != null) {
632                routeService.stop();
633            }
634        }
635    
636        public void addService(Object object) throws Exception {
637            if (object instanceof Service) {
638                Service service = (Service) object;
639                for (LifecycleStrategy strategy : lifecycleStrategies) {
640                    strategy.onServiceAdd(this, service, null);
641                }
642                servicesToClose.add(service);
643            }
644            startServices(object);
645        }
646    
647        public boolean hasService(Object object) {
648            if (object instanceof Service) {
649                return servicesToClose.contains(object);
650            }
651            return false;
652        }
653    
654        // Helper methods
655        // -----------------------------------------------------------------------
656    
657        public Language resolveLanguage(String language) {
658            Language answer;
659            synchronized (languages) {
660                answer = languages.get(language);
661    
662                // check if the language is singleton, if so return the shared instance
663                if (answer instanceof IsSingleton) {
664                    boolean singleton = ((IsSingleton) answer).isSingleton();
665                    if (singleton) {
666                        return answer;
667                    }
668                }
669    
670                // language not known or not singleton, then use resolver
671                answer = getLanguageResolver().resolveLanguage(language, this);
672                if (answer != null) {
673                    languages.put(language, answer);
674                }
675            }
676    
677            // no language resolved
678            return answer;
679        }
680    
681        // Properties
682        // -----------------------------------------------------------------------
683    
684        public TypeConverter getTypeConverter() {
685            if (typeConverter == null) {
686                synchronized (this) {
687                    // we can synchronize on this as there is only one instance
688                    // of the camel context (its the container)
689                    typeConverter = createTypeConverter();
690                    try {
691                        addService(typeConverter);
692                    } catch (Exception e) {
693                        throw ObjectHelper.wrapRuntimeCamelException(e);
694                    }
695                }
696            }
697            return typeConverter;
698        }
699    
700        public void setTypeConverter(TypeConverter typeConverter) {
701            this.typeConverter = typeConverter;
702        }
703    
704        public TypeConverterRegistry getTypeConverterRegistry() {
705            if (typeConverterRegistry == null) {
706                // init type converter as its lazy
707                if (typeConverter == null) {
708                    getTypeConverter();
709                }
710                // type converter is usually the default one that also is the registry
711                if (typeConverter instanceof DefaultTypeConverter) {
712                    typeConverterRegistry = (DefaultTypeConverter) typeConverter;
713                }
714            }
715            return typeConverterRegistry;
716        }
717    
718        public void setTypeConverterRegistry(TypeConverterRegistry typeConverterRegistry) {
719            this.typeConverterRegistry = typeConverterRegistry;
720        }
721    
722        public Injector getInjector() {
723            if (injector == null) {
724                injector = createInjector();
725            }
726            return injector;
727        }
728    
729        public void setInjector(Injector injector) {
730            this.injector = injector;
731        }
732    
733        public ComponentResolver getComponentResolver() {
734            if (componentResolver == null) {
735                componentResolver = createComponentResolver();
736            }
737            return componentResolver;
738        }
739    
740        public void setComponentResolver(ComponentResolver componentResolver) {
741            this.componentResolver = componentResolver;
742        }
743    
744        public LanguageResolver getLanguageResolver() {
745            return languageResolver;
746        }
747    
748        public void setLanguageResolver(LanguageResolver languageResolver) {
749            this.languageResolver = languageResolver;
750        }
751    
752        public boolean isAutoCreateComponents() {
753            return autoCreateComponents;
754        }
755    
756        public void setAutoCreateComponents(boolean autoCreateComponents) {
757            this.autoCreateComponents = autoCreateComponents;
758        }
759    
760        public Registry getRegistry() {
761            if (registry == null) {
762                registry = createRegistry();
763            }
764            return registry;
765        }
766    
767        /**
768         * Sets the registry to the given JNDI context
769         *
770         * @param jndiContext is the JNDI context to use as the registry
771         * @see #setRegistry(org.apache.camel.spi.Registry)
772         */
773        public void setJndiContext(Context jndiContext) {
774            setRegistry(new JndiRegistry(jndiContext));
775        }
776    
777        public void setRegistry(Registry registry) {
778            this.registry = registry;
779        }
780    
781        public List<LifecycleStrategy> getLifecycleStrategies() {
782            return lifecycleStrategies;
783        }
784    
785        public void setLifecycleStrategies(List<LifecycleStrategy> lifecycleStrategies) {
786            this.lifecycleStrategies = lifecycleStrategies;
787        }
788    
789        public void addLifecycleStrategy(LifecycleStrategy lifecycleStrategy) {
790            this.lifecycleStrategies.add(lifecycleStrategy);
791        }
792    
793        public List<RouteDefinition> getRouteDefinitions() {
794            return routeDefinitions;
795        }
796    
797        public RouteDefinition getRouteDefinition(String id) {
798            for (RouteDefinition route : routeDefinitions) {
799                if (route.getId().equals(id)) {
800                    return route;
801                }
802            }
803            return null;
804        }
805    
806        public List<InterceptStrategy> getInterceptStrategies() {
807            return interceptStrategies;
808        }
809    
810        public void setInterceptStrategies(List<InterceptStrategy> interceptStrategies) {
811            this.interceptStrategies = interceptStrategies;
812        }
813    
814        public void addInterceptStrategy(InterceptStrategy interceptStrategy) {
815            getInterceptStrategies().add(interceptStrategy);
816    
817            // for backwards compatible or if user add them here instead of the setXXX methods
818    
819            if (interceptStrategy instanceof Tracer) {
820                setTracing(true);
821            } else if (interceptStrategy instanceof HandleFault) {
822                setHandleFault(true);
823            } else if (interceptStrategy instanceof StreamCaching) {
824                setStreamCaching(true);
825            } else if (interceptStrategy instanceof Delayer) {
826                setDelayer(((Delayer)interceptStrategy).getDelay());
827            }
828        }
829    
830        public void setStreamCaching(Boolean cache) {
831            this.streamCache = cache;
832        }
833    
834        public Boolean isStreamCaching() {
835            return streamCache;
836        }
837    
838        public void setTracing(Boolean tracing) {
839            this.trace = tracing;
840        }
841    
842        public Boolean isTracing() {
843            return trace;
844        }
845    
846        public Boolean isHandleFault() {
847            return handleFault;
848        }
849    
850        public void setHandleFault(Boolean handleFault) {
851            this.handleFault = handleFault;
852        }
853    
854        public Long getDelayer() {
855            return delay;
856        }
857    
858        public void setDelayer(Long delay) {
859            this.delay = delay;
860        }
861    
862        public ProducerTemplate createProducerTemplate() {
863            return new DefaultProducerTemplate(this);
864        }
865    
866        public ConsumerTemplate createConsumerTemplate() {
867            return new DefaultConsumerTemplate(this);
868        }
869    
870        public ErrorHandlerBuilder getErrorHandlerBuilder() {
871            return errorHandlerBuilder;
872        }
873    
874        /**
875         * Sets the default error handler builder which is inherited by the routes
876         */
877        public void setErrorHandlerBuilder(ErrorHandlerBuilder errorHandlerBuilder) {
878            this.errorHandlerBuilder = errorHandlerBuilder;
879        }
880    
881        public void setProducerServicePool(ServicePool<Endpoint, Producer> producerServicePool) {
882            this.producerServicePool = producerServicePool;
883        }
884    
885        public ServicePool<Endpoint, Producer> getProducerServicePool() {
886            return producerServicePool;
887        }
888    
889        public void start() throws Exception {
890            boolean doNotStart = !firstStartDone && !isAutoStartup();
891            firstStartDone = true;
892    
893            if (doNotStart) {
894                LOG.info("Cannot start Apache Camel " + getVersion() + " (CamelContext:" + getName() + ") as it has been configured to not auto start");
895                return;
896            }
897    
898            super.start();
899    
900            LOG.debug("Starting routes...");
901    
902            // the context is now considered started (i.e. isStarted() == true))
903            // starting routes is done after, not during context startup
904            synchronized (this) {
905                // list of inputs to start when all the routes have been prepared for starting
906                // we use a tree map so the routes will be ordered according to startup order defined on the route
907                Map<Integer, DefaultRouteStartupOrder> inputs = new TreeMap<Integer, DefaultRouteStartupOrder>();
908    
909                // figure out the order in which the routes should be started
910                for (RouteService routeService : routeServices.values()) {
911                    Boolean autoStart = routeService.getRouteDefinition().isAutoStartup();
912                    if (autoStart == null || autoStart) {
913                        try {
914                            // add the inputs from this route service to the list to start afterwards
915                            // should be ordered according to the startup number
916                            Integer startupOrder = routeService.getRouteDefinition().getStartupOrder();
917                            if (startupOrder == null) {
918                                // auto assign a default startup order
919                                startupOrder = defaultRouteStartupOrder++;
920                            }
921    
922                            // create holder object that contains information about this route to be started
923                            Route route = routeService.getRoutes().iterator().next();
924                            DefaultRouteStartupOrder holder = new DefaultRouteStartupOrder(startupOrder, route, routeService);
925    
926                            // check for clash by startupOrder id
927                            DefaultRouteStartupOrder other = inputs.get(startupOrder);
928                            if (other != null) {
929                                String otherId = other.getRoute().getId();
930                                throw new FailedToStartRouteException(holder.getRoute().getId(), "startupOrder clash. Route " + otherId + " already has startupOrder "
931                                    + startupOrder + " configured which this route have as well. Please correct startupOrder to be unique among all your routes.");
932                            } else {
933                                // no clash then add the holder to the existing inputs of routes to be started
934                                inputs.put(startupOrder, holder);
935                            }
936                        } catch (FailedToStartRouteException e) {
937                            throw e;
938                        } catch (Exception e) {
939                            throw new FailedToStartRouteException(e);
940                        }
941                    } else {
942                        // should not start on startup
943                        LOG.info("Cannot start route " + routeService.getId() + " as it is configured with auto startup disabled.");
944                    }
945                }
946    
947                // now prepare the routes by starting its services before we start the input
948                for (Map.Entry<Integer, DefaultRouteStartupOrder> entry : inputs.entrySet()) {
949                    // defer starting inputs till later as we want to prepare the routes by starting
950                    // all their processors and child services etc.
951                    // then later we open the floods to Camel by starting the inputs
952                    // what this does is to ensure Camel is more robust on starting routes as all routes
953                    // will then be prepared in time before we start inputs which will consume messages to be routed
954                    RouteService routeService = entry.getValue().getRouteService();
955                    routeService.startInputs(false);
956                    try {
957                        routeService.start();
958                    } finally {
959                        routeService.startInputs(true);
960                    }
961                }
962    
963                // check for clash with multiple consumers of the same endpoints which is not allowed
964                List<Endpoint> routeInputs = new ArrayList<Endpoint>();
965                for (Map.Entry<Integer, DefaultRouteStartupOrder> entry : inputs.entrySet()) {
966                    Integer order = entry.getKey();
967                    Route route = entry.getValue().getRoute();
968                    RouteService routeService = entry.getValue().getRouteService();
969                    for (Consumer consumer : routeService.getInputs().values()) {
970                        Endpoint endpoint = consumer.getEndpoint();
971    
972                        // is multiple consumers supported
973                        boolean multipleConsumersSupported = false;
974                        if (endpoint instanceof MultipleConsumersSupport) {
975                            multipleConsumersSupported = ((MultipleConsumersSupport) endpoint).isMultipleConsumersSupported();
976                        }
977    
978                        if (!multipleConsumersSupported && routeInputs.contains(endpoint)) {
979                            throw new FailedToStartRouteException(routeService.getId(),
980                                "Multiple consumers for the same endpoint is not allowed: " + endpoint);
981                        } else {
982                            // start the
983                            if (LOG.isDebugEnabled()) {
984                                LOG.debug("Starting consumer (order: " + order + ") on route: " + route.getId());
985                            }
986                            for (LifecycleStrategy strategy : lifecycleStrategies) {
987                                strategy.onServiceAdd(this, consumer, route);
988                            }
989                            ServiceHelper.startService(consumer);
990    
991                            routeInputs.add(endpoint);
992    
993                            // add to the order which they was started, so we know how to stop them in reverse order
994                            routeStartupOrder.add(entry.getValue());
995                        }
996                    }
997                }
998            }
999    
1000            if (LOG.isDebugEnabled()) {
1001                for (int i = 0; i < getRoutes().size(); i++) {
1002                    LOG.debug("Route " + i + ": " + getRoutes().get(i));
1003                }
1004                LOG.debug("... Routes started");
1005            }
1006    
1007            LOG.info("Started " + getRoutes().size() + " routes");
1008    
1009            LOG.info("Apache Camel " + getVersion() + " (CamelContext:" + getName() + ") started");
1010            EventHelper.notifyCamelContextStarted(this);
1011        }
1012    
1013        // Implementation methods
1014        // -----------------------------------------------------------------------
1015    
1016        protected synchronized void doStart() throws Exception {
1017            LOG.info("Apache Camel " + getVersion() + " (CamelContext:" + getName() + ") is starting");
1018    
1019            try {
1020                doStartCamel();
1021            } catch (Exception e) {
1022                // fire event that we failed to start
1023                EventHelper.notifyCamelContextStartupFailed(this, e);
1024                // rethrown cause
1025                throw e;
1026            }
1027        }
1028    
1029        private void doStartCamel() throws Exception {
1030            startServices(producerServicePool);
1031    
1032            if (isStreamCaching()) {
1033                // only add a new stream cache if not already configured
1034                if (StreamCaching.getStreamCaching(this) == null) {
1035                    if (LOG.isDebugEnabled()) {
1036                        LOG.debug("StreamCaching is enabled");
1037                    }
1038                    addInterceptStrategy(new StreamCaching());
1039                }
1040            }
1041    
1042            if (isTracing()) {
1043                // tracing is added in the DefaultChannel so we can enable it on the fly
1044                LOG.debug("Tracing is enabled");
1045            }
1046    
1047            if (isHandleFault()) {
1048                // only add a new handle fault if not already configured
1049                if (HandleFault.getHandleFault(this) == null) {
1050                    LOG.debug("HandleFault is enabled");
1051                    addInterceptStrategy(new HandleFault());
1052                }
1053            }
1054    
1055            if (getDelayer() != null && getDelayer() > 0) {
1056                // only add a new delayer if not already configured
1057                if (Delayer.getDelayer(this) == null) {
1058                    long millis = getDelayer();
1059                    LOG.debug("Delayer is enabled with: " + millis + " ms.");
1060                    addInterceptStrategy(new Delayer(millis));
1061                }
1062            }
1063    
1064            // start management strategy before lifecycles are started
1065            getManagementStrategy().start();
1066    
1067            Iterator<LifecycleStrategy> it = lifecycleStrategies.iterator();
1068            while (it.hasNext()) {
1069                LifecycleStrategy strategy = it.next();
1070                try {
1071                    strategy.onContextStart(this);
1072                } catch (Exception e) {
1073                    // not all containers allow access to its MBeanServer (such as OC4j)
1074                    // so here we remove the troublesome strategy to be able to continue
1075                    LOG.warn("Cannot start lifecycle strategy: " + strategy + ". This strategy will be removed. Cause " + e.getMessage(), e);
1076                    it.remove();
1077                }
1078            }
1079    
1080            // must let some bootstrap service be started before we can notify the starting event
1081            EventHelper.notifyCamelContextStarting(this);
1082    
1083            forceLazyInitialization();
1084            startServices(components.values());
1085            addService(inflightRepository);
1086            addService(shutdownStrategy);
1087    
1088            // To avoid initiating the routeDefinitions after stopping the camel context
1089            if (!routeDefinitionInitiated) {
1090                startRouteDefinitions(routeDefinitions);
1091                routeDefinitionInitiated = true;
1092            }
1093    
1094            // starting will continue in the start method
1095        }
1096    
1097        protected synchronized void doStop() throws Exception {
1098            LOG.info("Apache Camel " + getVersion() + " (CamelContext:" + getName() + ") is stopping");
1099            EventHelper.notifyCamelContextStopping(this);
1100    
1101            // stop route inputs in the same order as they was started so we stop the very first inputs first
1102            shutdownStrategy.shutdown(this, getRouteStartupOrder());
1103            getRouteStartupOrder().clear();
1104    
1105            stopServices(routeServices.values());
1106            // do not clear route services as we can start Camel again and get the route back as before
1107    
1108            // the stop order is important
1109    
1110            stopServices(servicesToClose);
1111            servicesToClose.clear();
1112    
1113            stopServices(endpoints.values());
1114            endpoints.clear();
1115    
1116            stopServices(components.values());
1117            components.clear();
1118    
1119            // special shutdown of a shared producer service pool as it should only be shutdown by camel context
1120            if (producerServicePool instanceof SharedProducerServicePool) {
1121                ((SharedProducerServicePool) producerServicePool).shutdown(this);
1122            } else {
1123                stopServices(producerServicePool);
1124            }
1125            stopServices(inflightRepository);
1126    
1127            try {
1128                for (LifecycleStrategy strategy : lifecycleStrategies) {
1129                    strategy.onContextStop(this);
1130                }
1131            } catch (Exception e) {
1132                LOG.warn("Cannot stop lifecycle strategies: " + e.getMessage());
1133            }
1134    
1135            // must notify that we are stopped before stopping the management strategy
1136            EventHelper.notifyCamelContextStopped(this);
1137    
1138            // stop management as the last one
1139            stopServices(getManagementStrategy());
1140    
1141            LOG.info("Apache Camel " + getVersion() + " (CamelContext:" + getName() + ") stopped");
1142        }
1143    
1144        private void stopServices(Object service) throws Exception {
1145            // allow us to do custom work before delegating to service helper
1146            try {
1147                ServiceHelper.stopService(service);
1148            } catch (Exception e) {
1149                LOG.warn("Error occurred while stopping service: " + service + ". This exception will be ignored.");
1150                // fire event
1151                EventHelper.notifyServiceStopFailure(this, service, e);
1152            }
1153        }
1154    
1155        private void stopServices(Collection<?> services) throws Exception {
1156            // reverse stopping by default
1157            stopServices(services, true);
1158        }
1159    
1160        private void stopServices(Collection<?> services, boolean reverse) throws Exception {
1161            Collection<Object> list = CastUtils.cast(services);
1162            if (reverse) {
1163                ArrayList<Object> reverseList = new ArrayList<Object>(services);
1164                Collections.reverse(reverseList);
1165                list = reverseList;
1166            }
1167    
1168            for (Object service : list) {
1169                stopServices(service);
1170            }
1171        }
1172    
1173        private void startServices(Object service) throws Exception {
1174            ServiceHelper.startService(service);
1175        }
1176    
1177        protected void startRouteDefinitions(Collection<RouteDefinition> list) throws Exception {
1178            if (list != null) {
1179                for (RouteDefinition route : list) {
1180                    startRoute(route);
1181                }
1182            }
1183        }
1184    
1185        /**
1186         * Starts the given route service
1187         */
1188        protected synchronized void startRouteService(RouteService routeService) throws Exception {
1189            String key = routeService.getId();
1190            ServiceStatus status = getRouteStatus(key);
1191    
1192            if (status != null && status.isStarted()) {
1193                if (LOG.isDebugEnabled()) {
1194                    LOG.debug("Route " + key + " is already started");
1195                }
1196            } else {
1197                routeServices.put(key, routeService);
1198                if (shouldStartRoutes()) {
1199                    routeService.start();
1200                }
1201            }
1202        }
1203    
1204        /**
1205         * Lets force some lazy initialization to occur upfront before we start any
1206         * components and create routes
1207         */
1208        protected void forceLazyInitialization() {
1209            getInjector();
1210            getLanguageResolver();
1211            getTypeConverter();
1212        }
1213    
1214        /**
1215         * Lazily create a default implementation
1216         */
1217        protected TypeConverter createTypeConverter() {
1218            DefaultTypeConverter answer = new DefaultTypeConverter(packageScanClassResolver, getInjector(), getDefaultFactoryFinder());
1219            setTypeConverterRegistry(answer);
1220            return answer;
1221        }
1222    
1223        /**
1224         * Lazily create a default implementation
1225         */
1226        protected Injector createInjector() {
1227            FactoryFinder finder = getDefaultFactoryFinder();
1228            try {
1229                return (Injector) finder.newInstance("Injector");
1230            } catch (NoFactoryAvailableException e) {
1231                // lets use the default
1232                return new ReflectionInjector();
1233            }
1234        }
1235    
1236        /**
1237         * Lazily create a default implementation
1238         */
1239        protected ComponentResolver createComponentResolver() {
1240            return new DefaultComponentResolver();
1241        }
1242    
1243        /**
1244         * Lazily create a default implementation
1245         */
1246        protected Registry createRegistry() {
1247            return new JndiRegistry();
1248        }
1249    
1250        /**
1251         * A pluggable strategy to allow an endpoint to be created without requiring
1252         * a component to be its factory, such as for looking up the URI inside some
1253         * {@link Registry}
1254         *
1255         * @param uri the uri for the endpoint to be created
1256         * @return the newly created endpoint or null if it could not be resolved
1257         */
1258        protected Endpoint createEndpoint(String uri) {
1259            Object value = getRegistry().lookup(uri);
1260            if (value instanceof Endpoint) {
1261                return (Endpoint) value;
1262            } else if (value instanceof Processor) {
1263                return new ProcessorEndpoint(uri, this, (Processor) value);
1264            } else if (value != null) {
1265                return convertBeanToEndpoint(uri, value);
1266            }
1267            return null;
1268        }
1269    
1270        /**
1271         * Strategy method for attempting to convert the bean from a {@link Registry} to an endpoint using
1272         * some kind of transformation or wrapper
1273         *
1274         * @param uri  the uri for the endpoint (and name in the registry)
1275         * @param bean the bean to be converted to an endpoint, which will be not null
1276         * @return a new endpoint
1277         */
1278        protected Endpoint convertBeanToEndpoint(String uri, Object bean) {
1279            throw new IllegalArgumentException("uri: " + uri + " bean: " + bean
1280                    + " could not be converted to an Endpoint");
1281        }
1282    
1283        /**
1284         * Should we start newly added routes?
1285         */
1286        protected boolean shouldStartRoutes() {
1287            return isStarted() && !isStarting();
1288        }
1289    
1290        public void setDataFormats(Map<String, DataFormatDefinition> dataFormats) {
1291            this.dataFormats = dataFormats;
1292        }
1293    
1294        public Map<String, DataFormatDefinition> getDataFormats() {
1295            return dataFormats;
1296        }
1297    
1298        public Map<String, String> getProperties() {
1299            return properties;
1300        }
1301    
1302        public void setProperties(Map<String, String> properties) {
1303            this.properties = properties;
1304        }
1305    
1306        public FactoryFinder getDefaultFactoryFinder() {
1307            if (defaultFactoryFinder == null) {
1308                defaultFactoryFinder = factoryFinderResolver.resolveDefaultFactoryFinder(getClassResolver());
1309            }
1310            return defaultFactoryFinder;
1311        }
1312    
1313        public void setFactoryFinderResolver(FactoryFinderResolver resolver) {
1314            this.factoryFinderResolver = resolver;
1315        }
1316    
1317        public FactoryFinder getFactoryFinder(String path) throws NoFactoryAvailableException {
1318            synchronized (factories) {
1319                FactoryFinder answer = factories.get(path);
1320                if (answer == null) {
1321                    answer = factoryFinderResolver.resolveFactoryFinder(getClassResolver(), path);
1322                    factories.put(path, answer);
1323                }
1324                return answer;
1325            }
1326        }
1327    
1328        public ClassResolver getClassResolver() {
1329            return classResolver;
1330        }
1331    
1332        public void setClassResolver(ClassResolver classResolver) {
1333            this.classResolver = classResolver;
1334        }
1335    
1336        public PackageScanClassResolver getPackageScanClassResolver() {
1337            return packageScanClassResolver;
1338        }
1339    
1340        public void setPackageScanClassResolver(PackageScanClassResolver packageScanClassResolver) {
1341            this.packageScanClassResolver = packageScanClassResolver;
1342        }
1343    
1344        public List<String> getComponentNames() {
1345            synchronized (components) {
1346                List<String> answer = new ArrayList<String>();
1347                for (String name : components.keySet()) {
1348                    answer.add(name);
1349                }
1350                return answer;
1351            }
1352        }
1353    
1354        public List<String> getLanguageNames() {
1355            synchronized (languages) {
1356                List<String> answer = new ArrayList<String>();
1357                for (String name : languages.keySet()) {
1358                    answer.add(name);
1359                }
1360                return answer;
1361            }
1362        }
1363    
1364        public NodeIdFactory getNodeIdFactory() {
1365            return nodeIdFactory;
1366        }
1367    
1368        public void setNodeIdFactory(NodeIdFactory idFactory) {
1369            this.nodeIdFactory = idFactory;
1370        }
1371    
1372        public ManagementStrategy getManagementStrategy() {
1373            if (managementStrategyInitialized.compareAndSet(false, true)) {
1374                managementStrategy = createManagementStrategy();
1375            }
1376            return managementStrategy;
1377        }
1378    
1379        public void setManagementStrategy(ManagementStrategy managementStrategy) {
1380            this.managementStrategy = managementStrategy;
1381            // should be considered initialized as we use a custom strategy
1382            managementStrategyInitialized.set(true);
1383        }
1384    
1385        public InterceptStrategy getDefaultTracer() {
1386            if (defaultTracer == null) {
1387                defaultTracer = new Tracer();
1388            }
1389            return defaultTracer;
1390        }
1391    
1392        public void disableJMX() {
1393            disableJMX = true;
1394        }
1395    
1396        public InflightRepository getInflightRepository() {
1397            return inflightRepository;
1398        }
1399    
1400        public void setInflightRepository(InflightRepository repository) {
1401            this.inflightRepository = repository;
1402        }
1403    
1404        public void setAutoStartup(Boolean autoStartup) {
1405            this.autoStartup = autoStartup;
1406        }
1407    
1408        public Boolean isAutoStartup() {
1409            return autoStartup != null && autoStartup;
1410        }
1411    
1412        public ClassLoader getApplicationContextClassLoader() {
1413            return applicationContextClassLoader;
1414        }
1415    
1416        public void setApplicationContextClassLoader(ClassLoader classLoader) {
1417            applicationContextClassLoader = classLoader;
1418        }
1419    
1420        public DataFormatResolver getDataFormatResolver() {
1421            return dataFormatResolver;
1422        }
1423    
1424        public void setDataFormatResolver(DataFormatResolver dataFormatResolver) {
1425            this.dataFormatResolver = dataFormatResolver;
1426        }
1427    
1428        public DataFormat resolveDataFormat(String name) {
1429            return dataFormatResolver.resolveDataFormat(name, this);
1430        }
1431    
1432        public DataFormatDefinition resolveDataFormatDefinition(String name) {
1433            return dataFormatResolver.resolveDataFormatDefinition(name, this);
1434        }
1435    
1436        public ShutdownStrategy getShutdownStrategy() {
1437            return shutdownStrategy;
1438        }
1439    
1440        public void setShutdownStrategy(ShutdownStrategy shutdownStrategy) {
1441            this.shutdownStrategy = shutdownStrategy;
1442        }
1443    
1444        public ShutdownRoute getShutdownRoute() {
1445            return shutdownRoute;
1446        }
1447    
1448        public void setShutdownRoute(ShutdownRoute shutdownRoute) {
1449            this.shutdownRoute = shutdownRoute;
1450        }
1451    
1452        public ShutdownRunningTask getShutdownRunningTask() {
1453            return shutdownRunningTask;
1454        }
1455    
1456        public void setShutdownRunningTask(ShutdownRunningTask shutdownRunningTask) {
1457            this.shutdownRunningTask = shutdownRunningTask;
1458        }
1459    
1460        protected String getEndpointKey(String uri, Endpoint endpoint) {
1461            if (endpoint.isSingleton()) {
1462                return uri;
1463            } else {
1464                int counter = endpointKeyCounter.incrementAndGet();
1465                return uri + ":" + counter;
1466            }
1467        }
1468    
1469        protected Map<String, RouteService> getRouteServices() {
1470            return routeServices;
1471        }
1472    
1473        protected ManagementStrategy createManagementStrategy() {
1474            ManagementStrategy answer = null;
1475    
1476            if (disableJMX || Boolean.getBoolean(JmxSystemPropertyKeys.DISABLED)) {
1477                LOG.info("JMX is disabled. Using DefaultManagementStrategy.");
1478                answer = new DefaultManagementStrategy();
1479            } else {
1480                try {
1481                    LOG.info("JMX enabled. Using DefaultManagedLifecycleStrategy.");
1482                    answer = new ManagedManagementStrategy(new DefaultManagementAgent());
1483                    // prefer to have it at first strategy
1484                    lifecycleStrategies.add(0, new DefaultManagementLifecycleStrategy(this));
1485                } catch (NoClassDefFoundError e) {
1486                    // if we can't instantiate the JMX enabled strategy then fallback to default
1487                    // could be because of missing .jars on the classpath
1488                    LOG.warn("Could not find needed classes for JMX lifecycle strategy."
1489                            + " Needed class is in spring-context.jar using Spring 2.5 or newer"
1490                            + " (spring-jmx.jar using Spring 2.0.x)."
1491                            + " NoClassDefFoundError: " + e.getMessage());
1492                } catch (Exception e) {
1493                    LOG.warn("Could not create JMX lifecycle strategy, caused by: " + e.getMessage());
1494                }
1495            }
1496    
1497            if (answer == null) {
1498                LOG.warn("Cannot use JMX. Fallback to using DefaultManagementStrategy.");
1499                answer = new DefaultManagementStrategy();
1500            }
1501    
1502            return answer;
1503        }
1504    
1505        @Override
1506        public String toString() {
1507            return "CamelContext(" + getName() + ")";
1508        }
1509    
1510    }