001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.camel.impl;
018    
019    import java.util.ArrayList;
020    import java.util.Collection;
021    import java.util.HashMap;
022    import java.util.Iterator;
023    import java.util.List;
024    import java.util.Map;
025    import java.util.TreeMap;
026    import java.util.concurrent.Callable;
027    
028    import javax.naming.Context;
029    
030    import org.apache.camel.CamelContext;
031    import org.apache.camel.Component;
032    import org.apache.camel.ConsumerTemplate;
033    import org.apache.camel.Endpoint;
034    import org.apache.camel.IsSingleton;
035    import org.apache.camel.NoFactoryAvailableException;
036    import org.apache.camel.Processor;
037    import org.apache.camel.Producer;
038    import org.apache.camel.ProducerTemplate;
039    import org.apache.camel.ResolveEndpointFailedException;
040    import org.apache.camel.Route;
041    import org.apache.camel.RoutesBuilder;
042    import org.apache.camel.RuntimeCamelException;
043    import org.apache.camel.Service;
044    import org.apache.camel.ServiceStatus;
045    import org.apache.camel.TypeConverter;
046    import org.apache.camel.builder.ErrorHandlerBuilder;
047    import org.apache.camel.impl.converter.DefaultTypeConverter;
048    import org.apache.camel.management.InstrumentationLifecycleStrategy;
049    import org.apache.camel.management.JmxSystemPropertyKeys;
050    import org.apache.camel.model.DataFormatDefinition;
051    import org.apache.camel.model.RouteDefinition;
052    import org.apache.camel.processor.interceptor.Delayer;
053    import org.apache.camel.processor.interceptor.HandleFault;
054    import org.apache.camel.processor.interceptor.StreamCaching;
055    import org.apache.camel.processor.interceptor.TraceFormatter;
056    import org.apache.camel.processor.interceptor.Tracer;
057    import org.apache.camel.spi.ClassResolver;
058    import org.apache.camel.spi.ComponentResolver;
059    import org.apache.camel.spi.EndpointStrategy;
060    import org.apache.camel.spi.ExchangeConverter;
061    import org.apache.camel.spi.FactoryFinder;
062    import org.apache.camel.spi.FactoryFinderResolver;
063    import org.apache.camel.spi.Injector;
064    import org.apache.camel.spi.InterceptStrategy;
065    import org.apache.camel.spi.Language;
066    import org.apache.camel.spi.LanguageResolver;
067    import org.apache.camel.spi.LifecycleStrategy;
068    import org.apache.camel.spi.PackageScanClassResolver;
069    import org.apache.camel.spi.Registry;
070    import org.apache.camel.spi.RouteContext;
071    import org.apache.camel.spi.ServicePool;
072    import org.apache.camel.spi.TypeConverterRegistry;
073    import org.apache.camel.util.LRUCache;
074    import org.apache.camel.util.ObjectHelper;
075    import org.apache.camel.util.ReflectionInjector;
076    import org.apache.camel.util.SystemHelper;
077    import org.apache.camel.util.URISupport;
078    import org.apache.commons.logging.Log;
079    import org.apache.commons.logging.LogFactory;
080    
081    import static org.apache.camel.util.ServiceHelper.startServices;
082    import static org.apache.camel.util.ServiceHelper.stopServices;
083    
084    /**
085     * Represents the context used to configure routes and the policies to use.
086     *
087     * @version $Revision: 795369 $
088     */
089    public class DefaultCamelContext extends ServiceSupport implements CamelContext {
090        private static final transient Log LOG = LogFactory.getLog(DefaultCamelContext.class);
091        private static final String NAME_PREFIX = "camel-";
092        private static int nameSuffix;
093        private boolean routeDefinitionInitiated;
094        private String name;  
095        private final Map<String, Endpoint> endpoints = new LRUCache<String, Endpoint>(1000);
096        private final List<EndpointStrategy> endpointStrategies = new ArrayList<EndpointStrategy>();
097        private final Map<String, Component> components = new HashMap<String, Component>();
098        private List<Route> routes;
099        private final List<Service> servicesToClose = new ArrayList<Service>();
100        private TypeConverter typeConverter;
101        private TypeConverterRegistry typeConverterRegistry;
102        private ExchangeConverter exchangeConverter;
103        private Injector injector;
104        private ComponentResolver componentResolver;
105        private boolean autoCreateComponents = true;
106        private LanguageResolver languageResolver = new DefaultLanguageResolver();
107        private final Map<String, Language> languages = new HashMap<String, Language>();
108        private Registry registry;
109        private LifecycleStrategy lifecycleStrategy;
110        private final List<RouteDefinition> routeDefinitions = new ArrayList<RouteDefinition>();
111        private List<InterceptStrategy> interceptStrategies = new ArrayList<InterceptStrategy>();
112        private Boolean trace;
113        private Boolean streamCache = Boolean.FALSE;
114        private Boolean handleFault = Boolean.FALSE;
115        private Long delay;
116        private ErrorHandlerBuilder errorHandlerBuilder;
117        private Map<String, DataFormatDefinition> dataFormats = new HashMap<String, DataFormatDefinition>();
118        private Map<String, String> properties = new HashMap<String, String>();
119        private FactoryFinderResolver factoryFinderResolver = new DefaultFactoryFinderResolver();
120        private FactoryFinder defaultFactoryFinder;
121        private final Map<String, FactoryFinder> factories = new HashMap<String, FactoryFinder>();
122        private final Map<String, RouteService> routeServices = new HashMap<String, RouteService>();
123        private ClassResolver classResolver = new DefaultClassResolver();
124        private PackageScanClassResolver packageScanClassResolver;
125        // we use a capacity of 100 per endpoint, so for the same endpoint we have at most 100 producers in the pool
126        // so if we have 6 endpoints in the pool, we have 6 x 100 producers in total
127        private ServicePool<Endpoint, Producer> producerServicePool = new DefaultProducerServicePool(100);
128    
129        public DefaultCamelContext() {
130            super();
131            name = NAME_PREFIX + ++nameSuffix;
132    
133            if (Boolean.getBoolean(JmxSystemPropertyKeys.DISABLED)) {
134                LOG.info("JMX is disabled. Using DefaultLifecycleStrategy.");
135                lifecycleStrategy = new DefaultLifecycleStrategy();
136            } else {
137                try {
138                    LOG.info("JMX enabled. Using InstrumentationLifecycleStrategy.");
139                    lifecycleStrategy = new InstrumentationLifecycleStrategy();
140                } catch (NoClassDefFoundError e) {
141                    // if we can't instantiate the JMX enabled strategy then fallback to default
142                    // could be because of missing .jars on the classpath
143                    LOG.warn("Could not find needed classes for JMX lifecycle strategy."
144                            + " Needed class is in spring-context.jar using Spring 2.5 or newer ("
145                            + " spring-jmx.jar using Spring 2.0.x)."
146                            + " NoClassDefFoundError: " + e.getMessage());
147                } catch (Exception e) {
148                    LOG.warn("Could not create JMX lifecycle strategy, caused by: " + e.getMessage());
149                }
150                // if not created then fallback to default
151                if (lifecycleStrategy == null) {
152                    LOG.warn("Cannot use JMX lifecycle strategy. Using DefaultLifecycleStrategy instead.");
153                    lifecycleStrategy = new DefaultLifecycleStrategy();
154                }
155            }
156    
157            // use WebSphere specific resolver if running on WebSphere
158            if (WebSpherePacakageScanClassResolver.isWebSphereClassLoader(this.getClass().getClassLoader())) {
159                LOG.info("Using WebSphere specific PackageScanClassResolver");
160                packageScanClassResolver = new WebSpherePacakageScanClassResolver("META-INF/services/org/apache/camel/TypeConverter");
161            } else {
162                packageScanClassResolver = new DefaultPackageScanClassResolver();
163            }
164    
165        }
166    
167        /**
168         * Creates the {@link CamelContext} using the given JNDI context as the
169         * registry
170         */
171        public DefaultCamelContext(Context jndiContext) {
172            this();
173            setJndiContext(jndiContext);
174        }
175    
176        /**
177         * Creates the {@link CamelContext} using the given registry
178         */
179        public DefaultCamelContext(Registry registry) {
180            this();
181            this.registry = registry;
182        }
183    
184        public String getName() {
185            return name;
186        }
187    
188        /**
189         * Sets the name of the this context.
190         */
191        public void setName(String name) {
192            this.name = name;
193        }
194    
195        public void addComponent(String componentName, final Component component) {
196            ObjectHelper.notNull(component, "component");
197            synchronized (components) {
198                if (components.containsKey(componentName)) {
199                    throw new IllegalArgumentException("Cannot add component as its already previously added: " + componentName);
200                }
201                component.setCamelContext(this);
202                components.put(componentName, component);
203            }
204        }
205    
206        public Component getComponent(String name) {
207            // synchronize the look up and auto create so that 2 threads can't
208            // concurrently auto create the same component.
209            synchronized (components) {
210                Component component = components.get(name);
211                if (component == null && autoCreateComponents) {
212                    try {
213                        component = getComponentResolver().resolveComponent(name, this);
214                        if (component != null) {
215                            addComponent(name, component);
216                            if (isStarted() || isStarting()) {
217                                // If the component is looked up after the context is started,
218                                // lets start it up.
219                                startServices(component);
220                            }
221                        }
222                    } catch (Exception e) {
223                        throw new RuntimeCamelException("Could not auto create component: " + name, e);
224                    }
225                }
226                return component;
227            }
228        }
229    
230        public <T extends Component> T getComponent(String name, Class<T> componentType) {
231            Component component = getComponent(name);
232            if (componentType.isInstance(component)) {
233                return componentType.cast(component);
234            } else {
235                throw new IllegalArgumentException("The component is not of type: " + componentType + " but is: "
236                        + component);
237            }
238        }
239    
240        public Component removeComponent(String componentName) {
241            synchronized (components) {
242                return components.remove(componentName);
243            }
244        }
245    
246        public Component getOrCreateComponent(String componentName, Callable<Component> factory) {
247            synchronized (components) {
248                Component component = components.get(componentName);
249                if (component == null) {
250                    try {
251                        component = factory.call();
252                        if (component == null) {
253                            throw new RuntimeCamelException("Factory failed to create the " + componentName
254                                    + " component, it returned null.");
255                        }
256                        components.put(componentName, component);
257                        component.setCamelContext(this);
258                    } catch (Exception e) {
259                        throw new RuntimeCamelException("Factory failed to create the " + componentName
260                                + " component", e);
261                    }
262                }
263                return component;
264            }
265        }
266    
267        // Endpoint Management Methods
268        // -----------------------------------------------------------------------
269    
270        public Collection<Endpoint> getEndpoints() {
271            synchronized (endpoints) {
272                return new ArrayList<Endpoint>(endpoints.values());
273            }
274        }
275    
276        public Map<String, Endpoint> getEndpointMap() {
277            synchronized (endpoints) {
278                return new TreeMap<String, Endpoint>(endpoints);
279            }
280        }
281    
282        public Collection<Endpoint> getEndpoints(String uri) {
283            Collection<Endpoint> answer = new ArrayList<Endpoint>();
284            Collection<Endpoint> coll;
285            synchronized (endpoints) {
286                Endpoint ep = endpoints.get(uri);
287                if (ep != null) {
288                    answer.add(ep);
289                    return answer;
290                }
291                coll = new ArrayList<Endpoint>(endpoints.values());
292            }
293            for (Endpoint ep : coll) {
294                if (!ep.isSingleton() && uri.equals(ep.getEndpointUri())) {
295                    answer.add(ep);
296                }
297            }
298            return answer;
299        }
300    
301        public Collection<Endpoint> getSingletonEndpoints() {
302            Collection<Endpoint> answer = new ArrayList<Endpoint>();
303            Collection<Endpoint> coll = getEndpoints();
304            for (Endpoint ep : coll) {
305                if (ep.isSingleton()) {
306                    answer.add(ep);
307                }
308            }
309            return answer;
310        }
311    
312        public Endpoint addEndpoint(String uri, Endpoint endpoint) throws Exception {
313            Endpoint oldEndpoint;
314            synchronized (endpoints) {
315                startServices(endpoint);
316                oldEndpoint = endpoints.remove(uri);
317                addEndpointToRegistry(uri, endpoint);
318                if (oldEndpoint != null) {
319                    stopServices(oldEndpoint);
320                }
321            }
322            return oldEndpoint;
323        }
324    
325        public Collection<Endpoint> removeEndpoints(String uri) throws Exception {
326            Collection<Endpoint> answer = new ArrayList<Endpoint>();
327            synchronized (endpoints) {
328                Endpoint oldEndpoint = endpoints.remove(uri);
329                if (oldEndpoint != null) {
330                    answer.add(oldEndpoint);
331                    stopServices(oldEndpoint);
332                } else {
333                    for (Map.Entry entry : endpoints.entrySet()) {
334                        oldEndpoint = (Endpoint) entry.getValue();
335                        if (!oldEndpoint.isSingleton() && uri.equals(oldEndpoint.getEndpointUri())) {
336                            answer.add(oldEndpoint);
337                            stopServices(oldEndpoint);
338                            endpoints.remove(entry.getKey());
339                        }
340                    }
341                }
342            }
343            return answer;
344        }
345    
346        public Endpoint addSingletonEndpoint(String uri, Endpoint endpoint) throws Exception {
347            return addEndpoint(uri, endpoint);
348        }
349    
350        public Endpoint removeSingletonEndpoint(String uri) throws Exception {
351            Collection<Endpoint> answer = removeEndpoints(uri);
352            return (Endpoint) (answer.size() > 0 ? answer.toArray()[0] : null);
353        }
354    
355        public Endpoint getEndpoint(String uri) {
356            ObjectHelper.notEmpty(uri, "uri");
357    
358            // normalize uri so we can do endpoint hits with minor mistakes and parameters is not in the same order
359            try {
360                uri = URISupport.normalizeUri(uri);
361            } catch (Exception e) {
362                throw new ResolveEndpointFailedException(uri, e);
363            }
364    
365            if (LOG.isTraceEnabled()) {
366                LOG.trace("Getting endpoint with uri: " + uri);
367            }
368    
369            Endpoint answer;
370            String scheme = null;
371            synchronized (endpoints) {
372                answer = endpoints.get(uri);
373                if (answer == null) {
374                    try {
375                        // Use the URI prefix to find the component.
376                        String splitURI[] = ObjectHelper.splitOnCharacter(uri, ":", 2);
377                        if (splitURI[1] != null) {
378                            scheme = splitURI[0];
379                            Component component = getComponent(scheme);
380    
381                            // Ask the component to resolve the endpoint.
382                            if (component != null) {
383                                // Have the component create the endpoint if it can.
384                                answer = component.createEndpoint(uri);
385    
386                                if (answer != null && LOG.isDebugEnabled()) {
387                                    LOG.debug(uri + " converted to endpoint: " + answer + " by component: " + component);
388                                }
389                            }
390                        }
391    
392                        if (answer == null) {
393                            // no component then try in registry and elsewhere
394                            answer = createEndpoint(uri);
395                        }
396    
397                        if (answer != null) {
398                            addService(answer);
399                            Endpoint newAnswer = addEndpointToRegistry(uri, answer);
400                            lifecycleStrategy.onEndpointAdd(answer);
401                            answer = newAnswer;
402                        }
403                    } catch (Exception e) {
404                        throw new ResolveEndpointFailedException(uri, e);
405                    }
406                }
407            }
408    
409            // unknown scheme
410            if (answer == null && scheme != null) {
411                throw new ResolveEndpointFailedException(uri, "No component found with scheme: " + scheme);
412            }
413    
414            return answer;
415        }
416        
417        public <T extends Endpoint> T getEndpoint(String name, Class<T> endpointType) {
418            Endpoint endpoint = getEndpoint(name);
419    
420            if (endpoint instanceof InterceptSendToEndpoint) {
421                endpoint = ((InterceptSendToEndpoint) endpoint).getDelegate();
422            }
423            if (endpointType.isInstance(endpoint)) {
424                return endpointType.cast(endpoint);
425            } else {
426                throw new IllegalArgumentException("The endpoint is not of type: " + endpointType + " but is: "
427                        + endpoint.getClass().getCanonicalName());
428            }
429        }
430    
431        public void addRegisterEndpointCallback(EndpointStrategy strategy) {
432            if (!endpointStrategies.contains(strategy)) {
433                // let it be invoked for already registered endpoints so it can catch-up.
434                endpointStrategies.add(strategy);
435                for (Endpoint endpoint : getEndpoints()) {
436                    Endpoint newEndpoint = strategy.registerEndpoint(endpoint.getEndpointUri(), endpoint);
437                    if (newEndpoint != endpoint) {
438                        endpoints.put(getEndpointKey(newEndpoint.getEndpointUri(), newEndpoint), newEndpoint);
439                    }
440                }
441            }
442        }
443    
444        /**
445         * Strategy to add the given endpoint to the internal endpoint registry
446         *
447         * @param uri  uri of endpoint
448         * @param endpoint the endpoint to add
449         * @return the added endpoint
450         */
451        protected Endpoint addEndpointToRegistry(String uri, Endpoint endpoint) {
452            for (EndpointStrategy strategy : endpointStrategies) {
453                endpoint = strategy.registerEndpoint(uri, endpoint);
454            }
455            endpoints.put(getEndpointKey(uri, endpoint), endpoint);
456            return endpoint;
457        }
458    
459        // Route Management Methods
460        // -----------------------------------------------------------------------
461        public synchronized List<Route> getRoutes() {
462            if (routes == null) {
463                routes = new ArrayList<Route>();
464            }
465    
466            // lets return a copy of the collection as objects are removed later
467            // when services are stopped
468            return new ArrayList<Route>(routes);
469        }
470    
471        public void setRoutes(List<Route> routes) {
472            this.routes = routes;
473            throw new UnsupportedOperationException("Overriding existing routes is not supported yet, use addRoutes instead");
474        }
475    
476        synchronized void removeRouteCollection(Collection<Route> routes) {
477            if (this.routes != null) {
478                this.routes.removeAll(routes);
479            }
480        }
481    
482        synchronized void addRouteCollection(Collection<Route> routes) throws Exception {
483            if (this.routes == null) {
484                this.routes = new ArrayList<Route>();
485            }
486    
487            if (routes != null) {
488                this.routes.addAll(routes);
489            }
490        }
491    
492        public void addRoutes(RoutesBuilder builder) throws Exception {
493            if (LOG.isDebugEnabled()) {
494                LOG.debug("Adding routes from builder: " + builder);
495            }
496            // lets now add the routes from the builder
497            builder.addRoutesToCamelContext(this);
498        }
499    
500        public void addRouteDefinitions(Collection<RouteDefinition> routeDefinitions) throws Exception {
501            for (RouteDefinition routeDefinition : routeDefinitions) {
502                routeDefinition.setCamelContext(this);
503                removeRouteDefinition(routeDefinition);
504            }
505            this.routeDefinitions.addAll(routeDefinitions);
506            if (shouldStartRoutes()) {
507                startRouteDefinitions(routeDefinitions);
508            }
509        }
510    
511        /**
512         * Removes the route definition with the given key.
513         *
514         * @return true if one or more routes was removed
515         */
516        public boolean removeRouteDefinition(String key) {
517            boolean answer = false;
518            Iterator<RouteDefinition> iter = routeDefinitions.iterator();
519            while (iter.hasNext()) {
520                RouteDefinition route = iter.next();
521                if (route.idOrCreate().equals(key)) {
522                    iter.remove();
523                    answer = true;
524                }
525            }
526            return answer;
527        }
528    
529        public void removeRouteDefinitions(Collection<RouteDefinition> routeDefinitions) throws Exception {
530            this.routeDefinitions.removeAll(routeDefinitions);
531            for (RouteDefinition routeDefinition : routeDefinitions) {
532                removeRouteDefinition(routeDefinition);
533            }
534        }
535    
536        public void removeRouteDefinition(RouteDefinition routeDefinition) throws Exception {
537            String key = routeDefinition.idOrCreate();
538            stopRoute(key);
539            removeRouteDefinition(key);
540        }
541    
542        public ServiceStatus getRouteStatus(RouteDefinition route) {
543            return getRouteStatus(route.idOrCreate());
544        }
545    
546        /**
547         * Returns the status of the service of the given ID or null if there is no service created yet
548         */
549        public ServiceStatus getRouteStatus(String key) {
550            RouteService routeService = routeServices.get(key);
551            if (routeService != null) {
552                return routeService.getStatus();
553            }
554            return null;
555        }
556    
557        public void startRoute(RouteDefinition route) throws Exception {
558            Collection<Route> routes = new ArrayList<Route>();
559            List<RouteContext> routeContexts = route.addRoutes(this, routes);
560            RouteService routeService = new RouteService(this, route, routeContexts, routes);
561            startRouteService(routeService);
562        }
563    
564    
565        public void stopRoute(RouteDefinition route) throws Exception {
566            stopRoute(route.idOrCreate());
567        }
568    
569        /**
570         * Stops the route denoted by the given RouteType id
571         */
572        public synchronized void stopRoute(String key) throws Exception {
573            RouteService routeService = routeServices.remove(key);
574            if (routeService != null) {
575                routeService.stop();
576            }
577        }
578    
579    
580        /**
581         * Adds a service, starting it so that it will be stopped with this context
582         */
583        public void addService(Object object) throws Exception {
584            if (object instanceof Service) {
585                Service service = (Service) object;
586                getLifecycleStrategy().onServiceAdd(this, service);
587                service.start();
588                servicesToClose.add(service);
589            }
590        }
591    
592        // Helper methods
593        // -----------------------------------------------------------------------
594    
595        public Language resolveLanguage(String language) {
596            Language answer;
597            synchronized (languages) {
598                answer = languages.get(language);
599    
600                // check if the language is singleton, if so return the shared instance
601                if (answer instanceof IsSingleton) {
602                    boolean singleton = ((IsSingleton) answer).isSingleton();
603                    if (singleton) {
604                        return answer;
605                    }
606                }
607    
608                // language not known or not singleton, then use resolver
609                answer = getLanguageResolver().resolveLanguage(language, this);
610                if (answer != null) {
611                    languages.put(language, answer);
612                }
613            }
614    
615            // no language resolved
616            return answer;
617        }
618    
619        // Properties
620        // -----------------------------------------------------------------------
621        public ExchangeConverter getExchangeConverter() {
622            if (exchangeConverter == null) {
623                exchangeConverter = createExchangeConverter();
624            }
625            return exchangeConverter;
626        }
627    
628        public void setExchangeConverter(ExchangeConverter exchangeConverter) {
629            this.exchangeConverter = exchangeConverter;
630        }
631    
632        public TypeConverter getTypeConverter() {
633            if (typeConverter == null) {
634                typeConverter = createTypeConverter();
635            }
636            return typeConverter;
637        }
638    
639        public void setTypeConverter(TypeConverter typeConverter) {
640            this.typeConverter = typeConverter;
641        }
642    
643        public TypeConverterRegistry getTypeConverterRegistry() {
644            if (typeConverterRegistry == null) {
645                // init type converter as its lazy
646                if (typeConverter == null) {
647                    getTypeConverter();
648                }
649                // type converter is usually the default one that also is the registry
650                if (typeConverter instanceof DefaultTypeConverter) {
651                    typeConverterRegistry = (DefaultTypeConverter) typeConverter;
652                }
653            }
654            return typeConverterRegistry;
655        }
656    
657        public void setTypeConverterRegistry(TypeConverterRegistry typeConverterRegistry) {
658            this.typeConverterRegistry = typeConverterRegistry;
659        }
660        
661        public Injector getInjector() {
662            if (injector == null) {
663                injector = createInjector();
664            }
665            return injector;
666        }
667    
668        public void setInjector(Injector injector) {
669            this.injector = injector;
670        }
671    
672        public ComponentResolver getComponentResolver() {
673            if (componentResolver == null) {
674                componentResolver = createComponentResolver();
675            }
676            return componentResolver;
677        }
678    
679        public void setComponentResolver(ComponentResolver componentResolver) {
680            this.componentResolver = componentResolver;
681        }
682    
683        public LanguageResolver getLanguageResolver() {
684            return languageResolver;
685        }
686    
687        public void setLanguageResolver(LanguageResolver languageResolver) {
688            this.languageResolver = languageResolver;
689        }
690    
691        public boolean isAutoCreateComponents() {
692            return autoCreateComponents;
693        }
694    
695        public void setAutoCreateComponents(boolean autoCreateComponents) {
696            this.autoCreateComponents = autoCreateComponents;
697        }
698    
699        public Registry getRegistry() {
700            if (registry == null) {
701                registry = createRegistry();
702            }
703            return registry;
704        }
705    
706        /**
707         * Sets the registry to the given JNDI context
708         *
709         * @param jndiContext is the JNDI context to use as the registry
710         * @see #setRegistry(org.apache.camel.spi.Registry)
711         */
712        public void setJndiContext(Context jndiContext) {
713            setRegistry(new JndiRegistry(jndiContext));
714        }
715    
716        public void setRegistry(Registry registry) {
717            this.registry = registry;
718        }
719    
720        public LifecycleStrategy getLifecycleStrategy() {
721            return lifecycleStrategy;
722        }
723    
724        public void setLifecycleStrategy(LifecycleStrategy lifecycleStrategy) {
725            this.lifecycleStrategy = lifecycleStrategy;
726        }
727    
728        public List<RouteDefinition> getRouteDefinitions() {
729            return routeDefinitions;
730        }
731    
732        public List<InterceptStrategy> getInterceptStrategies() {
733            return interceptStrategies;
734        }
735    
736        public void setInterceptStrategies(List<InterceptStrategy> interceptStrategies) {
737            this.interceptStrategies = interceptStrategies;
738        }
739    
740        public void addInterceptStrategy(InterceptStrategy interceptStrategy) {
741            getInterceptStrategies().add(interceptStrategy);
742        }
743    
744        /**
745         * Returns true if tracing has been enabled or disabled via the {@link #setTrace(Boolean)} method
746         * or it has not been specified then default to the <b>camel.streamCache</b> system property
747         */
748        public boolean isStreamCacheEnabled() {
749            final Boolean value = getStreamCaching();
750            if (value != null) {
751                return value;
752            } else {
753                return SystemHelper.isSystemProperty("camel.streamCache");
754            }
755        }
756    
757        public Boolean getStreamCaching() {
758            return streamCache;
759        }
760    
761        public void setStreamCaching(Boolean cache) {
762            this.streamCache = cache;
763        }
764    
765        public void setTracing(Boolean tracing) {
766            // look if alredy enabled
767            Tracer tracer = Tracer.getTracer(this);
768            if (tracing && tracer == null) {
769                // not already enabled
770                addInterceptStrategy(new Tracer());
771            } else if (tracer != null) {
772                // disable existing tracer
773                for (InterceptStrategy strategy : interceptStrategies) {
774                    if (strategy instanceof Tracer) {
775                        interceptStrategies.remove(strategy);
776                    }
777                }
778            }
779        }
780    
781        /**
782         * Returns true if handle fault has been enabled
783         */
784        public boolean isHandleFaultEnabled() {
785            final Boolean value = getHandleFault();
786            if (value != null) {
787                return value;
788            } else {
789                return SystemHelper.isSystemProperty("camel.handleFault");
790            }
791        }
792    
793        public Boolean getHandleFault() {
794            return handleFault;
795        }
796    
797        public void setHandleFault(Boolean handleFault) {
798            this.handleFault = handleFault;
799        }
800    
801        /**
802         * Returns true if tracing has been enabled
803         */
804        public boolean isTraceEnabled() {
805            final Boolean value = getTrace();
806            if (value != null) {
807                return value;
808            } else {
809                return SystemHelper.isSystemProperty("camel.trace");
810            }
811        }
812    
813        public Boolean getTrace() {
814            return trace;
815        }
816    
817        public void setTrace(Boolean trace) {
818            this.trace = trace;
819        }
820    
821        /**
822         * Returns the delay in millis if delaying has been enabled. Returns 0 if not enabled.
823         */
824        public long isDelayEnabled() {
825            final Long value = getDelay();
826            if (value != null) {
827                return value;
828            } else {
829                String prop = SystemHelper.getSystemProperty("camel.delay");
830                return prop != null ? Long.getLong(prop) : 0;
831            }
832        }
833    
834        public Long getDelay() {
835            return delay;
836        }
837    
838        public void setDelay(Long delay) {
839            this.delay = delay;
840        }
841    
842        public ProducerTemplate createProducerTemplate() {
843            return new DefaultProducerTemplate(this);
844        }
845    
846        public ConsumerTemplate createConsumerTemplate() {
847            return new DefaultConsumerTemplate(this);
848        }
849    
850        public ErrorHandlerBuilder getErrorHandlerBuilder() {
851            return errorHandlerBuilder;
852        }
853    
854        /**
855         * Sets the default error handler builder which is inherited by the routes
856         */
857        public void setErrorHandlerBuilder(ErrorHandlerBuilder errorHandlerBuilder) {
858            this.errorHandlerBuilder = errorHandlerBuilder;
859        }
860    
861        public void setProducerServicePool(ServicePool<Endpoint, Producer> producerServicePool) {
862            this.producerServicePool = producerServicePool;
863        }
864    
865        public ServicePool<Endpoint, Producer> getProducerServicePool() {
866            return producerServicePool;
867        }
868    
869        public void start() throws Exception {
870            super.start();
871    
872            if (LOG.isDebugEnabled()) {
873                LOG.debug("Starting routes");
874            }
875            // the context is now considered started (i.e. isStarted() == true))
876            // starting routes is done after, not during context startup
877            synchronized (this) {
878                for (RouteService routeService : routeServices.values()) {
879                    routeService.start();
880                }
881            }
882            if (LOG.isDebugEnabled()) {
883                for (int i = 0; i < getRoutes().size(); i++) {
884                    LOG.debug("Route " + i + ": " + getRoutes().get(i));
885                }
886                LOG.debug("Started routes");
887            }
888    
889            LOG.info("Apache Camel " + getVersion() + " (CamelContext:" + getName() + ") started");
890        }
891    
892        // Implementation methods
893        // -----------------------------------------------------------------------
894    
895        protected void doStart() throws Exception {
896            LOG.info("Apache Camel " + getVersion() + " (CamelContext:" + getName() + ") is starting");
897    
898            startServices(producerServicePool);
899    
900            if (isStreamCacheEnabled()) {
901                // only add a new stream cache if not already configured
902                if (StreamCaching.getStreamCaching(this) == null) {
903                    LOG.debug("StreamCaching is enabled");
904                    addInterceptStrategy(new StreamCaching());
905                }
906            }
907    
908            if (isTraceEnabled()) {
909                // only add a new tracer if not already configured
910                if (Tracer.getTracer(this) == null) {
911                    Tracer tracer = new Tracer();
912                    // lets see if we have a formatter if so use it
913                    TraceFormatter formatter = this.getRegistry().lookup("traceFormatter", TraceFormatter.class);
914                    if (formatter != null) {
915                        tracer.setFormatter(formatter);
916                    }
917                    LOG.debug("Tracing is enabled");
918                    addInterceptStrategy(tracer);
919                }
920            }
921    
922            long delayInMillis = isDelayEnabled();
923            if (delayInMillis > 0) {
924                // only add a new delayer if not already configured
925                if (Delayer.getDelayer(this) == null) {
926                    LOG.debug("Delayer is enabled with: " + delayInMillis + " ms.");
927                    addInterceptStrategy(new Delayer(delayInMillis));
928                }
929            }
930    
931            if (isHandleFaultEnabled()) {
932                // only add a new handle fault if not already configured
933                if (HandleFault.getHandleFault(this) == null) {
934                    LOG.debug("HandleFault is enabled");
935                    addInterceptStrategy(new HandleFault());
936                }
937            }
938    
939            try {
940                lifecycleStrategy.onContextStart(this);
941            } catch (Exception e) {
942                // not all containers allow access to its MBeanServer (such as OC4j)
943                LOG.warn("Cannot start lifecycleStrategy: " + lifecycleStrategy + ". Cause: " + e.getMessage());
944                if (lifecycleStrategy instanceof InstrumentationLifecycleStrategy) {
945                    // fallback to non JMX lifecycle to allow Camel to startup
946                    LOG.warn("Will fallback to use default (non JMX) lifecycle strategy");
947                    lifecycleStrategy = new DefaultLifecycleStrategy();
948                    lifecycleStrategy.onContextStart(this);
949                }
950            }
951    
952            forceLazyInitialization();
953            if (components != null) {
954                for (Component component : components.values()) {
955                    startServices(component);
956                }
957            }
958             // To avoid initiating the routeDefinitions after stopping the camel context
959            if (!routeDefinitionInitiated) {            
960                startRouteDefinitions(routeDefinitions);
961                routeDefinitionInitiated = true;
962            }        
963        }
964    
965        protected synchronized void doStop() throws Exception {
966            LOG.info("Apache Camel " + getVersion() + " (CamelContext:" + getName() + ") is stopping");
967            stopServices(routeServices.values());
968            stopServices(servicesToClose);
969            if (components != null) {
970                for (Component component : components.values()) {
971                    stopServices(component);
972                }
973            }
974            servicesToClose.clear();
975            stopServices(producerServicePool);
976    
977            LOG.info("Apache Camel " + getVersion() + " (CamelContext:" + getName() + ") stopped");
978        }
979    
980        protected void startRouteDefinitions(Collection<RouteDefinition> list) throws Exception {
981            if (list != null) {
982                for (RouteDefinition route : list) {
983                    startRoute(route);
984                }
985            }
986        }
987    
988        /**
989         * Starts the given route service
990         */
991        protected synchronized void startRouteService(RouteService routeService) throws Exception {
992            String key = routeService.getId();
993            stopRoute(key);
994            routeServices.put(key, routeService);
995            if (shouldStartRoutes()) {
996                routeService.start();
997            }
998        }
999    
1000        /**
1001         * Lets force some lazy initialization to occur upfront before we start any
1002         * components and create routes
1003         */
1004        protected void forceLazyInitialization() {
1005            getExchangeConverter();
1006            getInjector();
1007            getLanguageResolver();
1008            getTypeConverter();
1009        }
1010    
1011        /**
1012         * Lazily create a default implementation
1013         */
1014        protected ExchangeConverter createExchangeConverter() {
1015            return new DefaultExchangeConverter();
1016        }
1017    
1018        /**
1019         * Lazily create a default implementation
1020         */
1021        protected TypeConverter createTypeConverter() {
1022            DefaultTypeConverter answer = new DefaultTypeConverter(packageScanClassResolver, getInjector(), getDefaultFactoryFinder());
1023            typeConverterRegistry = answer;
1024            return answer;
1025        }
1026    
1027        /**
1028         * Lazily create a default implementation
1029         */
1030        protected Injector createInjector() {
1031            FactoryFinder finder = getDefaultFactoryFinder();
1032            try {
1033                return (Injector) finder.newInstance("Injector");
1034            } catch (NoFactoryAvailableException e) {
1035                // lets use the default
1036                return new ReflectionInjector();
1037            }
1038        }
1039    
1040        /**
1041         * Lazily create a default implementation
1042         */
1043        protected ComponentResolver createComponentResolver() {
1044            return new DefaultComponentResolver();
1045        }
1046    
1047        /**
1048         * Lazily create a default implementation
1049         */
1050        protected Registry createRegistry() {
1051            return new JndiRegistry();
1052        }
1053    
1054        /**
1055         * A pluggable strategy to allow an endpoint to be created without requiring
1056         * a component to be its factory, such as for looking up the URI inside some
1057         * {@link Registry}
1058         *
1059         * @param uri the uri for the endpoint to be created
1060         * @return the newly created endpoint or null if it could not be resolved
1061         */
1062        protected Endpoint createEndpoint(String uri) {
1063            Object value = getRegistry().lookup(uri);
1064            if (value instanceof Endpoint) {
1065                return (Endpoint) value;
1066            } else if (value instanceof Processor) {
1067                return new ProcessorEndpoint(uri, this, (Processor) value);
1068            } else if (value != null) {
1069                return convertBeanToEndpoint(uri, value);
1070            }
1071            return null;
1072        }
1073    
1074        /**
1075         * Strategy method for attempting to convert the bean from a {@link Registry} to an endpoint using
1076         * some kind of transformation or wrapper
1077         *
1078         * @param uri  the uri for the endpoint (and name in the registry)
1079         * @param bean the bean to be converted to an endpoint, which will be not null
1080         * @return a new endpoint
1081         */
1082        protected Endpoint convertBeanToEndpoint(String uri, Object bean) {
1083            throw new IllegalArgumentException("uri: " + uri + " bean: " + bean
1084                    + " could not be converted to an Endpoint");
1085        }
1086    
1087        /**
1088         * Should we start newly added routes?
1089         */
1090        protected boolean shouldStartRoutes() {
1091            return isStarted() && !isStarting();
1092        }
1093    
1094        public void setDataFormats(Map<String, DataFormatDefinition> dataFormats) {
1095            this.dataFormats = dataFormats;
1096        }
1097    
1098        public Map<String, DataFormatDefinition> getDataFormats() {
1099            return dataFormats;
1100        }
1101    
1102        public Map<String, String> getProperties() {
1103            return properties;
1104        }
1105    
1106        public void setProperties(Map<String, String> properties) {
1107            this.properties = properties;
1108        }
1109    
1110        public FactoryFinder getDefaultFactoryFinder() {
1111            if (defaultFactoryFinder == null) {
1112                defaultFactoryFinder = factoryFinderResolver.resolveDefaultFactoryFinder(getClassResolver());
1113            }
1114            return defaultFactoryFinder;
1115        }
1116    
1117        public void setFactoryFinderResolver(FactoryFinderResolver resolver) {
1118            this.factoryFinderResolver = resolver;
1119        }
1120    
1121        public FactoryFinder getFactoryFinder(String path) throws NoFactoryAvailableException {
1122            synchronized (factories) {
1123                FactoryFinder answer = factories.get(path);
1124                if (answer == null) {
1125                    answer = factoryFinderResolver.resolveFactoryFinder(getClassResolver(), path);
1126                    factories.put(path, answer);
1127                }
1128                return answer;
1129            }
1130        }
1131    
1132        public ClassResolver getClassResolver() {
1133            return classResolver;
1134        }
1135    
1136        public void setClassResolver(ClassResolver classResolver) {
1137            this.classResolver = classResolver;
1138        }
1139    
1140        public PackageScanClassResolver getPackageScanClassResolver() {
1141            return packageScanClassResolver;
1142        }
1143    
1144        public void setPackageScanClassResolver(PackageScanClassResolver packageScanClassResolver) {
1145            this.packageScanClassResolver = packageScanClassResolver;
1146        }
1147    
1148        public List<String> getComponentNames() {
1149            synchronized (components) {
1150                List<String> answer = new ArrayList<String>();
1151                for (String name : components.keySet()) {
1152                    answer.add(name);
1153                }
1154                return answer;
1155            }
1156        }
1157    
1158        public List<String> getLanguageNames() {
1159            synchronized (languages) {
1160                List<String> answer = new ArrayList<String>();
1161                for (String name : languages.keySet()) {
1162                    answer.add(name);
1163                }
1164                return answer;
1165            }
1166        }
1167    
1168        protected synchronized String getEndpointKey(String uri, Endpoint endpoint) {
1169            if (endpoint.isSingleton()) {
1170                return uri;
1171            } else {
1172                // lets try find the first endpoint key which is free
1173                for (int counter = 0; true; counter++) {
1174                    String key = (counter > 0) ? uri + ":" + counter : uri;
1175                    if (!endpoints.containsKey(key)) {
1176                        return key;
1177                    }
1178                }
1179            }
1180        }
1181        
1182        protected Map<String, RouteService> getRouteServices() {
1183            return routeServices;
1184        }
1185    
1186        @Override
1187        public String toString() {
1188            return "DefaultCamelContext(" + getName() + ")";
1189        }
1190    
1191    }