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.core.xml;
018    
019    import java.util.ArrayList;
020    import java.util.HashSet;
021    import java.util.List;
022    import java.util.Map;
023    import java.util.Map.Entry;
024    import java.util.Set;
025    import javax.xml.bind.annotation.XmlAccessType;
026    import javax.xml.bind.annotation.XmlAccessorType;
027    import javax.xml.bind.annotation.XmlTransient;
028    
029    import org.apache.camel.CamelContext;
030    import org.apache.camel.CamelException;
031    import org.apache.camel.RoutesBuilder;
032    import org.apache.camel.ShutdownRoute;
033    import org.apache.camel.ShutdownRunningTask;
034    import org.apache.camel.builder.ErrorHandlerBuilderRef;
035    import org.apache.camel.builder.RouteBuilder;
036    import org.apache.camel.component.properties.PropertiesComponent;
037    import org.apache.camel.component.properties.PropertiesParser;
038    import org.apache.camel.component.properties.PropertiesResolver;
039    import org.apache.camel.core.xml.scan.PatternBasedPackageScanFilter;
040    import org.apache.camel.management.DefaultManagementAgent;
041    import org.apache.camel.management.DefaultManagementLifecycleStrategy;
042    import org.apache.camel.management.DefaultManagementStrategy;
043    import org.apache.camel.management.ManagedManagementStrategy;
044    import org.apache.camel.model.ContextScanDefinition;
045    import org.apache.camel.model.IdentifiedType;
046    import org.apache.camel.model.InterceptDefinition;
047    import org.apache.camel.model.InterceptFromDefinition;
048    import org.apache.camel.model.InterceptSendToEndpointDefinition;
049    import org.apache.camel.model.OnCompletionDefinition;
050    import org.apache.camel.model.OnExceptionDefinition;
051    import org.apache.camel.model.PackageScanDefinition;
052    import org.apache.camel.model.RouteBuilderDefinition;
053    import org.apache.camel.model.RouteContainer;
054    import org.apache.camel.model.RouteContextRefDefinition;
055    import org.apache.camel.model.RouteDefinition;
056    import org.apache.camel.model.RouteDefinitionHelper;
057    import org.apache.camel.model.ThreadPoolProfileDefinition;
058    import org.apache.camel.model.config.PropertiesDefinition;
059    import org.apache.camel.model.dataformat.DataFormatsDefinition;
060    import org.apache.camel.processor.interceptor.Delayer;
061    import org.apache.camel.processor.interceptor.HandleFault;
062    import org.apache.camel.processor.interceptor.TraceFormatter;
063    import org.apache.camel.processor.interceptor.Tracer;
064    import org.apache.camel.spi.ClassResolver;
065    import org.apache.camel.spi.Debugger;
066    import org.apache.camel.spi.EndpointStrategy;
067    import org.apache.camel.spi.EventFactory;
068    import org.apache.camel.spi.EventNotifier;
069    import org.apache.camel.spi.ExecutorServiceStrategy;
070    import org.apache.camel.spi.FactoryFinderResolver;
071    import org.apache.camel.spi.InflightRepository;
072    import org.apache.camel.spi.InterceptStrategy;
073    import org.apache.camel.spi.LifecycleStrategy;
074    import org.apache.camel.spi.ManagementNamingStrategy;
075    import org.apache.camel.spi.ManagementStrategy;
076    import org.apache.camel.spi.PackageScanClassResolver;
077    import org.apache.camel.spi.PackageScanFilter;
078    import org.apache.camel.spi.ProcessorFactory;
079    import org.apache.camel.spi.ShutdownStrategy;
080    import org.apache.camel.spi.ThreadPoolProfile;
081    import org.apache.camel.spi.UuidGenerator;
082    import org.apache.camel.util.CamelContextHelper;
083    import org.apache.camel.util.ObjectHelper;
084    import org.slf4j.Logger;
085    import org.slf4j.LoggerFactory;
086    
087    /**
088     * A factory to create and initialize a
089     * {@link CamelContext} and install routes either explicitly configured
090     * or found by searching the classpath for Java classes which extend
091     * {@link org.apache.camel.builder.RouteBuilder}.
092     *
093     * @version 
094     */
095    @XmlAccessorType(XmlAccessType.FIELD)
096    public abstract class AbstractCamelContextFactoryBean<T extends CamelContext> extends IdentifiedType implements RouteContainer {
097        private static final Logger LOG = LoggerFactory.getLogger(AbstractCamelContextFactoryBean.class);
098    
099        @XmlTransient
100        private List<RoutesBuilder> builders = new ArrayList<RoutesBuilder>();
101        @XmlTransient
102        private ClassLoader contextClassLoaderOnStart;
103    
104        public AbstractCamelContextFactoryBean() {
105            // Lets keep track of the class loader for when we actually do start things up
106            contextClassLoaderOnStart = Thread.currentThread().getContextClassLoader();
107        }
108    
109        public Object getObject() throws Exception {
110            return getContext();
111        }
112    
113        public Class getObjectType() {
114            return CamelContext.class;
115        }
116    
117        public boolean isSingleton() {
118            return true;
119        }
120    
121        public ClassLoader getContextClassLoaderOnStart() {
122            return contextClassLoaderOnStart;
123        }
124    
125        public void afterPropertiesSet() throws Exception {
126            if (ObjectHelper.isEmpty(getId())) {
127                throw new IllegalArgumentException("Id must be set");
128            }
129            if (getProperties() != null) {
130                getContext().setProperties(getProperties().asMap());
131            }
132    
133            // set the type converter mode first
134            if (getLazyLoadTypeConverters() != null) {
135                getContext().setLazyLoadTypeConverters(getLazyLoadTypeConverters());
136            }
137    
138            PackageScanClassResolver packageResolver = getBeanForType(PackageScanClassResolver.class);
139            if (packageResolver != null) {
140                LOG.info("Using custom PackageScanClassResolver: " + packageResolver);
141                getContext().setPackageScanClassResolver(packageResolver);
142            }
143            ClassResolver classResolver = getBeanForType(ClassResolver.class);
144            if (classResolver != null) {
145                LOG.info("Using custom ClassResolver: " + classResolver);
146                getContext().setClassResolver(classResolver);
147            }
148            FactoryFinderResolver factoryFinderResolver = getBeanForType(FactoryFinderResolver.class);
149            if (factoryFinderResolver != null) {
150                LOG.info("Using custom FactoryFinderResolver: " + factoryFinderResolver);
151                getContext().setFactoryFinderResolver(factoryFinderResolver);
152            }
153            ExecutorServiceStrategy executorServiceStrategy = getBeanForType(ExecutorServiceStrategy.class);
154            if (executorServiceStrategy != null) {
155                LOG.info("Using custom ExecutorServiceStrategy: " + executorServiceStrategy);
156                getContext().setExecutorServiceStrategy(executorServiceStrategy);
157            }
158            ProcessorFactory processorFactory = getBeanForType(ProcessorFactory.class);
159            if (processorFactory != null) {
160                LOG.info("Using custom ProcessorFactory: " + processorFactory);
161                getContext().setProcessorFactory(processorFactory);
162            }
163            Debugger debugger = getBeanForType(Debugger.class);
164            if (debugger != null) {
165                LOG.info("Using custom Debugger: " + debugger);
166                getContext().setDebugger(debugger);
167            }
168            UuidGenerator uuidGenerator = getBeanForType(UuidGenerator.class);
169            if (uuidGenerator != null) {
170                LOG.info("Using custom UuidGenerator: " + uuidGenerator);
171                getContext().setUuidGenerator(uuidGenerator);
172            }
173    
174            // set the custom registry if defined
175            initCustomRegistry(getContext());
176    
177            // setup property placeholder so we got it as early as possible
178            initPropertyPlaceholder();
179    
180            // setup JMX agent at first
181            initJMXAgent();
182    
183            Tracer tracer = getBeanForType(Tracer.class);
184            if (tracer != null) {
185                // use formatter if there is a TraceFormatter bean defined
186                TraceFormatter formatter = getBeanForType(TraceFormatter.class);
187                if (formatter != null) {
188                    tracer.setFormatter(formatter);
189                }
190                LOG.info("Using custom Tracer: " + tracer);
191                getContext().addInterceptStrategy(tracer);
192            }
193            HandleFault handleFault = getBeanForType(HandleFault.class);
194            if (handleFault != null) {
195                LOG.info("Using custom HandleFault: " + handleFault);
196                getContext().addInterceptStrategy(handleFault);
197            }
198            Delayer delayer = getBeanForType(Delayer.class);
199            if (delayer != null) {
200                LOG.info("Using custom Delayer: " + delayer);
201                getContext().addInterceptStrategy(delayer);
202            }
203            InflightRepository inflightRepository = getBeanForType(InflightRepository.class);
204            if (delayer != null) {
205                LOG.info("Using custom InflightRepository: " + inflightRepository);
206                getContext().setInflightRepository(inflightRepository);
207            }
208            ManagementStrategy managementStrategy = getBeanForType(ManagementStrategy.class);
209            if (managementStrategy != null) {
210                LOG.info("Using custom ManagementStrategy: " + managementStrategy);
211                getContext().setManagementStrategy(managementStrategy);
212            }
213            ManagementNamingStrategy managementNamingStrategy = getBeanForType(ManagementNamingStrategy.class);
214            if (managementNamingStrategy != null) {
215                LOG.info("Using custom ManagementNamingStrategy: " + managementNamingStrategy);
216                getContext().getManagementStrategy().setManagementNamingStrategy(managementNamingStrategy);
217            }
218            EventFactory eventFactory = getBeanForType(EventFactory.class);
219            if (eventFactory != null) {
220                LOG.info("Using custom EventFactory: " + eventFactory);
221                getContext().getManagementStrategy().setEventFactory(eventFactory);
222            }
223            // set the event notifier strategies if defined
224            Map<String, EventNotifier> eventNotifiers = getContext().getRegistry().lookupByType(EventNotifier.class);
225            if (eventNotifiers != null && !eventNotifiers.isEmpty()) {
226                for (Entry<String, EventNotifier> entry : eventNotifiers.entrySet()) {
227                    EventNotifier notifier = entry.getValue();
228                    // do not add if already added, for instance a tracer that is also an InterceptStrategy class
229                    if (!getContext().getManagementStrategy().getEventNotifiers().contains(notifier)) {
230                        LOG.info("Using custom EventNotifier with id: " + entry.getKey() + " and implementation: " + notifier);
231                        getContext().getManagementStrategy().addEventNotifier(notifier);
232                    }
233                }
234            }
235            // set endpoint strategies if defined
236            Map<String, EndpointStrategy> endpointStrategies = getContext().getRegistry().lookupByType(EndpointStrategy.class);
237            if (endpointStrategies != null && !endpointStrategies.isEmpty()) {
238                for (Entry<String, EndpointStrategy> entry : endpointStrategies.entrySet()) {
239                    EndpointStrategy strategy = entry.getValue();
240                    LOG.info("Using custom EndpointStrategy with id: " + entry.getKey() + " and implementation: " + strategy);
241                    getContext().addRegisterEndpointCallback(strategy);
242                }
243            }
244            // shutdown
245            ShutdownStrategy shutdownStrategy = getBeanForType(ShutdownStrategy.class);
246            if (shutdownStrategy != null) {
247                LOG.info("Using custom ShutdownStrategy: " + shutdownStrategy);
248                getContext().setShutdownStrategy(shutdownStrategy);
249            }
250            // add global interceptors
251            Map<String, InterceptStrategy> interceptStrategies = getContext().getRegistry().lookupByType(InterceptStrategy.class);
252            if (interceptStrategies != null && !interceptStrategies.isEmpty()) {
253                for (Entry<String, InterceptStrategy> entry : interceptStrategies.entrySet()) {
254                    InterceptStrategy strategy = entry.getValue();
255                    // do not add if already added, for instance a tracer that is also an InterceptStrategy class
256                    if (!getContext().getInterceptStrategies().contains(strategy)) {
257                        LOG.info("Using custom InterceptStrategy with id: " + entry.getKey() + " and implementation: " + strategy);
258                        getContext().addInterceptStrategy(strategy);
259                    }
260                }
261            }
262            // set the lifecycle strategy if defined
263            Map<String, LifecycleStrategy> lifecycleStrategies = getContext().getRegistry().lookupByType(LifecycleStrategy.class);
264            if (lifecycleStrategies != null && !lifecycleStrategies.isEmpty()) {
265                for (Entry<String, LifecycleStrategy> entry : lifecycleStrategies.entrySet()) {
266                    LifecycleStrategy strategy = entry.getValue();
267                    // do not add if already added, for instance a tracer that is also an InterceptStrategy class
268                    if (!getContext().getLifecycleStrategies().contains(strategy)) {
269                        LOG.info("Using custom LifecycleStrategy with id: " + entry.getKey() + " and implementation: " + strategy);
270                        getContext().addLifecycleStrategy(strategy);
271                    }
272                }
273            }
274    
275            // set the default thread pool profile if defined
276            initThreadPoolProfiles(getContext());
277    
278            // Set the application context and camelContext for the beanPostProcessor
279            initBeanPostProcessor(getContext());
280    
281            // init camel context
282            initCamelContext(getContext());
283    
284            // must init route refs before we prepare the routes below
285            initRouteRefs();
286    
287            // do special preparation for some concepts such as interceptors and policies
288            // this is needed as JAXB does not build exactly the same model definition as Spring DSL would do
289            // using route builders. So we have here a little custom code to fix the JAXB gaps
290            prepareRoutes();
291    
292            // and add the routes
293            getContext().addRouteDefinitions(getRoutes());
294    
295            if (LOG.isDebugEnabled()) {
296                LOG.debug("Found JAXB created routes: " + getRoutes());
297            }
298            findRouteBuilders();
299            installRoutes();
300        }
301    
302        /**
303         * Do special preparation for some concepts such as interceptors and policies
304         * this is needed as JAXB does not build exactly the same model definition as Spring DSL would do
305         * using route builders. So we have here a little custom code to fix the JAXB gaps
306         */
307        private void prepareRoutes() {
308            for (RouteDefinition route : getRoutes()) {
309                // leverage logic from route definition helper to prepare the route
310                RouteDefinitionHelper.prepareRoute(getContext(), route, getOnExceptions(), getIntercepts(), getInterceptFroms(),
311                        getInterceptSendToEndpoints(), getOnCompletions());
312    
313                // mark the route as prepared now
314                route.markPrepared();
315            }
316        }
317    
318        protected abstract void initCustomRegistry(T context);
319    
320        protected void initJMXAgent() throws Exception {
321            CamelJMXAgentDefinition camelJMXAgent = getCamelJMXAgent();
322    
323            boolean disabled = false;
324            if (camelJMXAgent != null) {
325                disabled = CamelContextHelper.parseBoolean(getContext(), camelJMXAgent.getDisabled());
326            }
327    
328            if (disabled) {
329                LOG.info("JMXAgent disabled");
330                // clear the existing lifecycle strategies define by the DefaultCamelContext constructor
331                getContext().getLifecycleStrategies().clear();
332                // no need to add a lifecycle strategy as we do not need one as JMX is disabled
333                getContext().setManagementStrategy(new DefaultManagementStrategy());
334            } else if (camelJMXAgent != null) {
335                LOG.info("JMXAgent enabled: " + camelJMXAgent);
336                DefaultManagementAgent agent = new DefaultManagementAgent(getContext());
337                agent.setConnectorPort(CamelContextHelper.parseInteger(getContext(), camelJMXAgent.getConnectorPort()));
338                agent.setCreateConnector(CamelContextHelper.parseBoolean(getContext(), camelJMXAgent.getCreateConnector()));
339                agent.setMBeanObjectDomainName(CamelContextHelper.parseText(getContext(), camelJMXAgent.getMbeanObjectDomainName()));
340                agent.setMBeanServerDefaultDomain(CamelContextHelper.parseText(getContext(), camelJMXAgent.getMbeanServerDefaultDomain()));
341                agent.setRegistryPort(CamelContextHelper.parseInteger(getContext(), camelJMXAgent.getRegistryPort()));
342                agent.setServiceUrlPath(CamelContextHelper.parseText(getContext(), camelJMXAgent.getServiceUrlPath()));
343                agent.setUsePlatformMBeanServer(CamelContextHelper.parseBoolean(getContext(), camelJMXAgent.getUsePlatformMBeanServer()));
344                agent.setOnlyRegisterProcessorWithCustomId(CamelContextHelper.parseBoolean(getContext(), camelJMXAgent.getOnlyRegisterProcessorWithCustomId()));
345                agent.setRegisterAlways(CamelContextHelper.parseBoolean(getContext(), camelJMXAgent.getRegisterAlways()));
346                agent.setRegisterNewRoutes(CamelContextHelper.parseBoolean(getContext(), camelJMXAgent.getRegisterNewRoutes()));
347    
348                ManagementStrategy managementStrategy = new ManagedManagementStrategy(agent);
349                getContext().setManagementStrategy(managementStrategy);
350    
351                // clear the existing lifecycle strategies define by the DefaultCamelContext constructor
352                getContext().getLifecycleStrategies().clear();
353                getContext().addLifecycleStrategy(new DefaultManagementLifecycleStrategy(getContext()));
354                // set additional configuration from camelJMXAgent
355                boolean onlyId = agent.getOnlyRegisterProcessorWithCustomId() != null && agent.getOnlyRegisterProcessorWithCustomId();
356                getContext().getManagementStrategy().onlyManageProcessorWithCustomId(onlyId);
357                getContext().getManagementStrategy().setStatisticsLevel(camelJMXAgent.getStatisticsLevel());
358            }
359        }
360    
361        protected void initPropertyPlaceholder() throws Exception {
362            if (getCamelPropertyPlaceholder() != null) {
363                CamelPropertyPlaceholderDefinition def = getCamelPropertyPlaceholder();
364    
365                PropertiesComponent pc = new PropertiesComponent();
366                pc.setLocation(def.getLocation());
367    
368                // if using a custom resolver
369                if (ObjectHelper.isNotEmpty(def.getPropertiesResolverRef())) {
370                    PropertiesResolver resolver = CamelContextHelper.mandatoryLookup(getContext(), def.getPropertiesResolverRef(),
371                                                                                     PropertiesResolver.class);
372                    pc.setPropertiesResolver(resolver);
373                }
374    
375                // if using a custom parser
376                if (ObjectHelper.isNotEmpty(def.getPropertiesParserRef())) {
377                    PropertiesParser parser = CamelContextHelper.mandatoryLookup(getContext(), def.getPropertiesParserRef(),
378                                                                                 PropertiesParser.class);
379                    pc.setPropertiesParser(parser);
380                }
381    
382                // register the properties component
383                getContext().addComponent("properties", pc);
384            }
385        }
386    
387        protected void initRouteRefs() throws Exception {
388            // add route refs to existing routes
389            if (getRouteRefs() != null) {
390                for (RouteContextRefDefinition ref : getRouteRefs()) {
391                    List<RouteDefinition> defs = ref.lookupRoutes(getContext());
392                    for (RouteDefinition def : defs) {
393                        if (LOG.isDebugEnabled()) {
394                            LOG.debug("Adding route from " + ref + " -> " + def);
395                        }
396                        // add in top as they are most likely to be common/shared
397                        // which you may want to start first
398                        getRoutes().add(0, def);
399                    }
400                }
401            }
402        }
403    
404        protected abstract <S> S getBeanForType(Class<S> clazz);
405    
406        public void destroy() throws Exception {
407            getContext().stop();
408        }
409    
410        // Properties
411        // -------------------------------------------------------------------------
412        public T getContext() {
413            return getContext(true);
414        }
415    
416        public abstract T getContext(boolean create);
417    
418        public abstract List<RouteDefinition> getRoutes();
419    
420        public abstract List<? extends AbstractCamelEndpointFactoryBean> getEndpoints();
421    
422        public abstract List<? extends AbstractCamelRedeliveryPolicyFactoryBean> getRedeliveryPolicies();
423    
424        public abstract List<InterceptDefinition> getIntercepts();
425    
426        public abstract List<InterceptFromDefinition> getInterceptFroms();
427    
428        public abstract List<InterceptSendToEndpointDefinition> getInterceptSendToEndpoints();
429    
430        public abstract PropertiesDefinition getProperties();
431    
432        public abstract String[] getPackages();
433    
434        public abstract PackageScanDefinition getPackageScan();
435    
436        public abstract void setPackageScan(PackageScanDefinition packageScan);
437    
438        public abstract ContextScanDefinition getContextScan();
439    
440        public abstract void setContextScan(ContextScanDefinition contextScan);
441    
442        public abstract CamelPropertyPlaceholderDefinition getCamelPropertyPlaceholder();
443    
444        public abstract String getTrace();
445    
446        public abstract String getStreamCache();
447    
448        public abstract String getDelayer();
449    
450        public abstract String getHandleFault();
451    
452        public abstract String getAutoStartup();
453    
454        public abstract String getUseMDCLogging();
455    
456        public abstract Boolean getLazyLoadTypeConverters();
457    
458        public abstract CamelJMXAgentDefinition getCamelJMXAgent();
459    
460        public abstract List<RouteBuilderDefinition> getBuilderRefs();
461    
462        public abstract List<RouteContextRefDefinition> getRouteRefs();
463    
464        public abstract String getErrorHandlerRef();
465    
466        public abstract DataFormatsDefinition getDataFormats();
467    
468        public abstract List<OnExceptionDefinition> getOnExceptions();
469    
470        public abstract List<OnCompletionDefinition> getOnCompletions();
471    
472        public abstract ShutdownRoute getShutdownRoute();
473    
474        public abstract ShutdownRunningTask getShutdownRunningTask();
475    
476        public abstract List<ThreadPoolProfileDefinition> getThreadPoolProfiles();
477    
478        public abstract String getDependsOn();
479    
480        // Implementation methods
481        // -------------------------------------------------------------------------
482    
483        /**
484         * Initializes the context
485         *
486         * @param ctx the context
487         * @throws Exception is thrown if error occurred
488         */
489        protected void initCamelContext(T ctx) throws Exception {
490            if (getStreamCache() != null) {
491                ctx.setStreamCaching(CamelContextHelper.parseBoolean(getContext(), getStreamCache()));
492            }
493            if (getTrace() != null) {
494                ctx.setTracing(CamelContextHelper.parseBoolean(getContext(), getTrace()));
495            }
496            if (getDelayer() != null) {
497                ctx.setDelayer(CamelContextHelper.parseLong(getContext(), getDelayer()));
498            }
499            if (getHandleFault() != null) {
500                ctx.setHandleFault(CamelContextHelper.parseBoolean(getContext(), getHandleFault()));
501            }
502            if (getErrorHandlerRef() != null) {
503                ctx.setErrorHandlerBuilder(new ErrorHandlerBuilderRef(getErrorHandlerRef()));
504            }
505            if (getAutoStartup() != null) {
506                ctx.setAutoStartup(CamelContextHelper.parseBoolean(getContext(), getAutoStartup()));
507            }
508            if (getUseMDCLogging() != null) {
509                ctx.setUseMDCLogging(CamelContextHelper.parseBoolean(getContext(), getUseMDCLogging()));
510            }
511            if (getShutdownRoute() != null) {
512                ctx.setShutdownRoute(getShutdownRoute());
513            }
514            if (getShutdownRunningTask() != null) {
515                ctx.setShutdownRunningTask(getShutdownRunningTask());
516            }
517            if (getDataFormats() != null) {
518                ctx.setDataFormats(getDataFormats().asMap());
519            }
520        }
521    
522        protected void initThreadPoolProfiles(T context) throws Exception {
523            Set<String> defaultIds = new HashSet<String>();
524    
525            // lookup and use custom profiles from the registry
526            Map<String, ThreadPoolProfile> profiles = context.getRegistry().lookupByType(ThreadPoolProfile.class);
527            if (profiles != null && !profiles.isEmpty()) {
528                for (Entry<String, ThreadPoolProfile> entry : profiles.entrySet()) {
529                    ThreadPoolProfile profile = entry.getValue();
530                    // do not add if already added, for instance a tracer that is also an InterceptStrategy class
531                    if (profile.isDefaultProfile()) {
532                        LOG.info("Using custom default ThreadPoolProfile with id: " + entry.getKey() + " and implementation: " + profile);
533                        context.getExecutorServiceStrategy().setDefaultThreadPoolProfile(profile);
534                        defaultIds.add(entry.getKey());
535                    } else {
536                        context.getExecutorServiceStrategy().registerThreadPoolProfile(profile);
537                    }
538                }
539            }
540    
541            // use custom profiles defined in the CamelContext
542            if (getThreadPoolProfiles() != null && !getThreadPoolProfiles().isEmpty()) {
543                for (ThreadPoolProfileDefinition profile : getThreadPoolProfiles()) {
544                    if (profile.isDefaultProfile()) {
545                        LOG.info("Using custom default ThreadPoolProfile with id: " + profile.getId() + " and implementation: " + profile);
546                        context.getExecutorServiceStrategy().setDefaultThreadPoolProfile(profile.asThreadPoolProfile(context));
547                        defaultIds.add(profile.getId());
548                    } else {
549                        context.getExecutorServiceStrategy().registerThreadPoolProfile(profile.asThreadPoolProfile(context));
550                    }
551                }
552            }
553    
554            // validate at most one is defined
555            if (defaultIds.size() > 1) {
556                throw new IllegalArgumentException("Only exactly one default ThreadPoolProfile is allowed, was " + defaultIds.size() + " ids: " + defaultIds);
557            }
558        }
559    
560        protected abstract void initBeanPostProcessor(T context);
561    
562        /**
563         * Strategy to install all available routes into the context
564         */
565        protected void installRoutes() throws Exception {
566            List<RouteBuilder> builders = new ArrayList<RouteBuilder>();
567    
568            // lets add route builders added from references
569            if (getBuilderRefs() != null) {
570                for (RouteBuilderDefinition builderRef : getBuilderRefs()) {
571                    RouteBuilder builder = builderRef.createRouteBuilder(getContext());
572                    if (builder != null) {
573                        builders.add(builder);
574                    } else {
575                        // support to get the route here
576                        RoutesBuilder routes = builderRef.createRoutes(getContext());
577                        if (routes != null) {
578                            this.builders.add(routes);
579                        } else {
580                            // Throw the exception that we can't find any build here
581                            throw new CamelException("Cannot find any routes with this RouteBuilder reference: " + builderRef);
582                        }
583                    }
584                }
585            }
586    
587            // install already configured routes
588            for (RoutesBuilder routeBuilder : this.builders) {
589                getContext().addRoutes(routeBuilder);
590            }
591    
592            // install builders
593            for (RouteBuilder builder : builders) {
594                // Inject the annotated resource
595                postProcessBeforeInit(builder);
596                getContext().addRoutes(builder);
597            }
598        }
599    
600        protected abstract void postProcessBeforeInit(RouteBuilder builder);
601    
602        /**
603         * Strategy method to try find {@link org.apache.camel.builder.RouteBuilder} instances on the classpath
604         */
605        protected void findRouteBuilders() throws Exception {
606            // package scan
607            addPackageElementContentsToScanDefinition();
608            PackageScanDefinition packageScanDef = getPackageScan();
609            if (packageScanDef != null && packageScanDef.getPackages().size() > 0) {
610                // use package scan filter
611                PatternBasedPackageScanFilter filter = new PatternBasedPackageScanFilter();
612                // support property placeholders in include and exclude
613                for (String include : packageScanDef.getIncludes()) {
614                    include = getContext().resolvePropertyPlaceholders(include);
615                    filter.addIncludePattern(include);
616                }
617                for (String exclude : packageScanDef.getExcludes()) {
618                    exclude = getContext().resolvePropertyPlaceholders(exclude);
619                    filter.addExcludePattern(exclude);
620                }
621    
622                String[] normalized = normalizePackages(getContext(), packageScanDef.getPackages());
623                findRouteBuildersByPackageScan(normalized, filter, builders);
624            }
625    
626            // context scan
627            ContextScanDefinition contextScanDef = getContextScan();
628            if (contextScanDef != null) {
629                // use package scan filter
630                PatternBasedPackageScanFilter filter = new PatternBasedPackageScanFilter();
631                // support property placeholders in include and exclude
632                for (String include : contextScanDef.getIncludes()) {
633                    include = getContext().resolvePropertyPlaceholders(include);
634                    filter.addIncludePattern(include);
635                }
636                for (String exclude : contextScanDef.getExcludes()) {
637                    exclude = getContext().resolvePropertyPlaceholders(exclude);
638                    filter.addExcludePattern(exclude);
639                }
640                findRouteBuildersByContextScan(filter, builders);
641            }
642        }
643    
644        protected abstract void findRouteBuildersByPackageScan(String[] packages, PackageScanFilter filter, List<RoutesBuilder> builders) throws Exception;
645    
646        protected abstract void findRouteBuildersByContextScan(PackageScanFilter filter, List<RoutesBuilder> builders) throws Exception;
647    
648        private void addPackageElementContentsToScanDefinition() {
649            PackageScanDefinition packageScanDef = getPackageScan();
650    
651            if (getPackages() != null && getPackages().length > 0) {
652                if (packageScanDef == null) {
653                    packageScanDef = new PackageScanDefinition();
654                    setPackageScan(packageScanDef);
655                }
656    
657                for (String pkg : getPackages()) {
658                    packageScanDef.getPackages().add(pkg);
659                }
660            }
661        }
662    
663        private String[] normalizePackages(T context, List<String> unnormalized) throws Exception {
664            List<String> packages = new ArrayList<String>();
665            for (String name : unnormalized) {
666                // it may use property placeholders
667                name = context.resolvePropertyPlaceholders(name);
668                name = ObjectHelper.normalizeClassName(name);
669                if (ObjectHelper.isNotEmpty(name)) {
670                    if (LOG.isTraceEnabled()) {
671                        LOG.trace("Using package: " + name + " to scan for RouteBuilder classes");
672                    }
673                    packages.add(name);
674                }
675            }
676            return packages.toArray(new String[packages.size()]);
677        }
678    
679    }