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.blueprint; 018 019 import java.util.ArrayList; 020 import java.util.Collection; 021 import java.util.List; 022 import java.util.Properties; 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.aries.blueprint.ExtendedBlueprintContainer; 032 import org.apache.camel.RoutesBuilder; 033 import org.apache.camel.ShutdownRoute; 034 import org.apache.camel.ShutdownRunningTask; 035 import org.apache.camel.builder.RouteBuilder; 036 import org.apache.camel.component.properties.PropertiesComponent; 037 import org.apache.camel.core.osgi.OsgiCamelContextPublisher; 038 import org.apache.camel.core.osgi.OsgiEventAdminNotifier; 039 import org.apache.camel.core.osgi.utils.BundleDelegatingClassLoader; 040 import org.apache.camel.core.xml.AbstractCamelContextFactoryBean; 041 import org.apache.camel.core.xml.CamelJMXAgentDefinition; 042 import org.apache.camel.core.xml.CamelPropertyPlaceholderDefinition; 043 import org.apache.camel.core.xml.CamelServiceExporterDefinition; 044 import org.apache.camel.model.ContextScanDefinition; 045 import org.apache.camel.model.InterceptDefinition; 046 import org.apache.camel.model.InterceptFromDefinition; 047 import org.apache.camel.model.InterceptSendToEndpointDefinition; 048 import org.apache.camel.model.OnCompletionDefinition; 049 import org.apache.camel.model.OnExceptionDefinition; 050 import org.apache.camel.model.PackageScanDefinition; 051 import org.apache.camel.model.RouteBuilderDefinition; 052 import org.apache.camel.model.RouteContextRefDefinition; 053 import org.apache.camel.model.RouteDefinition; 054 import org.apache.camel.model.ThreadPoolProfileDefinition; 055 import org.apache.camel.model.config.PropertiesDefinition; 056 import org.apache.camel.model.dataformat.DataFormatsDefinition; 057 import org.apache.camel.spi.PackageScanFilter; 058 import org.apache.camel.spi.Registry; 059 import org.osgi.framework.BundleContext; 060 import org.osgi.framework.ServiceReference; 061 import org.osgi.service.blueprint.container.BlueprintContainer; 062 import org.slf4j.Logger; 063 import org.slf4j.LoggerFactory; 064 065 /** 066 * A bean to create and initialize a {@link BlueprintCamelContext} 067 * and install routes either explicitly configured in 068 * Blueprint XML or found by searching the classpath for Java classes which extend 069 * {@link RouteBuilder} using the nested {@link #setPackages(String[])}. 070 * 071 * @version 072 */ 073 @XmlRootElement(name = "camelContext") 074 @XmlAccessorType(XmlAccessType.FIELD) 075 public class CamelContextFactoryBean extends AbstractCamelContextFactoryBean<BlueprintCamelContext> { 076 private static final Logger LOG = LoggerFactory.getLogger(CamelContextFactoryBean.class); 077 078 @XmlAttribute(name = "depends-on", required = false) 079 private String dependsOn; 080 @XmlAttribute(required = false) 081 private String trace; 082 @XmlAttribute(required = false) 083 private String streamCache = "false"; 084 @XmlAttribute(required = false) 085 private String delayer; 086 @XmlAttribute(required = false) 087 private String handleFault; 088 @XmlAttribute(required = false) 089 private String errorHandlerRef; 090 @XmlAttribute(required = false) 091 private String autoStartup = "true"; 092 @XmlAttribute(required = false) 093 private String useMDCLogging; 094 @XmlAttribute(required = false) 095 private String useBreadcrumb; 096 @XmlAttribute(required = false) 097 private String managementNamePattern; 098 @XmlAttribute(required = false) 099 private Boolean useBlueprintPropertyResolver; 100 @XmlAttribute(required = false) 101 private ShutdownRoute shutdownRoute; 102 @XmlAttribute(required = false) 103 private ShutdownRunningTask shutdownRunningTask; 104 @XmlAttribute(required = false) 105 @Deprecated 106 private Boolean lazyLoadTypeConverters; 107 @XmlElement(name = "properties", required = false) 108 private PropertiesDefinition properties; 109 @XmlElement(name = "propertyPlaceholder", type = CamelPropertyPlaceholderDefinition.class, required = false) 110 private CamelPropertyPlaceholderDefinition camelPropertyPlaceholder; 111 @XmlElement(name = "package", required = false) 112 private String[] packages = {}; 113 @XmlElement(name = "packageScan", type = PackageScanDefinition.class, required = false) 114 private PackageScanDefinition packageScan; 115 @XmlElement(name = "contextScan", type = ContextScanDefinition.class, required = false) 116 private ContextScanDefinition contextScan; 117 @XmlElement(name = "jmxAgent", type = CamelJMXAgentDefinition.class, required = false) 118 private CamelJMXAgentDefinition camelJMXAgent; 119 @XmlElements({ 120 @XmlElement(name = "template", type = CamelProducerTemplateFactoryBean.class, required = false), 121 @XmlElement(name = "consumerTemplate", type = CamelConsumerTemplateFactoryBean.class, required = false), 122 @XmlElement(name = "proxy", type = CamelProxyFactoryBean.class, required = false), 123 @XmlElement(name = "export", type = CamelServiceExporterDefinition.class, required = false), 124 @XmlElement(name = "errorHandler", type = CamelErrorHandlerFactoryBean.class, required = false) 125 }) 126 private List<?> beans; 127 @XmlElement(name = "routeBuilder", required = false) 128 private List<RouteBuilderDefinition> builderRefs = new ArrayList<RouteBuilderDefinition>(); 129 @XmlElement(name = "routeContextRef", required = false) 130 private List<RouteContextRefDefinition> routeRefs = new ArrayList<RouteContextRefDefinition>(); 131 @XmlElement(name = "threadPoolProfile", required = false) 132 private List<ThreadPoolProfileDefinition> threadPoolProfiles; 133 @XmlElement(name = "threadPool", required = false) 134 private List<CamelThreadPoolFactoryBean> threadPools; 135 @XmlElement(name = "endpoint", required = false) 136 private List<CamelEndpointFactoryBean> endpoints; 137 @XmlElement(name = "dataFormats", required = false) 138 private DataFormatsDefinition dataFormats; 139 @XmlElement(name = "redeliveryPolicyProfile", required = false) 140 private List<CamelRedeliveryPolicyFactoryBean> redeliveryPolicies; 141 @XmlElement(name = "onException", required = false) 142 private List<OnExceptionDefinition> onExceptions = new ArrayList<OnExceptionDefinition>(); 143 @XmlElement(name = "onCompletion", required = false) 144 private List<OnCompletionDefinition> onCompletions = new ArrayList<OnCompletionDefinition>(); 145 @XmlElement(name = "intercept", required = false) 146 private List<InterceptDefinition> intercepts = new ArrayList<InterceptDefinition>(); 147 @XmlElement(name = "interceptFrom", required = false) 148 private List<InterceptFromDefinition> interceptFroms = new ArrayList<InterceptFromDefinition>(); 149 @XmlElement(name = "interceptSendToEndpoint", required = false) 150 private List<InterceptSendToEndpointDefinition> interceptSendToEndpoints = new ArrayList<InterceptSendToEndpointDefinition>(); 151 @XmlElement(name = "route", required = false) 152 private List<RouteDefinition> routes = new ArrayList<RouteDefinition>(); 153 @XmlTransient 154 private BlueprintCamelContext context; 155 @XmlTransient 156 private BlueprintContainer blueprintContainer; 157 @XmlTransient 158 private BundleContext bundleContext; 159 @XmlTransient 160 private boolean implicitId; 161 162 163 public Class<BlueprintCamelContext> getObjectType() { 164 return BlueprintCamelContext.class; 165 } 166 167 @Override 168 public BlueprintCamelContext getContext(boolean create) { 169 if (context == null && create) { 170 context = createContext(); 171 if (!isImplicitId()) { 172 context.setName(getId()); 173 } 174 } 175 return context; 176 } 177 178 public void setBlueprintContainer(BlueprintContainer blueprintContainer) { 179 this.blueprintContainer = blueprintContainer; 180 } 181 182 public void setBundleContext(BundleContext bundleContext) { 183 this.bundleContext = bundleContext; 184 } 185 186 protected BlueprintCamelContext createContext() { 187 return new BlueprintCamelContext(bundleContext, blueprintContainer); 188 } 189 190 @Override 191 protected void initCustomRegistry(BlueprintCamelContext context) { 192 Registry registry = getBeanForType(Registry.class); 193 if (registry != null) { 194 LOG.info("Using custom Registry: " + registry); 195 context.setRegistry(registry); 196 } 197 } 198 199 @Override 200 protected <S> S getBeanForType(Class<S> clazz) { 201 Collection<S> objects = BlueprintContainerRegistry.lookupByType(blueprintContainer, clazz).values(); 202 if (objects.size() == 1) { 203 return objects.iterator().next(); 204 } 205 return null; 206 } 207 208 @Override 209 protected void initPropertyPlaceholder() throws Exception { 210 super.initPropertyPlaceholder(); 211 212 // if blueprint property resolver is enabled on CamelContext then bridge PropertiesComponent to blueprint 213 if (isUseBlueprintPropertyResolver()) { 214 // lookup existing configured properties component 215 PropertiesComponent pc = getContext().getComponent("properties", PropertiesComponent.class); 216 217 BlueprintPropertiesParser parser = new BlueprintPropertiesParser(pc, blueprintContainer, pc.getPropertiesParser()); 218 BlueprintPropertiesResolver resolver = new BlueprintPropertiesResolver(pc.getPropertiesResolver(), parser); 219 220 // any extra properties 221 ServiceReference ref = bundleContext.getServiceReference(PropertiesComponent.OVERRIDE_PROPERTIES); 222 if (ref != null) { 223 Properties extra = (Properties) bundleContext.getService(ref); 224 if (extra != null) { 225 pc.setOverrideProperties(extra); 226 } 227 } 228 229 // no locations has been set, so its a default component 230 if (pc.getLocations() == null) { 231 StringBuilder sb = new StringBuilder(); 232 String[] ids = parser.lookupPropertyPlaceholderIds(); 233 for (String id : ids) { 234 sb.append("blueprint:").append(id).append(","); 235 } 236 if (sb.length() > 0) { 237 // location supports multiple separated by comma 238 pc.setLocation(sb.toString()); 239 } 240 } 241 242 if (pc.getLocations() != null) { 243 // bridge camel properties with blueprint 244 pc.setPropertiesParser(parser); 245 pc.setPropertiesResolver(resolver); 246 } 247 } 248 } 249 250 @Override 251 protected void initBeanPostProcessor(BlueprintCamelContext context) { 252 } 253 254 @Override 255 protected void postProcessBeforeInit(RouteBuilder builder) { 256 } 257 258 @Override 259 protected void findRouteBuildersByPackageScan(String[] packages, PackageScanFilter filter, List<RoutesBuilder> builders) throws Exception { 260 // add filter to class resolver which then will filter 261 getContext().getPackageScanClassResolver().addFilter(filter); 262 ClassLoader classLoader = new BundleDelegatingClassLoader(((ExtendedBlueprintContainer) blueprintContainer).getBundleContext().getBundle()); 263 PackageScanRouteBuilderFinder finder = new PackageScanRouteBuilderFinder(getContext(), packages, classLoader, 264 getContext().getPackageScanClassResolver()); 265 finder.appendBuilders(builders); 266 267 // and remove the filter 268 getContext().getPackageScanClassResolver().removeFilter(filter); 269 } 270 271 @Override 272 protected void findRouteBuildersByContextScan(PackageScanFilter filter, List<RoutesBuilder> builders) throws Exception { 273 ContextScanRouteBuilderFinder finder = new ContextScanRouteBuilderFinder(getContext(), filter); 274 finder.appendBuilders(builders); 275 } 276 277 @Override 278 public void afterPropertiesSet() throws Exception { 279 super.afterPropertiesSet(); 280 // setup the application context classloader with the bundle delegating classloader 281 ClassLoader cl = new BundleDelegatingClassLoader(((ExtendedBlueprintContainer) blueprintContainer).getBundleContext().getBundle()); 282 LOG.debug("Set the application context classloader to: {}", cl); 283 getContext().setApplicationContextClassLoader(cl); 284 getContext().getManagementStrategy().addEventNotifier(new OsgiCamelContextPublisher(bundleContext)); 285 try { 286 getClass().getClassLoader().loadClass("org.osgi.service.event.EventAdmin"); 287 getContext().getManagementStrategy().addEventNotifier(new OsgiEventAdminNotifier(bundleContext)); 288 } catch (Throwable t) { 289 // Ignore, if the EventAdmin package is not available, just don't use it 290 LOG.debug("EventAdmin package is not available, just don't use it"); 291 } 292 } 293 294 public String getDependsOn() { 295 return dependsOn; 296 } 297 298 public void setDependsOn(String dependsOn) { 299 this.dependsOn = dependsOn; 300 } 301 302 public String getAutoStartup() { 303 return autoStartup; 304 } 305 306 public void setAutoStartup(String autoStartup) { 307 this.autoStartup = autoStartup; 308 } 309 310 public String getUseMDCLogging() { 311 return useMDCLogging; 312 } 313 314 public void setUseMDCLogging(String useMDCLogging) { 315 this.useMDCLogging = useMDCLogging; 316 } 317 318 public String getUseBreadcrumb() { 319 return useBreadcrumb; 320 } 321 322 public void setUseBreadcrumb(String useBreadcrumb) { 323 this.useBreadcrumb = useBreadcrumb; 324 } 325 326 public String getManagementNamePattern() { 327 return managementNamePattern; 328 } 329 330 public void setManagementNamePattern(String managementNamePattern) { 331 this.managementNamePattern = managementNamePattern; 332 } 333 334 @Deprecated 335 public Boolean getLazyLoadTypeConverters() { 336 // use false by default 337 return lazyLoadTypeConverters != null ? lazyLoadTypeConverters : Boolean.FALSE; 338 } 339 340 @Deprecated 341 public void setLazyLoadTypeConverters(Boolean lazyLoadTypeConverters) { 342 this.lazyLoadTypeConverters = lazyLoadTypeConverters; 343 } 344 345 public ShutdownRoute getShutdownRoute() { 346 return shutdownRoute; 347 } 348 349 public void setShutdownRoute(ShutdownRoute shutdownRoute) { 350 this.shutdownRoute = shutdownRoute; 351 } 352 353 public ShutdownRunningTask getShutdownRunningTask() { 354 return shutdownRunningTask; 355 } 356 357 public void setShutdownRunningTask(ShutdownRunningTask shutdownRunningTask) { 358 this.shutdownRunningTask = shutdownRunningTask; 359 } 360 361 public CamelPropertyPlaceholderDefinition getCamelPropertyPlaceholder() { 362 return camelPropertyPlaceholder; 363 } 364 365 public void setCamelPropertyPlaceholder(CamelPropertyPlaceholderDefinition camelPropertyPlaceholder) { 366 this.camelPropertyPlaceholder = camelPropertyPlaceholder; 367 } 368 369 public List<RouteContextRefDefinition> getRouteRefs() { 370 return routeRefs; 371 } 372 373 public void setRouteRefs(List<RouteContextRefDefinition> routeRefs) { 374 this.routeRefs = routeRefs; 375 } 376 377 public List<CamelRedeliveryPolicyFactoryBean> getRedeliveryPolicies() { 378 return redeliveryPolicies; 379 } 380 381 public void setRedeliveryPolicies(List<CamelRedeliveryPolicyFactoryBean> redeliveryPolicies) { 382 this.redeliveryPolicies = redeliveryPolicies; 383 } 384 385 public List<ThreadPoolProfileDefinition> getThreadPoolProfiles() { 386 return threadPoolProfiles; 387 } 388 389 public void setThreadPoolProfiles(List<ThreadPoolProfileDefinition> threadPoolProfiles) { 390 this.threadPoolProfiles = threadPoolProfiles; 391 } 392 393 public List<CamelThreadPoolFactoryBean> getThreadPools() { 394 return threadPools; 395 } 396 397 public void setThreadPools(List<CamelThreadPoolFactoryBean> threadPools) { 398 this.threadPools = threadPools; 399 } 400 401 public String getTrace() { 402 return trace; 403 } 404 405 public void setTrace(String trace) { 406 this.trace = trace; 407 } 408 409 public String getStreamCache() { 410 return streamCache; 411 } 412 413 public void setStreamCache(String streamCache) { 414 this.streamCache = streamCache; 415 } 416 417 public String getDelayer() { 418 return delayer; 419 } 420 421 public void setDelayer(String delayer) { 422 this.delayer = delayer; 423 } 424 425 public String getHandleFault() { 426 return handleFault; 427 } 428 429 public void setHandleFault(String handleFault) { 430 this.handleFault = handleFault; 431 } 432 433 public String getErrorHandlerRef() { 434 return errorHandlerRef; 435 } 436 437 public void setErrorHandlerRef(String errorHandlerRef) { 438 this.errorHandlerRef = errorHandlerRef; 439 } 440 441 public PropertiesDefinition getProperties() { 442 return properties; 443 } 444 445 public void setProperties(PropertiesDefinition properties) { 446 this.properties = properties; 447 } 448 449 public String[] getPackages() { 450 return packages; 451 } 452 453 public void setPackages(String[] packages) { 454 this.packages = packages; 455 } 456 457 public PackageScanDefinition getPackageScan() { 458 return packageScan; 459 } 460 461 public void setPackageScan(PackageScanDefinition packageScan) { 462 this.packageScan = packageScan; 463 } 464 465 public ContextScanDefinition getContextScan() { 466 return contextScan; 467 } 468 469 public void setContextScan(ContextScanDefinition contextScan) { 470 this.contextScan = contextScan; 471 } 472 473 public CamelJMXAgentDefinition getCamelJMXAgent() { 474 return camelJMXAgent; 475 } 476 477 public void setCamelJMXAgent(CamelJMXAgentDefinition camelJMXAgent) { 478 this.camelJMXAgent = camelJMXAgent; 479 } 480 481 public List<?> getBeans() { 482 return beans; 483 } 484 485 public void setBeans(List<?> beans) { 486 this.beans = beans; 487 } 488 489 public List<RouteBuilderDefinition> getBuilderRefs() { 490 return builderRefs; 491 } 492 493 public void setBuilderRefs(List<RouteBuilderDefinition> builderRefs) { 494 this.builderRefs = builderRefs; 495 } 496 497 public List<CamelEndpointFactoryBean> getEndpoints() { 498 return endpoints; 499 } 500 501 public void setEndpoints(List<CamelEndpointFactoryBean> endpoints) { 502 this.endpoints = endpoints; 503 } 504 505 public DataFormatsDefinition getDataFormats() { 506 return dataFormats; 507 } 508 509 public void setDataFormats(DataFormatsDefinition dataFormats) { 510 this.dataFormats = dataFormats; 511 } 512 513 public List<OnExceptionDefinition> getOnExceptions() { 514 return onExceptions; 515 } 516 517 public void setOnExceptions(List<OnExceptionDefinition> onExceptions) { 518 this.onExceptions = onExceptions; 519 } 520 521 public List<OnCompletionDefinition> getOnCompletions() { 522 return onCompletions; 523 } 524 525 public void setOnCompletions(List<OnCompletionDefinition> onCompletions) { 526 this.onCompletions = onCompletions; 527 } 528 529 public List<InterceptDefinition> getIntercepts() { 530 return intercepts; 531 } 532 533 public void setIntercepts(List<InterceptDefinition> intercepts) { 534 this.intercepts = intercepts; 535 } 536 537 public List<InterceptFromDefinition> getInterceptFroms() { 538 return interceptFroms; 539 } 540 541 public void setInterceptFroms(List<InterceptFromDefinition> interceptFroms) { 542 this.interceptFroms = interceptFroms; 543 } 544 545 public List<InterceptSendToEndpointDefinition> getInterceptSendToEndpoints() { 546 return interceptSendToEndpoints; 547 } 548 549 public void setInterceptSendToEndpoints(List<InterceptSendToEndpointDefinition> interceptSendToEndpoints) { 550 this.interceptSendToEndpoints = interceptSendToEndpoints; 551 } 552 553 public List<RouteDefinition> getRoutes() { 554 return routes; 555 } 556 557 public void setRoutes(List<RouteDefinition> routes) { 558 this.routes = routes; 559 } 560 561 public boolean isImplicitId() { 562 return implicitId; 563 } 564 565 public void setImplicitId(boolean flag) { 566 implicitId = flag; 567 } 568 569 public Boolean getUseBlueprintPropertyResolver() { 570 return useBlueprintPropertyResolver; 571 } 572 573 public void setUseBlueprintPropertyResolver(Boolean useBlueprintPropertyResolver) { 574 this.useBlueprintPropertyResolver = useBlueprintPropertyResolver; 575 } 576 577 public boolean isUseBlueprintPropertyResolver() { 578 // enable by default 579 return useBlueprintPropertyResolver == null || useBlueprintPropertyResolver.booleanValue(); 580 } 581 582 }