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.io.InputStream;
021    import java.util.ArrayList;
022    import java.util.Arrays;
023    import java.util.Collection;
024    import java.util.Collections;
025    import java.util.Date;
026    import java.util.HashMap;
027    import java.util.Iterator;
028    import java.util.LinkedHashMap;
029    import java.util.LinkedHashSet;
030    import java.util.List;
031    import java.util.Map;
032    import java.util.Properties;
033    import java.util.Set;
034    import java.util.TreeMap;
035    import java.util.concurrent.ScheduledExecutorService;
036    import java.util.concurrent.TimeUnit;
037    import java.util.concurrent.atomic.AtomicInteger;
038    import javax.naming.Context;
039    import javax.xml.bind.JAXBContext;
040    import javax.xml.bind.Unmarshaller;
041    
042    import org.apache.camel.CamelContext;
043    import org.apache.camel.CamelContextAware;
044    import org.apache.camel.Component;
045    import org.apache.camel.Consumer;
046    import org.apache.camel.ConsumerTemplate;
047    import org.apache.camel.Endpoint;
048    import org.apache.camel.ErrorHandlerFactory;
049    import org.apache.camel.FailedToStartRouteException;
050    import org.apache.camel.IsSingleton;
051    import org.apache.camel.MultipleConsumersSupport;
052    import org.apache.camel.NoFactoryAvailableException;
053    import org.apache.camel.NoSuchEndpointException;
054    import org.apache.camel.Processor;
055    import org.apache.camel.Producer;
056    import org.apache.camel.ProducerTemplate;
057    import org.apache.camel.ResolveEndpointFailedException;
058    import org.apache.camel.Route;
059    import org.apache.camel.RoutesBuilder;
060    import org.apache.camel.RuntimeCamelException;
061    import org.apache.camel.Service;
062    import org.apache.camel.ServiceStatus;
063    import org.apache.camel.ShutdownRoute;
064    import org.apache.camel.ShutdownRunningTask;
065    import org.apache.camel.StartupListener;
066    import org.apache.camel.StatefulService;
067    import org.apache.camel.SuspendableService;
068    import org.apache.camel.TypeConverter;
069    import org.apache.camel.VetoCamelContextStartException;
070    import org.apache.camel.builder.ErrorHandlerBuilder;
071    import org.apache.camel.component.properties.PropertiesComponent;
072    import org.apache.camel.impl.converter.BaseTypeConverterRegistry;
073    import org.apache.camel.impl.converter.DefaultTypeConverter;
074    import org.apache.camel.impl.converter.LazyLoadingTypeConverter;
075    import org.apache.camel.management.DefaultManagementMBeanAssembler;
076    import org.apache.camel.management.DefaultManagementStrategy;
077    import org.apache.camel.management.JmxSystemPropertyKeys;
078    import org.apache.camel.management.ManagementStrategyFactory;
079    import org.apache.camel.model.Constants;
080    import org.apache.camel.model.DataFormatDefinition;
081    import org.apache.camel.model.ModelCamelContext;
082    import org.apache.camel.model.RouteDefinition;
083    import org.apache.camel.model.RouteDefinitionHelper;
084    import org.apache.camel.model.RoutesDefinition;
085    import org.apache.camel.processor.interceptor.BacklogDebugger;
086    import org.apache.camel.processor.interceptor.BacklogTracer;
087    import org.apache.camel.processor.interceptor.Debug;
088    import org.apache.camel.processor.interceptor.Delayer;
089    import org.apache.camel.processor.interceptor.HandleFault;
090    import org.apache.camel.processor.interceptor.StreamCaching;
091    import org.apache.camel.processor.interceptor.Tracer;
092    import org.apache.camel.spi.CamelContextNameStrategy;
093    import org.apache.camel.spi.ClassResolver;
094    import org.apache.camel.spi.ComponentResolver;
095    import org.apache.camel.spi.Container;
096    import org.apache.camel.spi.DataFormat;
097    import org.apache.camel.spi.DataFormatResolver;
098    import org.apache.camel.spi.Debugger;
099    import org.apache.camel.spi.EndpointStrategy;
100    import org.apache.camel.spi.EventNotifier;
101    import org.apache.camel.spi.ExecutorServiceManager;
102    import org.apache.camel.spi.FactoryFinder;
103    import org.apache.camel.spi.FactoryFinderResolver;
104    import org.apache.camel.spi.InflightRepository;
105    import org.apache.camel.spi.Injector;
106    import org.apache.camel.spi.InterceptStrategy;
107    import org.apache.camel.spi.Language;
108    import org.apache.camel.spi.LanguageResolver;
109    import org.apache.camel.spi.LifecycleStrategy;
110    import org.apache.camel.spi.ManagementMBeanAssembler;
111    import org.apache.camel.spi.ManagementNameStrategy;
112    import org.apache.camel.spi.ManagementStrategy;
113    import org.apache.camel.spi.NodeIdFactory;
114    import org.apache.camel.spi.PackageScanClassResolver;
115    import org.apache.camel.spi.ProcessorFactory;
116    import org.apache.camel.spi.Registry;
117    import org.apache.camel.spi.RouteContext;
118    import org.apache.camel.spi.RouteStartupOrder;
119    import org.apache.camel.spi.ServicePool;
120    import org.apache.camel.spi.ShutdownStrategy;
121    import org.apache.camel.spi.StreamCachingStrategy;
122    import org.apache.camel.spi.TypeConverterRegistry;
123    import org.apache.camel.spi.UnitOfWorkFactory;
124    import org.apache.camel.spi.UuidGenerator;
125    import org.apache.camel.support.ServiceSupport;
126    import org.apache.camel.util.CamelContextHelper;
127    import org.apache.camel.util.EndpointHelper;
128    import org.apache.camel.util.EventHelper;
129    import org.apache.camel.util.IOHelper;
130    import org.apache.camel.util.IntrospectionSupport;
131    import org.apache.camel.util.LoadPropertiesException;
132    import org.apache.camel.util.ObjectHelper;
133    import org.apache.camel.util.ServiceHelper;
134    import org.apache.camel.util.StopWatch;
135    import org.apache.camel.util.StringHelper;
136    import org.apache.camel.util.TimeUtils;
137    import org.apache.camel.util.URISupport;
138    import org.slf4j.Logger;
139    import org.slf4j.LoggerFactory;
140    
141    /**
142     * Represents the context used to configure routes and the policies to use.
143     *
144     * @version 
145     */
146    @SuppressWarnings("deprecation")
147    public class DefaultCamelContext extends ServiceSupport implements ModelCamelContext, SuspendableService {
148        private final Logger log = LoggerFactory.getLogger(getClass());
149        private JAXBContext jaxbContext;
150        private CamelContextNameStrategy nameStrategy = new DefaultCamelContextNameStrategy();
151        private ManagementNameStrategy managementNameStrategy = new DefaultManagementNameStrategy(this);
152        private String managementName;
153        private ClassLoader applicationContextClassLoader;
154        private Map<EndpointKey, Endpoint> endpoints;
155        private final AtomicInteger endpointKeyCounter = new AtomicInteger();
156        private final List<EndpointStrategy> endpointStrategies = new ArrayList<EndpointStrategy>();
157        private final Map<String, Component> components = new HashMap<String, Component>();
158        private final Set<Route> routes = new LinkedHashSet<Route>();
159        private final List<Service> servicesToClose = new ArrayList<Service>();
160        private final Set<StartupListener> startupListeners = new LinkedHashSet<StartupListener>();
161        private TypeConverter typeConverter;
162        private TypeConverterRegistry typeConverterRegistry;
163        private Injector injector;
164        private ComponentResolver componentResolver;
165        private boolean autoCreateComponents = true;
166        private LanguageResolver languageResolver = new DefaultLanguageResolver();
167        private final Map<String, Language> languages = new HashMap<String, Language>();
168        private Registry registry;
169        private List<LifecycleStrategy> lifecycleStrategies = new ArrayList<LifecycleStrategy>();
170        private ManagementStrategy managementStrategy;
171        private ManagementMBeanAssembler managementMBeanAssembler;
172        private final List<RouteDefinition> routeDefinitions = new ArrayList<RouteDefinition>();
173        private List<InterceptStrategy> interceptStrategies = new ArrayList<InterceptStrategy>();
174    
175        // special flags to control the first startup which can are special
176        private volatile boolean firstStartDone;
177        private volatile boolean doNotStartRoutesOnFirstStart;
178        private final ThreadLocal<Boolean> isStartingRoutes = new ThreadLocal<Boolean>();
179        private Boolean autoStartup = Boolean.TRUE;
180        private Boolean trace = Boolean.FALSE;
181        private Boolean messageHistory = Boolean.TRUE;
182        private Boolean streamCache = Boolean.FALSE;
183        private Boolean handleFault = Boolean.FALSE;
184        private Boolean disableJMX = Boolean.FALSE;
185        private Boolean lazyLoadTypeConverters = Boolean.FALSE;
186        private Boolean typeConverterStatisticsEnabled = Boolean.FALSE;
187        private Boolean useMDCLogging = Boolean.FALSE;
188        private Boolean useBreadcrumb = Boolean.TRUE;
189        private Boolean allowUseOriginalMessage = Boolean.TRUE;
190        private Long delay;
191        private ErrorHandlerFactory errorHandlerBuilder;
192        private final Object errorHandlerExecutorServiceLock = new Object();
193        private ScheduledExecutorService errorHandlerExecutorService;
194        private Map<String, DataFormatDefinition> dataFormats = new HashMap<String, DataFormatDefinition>();
195        private DataFormatResolver dataFormatResolver = new DefaultDataFormatResolver();
196        private Map<String, String> properties = new HashMap<String, String>();
197        private FactoryFinderResolver factoryFinderResolver = new DefaultFactoryFinderResolver();
198        private FactoryFinder defaultFactoryFinder;
199        private PropertiesComponent propertiesComponent;
200        private StreamCachingStrategy streamCachingStrategy;
201        private final Map<String, FactoryFinder> factories = new HashMap<String, FactoryFinder>();
202        private final Map<String, RouteService> routeServices = new LinkedHashMap<String, RouteService>();
203        private final Map<String, RouteService> suspendedRouteServices = new LinkedHashMap<String, RouteService>();
204        private ClassResolver classResolver = new DefaultClassResolver();
205        private PackageScanClassResolver packageScanClassResolver;
206        // we use a capacity of 100 per endpoint, so for the same endpoint we have at most 100 producers in the pool
207        // so if we have 6 endpoints in the pool, we can have 6 x 100 producers in total
208        private ServicePool<Endpoint, Producer> producerServicePool = new SharedProducerServicePool(100);
209        private NodeIdFactory nodeIdFactory = new DefaultNodeIdFactory();
210        private ProcessorFactory processorFactory;
211        private InterceptStrategy defaultTracer;
212        private InterceptStrategy defaultBacklogTracer;
213        private InterceptStrategy defaultBacklogDebugger;
214        private InflightRepository inflightRepository = new DefaultInflightRepository();
215        private final List<RouteStartupOrder> routeStartupOrder = new ArrayList<RouteStartupOrder>();
216        // start auto assigning route ids using numbering 1000 and upwards
217        private int defaultRouteStartupOrder = 1000;
218        private ShutdownStrategy shutdownStrategy = new DefaultShutdownStrategy(this);
219        private ShutdownRoute shutdownRoute = ShutdownRoute.Default;
220        private ShutdownRunningTask shutdownRunningTask = ShutdownRunningTask.CompleteCurrentTaskOnly;
221        private ExecutorServiceManager executorServiceManager;
222        private Debugger debugger;
223        private UuidGenerator uuidGenerator = createDefaultUuidGenerator();
224        private UnitOfWorkFactory unitOfWorkFactory = new DefaultUnitOfWorkFactory();
225        private final StopWatch stopWatch = new StopWatch(false);
226        private Date startDate;
227    
228        /**
229         * Creates the {@link CamelContext} using {@link JndiRegistry} as registry,
230         * but will silently fallback and use {@link SimpleRegistry} if JNDI cannot be used.
231         * <p/>
232         * Use one of the other constructors to force use an explicit registry / JNDI.
233         */
234        public DefaultCamelContext() {
235            this.executorServiceManager = new DefaultExecutorServiceManager(this);
236    
237            // create endpoint registry at first since end users may access endpoints before CamelContext is started
238            this.endpoints = new EndpointRegistry(this);
239    
240            // use WebSphere specific resolver if running on WebSphere
241            if (WebSpherePackageScanClassResolver.isWebSphereClassLoader(this.getClass().getClassLoader())) {
242                log.info("Using WebSphere specific PackageScanClassResolver");
243                packageScanClassResolver = new WebSpherePackageScanClassResolver("META-INF/services/org/apache/camel/TypeConverter");
244            } else {
245                packageScanClassResolver = new DefaultPackageScanClassResolver();
246            }
247    
248            // setup management strategy first since end users may use it to add event notifiers
249            // using the management strategy before the CamelContext has been started
250            this.managementStrategy = createManagementStrategy();
251            this.managementMBeanAssembler = createManagementMBeanAssembler();
252    
253            Container.Instance.manage(this);
254        }
255    
256        /**
257         * Creates the {@link CamelContext} using the given JNDI context as the registry
258         *
259         * @param jndiContext the JNDI context
260         */
261        public DefaultCamelContext(Context jndiContext) {
262            this();
263            setJndiContext(jndiContext);
264        }
265    
266        /**
267         * Creates the {@link CamelContext} using the given registry
268         *
269         * @param registry the registry
270         */
271        public DefaultCamelContext(Registry registry) {
272            this();
273            setRegistry(registry);
274        }
275    
276        public String getName() {
277            return getNameStrategy().getName();
278        }
279    
280        /**
281         * Sets the name of the this context.
282         *
283         * @param name the name
284         */
285        public void setName(String name) {
286            // use an explicit name strategy since an explicit name was provided to be used
287            this.nameStrategy = new ExplicitCamelContextNameStrategy(name);
288        }
289    
290        public CamelContextNameStrategy getNameStrategy() {
291            return nameStrategy;
292        }
293    
294        public void setNameStrategy(CamelContextNameStrategy nameStrategy) {
295            this.nameStrategy = nameStrategy;
296        }
297    
298        public ManagementNameStrategy getManagementNameStrategy() {
299            return managementNameStrategy;
300        }
301    
302        public void setManagementNameStrategy(ManagementNameStrategy managementNameStrategy) {
303            this.managementNameStrategy = managementNameStrategy;
304        }
305    
306        public String getManagementName() {
307            return managementName;
308        }
309    
310        public void setManagementName(String managementName) {
311            this.managementName = managementName;
312        }
313    
314        public Component hasComponent(String componentName) {
315            return components.get(componentName);
316        }
317    
318        public void addComponent(String componentName, final Component component) {
319            ObjectHelper.notNull(component, "component");
320            synchronized (components) {
321                if (components.containsKey(componentName)) {
322                    throw new IllegalArgumentException("Cannot add component as its already previously added: " + componentName);
323                }
324                component.setCamelContext(this);
325                components.put(componentName, component);
326                for (LifecycleStrategy strategy : lifecycleStrategies) {
327                    strategy.onComponentAdd(componentName, component);
328                }
329    
330                // keep reference to properties component up to date
331                if (component instanceof PropertiesComponent && "properties".equals(componentName)) {
332                    propertiesComponent = (PropertiesComponent) component;
333                }
334            }
335        }
336    
337        public Component getComponent(String name) {
338            return getComponent(name, autoCreateComponents);
339        }
340    
341        public Component getComponent(String name, boolean autoCreateComponents) {
342            // synchronize the look up and auto create so that 2 threads can't
343            // concurrently auto create the same component.
344            synchronized (components) {
345                Component component = components.get(name);
346                if (component == null && autoCreateComponents) {
347                    try {
348                        if (log.isDebugEnabled()) {
349                            log.debug("Using ComponentResolver: {} to resolve component with name: {}", getComponentResolver(), name);
350                        }
351                        component = getComponentResolver().resolveComponent(name, this);
352                        if (component != null) {
353                            addComponent(name, component);
354                            if (isStarted() || isStarting()) {
355                                // If the component is looked up after the context is started, lets start it up.
356                                if (component instanceof Service) {
357                                    startService((Service)component);
358                                }
359                            }
360                        }
361                    } catch (Exception e) {
362                        throw new RuntimeCamelException("Cannot auto create component: " + name, e);
363                    }
364                }
365                log.trace("getComponent({}) -> {}", name, component);
366                return component;
367            }
368        }
369    
370        public <T extends Component> T getComponent(String name, Class<T> componentType) {
371            Component component = getComponent(name);
372            if (componentType.isInstance(component)) {
373                return componentType.cast(component);
374            } else {
375                String message;
376                if (component == null) {
377                    message = "Did not find component given by the name: " + name;
378                } else {
379                    message = "Found component of type: " + component.getClass() + " instead of expected: " + componentType;
380                }
381                throw new IllegalArgumentException(message);
382            }
383        }
384    
385        public Component removeComponent(String componentName) {
386            synchronized (components) {
387                Component oldComponent = components.remove(componentName);
388                if (oldComponent != null) {
389                    try {
390                        stopServices(oldComponent);
391                    } catch (Exception e) {
392                        log.warn("Error stopping component " + oldComponent + ". This exception will be ignored.", e);
393                    }
394                    for (LifecycleStrategy strategy : lifecycleStrategies) {
395                        strategy.onComponentRemove(componentName, oldComponent);
396                    }
397                }
398                // keep reference to properties component up to date
399                if (oldComponent != null && "properties".equals(componentName)) {
400                    propertiesComponent = null;
401                }
402                return oldComponent;
403            }
404        }
405    
406        // Endpoint Management Methods
407        // -----------------------------------------------------------------------
408    
409        public Collection<Endpoint> getEndpoints() {
410            return new ArrayList<Endpoint>(endpoints.values());
411        }
412    
413        public Map<String, Endpoint> getEndpointMap() {
414            Map<String, Endpoint> answer = new TreeMap<String, Endpoint>();
415            for (Map.Entry<EndpointKey, Endpoint> entry : endpoints.entrySet()) {
416                answer.put(entry.getKey().get(), entry.getValue());
417            }
418            return answer;
419        }
420    
421        public Endpoint hasEndpoint(String uri) {
422            return endpoints.get(getEndpointKey(uri));
423        }
424    
425        public Endpoint addEndpoint(String uri, Endpoint endpoint) throws Exception {
426            Endpoint oldEndpoint;
427    
428            startService(endpoint);
429            oldEndpoint = endpoints.remove(getEndpointKey(uri));
430            for (LifecycleStrategy strategy : lifecycleStrategies) {
431                strategy.onEndpointAdd(endpoint);
432            }
433            addEndpointToRegistry(uri, endpoint);
434            if (oldEndpoint != null) {
435                stopServices(oldEndpoint);
436            }
437    
438            return oldEndpoint;
439        }
440    
441        public Collection<Endpoint> removeEndpoints(String uri) throws Exception {
442            Collection<Endpoint> answer = new ArrayList<Endpoint>();
443            Endpoint oldEndpoint = endpoints.remove(getEndpointKey(uri));
444            if (oldEndpoint != null) {
445                answer.add(oldEndpoint);
446                stopServices(oldEndpoint);
447            } else {
448                for (Map.Entry<EndpointKey, Endpoint> entry : endpoints.entrySet()) {
449                    oldEndpoint = entry.getValue();
450                    if (EndpointHelper.matchEndpoint(this, oldEndpoint.getEndpointUri(), uri)) {
451                        try {
452                            stopServices(oldEndpoint);
453                        } catch (Exception e) {
454                            log.warn("Error stopping endpoint " + oldEndpoint + ". This exception will be ignored.", e);
455                        }
456                        answer.add(oldEndpoint);
457                        endpoints.remove(entry.getKey());
458                    }
459                }
460            }
461    
462            // notify lifecycle its being removed
463            for (Endpoint endpoint : answer) {
464                for (LifecycleStrategy strategy : lifecycleStrategies) {
465                    strategy.onEndpointRemove(endpoint);
466                }
467            }
468    
469            return answer;
470        }
471    
472        public Endpoint getEndpoint(String uri) {
473            ObjectHelper.notEmpty(uri, "uri");
474    
475            log.trace("Getting endpoint with uri: {}", uri);
476    
477            // in case path has property placeholders then try to let property component resolve those
478            try {
479                uri = resolvePropertyPlaceholders(uri);
480            } catch (Exception e) {
481                throw new ResolveEndpointFailedException(uri, e);
482            }
483    
484            final String rawUri = uri;
485    
486            // normalize uri so we can do endpoint hits with minor mistakes and parameters is not in the same order
487            uri = normalizeEndpointUri(uri);
488    
489            log.trace("Getting endpoint with raw uri: {}, normalized uri: {}", rawUri, uri);
490    
491            Endpoint answer;
492            String scheme = null;
493            EndpointKey key = getEndpointKey(uri);
494            answer = endpoints.get(key);
495            if (answer == null) {
496                try {
497                    // Use the URI prefix to find the component.
498                    String splitURI[] = ObjectHelper.splitOnCharacter(uri, ":", 2);
499                    if (splitURI[1] != null) {
500                        scheme = splitURI[0];
501                        log.trace("Endpoint uri: {} is from component with name: {}", uri, scheme);
502                        Component component = getComponent(scheme);
503    
504                        // Ask the component to resolve the endpoint.
505                        if (component != null) {
506                            log.trace("Creating endpoint from uri: {} using component: {}", uri, component);
507    
508                            // Have the component create the endpoint if it can.
509                            if (component.useRawUri()) {
510                                answer = component.createEndpoint(rawUri);
511                            } else {
512                                answer = component.createEndpoint(uri);
513                            }
514    
515                            if (answer != null && log.isDebugEnabled()) {
516                                log.debug("{} converted to endpoint: {} by component: {}", new Object[]{URISupport.sanitizeUri(uri), answer, component});
517                            }
518                        }
519                    }
520    
521                    if (answer == null) {
522                        // no component then try in registry and elsewhere
523                        answer = createEndpoint(uri);
524                        log.trace("No component to create endpoint from uri: {} fallback lookup in registry -> {}", uri, answer);
525                    }
526    
527                    if (answer != null) {
528                        addService(answer);
529                        answer = addEndpointToRegistry(uri, answer);
530                    }
531                } catch (Exception e) {
532                    throw new ResolveEndpointFailedException(uri, e);
533                }
534            }
535    
536            // unknown scheme
537            if (answer == null && scheme != null) {
538                throw new ResolveEndpointFailedException(uri, "No component found with scheme: " + scheme);
539            }
540    
541            return answer;
542        }
543    
544        public <T extends Endpoint> T getEndpoint(String name, Class<T> endpointType) {
545            Endpoint endpoint = getEndpoint(name);
546            if (endpoint == null) {
547                throw new NoSuchEndpointException(name);
548            }
549            if (endpoint instanceof InterceptSendToEndpoint) {
550                endpoint = ((InterceptSendToEndpoint) endpoint).getDelegate();
551            }
552            if (endpointType.isInstance(endpoint)) {
553                return endpointType.cast(endpoint);
554            } else {
555                throw new IllegalArgumentException("The endpoint is not of type: " + endpointType 
556                    + " but is: " + endpoint.getClass().getCanonicalName());
557            }
558        }
559    
560        public void addRegisterEndpointCallback(EndpointStrategy strategy) {
561            if (!endpointStrategies.contains(strategy)) {
562                // let it be invoked for already registered endpoints so it can catch-up.
563                endpointStrategies.add(strategy);
564                for (Endpoint endpoint : getEndpoints()) {
565                    Endpoint newEndpoint = strategy.registerEndpoint(endpoint.getEndpointUri(), endpoint);
566                    if (newEndpoint != null) {
567                        // put will replace existing endpoint with the new endpoint
568                        endpoints.put(getEndpointKey(endpoint.getEndpointUri()), newEndpoint);
569                    }
570                }
571            }
572        }
573    
574        /**
575         * Strategy to add the given endpoint to the internal endpoint registry
576         *
577         * @param uri      uri of the endpoint
578         * @param endpoint the endpoint to add
579         * @return the added endpoint
580         */
581        protected Endpoint addEndpointToRegistry(String uri, Endpoint endpoint) {
582            ObjectHelper.notEmpty(uri, "uri");
583            ObjectHelper.notNull(endpoint, "endpoint");
584    
585            // if there is endpoint strategies, then use the endpoints they return
586            // as this allows to intercept endpoints etc.
587            for (EndpointStrategy strategy : endpointStrategies) {
588                endpoint = strategy.registerEndpoint(uri, endpoint);
589            }
590            endpoints.put(getEndpointKey(uri, endpoint), endpoint);
591            return endpoint;
592        }
593    
594        /**
595         * Normalize uri so we can do endpoint hits with minor mistakes and parameters is not in the same order.
596         *
597         * @param uri the uri
598         * @return normalized uri
599         * @throws ResolveEndpointFailedException if uri cannot be normalized
600         */
601        protected static String normalizeEndpointUri(String uri) {
602            try {
603                uri = URISupport.normalizeUri(uri);
604            } catch (Exception e) {
605                throw new ResolveEndpointFailedException(uri, e);
606            }
607            return uri;
608        }
609    
610        /**
611         * Gets the endpoint key to use for lookup or whe adding endpoints to the {@link EndpointRegistry}
612         *
613         * @param uri the endpoint uri
614         * @return the key
615         */
616        protected EndpointKey getEndpointKey(String uri) {
617            return new EndpointKey(uri);
618        }
619    
620        /**
621         * Gets the endpoint key to use for lookup or whe adding endpoints to the {@link EndpointRegistry}
622         *
623         * @param uri      the endpoint uri
624         * @param endpoint the endpoint
625         * @return the key
626         */
627        protected EndpointKey getEndpointKey(String uri, Endpoint endpoint) {
628            if (endpoint != null && !endpoint.isSingleton()) {
629                int counter = endpointKeyCounter.incrementAndGet();
630                return new EndpointKey(uri + ":" + counter);
631            } else {
632                return new EndpointKey(uri);
633            }
634        }
635    
636        // Route Management Methods
637        // -----------------------------------------------------------------------
638    
639        public List<RouteStartupOrder> getRouteStartupOrder() {
640            return routeStartupOrder;
641        }
642    
643        public List<Route> getRoutes() {
644            // lets return a copy of the collection as objects are removed later when services are stopped
645            if (routes.isEmpty()) {
646                return Collections.emptyList();
647            } else {
648                return new ArrayList<Route>(routes);
649            }
650        }
651    
652        public Route getRoute(String id) {
653            for (Route route : getRoutes()) {
654                if (route.getId().equals(id)) {
655                    return route;
656                }
657            }
658            return null;
659        }
660    
661        @Deprecated
662        public void setRoutes(List<Route> routes) {
663            throw new UnsupportedOperationException("Overriding existing routes is not supported yet, use addRouteCollection instead");
664        }
665    
666        synchronized void removeRouteCollection(Collection<Route> routes) {
667            this.routes.removeAll(routes);
668        }
669    
670        synchronized void addRouteCollection(Collection<Route> routes) throws Exception {
671            this.routes.addAll(routes);
672        }
673    
674        public void addRoutes(RoutesBuilder builder) throws Exception {
675            log.debug("Adding routes from builder: {}", builder);
676            // lets now add the routes from the builder
677            builder.addRoutesToCamelContext(this);
678        }
679    
680        public synchronized RoutesDefinition loadRoutesDefinition(InputStream is) throws Exception {
681            // load routes using JAXB
682            if (jaxbContext == null) {
683                // must use classloader from CamelContext to have JAXB working
684                jaxbContext = JAXBContext.newInstance(Constants.JAXB_CONTEXT_PACKAGES, CamelContext.class.getClassLoader());
685            }
686    
687            Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
688            Object result = unmarshaller.unmarshal(is);
689    
690            if (result == null) {
691                throw new IOException("Cannot unmarshal to routes using JAXB from input stream: " + is);
692            }
693    
694            // can either be routes or a single route
695            RoutesDefinition answer = null;
696            if (result instanceof RouteDefinition) {
697                RouteDefinition route = (RouteDefinition) result;
698                answer = new RoutesDefinition();
699                answer.getRoutes().add(route);
700            } else if (result instanceof RoutesDefinition) {
701                answer = (RoutesDefinition) result;
702            } else {
703                throw new IllegalArgumentException("Unmarshalled object is an unsupported type: " + ObjectHelper.className(result) + " -> " + result);
704            }
705    
706            return answer;
707        }
708    
709        public synchronized void addRouteDefinitions(Collection<RouteDefinition> routeDefinitions) throws Exception {
710            for (RouteDefinition routeDefinition : routeDefinitions) {
711                removeRouteDefinition(routeDefinition);
712            }
713            this.routeDefinitions.addAll(routeDefinitions);
714            if (shouldStartRoutes()) {
715                startRouteDefinitions(routeDefinitions);
716            }
717        }
718    
719        public void addRouteDefinition(RouteDefinition routeDefinition) throws Exception {
720            addRouteDefinitions(Arrays.asList(routeDefinition));
721        }
722    
723        /**
724         * Removes the route definition with the given key.
725         *
726         * @return true if one or more routes was removed
727         */
728        protected boolean removeRouteDefinition(String key) {
729            boolean answer = false;
730            Iterator<RouteDefinition> iter = routeDefinitions.iterator();
731            while (iter.hasNext()) {
732                RouteDefinition route = iter.next();
733                if (route.idOrCreate(nodeIdFactory).equals(key)) {
734                    iter.remove();
735                    answer = true;
736                }
737            }
738            return answer;
739        }
740    
741        public synchronized void removeRouteDefinitions(Collection<RouteDefinition> routeDefinitions) throws Exception {
742            for (RouteDefinition routeDefinition : routeDefinitions) {
743                removeRouteDefinition(routeDefinition);
744            }
745        }
746    
747        public synchronized void removeRouteDefinition(RouteDefinition routeDefinition) throws Exception {
748            String id = routeDefinition.idOrCreate(nodeIdFactory);
749            stopRoute(id);
750            removeRoute(id);
751            this.routeDefinitions.remove(routeDefinition);
752        }
753    
754        public ServiceStatus getRouteStatus(String key) {
755            RouteService routeService = routeServices.get(key);
756            if (routeService != null) {
757                return routeService.getStatus();
758            }
759            return null;
760        }
761    
762        public void startRoute(RouteDefinition route) throws Exception {
763            // assign ids to the routes and validate that the id's is all unique
764            RouteDefinitionHelper.forceAssignIds(this, routeDefinitions);
765            String duplicate = RouteDefinitionHelper.validateUniqueIds(route, routeDefinitions);
766            if (duplicate != null) {
767                throw new FailedToStartRouteException(route.getId(), "duplicate id detected: " + duplicate + ". Please correct ids to be unique among all your routes.");
768            }
769    
770            // indicate we are staring the route using this thread so
771            // we are able to query this if needed
772            isStartingRoutes.set(true);
773            try {
774                // must ensure route is prepared, before we can start it
775                route.prepare(this);
776    
777                List<Route> routes = new ArrayList<Route>();
778                List<RouteContext> routeContexts = route.addRoutes(this, routes);
779                RouteService routeService = new RouteService(this, route, routeContexts, routes);
780                startRouteService(routeService, true);
781            } finally {
782                // we are done staring routes
783                isStartingRoutes.remove();
784            }
785        }
786    
787        public boolean isStartingRoutes() {
788            Boolean answer = isStartingRoutes.get();
789            return answer != null && answer;
790        }
791    
792        public void stopRoute(RouteDefinition route) throws Exception {
793            stopRoute(route.idOrCreate(nodeIdFactory));
794        }
795    
796        public synchronized void startRoute(String routeId) throws Exception {
797            RouteService routeService = routeServices.get(routeId);
798            if (routeService != null) {
799                startRouteService(routeService, false);
800            }
801        }
802    
803        public synchronized void resumeRoute(String routeId) throws Exception {
804            if (!routeSupportsSuspension(routeId)) {
805                // start route if suspension is not supported
806                startRoute(routeId);
807                return;
808            }
809    
810            RouteService routeService = routeServices.get(routeId);
811            if (routeService != null) {
812                resumeRouteService(routeService);
813            }
814        }
815    
816        public synchronized boolean stopRoute(String routeId, long timeout, TimeUnit timeUnit, boolean abortAfterTimeout) throws Exception {
817            RouteService routeService = routeServices.get(routeId);
818            if (routeService != null) {
819                RouteStartupOrder route = new DefaultRouteStartupOrder(1, routeService.getRoutes().iterator().next(), routeService);
820    
821                boolean completed = getShutdownStrategy().shutdown(this, route, timeout, timeUnit, abortAfterTimeout);
822                if (completed) {
823                    // must stop route service as well
824                    stopRouteService(routeService, false);
825                } else {
826                    // shutdown was aborted, make sure route is re-started properly
827                    startRouteService(routeService, false);
828                }
829                return completed;
830            } 
831            return false;
832        }
833        
834        public synchronized void stopRoute(String routeId) throws Exception {
835            RouteService routeService = routeServices.get(routeId);
836            if (routeService != null) {
837                List<RouteStartupOrder> routes = new ArrayList<RouteStartupOrder>(1);
838                RouteStartupOrder order = new DefaultRouteStartupOrder(1, routeService.getRoutes().iterator().next(), routeService);
839                routes.add(order);
840    
841                getShutdownStrategy().shutdown(this, routes);
842                // must stop route service as well
843                stopRouteService(routeService, false);
844            }
845        }
846    
847        public synchronized void stopRoute(String routeId, long timeout, TimeUnit timeUnit) throws Exception {
848            RouteService routeService = routeServices.get(routeId);
849            if (routeService != null) {
850                List<RouteStartupOrder> routes = new ArrayList<RouteStartupOrder>(1);
851                RouteStartupOrder order = new DefaultRouteStartupOrder(1, routeService.getRoutes().iterator().next(), routeService);
852                routes.add(order);
853    
854                getShutdownStrategy().shutdown(this, routes, timeout, timeUnit);
855                // must stop route service as well
856                stopRouteService(routeService, false);
857            }
858        }
859    
860        public synchronized void shutdownRoute(String routeId) throws Exception {
861            RouteService routeService = routeServices.get(routeId);
862            if (routeService != null) {
863                List<RouteStartupOrder> routes = new ArrayList<RouteStartupOrder>(1);
864                RouteStartupOrder order = new DefaultRouteStartupOrder(1, routeService.getRoutes().iterator().next(), routeService);
865                routes.add(order);
866    
867                getShutdownStrategy().shutdown(this, routes);
868                // must stop route service as well (and remove the routes from management)
869                stopRouteService(routeService, true);
870            }
871        }
872    
873        public synchronized void shutdownRoute(String routeId, long timeout, TimeUnit timeUnit) throws Exception {
874            RouteService routeService = routeServices.get(routeId);
875            if (routeService != null) {
876                List<RouteStartupOrder> routes = new ArrayList<RouteStartupOrder>(1);
877                RouteStartupOrder order = new DefaultRouteStartupOrder(1, routeService.getRoutes().iterator().next(), routeService);
878                routes.add(order);
879    
880                getShutdownStrategy().shutdown(this, routes, timeout, timeUnit);
881                // must stop route service as well (and remove the routes from management)
882                stopRouteService(routeService, true);
883            } 
884        }
885    
886        public synchronized boolean removeRoute(String routeId) throws Exception {
887            RouteService routeService = routeServices.get(routeId);
888            if (routeService != null) {
889                if (getRouteStatus(routeId).isStopped()) {
890                    routeService.setRemovingRoutes(true);
891                    shutdownRouteService(routeService);
892                    removeRouteDefinition(routeId);
893                    routeServices.remove(routeId);
894                    // remove route from startup order as well, as it was removed
895                    Iterator<RouteStartupOrder> it = routeStartupOrder.iterator();
896                    while (it.hasNext()) {
897                        RouteStartupOrder order = it.next();
898                        if (order.getRoute().getId().equals(routeId)) {
899                            it.remove();
900                        }
901                    }
902                    return true;
903                } else {
904                    return false;
905                }
906            }
907            return false;
908        }
909    
910        public synchronized void suspendRoute(String routeId) throws Exception {
911            if (!routeSupportsSuspension(routeId)) {
912                // stop if we suspend is not supported
913                stopRoute(routeId);
914                return;
915            }
916    
917            RouteService routeService = routeServices.get(routeId);
918            if (routeService != null) {
919                List<RouteStartupOrder> routes = new ArrayList<RouteStartupOrder>(1);
920                RouteStartupOrder order = new DefaultRouteStartupOrder(1, routeService.getRoutes().iterator().next(), routeService);
921                routes.add(order);
922    
923                getShutdownStrategy().suspend(this, routes);
924                // must suspend route service as well
925                suspendRouteService(routeService);
926            }
927        }
928    
929        public synchronized void suspendRoute(String routeId, long timeout, TimeUnit timeUnit) throws Exception {
930            if (!routeSupportsSuspension(routeId)) {
931                stopRoute(routeId, timeout, timeUnit);
932                return;
933            }
934    
935            RouteService routeService = routeServices.get(routeId);
936            if (routeService != null) {
937                List<RouteStartupOrder> routes = new ArrayList<RouteStartupOrder>(1);
938                RouteStartupOrder order = new DefaultRouteStartupOrder(1, routeService.getRoutes().iterator().next(), routeService);
939                routes.add(order);
940    
941                getShutdownStrategy().suspend(this, routes, timeout, timeUnit);
942                // must suspend route service as well
943                suspendRouteService(routeService);
944            }
945        }
946    
947        public void addService(Object object) throws Exception {
948            doAddService(object, true);
949        }
950    
951        private void doAddService(Object object, boolean closeOnShutdown) throws Exception {
952            // inject CamelContext
953            if (object instanceof CamelContextAware) {
954                CamelContextAware aware = (CamelContextAware) object;
955                aware.setCamelContext(this);
956            }
957    
958            if (object instanceof Service) {
959                Service service = (Service) object;
960    
961                for (LifecycleStrategy strategy : lifecycleStrategies) {
962                    if (service instanceof Endpoint) {
963                        // use specialized endpoint add
964                        strategy.onEndpointAdd((Endpoint) service);
965                    } else {
966                        strategy.onServiceAdd(this, service, null);
967                    }
968                }
969    
970                // only add to services to close if its a singleton
971                // otherwise we could for example end up with a lot of prototype scope endpoints
972                boolean singleton = true; // assume singleton by default
973                if (service instanceof IsSingleton) {
974                    singleton = ((IsSingleton) service).isSingleton();
975                }
976                // do not add endpoints as they have their own list
977                if (singleton && !(service instanceof Endpoint)) {
978                    // only add to list of services to close if its not already there
979                    if (closeOnShutdown && !hasService(service)) {
980                        servicesToClose.add(service);
981                    }
982                }
983            }
984    
985            // and then ensure service is started (as stated in the javadoc)
986            if (object instanceof Service) {
987                startService((Service)object);
988            } else if (object instanceof Collection<?>) {
989                startServices((Collection<?>)object);
990            }
991        }
992    
993        public boolean removeService(Object object) throws Exception {
994            if (object instanceof Service) {
995                Service service = (Service) object;
996    
997                for (LifecycleStrategy strategy : lifecycleStrategies) {
998                    if (service instanceof Endpoint) {
999                        // use specialized endpoint remove
1000                        strategy.onEndpointRemove((Endpoint) service);
1001                    } else {
1002                        strategy.onServiceRemove(this, service, null);
1003                    }
1004                }
1005                return servicesToClose.remove(service);
1006            }
1007            return false;
1008        }
1009    
1010        public boolean hasService(Object object) {
1011            if (object instanceof Service) {
1012                Service service = (Service) object;
1013                return servicesToClose.contains(service);
1014            }
1015            return false;
1016        }
1017    
1018        public void addStartupListener(StartupListener listener) throws Exception {
1019            // either add to listener so we can invoke then later when CamelContext has been started
1020            // or invoke the callback right now
1021            if (isStarted()) {
1022                listener.onCamelContextStarted(this, true);
1023            } else {
1024                startupListeners.add(listener);
1025            }
1026        }
1027    
1028        public Map<String, Properties> findComponents() throws LoadPropertiesException, IOException {
1029            return CamelContextHelper.findComponents(this);
1030        }
1031    
1032        public String getComponentDocumentation(String componentName) throws IOException {
1033            String packageName = sanitizeComponentName(componentName);
1034            String path = CamelContextHelper.COMPONENT_DOCUMENTATION_PREFIX + packageName + "/" + componentName + ".html";
1035            ClassResolver resolver = getClassResolver();
1036            InputStream inputStream = resolver.loadResourceAsStream(path);
1037            log.debug("Loading component documentation for: {} using class resolver: {} -> {}", new Object[]{componentName, resolver, inputStream});
1038            if (inputStream != null) {
1039                try {
1040                    return IOHelper.loadText(inputStream);
1041                } finally {
1042                    IOHelper.close(inputStream);
1043                }
1044            }
1045            return null;
1046        }
1047    
1048        /**
1049         * Sanitizes the component name by removing dash (-) in the name, when using the component name to load
1050         * resources from the classpath.
1051         */
1052        private static String sanitizeComponentName(String componentName) {
1053            // the ftp components are in a special package
1054            if ("ftp".equals(componentName) || "ftps".equals(componentName) || "sftp".equals(componentName)) {
1055                return "file/remote";
1056            }
1057            return componentName.replaceAll("-", "");
1058        }
1059    
1060        public String createRouteStaticEndpointJson(String routeId) {
1061            List<RouteDefinition> routes = new ArrayList<RouteDefinition>();
1062            if (routeId != null) {
1063                RouteDefinition route = getRouteDefinition(routeId);
1064                if (route == null) {
1065                    throw new IllegalArgumentException("Route with id " + routeId + " does not exist");
1066                }
1067                routes.add(route);
1068            } else {
1069                routes.addAll(getRouteDefinitions());
1070            }
1071    
1072            StringBuilder buffer = new StringBuilder("{\n  \"routes\": {");
1073            boolean firstRoute = true;
1074            for (RouteDefinition route : routes) {
1075                if (!firstRoute) {
1076                    buffer.append("\n    },");
1077                } else {
1078                    firstRoute = false;
1079                }
1080    
1081                String id = route.getId();
1082                buffer.append("\n    \"" + id + "\": {");
1083                buffer.append("\n      \"inputs\": [");
1084                Set<String> inputs = RouteDefinitionHelper.gatherAllStaticEndpointUris(route, true, false);
1085                boolean first = true;
1086                for (String input : inputs) {
1087                    if (!first) {
1088                        buffer.append(",");
1089                    } else {
1090                        first = false;
1091                    }
1092                    buffer.append("\n        ");
1093                    buffer.append(StringHelper.toJson("uri", input, true));
1094                }
1095                buffer.append("\n      ]");
1096    
1097                buffer.append(",");
1098                buffer.append("\n      \"outputs\": [");
1099                Set<String> outputs = RouteDefinitionHelper.gatherAllStaticEndpointUris(route, false, true);
1100                first = true;
1101                for (String output : outputs) {
1102                    if (!first) {
1103                        buffer.append(",");
1104                    } else {
1105                        first = false;
1106                    }
1107                    buffer.append("\n        ");
1108                    buffer.append(StringHelper.toJson("uri", output, true));
1109                }
1110                buffer.append("\n      ]");
1111            }
1112            buffer.append("\n    }");
1113            buffer.append("\n  }\n}\n");
1114    
1115            return buffer.toString();
1116        }
1117    
1118        // Helper methods
1119        // -----------------------------------------------------------------------
1120    
1121        public Language resolveLanguage(String language) {
1122            Language answer;
1123            synchronized (languages) {
1124                answer = languages.get(language);
1125    
1126                // check if the language is singleton, if so return the shared instance
1127                if (answer instanceof IsSingleton) {
1128                    boolean singleton = ((IsSingleton) answer).isSingleton();
1129                    if (singleton) {
1130                        return answer;
1131                    }
1132                }
1133    
1134                // language not known or not singleton, then use resolver
1135                answer = getLanguageResolver().resolveLanguage(language, this);
1136    
1137                // inject CamelContext if aware
1138                if (answer != null) {
1139                    if (answer instanceof CamelContextAware) {
1140                        ((CamelContextAware) answer).setCamelContext(this);
1141                    }
1142                    if (answer instanceof Service) {
1143                        try {
1144                            startService((Service) answer);
1145                        } catch (Exception e) {
1146                            throw ObjectHelper.wrapRuntimeCamelException(e);
1147                        }
1148                    }
1149    
1150                    languages.put(language, answer);
1151                }
1152            }
1153    
1154            // no language resolved
1155            return answer;
1156        }
1157        
1158        public String getPropertyPrefixToken() {
1159            PropertiesComponent pc = getPropertiesComponent();
1160            
1161            if (pc != null) {
1162                return pc.getPrefixToken();
1163            } else {
1164                return null;
1165            }
1166        }
1167        
1168        public String getPropertySuffixToken() {
1169            PropertiesComponent pc = getPropertiesComponent();
1170            
1171            if (pc != null) {
1172                return pc.getSuffixToken();
1173            } else {
1174                return null;
1175            }
1176        }
1177    
1178        public String resolvePropertyPlaceholders(String text) throws Exception {
1179            // While it is more efficient to only do the lookup if we are sure we need the component,
1180            // with custom tokens, we cannot know if the URI contains a property or not without having
1181            // the component.  We also lose fail-fast behavior for the missing component with this change.
1182            PropertiesComponent pc = getPropertiesComponent();
1183    
1184            // Do not parse uris that are designated for the properties component as it will handle that itself
1185            if (text != null && !text.startsWith("properties:")) {
1186                // No component, assume default tokens.
1187                if (pc == null && text.contains(PropertiesComponent.DEFAULT_PREFIX_TOKEN)) {
1188    
1189                    // try to lookup component, as we may be initializing CamelContext itself
1190                    Component existing = lookupPropertiesComponent();
1191                    if (existing != null) {
1192                        if (existing instanceof PropertiesComponent) {
1193                            pc = (PropertiesComponent) existing;
1194                        } else {
1195                            // properties component must be expected type
1196                            throw new IllegalArgumentException("Found properties component of type: " + existing.getClass() + " instead of expected: " + PropertiesComponent.class);
1197                        }
1198                    }
1199    
1200                    if (pc != null) {
1201                        // the parser will throw exception if property key was not found
1202                        String answer = pc.parseUri(text);
1203                        log.debug("Resolved text: {} -> {}", text, answer);
1204                        return answer;
1205                    } else {
1206                        throw new IllegalArgumentException("PropertiesComponent with name properties must be defined"
1207                                + " in CamelContext to support property placeholders.");
1208                    }
1209                    
1210                // Component available, use actual tokens
1211                } else if (pc != null && text.contains(pc.getPrefixToken())) {
1212                    // the parser will throw exception if property key was not found
1213                    String answer = pc.parseUri(text);
1214                    log.debug("Resolved text: {} -> {}", text, answer);
1215                    return answer; 
1216                }
1217            }
1218    
1219            // return original text as is
1220            return text;
1221        }
1222        
1223        // Properties
1224        // -----------------------------------------------------------------------
1225    
1226        public TypeConverter getTypeConverter() {
1227            if (typeConverter == null) {
1228                synchronized (this) {
1229                    // we can synchronize on this as there is only one instance
1230                    // of the camel context (its the container)
1231                    typeConverter = createTypeConverter();
1232                    try {
1233                        // must add service eager
1234                        addService(typeConverter);
1235                    } catch (Exception e) {
1236                        throw ObjectHelper.wrapRuntimeCamelException(e);
1237                    }
1238                }
1239            }
1240            return typeConverter;
1241        }
1242    
1243        public void setTypeConverter(TypeConverter typeConverter) {
1244            this.typeConverter = typeConverter;
1245            try {
1246                // must add service eager
1247                addService(typeConverter);
1248            } catch (Exception e) {
1249                throw ObjectHelper.wrapRuntimeCamelException(e);
1250            }
1251        }
1252    
1253        public TypeConverterRegistry getTypeConverterRegistry() {
1254            if (typeConverterRegistry == null) {
1255                // init type converter as its lazy
1256                if (typeConverter == null) {
1257                    getTypeConverter();
1258                }
1259                if (typeConverter instanceof TypeConverterRegistry) {
1260                    typeConverterRegistry = (TypeConverterRegistry) typeConverter;
1261                }
1262            }
1263            return typeConverterRegistry;
1264        }
1265    
1266        public void setTypeConverterRegistry(TypeConverterRegistry typeConverterRegistry) {
1267            this.typeConverterRegistry = typeConverterRegistry;
1268        }
1269    
1270        public Injector getInjector() {
1271            if (injector == null) {
1272                injector = createInjector();
1273            }
1274            return injector;
1275        }
1276    
1277        public void setInjector(Injector injector) {
1278            this.injector = injector;
1279        }
1280    
1281        public ManagementMBeanAssembler getManagementMBeanAssembler() {
1282            return managementMBeanAssembler;
1283        }
1284    
1285        public void setManagementMBeanAssembler(ManagementMBeanAssembler managementMBeanAssembler) {
1286            this.managementMBeanAssembler = managementMBeanAssembler;
1287        }
1288    
1289        public ComponentResolver getComponentResolver() {
1290            if (componentResolver == null) {
1291                componentResolver = createComponentResolver();
1292            }
1293            return componentResolver;
1294        }
1295    
1296        public void setComponentResolver(ComponentResolver componentResolver) {
1297            this.componentResolver = componentResolver;
1298        }
1299    
1300        public LanguageResolver getLanguageResolver() {
1301            if (languageResolver == null) {
1302                languageResolver = new DefaultLanguageResolver();
1303            }
1304            return languageResolver;
1305        }
1306    
1307        public void setLanguageResolver(LanguageResolver languageResolver) {
1308            this.languageResolver = languageResolver;
1309        }
1310    
1311        public boolean isAutoCreateComponents() {
1312            return autoCreateComponents;
1313        }
1314    
1315        public void setAutoCreateComponents(boolean autoCreateComponents) {
1316            this.autoCreateComponents = autoCreateComponents;
1317        }
1318    
1319        public Registry getRegistry() {
1320            if (registry == null) {
1321                registry = createRegistry();
1322                setRegistry(registry);
1323            }
1324            return registry;
1325        }
1326    
1327        public <T> T getRegistry(Class<T> type) {
1328            Registry reg = getRegistry();
1329    
1330            // unwrap the property placeholder delegate
1331            if (reg instanceof PropertyPlaceholderDelegateRegistry) {
1332                reg = ((PropertyPlaceholderDelegateRegistry) reg).getRegistry();
1333            }
1334    
1335            if (type.isAssignableFrom(reg.getClass())) {
1336                return type.cast(reg);
1337            } else if (reg instanceof CompositeRegistry) {
1338                List<Registry> list = ((CompositeRegistry) reg).getRegistryList();
1339                for (Registry r : list) {
1340                    if (type.isAssignableFrom(r.getClass())) {
1341                        return type.cast(r);
1342                    }
1343                }
1344            }
1345            return null;
1346        }
1347    
1348        /**
1349         * Sets the registry to the given JNDI context
1350         *
1351         * @param jndiContext is the JNDI context to use as the registry
1352         * @see #setRegistry(org.apache.camel.spi.Registry)
1353         */
1354        public void setJndiContext(Context jndiContext) {
1355            setRegistry(new JndiRegistry(jndiContext));
1356        }
1357    
1358        public void setRegistry(Registry registry) {
1359            // wrap the registry so we always do property placeholder lookups
1360            if (!(registry instanceof PropertyPlaceholderDelegateRegistry)) {
1361                registry = new PropertyPlaceholderDelegateRegistry(this, registry);
1362            }
1363            this.registry = registry;
1364        }
1365    
1366        public List<LifecycleStrategy> getLifecycleStrategies() {
1367            return lifecycleStrategies;
1368        }
1369    
1370        public void setLifecycleStrategies(List<LifecycleStrategy> lifecycleStrategies) {
1371            this.lifecycleStrategies = lifecycleStrategies;
1372        }
1373    
1374        public void addLifecycleStrategy(LifecycleStrategy lifecycleStrategy) {
1375            this.lifecycleStrategies.add(lifecycleStrategy);
1376        }
1377    
1378        public synchronized List<RouteDefinition> getRouteDefinitions() {
1379            return routeDefinitions;
1380        }
1381    
1382        public synchronized RouteDefinition getRouteDefinition(String id) {
1383            for (RouteDefinition route : routeDefinitions) {
1384                if (route.getId().equals(id)) {
1385                    return route;
1386                }
1387            }
1388            return null;
1389        }
1390    
1391        public List<InterceptStrategy> getInterceptStrategies() {
1392            return interceptStrategies;
1393        }
1394    
1395        public void setInterceptStrategies(List<InterceptStrategy> interceptStrategies) {
1396            this.interceptStrategies = interceptStrategies;
1397        }
1398    
1399        public void addInterceptStrategy(InterceptStrategy interceptStrategy) {
1400            getInterceptStrategies().add(interceptStrategy);
1401    
1402            // for backwards compatible or if user add them here instead of the setXXX methods
1403    
1404            if (interceptStrategy instanceof Tracer) {
1405                setTracing(true);
1406            } else if (interceptStrategy instanceof HandleFault) {
1407                setHandleFault(true);
1408            } else if (interceptStrategy instanceof StreamCaching) {
1409                setStreamCaching(true);
1410            } else if (interceptStrategy instanceof Delayer) {
1411                setDelayer(((Delayer)interceptStrategy).getDelay());
1412            }
1413        }
1414    
1415        public void setStreamCaching(Boolean cache) {
1416            this.streamCache = cache;
1417        }
1418    
1419        public Boolean isStreamCaching() {
1420            return streamCache;
1421        }
1422    
1423        public void setTracing(Boolean tracing) {
1424            this.trace = tracing;
1425        }
1426    
1427        public Boolean isTracing() {
1428            return trace;
1429        }
1430    
1431        public Boolean isMessageHistory() {
1432            return messageHistory;
1433        }
1434    
1435        public void setMessageHistory(Boolean messageHistory) {
1436            this.messageHistory = messageHistory;
1437        }
1438    
1439        public Boolean isHandleFault() {
1440            return handleFault;
1441        }
1442    
1443        public void setHandleFault(Boolean handleFault) {
1444            this.handleFault = handleFault;
1445        }
1446    
1447        public Long getDelayer() {
1448            return delay;
1449        }
1450    
1451        public void setDelayer(Long delay) {
1452            this.delay = delay;
1453        }
1454    
1455        public ProducerTemplate createProducerTemplate() {
1456            int size = CamelContextHelper.getMaximumCachePoolSize(this);
1457            return createProducerTemplate(size);
1458        }
1459    
1460        public ProducerTemplate createProducerTemplate(int maximumCacheSize) {
1461            DefaultProducerTemplate answer = new DefaultProducerTemplate(this);
1462            answer.setMaximumCacheSize(maximumCacheSize);
1463            // start it so its ready to use
1464            try {
1465                startService(answer);
1466            } catch (Exception e) {
1467                throw ObjectHelper.wrapRuntimeCamelException(e);
1468            }
1469            return answer;
1470        }
1471    
1472        public ConsumerTemplate createConsumerTemplate() {
1473            int size = CamelContextHelper.getMaximumCachePoolSize(this);
1474            return createConsumerTemplate(size);
1475        }
1476    
1477        public ConsumerTemplate createConsumerTemplate(int maximumCacheSize) {
1478            DefaultConsumerTemplate answer = new DefaultConsumerTemplate(this);
1479            answer.setMaximumCacheSize(maximumCacheSize);
1480            // start it so its ready to use
1481            try {
1482                startService(answer);
1483            } catch (Exception e) {
1484                throw ObjectHelper.wrapRuntimeCamelException(e);
1485            }
1486            return answer;
1487        }
1488    
1489        public ErrorHandlerBuilder getErrorHandlerBuilder() {
1490            return (ErrorHandlerBuilder)errorHandlerBuilder;
1491        }
1492    
1493        public void setErrorHandlerBuilder(ErrorHandlerFactory errorHandlerBuilder) {
1494            this.errorHandlerBuilder = errorHandlerBuilder;
1495        }
1496    
1497        public ScheduledExecutorService getErrorHandlerExecutorService() {
1498            synchronized (errorHandlerExecutorServiceLock) {
1499                if (errorHandlerExecutorService == null) {
1500                    // setup default thread pool for error handler
1501                    errorHandlerExecutorService = getExecutorServiceManager().newDefaultScheduledThreadPool("ErrorHandlerRedeliveryThreadPool", "ErrorHandlerRedeliveryTask");
1502                }
1503            }
1504            return errorHandlerExecutorService;
1505        }
1506    
1507        public void setProducerServicePool(ServicePool<Endpoint, Producer> producerServicePool) {
1508            this.producerServicePool = producerServicePool;
1509        }
1510    
1511        public ServicePool<Endpoint, Producer> getProducerServicePool() {
1512            return producerServicePool;
1513        }
1514    
1515        public UnitOfWorkFactory getUnitOfWorkFactory() {
1516            return unitOfWorkFactory;
1517        }
1518    
1519        public void setUnitOfWorkFactory(UnitOfWorkFactory unitOfWorkFactory) {
1520            this.unitOfWorkFactory = unitOfWorkFactory;
1521        }
1522    
1523        public String getUptime() {
1524            // compute and log uptime
1525            if (startDate == null) {
1526                return "not started";
1527            }
1528            long delta = new Date().getTime() - startDate.getTime();
1529            return TimeUtils.printDuration(delta);
1530        }
1531    
1532        @Override
1533        protected void doSuspend() throws Exception {
1534            EventHelper.notifyCamelContextSuspending(this);
1535    
1536            log.info("Apache Camel " + getVersion() + " (CamelContext: " + getName() + ") is suspending");
1537            StopWatch watch = new StopWatch();
1538    
1539            // update list of started routes to be suspended
1540            // because we only want to suspend started routes
1541            // (so when we resume we only resume the routes which actually was suspended)
1542            for (Map.Entry<String, RouteService> entry : getRouteServices().entrySet()) {
1543                if (entry.getValue().getStatus().isStarted()) {
1544                    suspendedRouteServices.put(entry.getKey(), entry.getValue());
1545                }
1546            }
1547    
1548            // assemble list of startup ordering so routes can be shutdown accordingly
1549            List<RouteStartupOrder> orders = new ArrayList<RouteStartupOrder>();
1550            for (Map.Entry<String, RouteService> entry : suspendedRouteServices.entrySet()) {
1551                Route route = entry.getValue().getRoutes().iterator().next();
1552                Integer order = entry.getValue().getRouteDefinition().getStartupOrder();
1553                if (order == null) {
1554                    order = defaultRouteStartupOrder++;
1555                }
1556                orders.add(new DefaultRouteStartupOrder(order, route, entry.getValue()));
1557            }
1558    
1559            // suspend routes using the shutdown strategy so it can shutdown in correct order
1560            // routes which doesn't support suspension will be stopped instead
1561            getShutdownStrategy().suspend(this, orders);
1562    
1563            // mark the route services as suspended or stopped
1564            for (RouteService service : suspendedRouteServices.values()) {
1565                if (routeSupportsSuspension(service.getId())) {
1566                    service.suspend();
1567                } else {
1568                    service.stop();
1569                }
1570            }
1571    
1572            watch.stop();
1573            if (log.isInfoEnabled()) {
1574                log.info("Apache Camel " + getVersion() + " (CamelContext: " + getName() + ") is suspended in " + TimeUtils.printDuration(watch.taken()));
1575            }
1576    
1577            EventHelper.notifyCamelContextSuspended(this);
1578        }
1579    
1580        @Override
1581        protected void doResume() throws Exception {
1582            try {
1583                EventHelper.notifyCamelContextResuming(this);
1584    
1585                log.info("Apache Camel " + getVersion() + " (CamelContext: " + getName() + ") is resuming");
1586                StopWatch watch = new StopWatch();
1587    
1588                // start the suspended routes (do not check for route clashes, and indicate)
1589                doStartOrResumeRoutes(suspendedRouteServices, false, true, true, false);
1590    
1591                // mark the route services as resumed (will be marked as started) as well
1592                for (RouteService service : suspendedRouteServices.values()) {
1593                    if (routeSupportsSuspension(service.getId())) {
1594                        service.resume();
1595                    } else {
1596                        service.start();
1597                    }
1598                }
1599    
1600                watch.stop();
1601                if (log.isInfoEnabled()) {
1602                    log.info("Resumed " + suspendedRouteServices.size() + " routes");
1603                    log.info("Apache Camel " + getVersion() + " (CamelContext: " + getName() + ") resumed in " + TimeUtils.printDuration(watch.taken()));
1604                }
1605    
1606                // and clear the list as they have been resumed
1607                suspendedRouteServices.clear();
1608    
1609                EventHelper.notifyCamelContextResumed(this);
1610            } catch (Exception e) {
1611                EventHelper.notifyCamelContextResumeFailed(this, e);
1612                throw e;
1613            }
1614        }
1615    
1616        public void start() throws Exception {
1617            startDate = new Date();
1618            stopWatch.restart();
1619            log.info("Apache Camel " + getVersion() + " (CamelContext: " + getName() + ") is starting");
1620    
1621            doNotStartRoutesOnFirstStart = !firstStartDone && !isAutoStartup();
1622    
1623            // if the context was configured with auto startup = false, and we are already started,
1624            // then we may need to start the routes on the 2nd start call
1625            if (firstStartDone && !isAutoStartup() && isStarted()) {
1626                // invoke this logic to warm up the routes and if possible also start the routes
1627                doStartOrResumeRoutes(routeServices, true, true, false, true);
1628            }
1629    
1630            // super will invoke doStart which will prepare internal services and start routes etc.
1631            try {
1632                firstStartDone = true;
1633                super.start();
1634            } catch (VetoCamelContextStartException e) {
1635                if (e.isRethrowException()) {
1636                    throw e;
1637                } else {
1638                    log.info("CamelContext ({}) vetoed to not start due {}", getName(), e.getMessage());
1639                    // swallow exception and change state of this camel context to stopped
1640                    stop();
1641                    return;
1642                }
1643            }
1644    
1645            stopWatch.stop();
1646            if (log.isInfoEnabled()) {
1647                // count how many routes are actually started
1648                int started = 0;
1649                for (Route route : getRoutes()) {
1650                    if (getRouteStatus(route.getId()).isStarted()) {
1651                        started++;
1652                    }
1653                }
1654                log.info("Total " + getRoutes().size() + " routes, of which " + started + " is started.");
1655                log.info("Apache Camel " + getVersion() + " (CamelContext: " + getName() + ") started in " + TimeUtils.printDuration(stopWatch.taken()));
1656            }
1657            EventHelper.notifyCamelContextStarted(this);
1658        }
1659    
1660        // Implementation methods
1661        // -----------------------------------------------------------------------
1662    
1663        protected synchronized void doStart() throws Exception {
1664            try {
1665                doStartCamel();
1666            } catch (Exception e) {
1667                // fire event that we failed to start
1668                EventHelper.notifyCamelContextStartupFailed(this, e);
1669                // rethrow cause
1670                throw e;
1671            }
1672        }
1673    
1674        private void doStartCamel() throws Exception {
1675            if (applicationContextClassLoader == null) {
1676                // use the classloader that loaded this class
1677                setApplicationContextClassLoader(this.getClass().getClassLoader());
1678            }
1679    
1680            if (log.isDebugEnabled()) {
1681                log.debug("Using ClassResolver={}, PackageScanClassResolver={}, ApplicationContextClassLoader={}",
1682                        new Object[]{getClassResolver(), getPackageScanClassResolver(), getApplicationContextClassLoader()});
1683            }
1684    
1685            if (isStreamCaching()) {
1686                log.info("StreamCaching is enabled on CamelContext: {}", getName());
1687            }
1688    
1689            if (isTracing()) {
1690                // tracing is added in the DefaultChannel so we can enable it on the fly
1691                log.info("Tracing is enabled on CamelContext: {}", getName());
1692            }
1693    
1694            if (isUseMDCLogging()) {
1695                // log if MDC has been enabled
1696                log.info("MDC logging is enabled on CamelContext: {}", getName());
1697            }
1698    
1699            if (isHandleFault()) {
1700                // only add a new handle fault if not already configured
1701                if (HandleFault.getHandleFault(this) == null) {
1702                    log.info("HandleFault is enabled on CamelContext: {}", getName());
1703                    addInterceptStrategy(new HandleFault());
1704                }
1705            }
1706    
1707            if (getDelayer() != null && getDelayer() > 0) {
1708                log.info("Delayer is enabled with: {} ms. on CamelContext: {}", getDelayer(), getName());
1709            }
1710            
1711            // register debugger
1712            if (getDebugger() != null) {
1713                log.info("Debugger: {} is enabled on CamelContext: {}", getDebugger(), getName());
1714                // register this camel context on the debugger
1715                getDebugger().setCamelContext(this);
1716                startService(getDebugger());
1717                addInterceptStrategy(new Debug(getDebugger()));
1718            }
1719    
1720            // start management strategy before lifecycles are started
1721            ManagementStrategy managementStrategy = getManagementStrategy();
1722            // inject CamelContext if aware
1723            if (managementStrategy instanceof CamelContextAware) {
1724                ((CamelContextAware) managementStrategy).setCamelContext(this);
1725            }
1726            ServiceHelper.startService(managementStrategy);
1727    
1728            // start lifecycle strategies
1729            ServiceHelper.startServices(lifecycleStrategies);
1730            Iterator<LifecycleStrategy> it = lifecycleStrategies.iterator();
1731            while (it.hasNext()) {
1732                LifecycleStrategy strategy = it.next();
1733                try {
1734                    strategy.onContextStart(this);
1735                } catch (VetoCamelContextStartException e) {
1736                    // okay we should not start Camel since it was vetoed
1737                    log.warn("Lifecycle strategy vetoed starting CamelContext ({}) due {}", getName(), e.getMessage());
1738                    throw e;
1739                } catch (Exception e) {
1740                    log.warn("Lifecycle strategy " + strategy + " failed starting CamelContext ({}) due {}", getName(), e.getMessage());
1741                    throw e;
1742                }
1743            }
1744    
1745            // start notifiers as services
1746            for (EventNotifier notifier : getManagementStrategy().getEventNotifiers()) {
1747                if (notifier instanceof Service) {
1748                    Service service = (Service) notifier;
1749                    for (LifecycleStrategy strategy : lifecycleStrategies) {
1750                        strategy.onServiceAdd(this, service, null);
1751                    }
1752                }
1753                if (notifier instanceof Service) {
1754                    startService((Service)notifier);
1755                }
1756            }
1757    
1758            // must let some bootstrap service be started before we can notify the starting event
1759            EventHelper.notifyCamelContextStarting(this);
1760    
1761            forceLazyInitialization();
1762    
1763            // re-create endpoint registry as the cache size limit may be set after the constructor of this instance was called.
1764            // and we needed to create endpoints up-front as it may be accessed before this context is started
1765            endpoints = new EndpointRegistry(this, endpoints);
1766            addService(endpoints);
1767            // special for executorServiceManager as want to stop it manually
1768            doAddService(executorServiceManager, false);
1769            addService(producerServicePool);
1770            addService(inflightRepository);
1771            addService(shutdownStrategy);
1772            addService(packageScanClassResolver);
1773    
1774            // eager lookup any configured properties component to avoid subsequent lookup attempts which may impact performance
1775            // due we use properties component for property placeholder resolution at runtime
1776            Component existing = lookupPropertiesComponent();
1777            if (existing != null) {
1778                // store reference to the existing properties component
1779                if (existing instanceof PropertiesComponent) {
1780                    propertiesComponent = (PropertiesComponent) existing;
1781                } else {
1782                    // properties component must be expected type
1783                    throw new IllegalArgumentException("Found properties component of type: " + existing.getClass() + " instead of expected: " + PropertiesComponent.class);
1784                }
1785            }
1786    
1787            // start components
1788            startServices(components.values());
1789    
1790            // start the route definitions before the routes is started
1791            startRouteDefinitions(routeDefinitions);
1792    
1793            // is there any stream caching enabled then log an info about this and its limit of spooling to disk, so people is aware of this
1794            boolean streamCachingInUse = isStreamCaching();
1795            if (!streamCachingInUse) {
1796                for (RouteDefinition route : routeDefinitions) {
1797                    Boolean routeCache = CamelContextHelper.parseBoolean(this, route.getStreamCache());
1798                    if (routeCache != null && routeCache) {
1799                        streamCachingInUse = true;
1800                        break;
1801                    }
1802                }
1803            }
1804    
1805            if (isAllowUseOriginalMessage()) {
1806                log.info("AllowUseOriginalMessage is enabled. If access to the original message is not needed,"
1807                        + " then its recommended to turn this option off as it may improve performance.");
1808            }
1809    
1810            if (streamCachingInUse) {
1811                // stream caching is in use so enable the strategy
1812                getStreamCachingStrategy().setEnabled(true);
1813                addService(getStreamCachingStrategy());
1814            } else {
1815                // log if stream caching is not in use as this can help people to enable it if they use streams
1816                log.info("StreamCaching is not in use. If using streams then its recommended to enable stream caching."
1817                        + " See more details at http://camel.apache.org/stream-caching.html");
1818            }
1819    
1820            // start routes
1821            if (doNotStartRoutesOnFirstStart) {
1822                log.debug("Skip starting of routes as CamelContext has been configured with autoStartup=false");
1823            }
1824    
1825            // invoke this logic to warmup the routes and if possible also start the routes
1826            doStartOrResumeRoutes(routeServices, true, !doNotStartRoutesOnFirstStart, false, true);
1827    
1828            // starting will continue in the start method
1829        }
1830    
1831        protected synchronized void doStop() throws Exception {
1832            stopWatch.restart();
1833            log.info("Apache Camel " + getVersion() + " (CamelContext: " + getName() + ") is shutting down");
1834            EventHelper.notifyCamelContextStopping(this);
1835    
1836            // stop route inputs in the same order as they was started so we stop the very first inputs first
1837            try {
1838                // force shutting down routes as they may otherwise cause shutdown to hang
1839                shutdownStrategy.shutdownForced(this, getRouteStartupOrder());
1840            } catch (Throwable e) {
1841                log.warn("Error occurred while shutting down routes. This exception will be ignored.", e);
1842            }
1843            getRouteStartupOrder().clear();
1844    
1845            shutdownServices(routeServices.values());
1846            // do not clear route services or startup listeners as we can start Camel again and get the route back as before
1847    
1848            // but clear any suspend routes
1849            suspendedRouteServices.clear();
1850    
1851            // the stop order is important
1852    
1853            // shutdown default error handler thread pool
1854            if (errorHandlerExecutorService != null) {
1855                // force shutting down the thread pool
1856                getExecutorServiceManager().shutdownNow(errorHandlerExecutorService);
1857                errorHandlerExecutorService = null;
1858            }
1859    
1860            // shutdown debugger
1861            ServiceHelper.stopAndShutdownService(getDebugger());
1862    
1863            shutdownServices(endpoints.values());
1864            endpoints.clear();
1865    
1866            shutdownServices(components.values());
1867            components.clear();
1868    
1869            shutdownServices(languages.values());
1870            languages.clear();
1871    
1872            try {
1873                for (LifecycleStrategy strategy : lifecycleStrategies) {
1874                    strategy.onContextStop(this);
1875                }
1876            } catch (Throwable e) {
1877                log.warn("Error occurred while stopping lifecycle strategies. This exception will be ignored.", e);
1878            }
1879    
1880            // shutdown services as late as possible
1881            shutdownServices(servicesToClose);
1882            servicesToClose.clear();
1883    
1884            // must notify that we are stopped before stopping the management strategy
1885            EventHelper.notifyCamelContextStopped(this);
1886    
1887            // stop the notifier service
1888            for (EventNotifier notifier : getManagementStrategy().getEventNotifiers()) {
1889                shutdownServices(notifier);
1890            }
1891    
1892            // shutdown executor service and management as the last one
1893            shutdownServices(executorServiceManager);
1894            shutdownServices(managementStrategy);
1895            shutdownServices(managementMBeanAssembler);
1896            shutdownServices(lifecycleStrategies);
1897            // do not clear lifecycleStrategies as we can start Camel again and get the route back as before
1898    
1899            // stop the lazy created so they can be re-created on restart
1900            forceStopLazyInitialization();
1901    
1902            // stop to clear introspection cache
1903            IntrospectionSupport.stop();
1904    
1905            stopWatch.stop();
1906            if (log.isInfoEnabled()) {
1907                log.info("Apache Camel " + getVersion() + " (CamelContext: " + getName() + ") uptime {}", getUptime());
1908                log.info("Apache Camel " + getVersion() + " (CamelContext: " + getName() + ") is shutdown in " + TimeUtils.printDuration(stopWatch.taken()));
1909            }
1910    
1911            // and clear start date
1912            startDate = null;
1913        }
1914    
1915        /**
1916         * Starts or resumes the routes
1917         *
1918         * @param routeServices  the routes to start (will only start a route if its not already started)
1919         * @param checkClash     whether to check for startup ordering clash
1920         * @param startConsumer  whether the route consumer should be started. Can be used to warmup the route without starting the consumer.
1921         * @param resumeConsumer whether the route consumer should be resumed.
1922         * @param addingRoutes   whether we are adding new routes
1923         * @throws Exception is thrown if error starting routes
1924         */
1925        protected void doStartOrResumeRoutes(Map<String, RouteService> routeServices, boolean checkClash,
1926                                             boolean startConsumer, boolean resumeConsumer, boolean addingRoutes) throws Exception {
1927            // filter out already started routes
1928            Map<String, RouteService> filtered = new LinkedHashMap<String, RouteService>();
1929            for (Map.Entry<String, RouteService> entry : routeServices.entrySet()) {
1930                boolean startable = false;
1931    
1932                Consumer consumer = entry.getValue().getRoutes().iterator().next().getConsumer();
1933                if (consumer instanceof SuspendableService) {
1934                    // consumer could be suspended, which is not reflected in the RouteService status
1935                    startable = ((SuspendableService) consumer).isSuspended();
1936                }
1937    
1938                if (!startable && consumer instanceof StatefulService) {
1939                    // consumer could be stopped, which is not reflected in the RouteService status
1940                    startable = ((StatefulService) consumer).getStatus().isStartable();
1941                } else if (!startable) {
1942                    // no consumer so use state from route service
1943                    startable = entry.getValue().getStatus().isStartable();
1944                }
1945    
1946                if (startable) {
1947                    filtered.put(entry.getKey(), entry.getValue());
1948                }
1949            }
1950    
1951            if (!filtered.isEmpty()) {
1952                // the context is now considered started (i.e. isStarted() == true))
1953                // starting routes is done after, not during context startup
1954                safelyStartRouteServices(checkClash, startConsumer, resumeConsumer, addingRoutes, filtered.values());
1955            }
1956    
1957            // now notify any startup aware listeners as all the routes etc has been started,
1958            // allowing the listeners to do custom work after routes has been started
1959            for (StartupListener startup : startupListeners) {
1960                startup.onCamelContextStarted(this, isStarted());
1961            }
1962        }
1963    
1964        protected boolean routeSupportsSuspension(String routeId) {
1965            RouteService routeService = routeServices.get(routeId);
1966            if (routeService != null) {
1967                return routeService.getRoutes().iterator().next().supportsSuspension();
1968            }
1969            return false;
1970        }
1971    
1972        private void shutdownServices(Object service) {
1973            // do not rethrow exception as we want to keep shutting down in case of problems
1974    
1975            // allow us to do custom work before delegating to service helper
1976            try {
1977                if (service instanceof Service) {
1978                    ServiceHelper.stopAndShutdownService(service);
1979                } else if (service instanceof Collection) {
1980                    ServiceHelper.stopAndShutdownServices((Collection<?>)service);
1981                }
1982            } catch (Throwable e) {
1983                log.warn("Error occurred while shutting down service: " + service + ". This exception will be ignored.", e);
1984                // fire event
1985                EventHelper.notifyServiceStopFailure(this, service, e);
1986            }
1987        }
1988    
1989        private void shutdownServices(Collection<?> services) {
1990            // reverse stopping by default
1991            shutdownServices(services, true);
1992        }
1993    
1994        private void shutdownServices(Collection<?> services, boolean reverse) {
1995            Collection<?> list = services;
1996            if (reverse) {
1997                List<Object> reverseList = new ArrayList<Object>(services);
1998                Collections.reverse(reverseList);
1999                list = reverseList;
2000            }
2001    
2002            for (Object service : list) {
2003                shutdownServices(service);
2004            }
2005        }
2006    
2007        private void startService(Service service) throws Exception {
2008            // and register startup aware so they can be notified when
2009            // camel context has been started
2010            if (service instanceof StartupListener) {
2011                StartupListener listener = (StartupListener) service;
2012                addStartupListener(listener);
2013            }
2014    
2015            service.start();
2016        }
2017        
2018        private void startServices(Collection<?> services) throws Exception {
2019            for (Object element : services) {
2020                if (element instanceof Service) {
2021                    startService((Service)element);
2022                }
2023            }
2024        }
2025    
2026        private void stopServices(Object service) throws Exception {
2027            // allow us to do custom work before delegating to service helper
2028            try {
2029                ServiceHelper.stopService(service);
2030            } catch (Exception e) {
2031                // fire event
2032                EventHelper.notifyServiceStopFailure(this, service, e);
2033                // rethrow to signal error with stopping
2034                throw e;
2035            }
2036        }
2037    
2038        protected void startRouteDefinitions(Collection<RouteDefinition> list) throws Exception {
2039            if (list != null) {
2040                for (RouteDefinition route : list) {
2041                    startRoute(route);
2042                }
2043            }
2044        }
2045    
2046        /**
2047         * Starts the given route service
2048         */
2049        protected synchronized void startRouteService(RouteService routeService, boolean addingRoutes) throws Exception {
2050            // we may already be starting routes so remember this, so we can unset accordingly in finally block
2051            boolean alreadyStartingRoutes = isStartingRoutes();
2052            if (!alreadyStartingRoutes) {
2053                isStartingRoutes.set(true);
2054            }
2055    
2056            try {
2057                // the route service could have been suspended, and if so then resume it instead
2058                if (routeService.getStatus().isSuspended()) {
2059                    resumeRouteService(routeService);
2060                } else {
2061                    // start the route service
2062                    routeServices.put(routeService.getId(), routeService);
2063                    if (shouldStartRoutes()) {
2064                        // this method will log the routes being started
2065                        safelyStartRouteServices(true, true, true, false, addingRoutes, routeService);
2066                        // start route services if it was configured to auto startup and we are not adding routes
2067                        boolean autoStartup = routeService.getRouteDefinition().isAutoStartup(this);
2068                        if (!addingRoutes || autoStartup) {
2069                            // start the route since auto start is enabled or we are starting a route (not adding new routes)
2070                            routeService.start();
2071                        }
2072                    }
2073                }
2074            } finally {
2075                if (!alreadyStartingRoutes) {
2076                    isStartingRoutes.remove();
2077                }
2078            }
2079        }
2080    
2081        /**
2082         * Resumes the given route service
2083         */
2084        protected synchronized void resumeRouteService(RouteService routeService) throws Exception {
2085            // the route service could have been stopped, and if so then start it instead
2086            if (!routeService.getStatus().isSuspended()) {
2087                startRouteService(routeService, false);
2088            } else {
2089                // resume the route service
2090                if (shouldStartRoutes()) {
2091                    // this method will log the routes being started
2092                    safelyStartRouteServices(true, false, true, true, false, routeService);
2093                    // must resume route service as well
2094                    routeService.resume();
2095                }
2096            }
2097        }
2098    
2099        protected synchronized void stopRouteService(RouteService routeService, boolean removingRoutes) throws Exception {
2100            routeService.setRemovingRoutes(removingRoutes);
2101            stopRouteService(routeService);
2102        }
2103        
2104        protected void logRouteState(Route route, String state) {
2105            if (log.isInfoEnabled()) {
2106                if (route.getConsumer() != null) {
2107                    log.info("Route: {} is {}, was consuming from: {}", new Object[]{route.getId(), state, route.getConsumer().getEndpoint()});
2108                } else {
2109                    log.info("Route: {} is {}.", route.getId(), state);
2110                }
2111            }
2112        }
2113        
2114        protected synchronized void stopRouteService(RouteService routeService) throws Exception {
2115            routeService.stop();
2116            for (Route route : routeService.getRoutes()) {
2117                logRouteState(route, "stopped");
2118            }
2119        }
2120    
2121        protected synchronized void shutdownRouteService(RouteService routeService) throws Exception {
2122            routeService.shutdown();
2123            for (Route route : routeService.getRoutes()) {
2124                logRouteState(route, "shutdown and removed");
2125            }
2126        }
2127    
2128        protected synchronized void suspendRouteService(RouteService routeService) throws Exception {
2129            routeService.setRemovingRoutes(false);
2130            routeService.suspend();
2131            for (Route route : routeService.getRoutes()) {
2132                logRouteState(route, "suspended");
2133            }
2134        }
2135    
2136        /**
2137         * Starts the routes services in a proper manner which ensures the routes will be started in correct order,
2138         * check for clash and that the routes will also be shutdown in correct order as well.
2139         * <p/>
2140         * This method <b>must</b> be used to start routes in a safe manner.
2141         *
2142         * @param checkClash     whether to check for startup order clash
2143         * @param startConsumer  whether the route consumer should be started. Can be used to warmup the route without starting the consumer.
2144         * @param resumeConsumer whether the route consumer should be resumed.
2145         * @param addingRoutes   whether we are adding new routes
2146         * @param routeServices  the routes
2147         * @throws Exception is thrown if error starting the routes
2148         */
2149        protected synchronized void safelyStartRouteServices(boolean checkClash, boolean startConsumer, boolean resumeConsumer,
2150                                                             boolean addingRoutes, Collection<RouteService> routeServices) throws Exception {
2151            // list of inputs to start when all the routes have been prepared for starting
2152            // we use a tree map so the routes will be ordered according to startup order defined on the route
2153            Map<Integer, DefaultRouteStartupOrder> inputs = new TreeMap<Integer, DefaultRouteStartupOrder>();
2154    
2155            // figure out the order in which the routes should be started
2156            for (RouteService routeService : routeServices) {
2157                DefaultRouteStartupOrder order = doPrepareRouteToBeStarted(routeService);
2158                // check for clash before we add it as input
2159                if (checkClash) {
2160                    doCheckStartupOrderClash(order, inputs);
2161                }
2162                inputs.put(order.getStartupOrder(), order);
2163            }
2164    
2165            // warm up routes before we start them
2166            doWarmUpRoutes(inputs, startConsumer);
2167    
2168            if (startConsumer) {
2169                if (resumeConsumer) {
2170                    // and now resume the routes
2171                    doResumeRouteConsumers(inputs, addingRoutes);
2172                } else {
2173                    // and now start the routes
2174                    // and check for clash with multiple consumers of the same endpoints which is not allowed
2175                    doStartRouteConsumers(inputs, addingRoutes);
2176                }
2177            }
2178    
2179            // inputs no longer needed
2180            inputs.clear();
2181        }
2182    
2183        /**
2184         * @see #safelyStartRouteServices(boolean,boolean,boolean,boolean,java.util.Collection)
2185         */
2186        protected synchronized void safelyStartRouteServices(boolean forceAutoStart, boolean checkClash, boolean startConsumer,
2187                                                             boolean resumeConsumer, boolean addingRoutes, RouteService... routeServices) throws Exception {
2188            safelyStartRouteServices(checkClash, startConsumer, resumeConsumer, addingRoutes, Arrays.asList(routeServices));
2189        }
2190    
2191        private DefaultRouteStartupOrder doPrepareRouteToBeStarted(RouteService routeService) {
2192            // add the inputs from this route service to the list to start afterwards
2193            // should be ordered according to the startup number
2194            Integer startupOrder = routeService.getRouteDefinition().getStartupOrder();
2195            if (startupOrder == null) {
2196                // auto assign a default startup order
2197                startupOrder = defaultRouteStartupOrder++;
2198            }
2199    
2200            // create holder object that contains information about this route to be started
2201            Route route = routeService.getRoutes().iterator().next();
2202            return new DefaultRouteStartupOrder(startupOrder, route, routeService);
2203        }
2204    
2205        private boolean doCheckStartupOrderClash(DefaultRouteStartupOrder answer, Map<Integer, DefaultRouteStartupOrder> inputs) throws FailedToStartRouteException {
2206            // check for clash by startupOrder id
2207            DefaultRouteStartupOrder other = inputs.get(answer.getStartupOrder());
2208            if (other != null && answer != other) {
2209                String otherId = other.getRoute().getId();
2210                throw new FailedToStartRouteException(answer.getRoute().getId(), "startupOrder clash. Route " + otherId + " already has startupOrder "
2211                    + answer.getStartupOrder() + " configured which this route have as well. Please correct startupOrder to be unique among all your routes.");
2212            }
2213            // check in existing already started as well
2214            for (RouteStartupOrder order : routeStartupOrder) {
2215                String otherId = order.getRoute().getId();
2216                if (answer.getRoute().getId().equals(otherId)) {
2217                    // its the same route id so skip clash check as its the same route (can happen when using suspend/resume)
2218                } else if (answer.getStartupOrder() == order.getStartupOrder()) {
2219                    throw new FailedToStartRouteException(answer.getRoute().getId(), "startupOrder clash. Route " + otherId + " already has startupOrder "
2220                        + answer.getStartupOrder() + " configured which this route have as well. Please correct startupOrder to be unique among all your routes.");
2221                }
2222            }
2223            return true;
2224        }
2225    
2226        private void doWarmUpRoutes(Map<Integer, DefaultRouteStartupOrder> inputs, boolean autoStartup) throws Exception {
2227            // now prepare the routes by starting its services before we start the input
2228            for (Map.Entry<Integer, DefaultRouteStartupOrder> entry : inputs.entrySet()) {
2229                // defer starting inputs till later as we want to prepare the routes by starting
2230                // all their processors and child services etc.
2231                // then later we open the floods to Camel by starting the inputs
2232                // what this does is to ensure Camel is more robust on starting routes as all routes
2233                // will then be prepared in time before we start inputs which will consume messages to be routed
2234                RouteService routeService = entry.getValue().getRouteService();
2235                log.debug("Warming up route id: {} having autoStartup={}", routeService.getId(), autoStartup);
2236                routeService.warmUp();
2237            }
2238        }
2239    
2240        private void doResumeRouteConsumers(Map<Integer, DefaultRouteStartupOrder> inputs, boolean addingRoutes) throws Exception {
2241            doStartOrResumeRouteConsumers(inputs, true, addingRoutes);
2242        }
2243    
2244        private void doStartRouteConsumers(Map<Integer, DefaultRouteStartupOrder> inputs, boolean addingRoutes) throws Exception {
2245            doStartOrResumeRouteConsumers(inputs, false, addingRoutes);
2246        }
2247    
2248        private void doStartOrResumeRouteConsumers(Map<Integer, DefaultRouteStartupOrder> inputs, boolean resumeOnly, boolean addingRoute) throws Exception {
2249            List<Endpoint> routeInputs = new ArrayList<Endpoint>();
2250    
2251            for (Map.Entry<Integer, DefaultRouteStartupOrder> entry : inputs.entrySet()) {
2252                Integer order = entry.getKey();
2253                Route route = entry.getValue().getRoute();
2254                RouteService routeService = entry.getValue().getRouteService();
2255    
2256                // if we are starting camel, then skip routes which are configured to not be auto started
2257                boolean autoStartup = routeService.getRouteDefinition().isAutoStartup(this);
2258                if (addingRoute && !autoStartup) {
2259                    log.info("Skipping starting of route " + routeService.getId() + " as its configured with autoStartup=false");
2260                    continue;
2261                }
2262    
2263                // start the service
2264                for (Consumer consumer : routeService.getInputs().values()) {
2265                    Endpoint endpoint = consumer.getEndpoint();
2266    
2267                    // check multiple consumer violation, with the other routes to be started
2268                    if (!doCheckMultipleConsumerSupportClash(endpoint, routeInputs)) {
2269                        throw new FailedToStartRouteException(routeService.getId(),
2270                            "Multiple consumers for the same endpoint is not allowed: " + endpoint);
2271                    }
2272                    
2273                    // check for multiple consumer violations with existing routes which
2274                    // have already been started, or is currently starting
2275                    List<Endpoint> existingEndpoints = new ArrayList<Endpoint>();
2276                    for (Route existingRoute : getRoutes()) {
2277                        if (route.getId().equals(existingRoute.getId())) {
2278                            // skip ourselves
2279                            continue;
2280                        }
2281                        Endpoint existing = existingRoute.getEndpoint();
2282                        ServiceStatus status = getRouteStatus(existingRoute.getId());
2283                        if (status != null && (status.isStarted() || status.isStarting())) {
2284                            existingEndpoints.add(existing);
2285                        }
2286                    }
2287                    if (!doCheckMultipleConsumerSupportClash(endpoint, existingEndpoints)) {
2288                        throw new FailedToStartRouteException(routeService.getId(),
2289                                "Multiple consumers for the same endpoint is not allowed: " + endpoint);
2290                    }
2291    
2292                    // start the consumer on the route
2293                    log.debug("Route: {} >>> {}", route.getId(), route);
2294                    if (resumeOnly) {
2295                        log.debug("Resuming consumer (order: {}) on route: {}", order, route.getId());
2296                    } else {
2297                        log.debug("Starting consumer (order: {}) on route: {}", order, route.getId());
2298                    }
2299    
2300                    if (resumeOnly && route.supportsSuspension()) {
2301                        // if we are resuming and the route can be resumed
2302                        ServiceHelper.resumeService(consumer);
2303                        log.info("Route: " + route.getId() + " resumed and consuming from: " + endpoint);
2304                    } else {
2305                        // when starting we should invoke the lifecycle strategies
2306                        for (LifecycleStrategy strategy : lifecycleStrategies) {
2307                            strategy.onServiceAdd(this, consumer, route);
2308                        }
2309                        startService(consumer);
2310                        log.info("Route: " + route.getId() + " started and consuming from: " + endpoint);
2311                    }
2312    
2313                    routeInputs.add(endpoint);
2314    
2315                    // add to the order which they was started, so we know how to stop them in reverse order
2316                    // but only add if we haven't already registered it before (we dont want to double add when restarting)
2317                    boolean found = false;
2318                    for (RouteStartupOrder other : routeStartupOrder) {
2319                        if (other.getRoute().getId().equals(route.getId())) {
2320                            found = true;
2321                            break;
2322                        }
2323                    }
2324                    if (!found) {
2325                        routeStartupOrder.add(entry.getValue());
2326                    }
2327                }
2328    
2329                if (resumeOnly) {
2330                    routeService.resume();
2331                } else {
2332                    // and start the route service (no need to start children as they are already warmed up)
2333                    routeService.start(false);
2334                }
2335            }
2336        }
2337    
2338        private boolean doCheckMultipleConsumerSupportClash(Endpoint endpoint, List<Endpoint> routeInputs) {
2339            // is multiple consumers supported
2340            boolean multipleConsumersSupported = false;
2341            if (endpoint instanceof MultipleConsumersSupport) {
2342                multipleConsumersSupported = ((MultipleConsumersSupport) endpoint).isMultipleConsumersSupported();
2343            }
2344    
2345            if (multipleConsumersSupported) {
2346                // multiple consumer allowed, so return true
2347                return true;
2348            }
2349    
2350            // check in progress list
2351            if (routeInputs.contains(endpoint)) {
2352                return false;
2353            }
2354    
2355            return true;
2356        }
2357    
2358        /**
2359         * Force some lazy initialization to occur upfront before we start any
2360         * components and create routes
2361         */
2362        protected void forceLazyInitialization() {
2363            getRegistry();
2364            getInjector();
2365            getLanguageResolver();
2366            getTypeConverterRegistry();
2367            getTypeConverter();
2368    
2369            if (isTypeConverterStatisticsEnabled() != null) {
2370                getTypeConverterRegistry().getStatistics().setStatisticsEnabled(isTypeConverterStatisticsEnabled());
2371            }
2372        }
2373    
2374        /**
2375         * Force clear lazy initialization so they can be re-created on restart
2376         */
2377        protected void forceStopLazyInitialization() {
2378            injector = null;
2379            languageResolver = null;
2380            typeConverterRegistry = null;
2381            typeConverter = null;
2382        }
2383    
2384        /**
2385         * Lazily create a default implementation
2386         */
2387        protected TypeConverter createTypeConverter() {
2388            BaseTypeConverterRegistry answer;
2389            if (isLazyLoadTypeConverters()) {
2390                answer = new LazyLoadingTypeConverter(packageScanClassResolver, getInjector(), getDefaultFactoryFinder());
2391            } else {
2392                answer = new DefaultTypeConverter(packageScanClassResolver, getInjector(), getDefaultFactoryFinder());
2393            }
2394            setTypeConverterRegistry(answer);
2395            return answer;
2396        }
2397    
2398        /**
2399         * Lazily create a default implementation
2400         */
2401        protected Injector createInjector() {
2402            FactoryFinder finder = getDefaultFactoryFinder();
2403            try {
2404                return (Injector) finder.newInstance("Injector");
2405            } catch (NoFactoryAvailableException e) {
2406                // lets use the default injector
2407                return new DefaultInjector(this);
2408            }
2409        }
2410    
2411        /**
2412         * Lazily create a default implementation
2413         */
2414        protected ManagementMBeanAssembler createManagementMBeanAssembler() {
2415            return new DefaultManagementMBeanAssembler(this);
2416        }
2417    
2418        /**
2419         * Lazily create a default implementation
2420         */
2421        protected ComponentResolver createComponentResolver() {
2422            return new DefaultComponentResolver();
2423        }
2424    
2425        /**
2426         * Lazily create a default implementation
2427         */
2428        protected Registry createRegistry() {
2429            JndiRegistry jndi = new JndiRegistry();
2430            try {
2431                // getContext() will force setting up JNDI
2432                jndi.getContext();
2433                return jndi;
2434            } catch (Throwable e) {
2435                log.debug("Cannot create javax.naming.InitialContext due " + e.getMessage() + ". Will fallback and use SimpleRegistry instead. This exception is ignored.", e);
2436                return new SimpleRegistry();
2437            }
2438        }
2439    
2440        /**
2441         * A pluggable strategy to allow an endpoint to be created without requiring
2442         * a component to be its factory, such as for looking up the URI inside some
2443         * {@link Registry}
2444         *
2445         * @param uri the uri for the endpoint to be created
2446         * @return the newly created endpoint or null if it could not be resolved
2447         */
2448        protected Endpoint createEndpoint(String uri) {
2449            Object value = getRegistry().lookupByName(uri);
2450            if (value instanceof Endpoint) {
2451                return (Endpoint) value;
2452            } else if (value instanceof Processor) {
2453                return new ProcessorEndpoint(uri, this, (Processor) value);
2454            } else if (value != null) {
2455                return convertBeanToEndpoint(uri, value);
2456            }
2457            return null;
2458        }
2459    
2460        /**
2461         * Strategy method for attempting to convert the bean from a {@link Registry} to an endpoint using
2462         * some kind of transformation or wrapper
2463         *
2464         * @param uri  the uri for the endpoint (and name in the registry)
2465         * @param bean the bean to be converted to an endpoint, which will be not null
2466         * @return a new endpoint
2467         */
2468        protected Endpoint convertBeanToEndpoint(String uri, Object bean) {
2469            throw new IllegalArgumentException("uri: " + uri + " bean: " + bean
2470                    + " could not be converted to an Endpoint");
2471        }
2472    
2473        /**
2474         * Should we start newly added routes?
2475         */
2476        protected boolean shouldStartRoutes() {
2477            return isStarted() && !isStarting();
2478        }
2479        
2480        /**
2481         * Gets the properties component in use.
2482         * Returns {@code null} if no properties component is in use.
2483         */
2484        protected PropertiesComponent getPropertiesComponent() {
2485            return propertiesComponent;
2486        }
2487    
2488        public void setDataFormats(Map<String, DataFormatDefinition> dataFormats) {
2489            this.dataFormats = dataFormats;
2490        }
2491    
2492        public Map<String, DataFormatDefinition> getDataFormats() {
2493            return dataFormats;
2494        }
2495    
2496        public Map<String, String> getProperties() {
2497            return properties;
2498        }
2499    
2500        public void setProperties(Map<String, String> properties) {
2501            this.properties = properties;
2502        }
2503    
2504        public FactoryFinder getDefaultFactoryFinder() {
2505            if (defaultFactoryFinder == null) {
2506                defaultFactoryFinder = factoryFinderResolver.resolveDefaultFactoryFinder(getClassResolver());
2507            }
2508            return defaultFactoryFinder;
2509        }
2510    
2511        public void setFactoryFinderResolver(FactoryFinderResolver resolver) {
2512            this.factoryFinderResolver = resolver;
2513        }
2514    
2515        public FactoryFinder getFactoryFinder(String path) throws NoFactoryAvailableException {
2516            synchronized (factories) {
2517                FactoryFinder answer = factories.get(path);
2518                if (answer == null) {
2519                    answer = factoryFinderResolver.resolveFactoryFinder(getClassResolver(), path);
2520                    factories.put(path, answer);
2521                }
2522                return answer;
2523            }
2524        }
2525    
2526        public ClassResolver getClassResolver() {
2527            return classResolver;
2528        }
2529    
2530        public void setClassResolver(ClassResolver classResolver) {
2531            this.classResolver = classResolver;
2532        }
2533    
2534        public PackageScanClassResolver getPackageScanClassResolver() {
2535            return packageScanClassResolver;
2536        }
2537    
2538        public void setPackageScanClassResolver(PackageScanClassResolver packageScanClassResolver) {
2539            this.packageScanClassResolver = packageScanClassResolver;
2540        }
2541    
2542        public List<String> getComponentNames() {
2543            synchronized (components) {
2544                List<String> answer = new ArrayList<String>();
2545                for (String name : components.keySet()) {
2546                    answer.add(name);
2547                }
2548                return answer;
2549            }
2550        }
2551    
2552        public List<String> getLanguageNames() {
2553            synchronized (languages) {
2554                List<String> answer = new ArrayList<String>();
2555                for (String name : languages.keySet()) {
2556                    answer.add(name);
2557                }
2558                return answer;
2559            }
2560        }
2561    
2562        public NodeIdFactory getNodeIdFactory() {
2563            return nodeIdFactory;
2564        }
2565    
2566        public void setNodeIdFactory(NodeIdFactory idFactory) {
2567            this.nodeIdFactory = idFactory;
2568        }
2569    
2570        public ManagementStrategy getManagementStrategy() {
2571            return managementStrategy;
2572        }
2573    
2574        public void setManagementStrategy(ManagementStrategy managementStrategy) {
2575            this.managementStrategy = managementStrategy;
2576        }
2577    
2578        public InterceptStrategy getDefaultTracer() {
2579            if (defaultTracer == null) {
2580                defaultTracer = new Tracer();
2581            }
2582            return defaultTracer;
2583        }
2584    
2585        public void setDefaultTracer(InterceptStrategy tracer) {
2586            this.defaultTracer = tracer;
2587        }
2588    
2589        public InterceptStrategy getDefaultBacklogTracer() {
2590            if (defaultBacklogTracer == null) {
2591                defaultBacklogTracer = new BacklogTracer(this);
2592            }
2593            return defaultBacklogTracer;
2594        }
2595    
2596        public void setDefaultBacklogTracer(InterceptStrategy backlogTracer) {
2597            this.defaultBacklogTracer = backlogTracer;
2598        }
2599    
2600        public InterceptStrategy getDefaultBacklogDebugger() {
2601            if (defaultBacklogDebugger == null) {
2602                defaultBacklogDebugger = new BacklogDebugger(this);
2603            }
2604            return defaultBacklogDebugger;
2605        }
2606    
2607        public void setDefaultBacklogDebugger(InterceptStrategy defaultBacklogDebugger) {
2608            this.defaultBacklogDebugger = defaultBacklogDebugger;
2609        }
2610    
2611        public void disableJMX() {
2612            if (isStarting() || isStarted()) {
2613                throw new IllegalStateException("Disabling JMX can only be done when CamelContext has not been started");
2614            }
2615            managementStrategy = new DefaultManagementStrategy(this);
2616            // must clear lifecycle strategies as we add DefaultManagementLifecycleStrategy by default for JMX support
2617            lifecycleStrategies.clear();
2618        }
2619    
2620        public InflightRepository getInflightRepository() {
2621            return inflightRepository;
2622        }
2623    
2624        public void setInflightRepository(InflightRepository repository) {
2625            this.inflightRepository = repository;
2626        }
2627    
2628        public void setAutoStartup(Boolean autoStartup) {
2629            this.autoStartup = autoStartup;
2630        }
2631    
2632        public Boolean isAutoStartup() {
2633            return autoStartup != null && autoStartup;
2634        }
2635    
2636        @Deprecated
2637        public Boolean isLazyLoadTypeConverters() {
2638            return lazyLoadTypeConverters != null && lazyLoadTypeConverters;
2639        }
2640    
2641        @Deprecated
2642        public void setLazyLoadTypeConverters(Boolean lazyLoadTypeConverters) {
2643            this.lazyLoadTypeConverters = lazyLoadTypeConverters;
2644        }
2645    
2646        public Boolean isTypeConverterStatisticsEnabled() {
2647            return typeConverterStatisticsEnabled != null && typeConverterStatisticsEnabled;
2648        }
2649    
2650        public void setTypeConverterStatisticsEnabled(Boolean typeConverterStatisticsEnabled) {
2651            this.typeConverterStatisticsEnabled = typeConverterStatisticsEnabled;
2652        }
2653    
2654        public Boolean isUseMDCLogging() {
2655            return useMDCLogging != null && useMDCLogging;
2656        }
2657    
2658        public void setUseMDCLogging(Boolean useMDCLogging) {
2659            this.useMDCLogging = useMDCLogging;
2660        }
2661    
2662        public Boolean isUseBreadcrumb() {
2663            return useBreadcrumb != null && useBreadcrumb;
2664        }
2665    
2666        public void setUseBreadcrumb(Boolean useBreadcrumb) {
2667            this.useBreadcrumb = useBreadcrumb;
2668        }
2669    
2670        public ClassLoader getApplicationContextClassLoader() {
2671            return applicationContextClassLoader;
2672        }
2673    
2674        public void setApplicationContextClassLoader(ClassLoader classLoader) {
2675            applicationContextClassLoader = classLoader;
2676        }
2677    
2678        public DataFormatResolver getDataFormatResolver() {
2679            return dataFormatResolver;
2680        }
2681    
2682        public void setDataFormatResolver(DataFormatResolver dataFormatResolver) {
2683            this.dataFormatResolver = dataFormatResolver;
2684        }
2685    
2686        public DataFormat resolveDataFormat(String name) {
2687            DataFormat answer = dataFormatResolver.resolveDataFormat(name, this);
2688    
2689            // inject CamelContext if aware
2690            if (answer != null && answer instanceof CamelContextAware) {
2691                ((CamelContextAware) answer).setCamelContext(this);
2692            }
2693    
2694            return answer;
2695        }
2696    
2697        public DataFormatDefinition resolveDataFormatDefinition(String name) {
2698            // lookup type and create the data format from it
2699            DataFormatDefinition type = lookup(this, name, DataFormatDefinition.class);
2700            if (type == null && getDataFormats() != null) {
2701                type = getDataFormats().get(name);
2702            }
2703            return type;
2704        }
2705    
2706        private static <T> T lookup(CamelContext context, String ref, Class<T> type) {
2707            try {
2708                return context.getRegistry().lookupByNameAndType(ref, type);
2709            } catch (Exception e) {
2710                // need to ignore not same type and return it as null
2711                return null;
2712            }
2713        }
2714    
2715        protected Component lookupPropertiesComponent() {
2716            // no existing properties component so lookup and add as component if possible
2717            PropertiesComponent answer = (PropertiesComponent) hasComponent("properties");
2718            if (answer == null) {
2719                answer = getRegistry().lookupByNameAndType("properties", PropertiesComponent.class);
2720                if (answer != null) {
2721                    addComponent("properties", answer);
2722                }
2723            }
2724            return answer;
2725        }
2726    
2727        public ShutdownStrategy getShutdownStrategy() {
2728            return shutdownStrategy;
2729        }
2730    
2731        public void setShutdownStrategy(ShutdownStrategy shutdownStrategy) {
2732            this.shutdownStrategy = shutdownStrategy;
2733        }
2734    
2735        public ShutdownRoute getShutdownRoute() {
2736            return shutdownRoute;
2737        }
2738    
2739        public void setShutdownRoute(ShutdownRoute shutdownRoute) {
2740            this.shutdownRoute = shutdownRoute;
2741        }
2742    
2743        public ShutdownRunningTask getShutdownRunningTask() {
2744            return shutdownRunningTask;
2745        }
2746    
2747        public void setShutdownRunningTask(ShutdownRunningTask shutdownRunningTask) {
2748            this.shutdownRunningTask = shutdownRunningTask;
2749        }
2750    
2751        public void setAllowUseOriginalMessage(Boolean allowUseOriginalMessage) {
2752            this.allowUseOriginalMessage = allowUseOriginalMessage;
2753        }
2754    
2755        public Boolean isAllowUseOriginalMessage() {
2756            return allowUseOriginalMessage != null && allowUseOriginalMessage;
2757        }
2758    
2759        public ExecutorServiceManager getExecutorServiceManager() {
2760            return this.executorServiceManager;
2761        }
2762    
2763        @Deprecated
2764        public org.apache.camel.spi.ExecutorServiceStrategy getExecutorServiceStrategy() {
2765            // its okay to create a new instance as its stateless, and just delegate
2766            // ExecutorServiceManager which is the new API
2767            return new DefaultExecutorServiceStrategy(this);
2768        }
2769    
2770        public void setExecutorServiceManager(ExecutorServiceManager executorServiceManager) {
2771            this.executorServiceManager = executorServiceManager;
2772        }
2773    
2774        public ProcessorFactory getProcessorFactory() {
2775            return processorFactory;
2776        }
2777    
2778        public void setProcessorFactory(ProcessorFactory processorFactory) {
2779            this.processorFactory = processorFactory;
2780        }
2781    
2782        public Debugger getDebugger() {
2783            return debugger;
2784        }
2785    
2786        public void setDebugger(Debugger debugger) {
2787            this.debugger = debugger;
2788        }
2789        
2790        public UuidGenerator getUuidGenerator() {
2791            return uuidGenerator;
2792        }
2793    
2794        public void setUuidGenerator(UuidGenerator uuidGenerator) {
2795            this.uuidGenerator = uuidGenerator;
2796        }
2797    
2798        public StreamCachingStrategy getStreamCachingStrategy() {
2799            if (streamCachingStrategy == null) {
2800                streamCachingStrategy = new DefaultStreamCachingStrategy();
2801            }
2802            return streamCachingStrategy;
2803        }
2804    
2805        public void setStreamCachingStrategy(StreamCachingStrategy streamCachingStrategy) {
2806            this.streamCachingStrategy = streamCachingStrategy;
2807        }
2808    
2809        @Override
2810        public String getProperty(String name) {
2811            String value = getProperties().get(name);
2812            if (ObjectHelper.isNotEmpty(value)) {
2813                try {
2814                    value = resolvePropertyPlaceholders(value);
2815                } catch (Exception e) {
2816                    throw new RuntimeCamelException("Error getting property: " + name, e);
2817                }
2818            }
2819            return value;
2820        }
2821    
2822        protected Map<String, RouteService> getRouteServices() {
2823            return routeServices;
2824        }
2825    
2826        protected ManagementStrategy createManagementStrategy() {
2827            return new ManagementStrategyFactory().create(this, disableJMX || Boolean.getBoolean(JmxSystemPropertyKeys.DISABLED));
2828        }
2829    
2830        /**
2831         * Reset context counter to a preset value. Mostly used for tests to ensure a predictable getName()
2832         *
2833         * @param value new value for the context counter
2834         */
2835        public static void setContextCounter(int value) {
2836            DefaultCamelContextNameStrategy.setCounter(value);
2837            DefaultManagementNameStrategy.setCounter(value);
2838        }
2839    
2840        private static UuidGenerator createDefaultUuidGenerator() {
2841            if (System.getProperty("com.google.appengine.runtime.environment") != null) {
2842                // either "Production" or "Development"
2843                return new JavaUuidGenerator();
2844            } else {
2845                return new ActiveMQUuidGenerator();
2846            }
2847        }
2848    
2849        @Override
2850        public String toString() {
2851            return "CamelContext(" + getName() + ")";
2852        }
2853    }