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