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.spring;
018
019 import java.util.ArrayList;
020 import java.util.List;
021 import javax.xml.bind.annotation.XmlAccessType;
022 import javax.xml.bind.annotation.XmlAccessorType;
023 import javax.xml.bind.annotation.XmlAttribute;
024 import javax.xml.bind.annotation.XmlElement;
025 import javax.xml.bind.annotation.XmlElements;
026 import javax.xml.bind.annotation.XmlRootElement;
027 import javax.xml.bind.annotation.XmlTransient;
028
029 import org.apache.camel.CamelException;
030 import org.apache.camel.Routes;
031 import org.apache.camel.builder.ErrorHandlerBuilder;
032 import org.apache.camel.builder.RouteBuilder;
033 import org.apache.camel.impl.DefaultLifecycleStrategy;
034 import org.apache.camel.management.DefaultInstrumentationAgent;
035 import org.apache.camel.management.InstrumentationLifecycleStrategy;
036 import org.apache.camel.model.FromDefinition;
037 import org.apache.camel.model.IdentifiedType;
038 import org.apache.camel.model.InterceptDefinition;
039 import org.apache.camel.model.InterceptFromDefinition;
040 import org.apache.camel.model.InterceptSendToEndpointDefinition;
041 import org.apache.camel.model.OnCompletionDefinition;
042 import org.apache.camel.model.OnExceptionDefinition;
043 import org.apache.camel.model.PolicyDefinition;
044 import org.apache.camel.model.ProcessorDefinition;
045 import org.apache.camel.model.RouteBuilderDefinition;
046 import org.apache.camel.model.RouteContainer;
047 import org.apache.camel.model.RouteDefinition;
048 import org.apache.camel.model.TransactedDefinition;
049 import org.apache.camel.model.config.PropertiesDefinition;
050 import org.apache.camel.model.dataformat.DataFormatsDefinition;
051 import org.apache.camel.processor.interceptor.Debugger;
052 import org.apache.camel.processor.interceptor.Delayer;
053 import org.apache.camel.processor.interceptor.HandleFault;
054 import org.apache.camel.processor.interceptor.TraceFormatter;
055 import org.apache.camel.processor.interceptor.Tracer;
056 import org.apache.camel.spi.ClassResolver;
057 import org.apache.camel.spi.FactoryFinderResolver;
058 import org.apache.camel.spi.LifecycleStrategy;
059 import org.apache.camel.spi.PackageScanClassResolver;
060 import org.apache.camel.spi.Registry;
061 import org.apache.camel.util.EndpointHelper;
062 import org.apache.camel.util.ObjectHelper;
063 import org.apache.commons.logging.Log;
064 import org.apache.commons.logging.LogFactory;
065 import org.springframework.beans.factory.DisposableBean;
066 import org.springframework.beans.factory.FactoryBean;
067 import org.springframework.beans.factory.InitializingBean;
068 import org.springframework.beans.factory.config.BeanPostProcessor;
069 import org.springframework.context.ApplicationContext;
070 import org.springframework.context.ApplicationContextAware;
071 import org.springframework.context.ApplicationEvent;
072 import org.springframework.context.ApplicationListener;
073 import org.springframework.context.event.ContextRefreshedEvent;
074 import static org.apache.camel.util.ObjectHelper.wrapRuntimeCamelException;
075
076 /**
077 * A Spring {@link FactoryBean} to create and initialize a
078 * {@link SpringCamelContext} and install routes either explicitly configured in
079 * Spring XML or found by searching the classpath for Java classes which extend
080 * {@link RouteBuilder} using the nested {@link #setPackages(String[])}.
081 *
082 * @version $Revision: 781349 $
083 */
084 @XmlRootElement(name = "camelContext")
085 @XmlAccessorType(XmlAccessType.FIELD)
086 public class CamelContextFactoryBean extends IdentifiedType implements RouteContainer, FactoryBean, InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener {
087 private static final Log LOG = LogFactory.getLog(CamelContextFactoryBean.class);
088
089 @XmlAttribute(required = false)
090 private Boolean trace;
091 @XmlAttribute(required = false)
092 private Boolean streamCache = Boolean.TRUE;
093 @XmlAttribute(required = false)
094 private Long delay;
095 @XmlAttribute(required = false)
096 private Boolean handleFault;
097 @XmlAttribute(required = false)
098 private String errorHandlerRef;
099 @XmlAttribute(required = false)
100 private Boolean shouldStartContext = Boolean.TRUE;
101 @XmlElement(name = "properties", required = false)
102 private PropertiesDefinition properties;
103 @XmlElement(name = "package", required = false)
104 private String[] packages = {};
105 @XmlElement(name = "jmxAgent", type = CamelJMXAgentDefinition.class, required = false)
106 private CamelJMXAgentDefinition camelJMXAgent;
107 @XmlElements({
108 @XmlElement(name = "beanPostProcessor", type = CamelBeanPostProcessor.class, required = false),
109 @XmlElement(name = "template", type = CamelProducerTemplateFactoryBean.class, required = false),
110 @XmlElement(name = "consumerTemplate", type = CamelConsumerTemplateFactoryBean.class, required = false),
111 @XmlElement(name = "proxy", type = CamelProxyFactoryDefinition.class, required = false),
112 @XmlElement(name = "export", type = CamelServiceExporterDefinition.class, required = false)})
113 private List beans;
114 @XmlElement(name = "routeBuilder", required = false)
115 private List<RouteBuilderDefinition> builderRefs = new ArrayList<RouteBuilderDefinition>();
116 @XmlElement(name = "endpoint", required = false)
117 private List<CamelEndpointFactoryBean> endpoints;
118 @XmlElement(name = "dataFormats", required = false)
119 private DataFormatsDefinition dataFormats;
120 @XmlElement(name = "onException", required = false)
121 private List<OnExceptionDefinition> onExceptions = new ArrayList<OnExceptionDefinition>();
122 @XmlElement(name = "onCompletion", required = false)
123 private List<OnCompletionDefinition> onCompletions = new ArrayList<OnCompletionDefinition>();
124 @XmlElement(name = "intercept", required = false)
125 private List<InterceptDefinition> intercepts = new ArrayList<InterceptDefinition>();
126 @XmlElement(name = "interceptFrom", required = false)
127 private List<InterceptFromDefinition> interceptFroms = new ArrayList<InterceptFromDefinition>();
128 @XmlElement(name = "interceptSendToEndpoint", required = false)
129 private List<InterceptSendToEndpointDefinition> interceptSendToEndpoints = new ArrayList<InterceptSendToEndpointDefinition>();
130 @XmlElement(name = "route", required = false)
131 private List<RouteDefinition> routes = new ArrayList<RouteDefinition>();
132 @XmlTransient
133 private SpringCamelContext context;
134 @XmlTransient
135 private RouteBuilder routeBuilder;
136 @XmlTransient
137 private List<Routes> additionalBuilders = new ArrayList<Routes>();
138 @XmlTransient
139 private ApplicationContext applicationContext;
140 @XmlTransient
141 private ClassLoader contextClassLoaderOnStart;
142 @XmlTransient
143 private BeanPostProcessor beanPostProcessor;
144
145 public CamelContextFactoryBean() {
146 // Lets keep track of the class loader for when we actually do start things up
147 contextClassLoaderOnStart = Thread.currentThread().getContextClassLoader();
148 }
149
150 public Object getObject() throws Exception {
151 return getContext();
152 }
153
154 public Class getObjectType() {
155 return SpringCamelContext.class;
156 }
157
158 public boolean isSingleton() {
159 return true;
160 }
161
162 public ClassLoader getContextClassLoaderOnStart() {
163 return contextClassLoaderOnStart;
164 }
165
166 public List<Routes> getAdditionalBuilders() {
167 return additionalBuilders;
168 }
169
170 public void afterPropertiesSet() throws Exception {
171 if (properties != null) {
172 getContext().setProperties(properties.asMap());
173 }
174 // set the resolvers first
175 PackageScanClassResolver packageResolver = getBeanForType(PackageScanClassResolver.class);
176 if (packageResolver != null) {
177 getContext().setPackageScanClassResolver(packageResolver);
178 }
179 ClassResolver classResolver = getBeanForType(ClassResolver.class);
180 if (classResolver != null) {
181 getContext().setClassResolver(classResolver);
182 }
183 FactoryFinderResolver factoryFinderResolver = getBeanForType(FactoryFinderResolver.class);
184 if (factoryFinderResolver != null) {
185 getContext().setFactoryFinderResolver(factoryFinderResolver);
186 }
187
188 Debugger debugger = getBeanForType(Debugger.class);
189 if (debugger != null) {
190 getContext().addInterceptStrategy(debugger);
191 }
192
193 Tracer tracer = getBeanForType(Tracer.class);
194 if (tracer != null) {
195 // use formatter if there is a TraceFormatter bean defined
196 TraceFormatter formatter = getBeanForType(TraceFormatter.class);
197 if (formatter != null) {
198 tracer.setFormatter(formatter);
199 }
200 getContext().addInterceptStrategy(tracer);
201 }
202
203 HandleFault handleFault = getBeanForType(HandleFault.class);
204 if (handleFault != null) {
205 getContext().addInterceptStrategy(handleFault);
206 }
207
208 Delayer delayer = getBeanForType(Delayer.class);
209 if (delayer != null) {
210 getContext().addInterceptStrategy(delayer);
211 }
212
213 // set the lifecycle strategy if defined
214 LifecycleStrategy lifecycleStrategy = getBeanForType(LifecycleStrategy.class);
215 if (lifecycleStrategy != null) {
216 getContext().setLifecycleStrategy(lifecycleStrategy);
217 }
218
219 // set the strategy if defined
220 Registry registry = getBeanForType(Registry.class);
221 if (registry != null) {
222 getContext().setRegistry(registry);
223 }
224
225 // Set the application context and camelContext for the beanPostProcessor
226 if (beanPostProcessor != null) {
227 if (beanPostProcessor instanceof ApplicationContextAware) {
228 ((ApplicationContextAware)beanPostProcessor).setApplicationContext(applicationContext);
229 }
230 if (beanPostProcessor instanceof CamelBeanPostProcessor) {
231 ((CamelBeanPostProcessor)beanPostProcessor).setCamelContext(getContext());
232 }
233 }
234
235 // do special preparation for some concepts such as interceptors and policies
236 // this is needed as JAXB does not build excaclty the same model definition as Spring DSL would do
237 // using route builders. So we have here a little custom code to fix the JAXB gaps
238 for (RouteDefinition route : routes) {
239 // interceptors should be first
240 initInterceptors(route);
241 // then on completion
242 initOnCompletions(route);
243 // then polices
244 initPolicies(route);
245 // and last on exception
246 initOnExceptions(route);
247 }
248
249 if (dataFormats != null) {
250 getContext().setDataFormats(dataFormats.asMap());
251 }
252
253 // lets force any lazy creation
254 getContext().addRouteDefinitions(routes);
255
256 // setup JMX agent
257 initJMXAgent();
258
259 if (LOG.isDebugEnabled()) {
260 LOG.debug("Found JAXB created routes: " + getRoutes());
261 }
262 findRouteBuilders();
263 installRoutes();
264 }
265
266 private void initOnExceptions(RouteDefinition route) {
267 List<ProcessorDefinition<?>> outputs = new ArrayList<ProcessorDefinition<?>>();
268 List<ProcessorDefinition<?>> exceptionHandlers = new ArrayList<ProcessorDefinition<?>>();
269
270 // add global on exceptions if any
271 if (onExceptions != null && !onExceptions.isEmpty()) {
272 // on exceptions must be added at top, so the route flow is correct as
273 // on exceptions should be the first outputs
274 route.getOutputs().addAll(0, onExceptions);
275 }
276
277 for (ProcessorDefinition output : route.getOutputs()) {
278 // split into on exception and regular outputs
279 if (output instanceof OnExceptionDefinition) {
280 exceptionHandlers.add(output);
281 } else {
282 outputs.add(output);
283 }
284 }
285
286 // clearing the outputs
287 route.clearOutput();
288
289 // add exception handlers as top children
290 route.getOutputs().addAll(exceptionHandlers);
291
292 // and the remaining outputs
293 route.getOutputs().addAll(outputs);
294 }
295
296 private void initInterceptors(RouteDefinition route) {
297
298 // configure intercept
299 for (InterceptDefinition intercept : getIntercepts()) {
300 intercept.afterPropertiesSet();
301 // add as first output so intercept is handled before the acutal route and that gives
302 // us the needed head start to init and be able to intercept all the remaining processing steps
303 route.getOutputs().add(0, intercept);
304 }
305
306 // configure intercept from
307 for (InterceptFromDefinition intercept : getInterceptFroms()) {
308
309 // should we only apply interceptor for a given endpoint uri
310 boolean match = true;
311 if (intercept.getUri() != null) {
312 match = false;
313 for (FromDefinition input : route.getInputs()) {
314 if (EndpointHelper.matchEndpoint(input.getUri(), intercept.getUri())) {
315 match = true;
316 break;
317 }
318 }
319 }
320
321 if (match) {
322 intercept.afterPropertiesSet();
323 // add as first output so intercept is handled before the acutal route and that gives
324 // us the needed head start to init and be able to intercept all the remaining processing steps
325 route.getOutputs().add(0, intercept);
326 }
327 }
328
329 // configure intercept send to endpoint
330 for (InterceptSendToEndpointDefinition intercept : getInterceptSendToEndpoints()) {
331 intercept.afterPropertiesSet();
332 // add as first output so intercept is handled before the acutal route and that gives
333 // us the needed head start to init and be able to intercept all the remaining processing steps
334 route.getOutputs().add(0, intercept);
335 }
336
337 }
338
339 private void initOnCompletions(RouteDefinition route) {
340 // only add global onCompletion if there are no route alredy
341 boolean hasRouteScope = false;
342 for (ProcessorDefinition out : route.getOutputs()) {
343 if (out instanceof OnCompletionDefinition) {
344 hasRouteScope = true;
345 break;
346 }
347 }
348 // only add global onCompletion if we do *not* have any route onCompletion defined in the route
349 // add onCompletion *after* intercept, as its important intercept is first
350 if (!hasRouteScope) {
351 int index = 0;
352 for (int i = 0; i < route.getOutputs().size(); i++) {
353 index = i;
354 ProcessorDefinition out = route.getOutputs().get(i);
355 if (!(out instanceof InterceptDefinition)) {
356 break;
357 }
358 }
359 route.getOutputs().addAll(index, getOnCompletions());
360 }
361 }
362
363 private void initPolicies(RouteDefinition route) {
364 // setup the policies as JAXB yet again have not created a correct model for us
365 List<ProcessorDefinition> types = route.getOutputs();
366 // we need to types as transacted cannot extend policy due JAXB limitations
367 PolicyDefinition policy = null;
368 TransactedDefinition transacted = null;
369 for (ProcessorDefinition type : types) {
370 if (type instanceof PolicyDefinition) {
371 policy = (PolicyDefinition) type;
372 } else if (type instanceof TransactedDefinition) {
373 transacted = (TransactedDefinition) type;
374 } else if (policy != null) {
375 // the outputs should be moved to the policy
376 policy.addOutput(type);
377 } else if (transacted != null) {
378 // the outputs should be moved to the transacted policy
379 transacted.addOutput(type);
380 }
381 }
382 // did we find a policy if so replace it as the only output on the route
383 if (policy != null) {
384 route.clearOutput();
385 route.addOutput(policy);
386 } else if (transacted != null) {
387 route.clearOutput();
388 route.addOutput(transacted);
389 }
390 }
391
392 private void initJMXAgent() throws Exception {
393 if (camelJMXAgent != null && camelJMXAgent.isDisabled()) {
394 LOG.info("JMXAgent disabled");
395 getContext().setLifecycleStrategy(new DefaultLifecycleStrategy());
396 } else if (camelJMXAgent != null) {
397 DefaultInstrumentationAgent agent = new DefaultInstrumentationAgent();
398 agent.setConnectorPort(camelJMXAgent.getConnectorPort());
399 agent.setCreateConnector(camelJMXAgent.isCreateConnector());
400 agent.setMBeanObjectDomainName(camelJMXAgent.getMbeanObjectDomainName());
401 agent.setMBeanServerDefaultDomain(camelJMXAgent.getMbeanServerDefaultDomain());
402 agent.setRegistryPort(camelJMXAgent.getRegistryPort());
403 agent.setServiceUrlPath(camelJMXAgent.getServiceUrlPath());
404 agent.setUsePlatformMBeanServer(camelJMXAgent.isUsePlatformMBeanServer());
405 agent.setOnlyRegisterProcessorWithCustomId(camelJMXAgent.getOnlyRegisterProcessorWithCustomId());
406
407 LOG.info("JMXAgent enabled: " + camelJMXAgent);
408 getContext().setLifecycleStrategy(new InstrumentationLifecycleStrategy(agent));
409 }
410 }
411
412 @SuppressWarnings("unchecked")
413 private <T> T getBeanForType(Class<T> clazz) {
414 T bean = null;
415 String[] names = getApplicationContext().getBeanNamesForType(clazz, true, true);
416 if (names.length == 1) {
417 bean = (T) getApplicationContext().getBean(names[0], clazz);
418 }
419 if (bean == null) {
420 ApplicationContext parentContext = getApplicationContext().getParent();
421 if (parentContext != null) {
422 names = parentContext.getBeanNamesForType(clazz, true, true);
423 if (names.length == 1) {
424 bean = (T) parentContext.getBean(names[0], clazz);
425 }
426 }
427 }
428 return bean;
429
430 }
431
432 public void destroy() throws Exception {
433 getContext().stop();
434 }
435
436 public void onApplicationEvent(ApplicationEvent event) {
437 if (context != null) {
438 // let the spring camel context handle the events
439 context.onApplicationEvent(event);
440 } else {
441 if (LOG.isDebugEnabled()) {
442 LOG.debug("Publishing spring-event: " + event);
443 }
444
445 if (event instanceof ContextRefreshedEvent) {
446 // now lets start the CamelContext so that all its possible
447 // dependencies are initialized
448 try {
449 LOG.debug("Starting the context now!");
450 getContext().start();
451 } catch (Exception e) {
452 throw wrapRuntimeCamelException(e);
453 }
454 }
455 }
456 }
457
458 // Properties
459 // -------------------------------------------------------------------------
460 public SpringCamelContext getContext() throws Exception {
461 if (context == null) {
462 context = createContext();
463 }
464 return context;
465 }
466
467 public void setContext(SpringCamelContext context) {
468 this.context = context;
469 }
470
471 public List<RouteDefinition> getRoutes() {
472 return routes;
473 }
474
475 public void setRoutes(List<RouteDefinition> routes) {
476 this.routes = routes;
477 }
478
479 public List<InterceptDefinition> getIntercepts() {
480 return intercepts;
481 }
482
483 public void setIntercepts(List<InterceptDefinition> intercepts) {
484 this.intercepts = intercepts;
485 }
486
487 public List<InterceptFromDefinition> getInterceptFroms() {
488 return interceptFroms;
489 }
490
491 public void setInterceptFroms(List<InterceptFromDefinition> interceptFroms) {
492 this.interceptFroms = interceptFroms;
493 }
494
495 public List<InterceptSendToEndpointDefinition> getInterceptSendToEndpoints() {
496 return interceptSendToEndpoints;
497 }
498
499 public void setInterceptSendToEndpoints(List<InterceptSendToEndpointDefinition> interceptSendToEndpoints) {
500 this.interceptSendToEndpoints = interceptSendToEndpoints;
501 }
502
503 public RouteBuilder getRouteBuilder() {
504 return routeBuilder;
505 }
506
507 /**
508 * Set a single {@link RouteBuilder} to be used to create the default routes
509 * on startup
510 */
511 public void setRouteBuilder(RouteBuilder routeBuilder) {
512 this.routeBuilder = routeBuilder;
513 }
514
515 /**
516 * Set a collection of {@link RouteBuilder} instances to be used to create
517 * the default routes on startup
518 */
519 public void setRouteBuilders(RouteBuilder[] builders) {
520 for (RouteBuilder builder : builders) {
521 additionalBuilders.add(builder);
522 }
523 }
524
525 public ApplicationContext getApplicationContext() {
526 if (applicationContext == null) {
527 throw new IllegalArgumentException("No applicationContext has been injected!");
528 }
529 return applicationContext;
530 }
531
532 public void setApplicationContext(ApplicationContext applicationContext) {
533 this.applicationContext = applicationContext;
534 }
535
536 public PropertiesDefinition getProperties() {
537 return properties;
538 }
539
540 public void setProperties(PropertiesDefinition properties) {
541 this.properties = properties;
542 }
543
544 public String[] getPackages() {
545 return packages;
546 }
547
548 /**
549 * Sets the package names to be recursively searched for Java classes which
550 * extend {@link RouteBuilder} to be auto-wired up to the
551 * {@link SpringCamelContext} as a route. Note that classes are excluded if
552 * they are specifically configured in the spring.xml
553 *
554 * @param packages the package names which are recursively searched
555 */
556 public void setPackages(String[] packages) {
557 this.packages = packages;
558 }
559
560 public void setBeanPostProcessor(BeanPostProcessor postProcessor) {
561 this.beanPostProcessor = postProcessor;
562 }
563
564 public BeanPostProcessor getBeanPostProcessor() {
565 return beanPostProcessor;
566 }
567
568 public void setCamelJMXAgent(CamelJMXAgentDefinition agent) {
569 camelJMXAgent = agent;
570 }
571
572 public Boolean getTrace() {
573 return trace;
574 }
575
576 public void setTrace(Boolean trace) {
577 this.trace = trace;
578 }
579
580 public Boolean getStreamCache() {
581 return streamCache;
582 }
583
584 public void setStreamCache(Boolean streamCache) {
585 this.streamCache = streamCache;
586 }
587
588 public Long getDelay() {
589 return delay;
590 }
591
592 public void setDelay(Long delay) {
593 this.delay = delay;
594 }
595
596 public Boolean getHandleFault() {
597 return handleFault;
598 }
599
600 public void setHandleFault(Boolean handleFault) {
601 this.handleFault = handleFault;
602 }
603
604 public CamelJMXAgentDefinition getCamelJMXAgent() {
605 return camelJMXAgent;
606 }
607
608 public List<RouteBuilderDefinition> getBuilderRefs() {
609 return builderRefs;
610 }
611
612 public void setBuilderRefs(List<RouteBuilderDefinition> builderRefs) {
613 this.builderRefs = builderRefs;
614 }
615
616 public String getErrorHandlerRef() {
617 return errorHandlerRef;
618 }
619
620 /**
621 * Sets the name of the error handler object used to default the error handling strategy
622 *
623 * @param errorHandlerRef the Spring bean ref of the error handler
624 */
625 public void setErrorHandlerRef(String errorHandlerRef) {
626 this.errorHandlerRef = errorHandlerRef;
627 }
628
629 public Boolean getShouldStartContext() {
630 return shouldStartContext;
631 }
632
633 public void setShouldStartContext(Boolean shouldStartContext) {
634 this.shouldStartContext = shouldStartContext;
635 }
636
637 public void setDataFormats(DataFormatsDefinition dataFormats) {
638 this.dataFormats = dataFormats;
639 }
640
641 public DataFormatsDefinition getDataFormats() {
642 return dataFormats;
643 }
644
645 public void setOnExceptions(List<OnExceptionDefinition> onExceptions) {
646 this.onExceptions = onExceptions;
647 }
648
649 public List<OnExceptionDefinition> getOnExceptions() {
650 return onExceptions;
651 }
652
653 public List<OnCompletionDefinition> getOnCompletions() {
654 return onCompletions;
655 }
656
657 public void setOnCompletions(List<OnCompletionDefinition> onCompletions) {
658 this.onCompletions = onCompletions;
659 }
660
661 // Implementation methods
662 // -------------------------------------------------------------------------
663
664 /**
665 * Create the context
666 */
667 protected SpringCamelContext createContext() {
668 SpringCamelContext ctx = new SpringCamelContext(getApplicationContext());
669 ctx.setName(getId());
670 if (streamCache != null) {
671 ctx.setStreamCaching(streamCache);
672 }
673 if (trace != null) {
674 ctx.setTrace(trace);
675 }
676 if (delay != null) {
677 ctx.setDelay(delay);
678 }
679 if (handleFault != null) {
680 ctx.setHandleFault(handleFault);
681 }
682 if (errorHandlerRef != null) {
683 ErrorHandlerBuilder errorHandlerBuilder = (ErrorHandlerBuilder) getApplicationContext().getBean(errorHandlerRef, ErrorHandlerBuilder.class);
684 if (errorHandlerBuilder == null) {
685 throw new IllegalArgumentException("Could not find bean: " + errorHandlerRef);
686 }
687 ctx.setErrorHandlerBuilder(errorHandlerBuilder);
688 }
689
690 if (shouldStartContext != null) {
691 ctx.setShouldStartContext(shouldStartContext);
692 }
693
694 return ctx;
695 }
696
697 /**
698 * Strategy to install all available routes into the context
699 */
700 @SuppressWarnings("unchecked")
701 protected void installRoutes() throws Exception {
702 List<RouteBuilder> builders = new ArrayList<RouteBuilder>();
703
704 if (routeBuilder != null) {
705 builders.add(routeBuilder);
706 }
707
708 // lets add route builders added from references
709 if (builderRefs != null) {
710 for (RouteBuilderDefinition builderRef : builderRefs) {
711 RouteBuilder builder = builderRef.createRouteBuilder(getContext());
712 if (builder != null) {
713 builders.add(builder);
714 } else {
715 // support to get the route here
716 Routes routes = builderRef.createRoutes(getContext());
717 if (routes != null) {
718 additionalBuilders.add(routes);
719 } else {
720 // Throw the exception that we can't find any build here
721 throw new CamelException("Cannot find any routes with this RouteBuilder reference: " + builderRef);
722 }
723 }
724
725 }
726 }
727
728 // install already configured routes
729 for (Routes routeBuilder : additionalBuilders) {
730 getContext().addRoutes(routeBuilder);
731 }
732
733 // install builders
734 for (RouteBuilder builder : builders) {
735 if (beanPostProcessor != null) {
736 // Inject the annotated resource
737 beanPostProcessor.postProcessBeforeInitialization(builder, builder.toString());
738 }
739 getContext().addRoutes(builder);
740 }
741 }
742
743 /**
744 * Strategy method to try find {@link RouteBuilder} instances on the classpath
745 */
746 protected void findRouteBuilders() throws Exception {
747 List<String> packages = new ArrayList<String>();
748
749 if (getPackages() != null && getPackages().length > 0) {
750
751 // normalize packages as end user can have inserted spaces or \n or the likes
752 for (String name : getPackages()) {
753 name = ObjectHelper.normalizeClassName(name);
754 if (ObjectHelper.isNotEmpty(name)) {
755 packages.add(name);
756 }
757 }
758 String[] normalized = packages.toArray(new String[packages.size()]);
759
760 RouteBuilderFinder finder = new RouteBuilderFinder(getContext(), normalized, getContextClassLoaderOnStart(),
761 getBeanPostProcessor(), getContext().getPackageScanClassResolver());
762 finder.appendBuilders(getAdditionalBuilders());
763 }
764 }
765
766 }