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 */ 017package org.apache.camel.blueprint.handler; 018 019import java.lang.reflect.Field; 020import java.lang.reflect.Method; 021import java.lang.reflect.Modifier; 022import java.net.URI; 023import java.net.URISyntaxException; 024import java.net.URL; 025import java.util.Arrays; 026import java.util.HashSet; 027import java.util.List; 028import java.util.Map; 029import java.util.Set; 030import java.util.concurrent.Callable; 031import javax.xml.bind.Binder; 032import javax.xml.bind.JAXBContext; 033import javax.xml.bind.JAXBException; 034 035import org.w3c.dom.Document; 036import org.w3c.dom.Element; 037import org.w3c.dom.NamedNodeMap; 038import org.w3c.dom.Node; 039import org.w3c.dom.NodeList; 040 041import org.apache.aries.blueprint.BeanProcessor; 042import org.apache.aries.blueprint.ComponentDefinitionRegistry; 043import org.apache.aries.blueprint.ComponentDefinitionRegistryProcessor; 044import org.apache.aries.blueprint.NamespaceHandler; 045import org.apache.aries.blueprint.ParserContext; 046import org.apache.aries.blueprint.PassThroughMetadata; 047import org.apache.aries.blueprint.mutable.MutableBeanMetadata; 048import org.apache.aries.blueprint.mutable.MutablePassThroughMetadata; 049import org.apache.aries.blueprint.mutable.MutableRefMetadata; 050import org.apache.aries.blueprint.mutable.MutableReferenceMetadata; 051import org.apache.camel.BeanInject; 052import org.apache.camel.CamelContext; 053import org.apache.camel.Endpoint; 054import org.apache.camel.EndpointInject; 055import org.apache.camel.Produce; 056import org.apache.camel.PropertyInject; 057import org.apache.camel.blueprint.BlueprintCamelContext; 058import org.apache.camel.blueprint.BlueprintModelJAXBContextFactory; 059import org.apache.camel.blueprint.CamelContextFactoryBean; 060import org.apache.camel.blueprint.CamelEndpointFactoryBean; 061import org.apache.camel.blueprint.CamelRestContextFactoryBean; 062import org.apache.camel.blueprint.CamelRouteContextFactoryBean; 063import org.apache.camel.builder.xml.Namespaces; 064import org.apache.camel.component.properties.PropertiesComponent; 065import org.apache.camel.core.xml.AbstractCamelFactoryBean; 066import org.apache.camel.impl.CamelPostProcessorHelper; 067import org.apache.camel.impl.DefaultCamelContextNameStrategy; 068import org.apache.camel.model.AggregateDefinition; 069import org.apache.camel.model.CatchDefinition; 070import org.apache.camel.model.DataFormatDefinition; 071import org.apache.camel.model.ExpressionNode; 072import org.apache.camel.model.ExpressionSubElementDefinition; 073import org.apache.camel.model.FromDefinition; 074import org.apache.camel.model.MarshalDefinition; 075import org.apache.camel.model.OnExceptionDefinition; 076import org.apache.camel.model.ProcessorDefinition; 077import org.apache.camel.model.ResequenceDefinition; 078import org.apache.camel.model.RouteDefinition; 079import org.apache.camel.model.SendDefinition; 080import org.apache.camel.model.SortDefinition; 081import org.apache.camel.model.ToDefinition; 082import org.apache.camel.model.ToDynamicDefinition; 083import org.apache.camel.model.UnmarshalDefinition; 084import org.apache.camel.model.WireTapDefinition; 085import org.apache.camel.model.language.ExpressionDefinition; 086import org.apache.camel.model.rest.RestBindingMode; 087import org.apache.camel.model.rest.RestDefinition; 088import org.apache.camel.model.rest.VerbDefinition; 089import org.apache.camel.spi.CamelContextNameStrategy; 090import org.apache.camel.spi.ComponentResolver; 091import org.apache.camel.spi.DataFormatResolver; 092import org.apache.camel.spi.LanguageResolver; 093import org.apache.camel.spi.NamespaceAware; 094import org.apache.camel.util.ObjectHelper; 095import org.apache.camel.util.URISupport; 096import org.apache.camel.util.blueprint.KeyStoreParametersFactoryBean; 097import org.apache.camel.util.blueprint.SSLContextParametersFactoryBean; 098import org.apache.camel.util.blueprint.SecureRandomParametersFactoryBean; 099import org.apache.camel.util.jsse.KeyStoreParameters; 100import org.apache.camel.util.jsse.SSLContextParameters; 101import org.apache.camel.util.jsse.SecureRandomParameters; 102import org.osgi.framework.Bundle; 103import org.osgi.service.blueprint.container.BlueprintContainer; 104import org.osgi.service.blueprint.container.ComponentDefinitionException; 105import org.osgi.service.blueprint.reflect.BeanMetadata; 106import org.osgi.service.blueprint.reflect.ComponentMetadata; 107import org.osgi.service.blueprint.reflect.Metadata; 108import org.osgi.service.blueprint.reflect.RefMetadata; 109import org.slf4j.Logger; 110import org.slf4j.LoggerFactory; 111 112import static org.osgi.service.blueprint.reflect.ComponentMetadata.ACTIVATION_LAZY; 113import static org.osgi.service.blueprint.reflect.ServiceReferenceMetadata.AVAILABILITY_MANDATORY; 114import static org.osgi.service.blueprint.reflect.ServiceReferenceMetadata.AVAILABILITY_OPTIONAL; 115 116/** 117 * Camel {@link NamespaceHandler} to parse the Camel related namespaces. 118 */ 119public class CamelNamespaceHandler implements NamespaceHandler { 120 121 public static final String BLUEPRINT_NS = "http://camel.apache.org/schema/blueprint"; 122 public static final String SPRING_NS = "http://camel.apache.org/schema/spring"; 123 124 private static final String CAMEL_CONTEXT = "camelContext"; 125 private static final String ROUTE_CONTEXT = "routeContext"; 126 private static final String REST_CONTEXT = "restContext"; 127 private static final String ENDPOINT = "endpoint"; 128 private static final String KEY_STORE_PARAMETERS = "keyStoreParameters"; 129 private static final String SECURE_RANDOM_PARAMETERS = "secureRandomParameters"; 130 private static final String SSL_CONTEXT_PARAMETERS = "sslContextParameters"; 131 132 private static final Logger LOG = LoggerFactory.getLogger(CamelNamespaceHandler.class); 133 134 private JAXBContext jaxbContext; 135 136 /** 137 * Prepares the nodes before parsing. 138 */ 139 public static void doBeforeParse(Node node, String fromNamespace, String toNamespace) { 140 if (node.getNodeType() == Node.ELEMENT_NODE) { 141 Document doc = node.getOwnerDocument(); 142 if (node.getNamespaceURI().equals(fromNamespace)) { 143 doc.renameNode(node, toNamespace, node.getLocalName()); 144 } 145 146 // remove whitespace noise from uri, xxxUri attributes, eg new lines, and tabs etc, which allows end users to format 147 // their Camel routes in more human readable format, but at runtime those attributes must be trimmed 148 // the parser removes most of the noise, but keeps double spaces in the attribute values 149 NamedNodeMap map = node.getAttributes(); 150 for (int i = 0; i < map.getLength(); i++) { 151 Node att = map.item(i); 152 if (att.getNodeName().equals("uri") || att.getNodeName().endsWith("Uri")) { 153 final String value = att.getNodeValue(); 154 String before = ObjectHelper.before(value, "?"); 155 String after = ObjectHelper.after(value, "?"); 156 157 if (before != null && after != null) { 158 // remove all double spaces in the uri parameters 159 String changed = after.replaceAll("\\s{2,}", ""); 160 if (!after.equals(changed)) { 161 String newAtr = before.trim() + "?" + changed.trim(); 162 LOG.debug("Removed whitespace noise from attribute {} -> {}", value, newAtr); 163 att.setNodeValue(newAtr); 164 } 165 } 166 } 167 } 168 } 169 NodeList list = node.getChildNodes(); 170 for (int i = 0; i < list.getLength(); ++i) { 171 doBeforeParse(list.item(i), fromNamespace, toNamespace); 172 } 173 } 174 175 public URL getSchemaLocation(String namespace) { 176 return getClass().getClassLoader().getResource("camel-blueprint.xsd"); 177 } 178 179 @SuppressWarnings({"unchecked", "rawtypes"}) 180 public Set<Class> getManagedClasses() { 181 return new HashSet<Class>(Arrays.asList(BlueprintCamelContext.class)); 182 } 183 184 public Metadata parse(Element element, ParserContext context) { 185 LOG.trace("Parsing element {}", element); 186 187 try { 188 // as the camel-core model namespace is Spring we need to rename from blueprint to spring 189 doBeforeParse(element, BLUEPRINT_NS, SPRING_NS); 190 191 if (element.getLocalName().equals(CAMEL_CONTEXT)) { 192 return parseCamelContextNode(element, context); 193 } 194 if (element.getLocalName().equals(ROUTE_CONTEXT)) { 195 return parseRouteContextNode(element, context); 196 } 197 if (element.getLocalName().equals(REST_CONTEXT)) { 198 return parseRestContextNode(element, context); 199 } 200 if (element.getLocalName().equals(ENDPOINT)) { 201 return parseEndpointNode(element, context); 202 } 203 if (element.getLocalName().equals(KEY_STORE_PARAMETERS)) { 204 return parseKeyStoreParametersNode(element, context); 205 } 206 if (element.getLocalName().equals(SECURE_RANDOM_PARAMETERS)) { 207 return parseSecureRandomParametersNode(element, context); 208 } 209 if (element.getLocalName().equals(SSL_CONTEXT_PARAMETERS)) { 210 return parseSSLContextParametersNode(element, context); 211 } 212 } finally { 213 // make sure to rename back so we leave the DOM as-is 214 doBeforeParse(element, SPRING_NS, BLUEPRINT_NS); 215 } 216 217 return null; 218 } 219 220 private Metadata parseCamelContextNode(Element element, ParserContext context) { 221 LOG.trace("Parsing CamelContext {}", element); 222 // Find the id, generate one if needed 223 String contextId = element.getAttribute("id"); 224 boolean implicitId = false; 225 226 // let's avoid folks having to explicitly give an ID to a camel context 227 if (ObjectHelper.isEmpty(contextId)) { 228 // if no explicit id was set then use a default auto generated name 229 CamelContextNameStrategy strategy = new DefaultCamelContextNameStrategy(); 230 contextId = strategy.getName(); 231 element.setAttributeNS(null, "id", contextId); 232 implicitId = true; 233 } 234 235 // now let's parse the routes with JAXB 236 Binder<Node> binder; 237 try { 238 binder = getJaxbContext().createBinder(); 239 } catch (JAXBException e) { 240 throw new ComponentDefinitionException("Failed to create the JAXB binder : " + e, e); 241 } 242 Object value = parseUsingJaxb(element, context, binder); 243 if (!(value instanceof CamelContextFactoryBean)) { 244 throw new ComponentDefinitionException("Expected an instance of " + CamelContextFactoryBean.class); 245 } 246 247 CamelContextFactoryBean ccfb = (CamelContextFactoryBean) value; 248 ccfb.setImplicitId(implicitId); 249 250 // The properties component is always used / created by the CamelContextFactoryBean 251 // so we need to ensure that the resolver is ready to use 252 ComponentMetadata propertiesComponentResolver = getComponentResolverReference(context, "properties"); 253 254 MutablePassThroughMetadata factory = context.createMetadata(MutablePassThroughMetadata.class); 255 factory.setId(".camelBlueprint.passThrough." + contextId); 256 factory.setObject(new PassThroughCallable<Object>(value)); 257 258 MutableBeanMetadata factory2 = context.createMetadata(MutableBeanMetadata.class); 259 factory2.setId(".camelBlueprint.factory." + contextId); 260 factory2.setFactoryComponent(factory); 261 factory2.setFactoryMethod("call"); 262 factory2.setInitMethod("afterPropertiesSet"); 263 factory2.setDestroyMethod("destroy"); 264 factory2.addProperty("blueprintContainer", createRef(context, "blueprintContainer")); 265 factory2.addProperty("bundleContext", createRef(context, "blueprintBundleContext")); 266 factory2.addDependsOn(propertiesComponentResolver.getId()); 267 // We need to add other components which the camel context dependsOn 268 if (ObjectHelper.isNotEmpty(ccfb.getDependsOn())) { 269 factory2.setDependsOn(Arrays.asList(ccfb.getDependsOn().split(" |,"))); 270 } 271 context.getComponentDefinitionRegistry().registerComponentDefinition(factory2); 272 273 MutableBeanMetadata ctx = context.createMetadata(MutableBeanMetadata.class); 274 ctx.setId(contextId); 275 ctx.setRuntimeClass(BlueprintCamelContext.class); 276 ctx.setFactoryComponent(factory2); 277 ctx.setFactoryMethod("getContext"); 278 ctx.setInitMethod("init"); 279 ctx.setDestroyMethod("destroy"); 280 281 // Register factory beans 282 registerBeans(context, contextId, ccfb.getThreadPools()); 283 registerBeans(context, contextId, ccfb.getEndpoints()); 284 registerBeans(context, contextId, ccfb.getRedeliveryPolicies()); 285 registerBeans(context, contextId, ccfb.getBeans()); 286 287 // Register processors 288 MutablePassThroughMetadata beanProcessorFactory = context.createMetadata(MutablePassThroughMetadata.class); 289 beanProcessorFactory.setId(".camelBlueprint.processor.bean.passThrough." + contextId); 290 beanProcessorFactory.setObject(new PassThroughCallable<Object>(new CamelInjector(contextId))); 291 292 MutableBeanMetadata beanProcessor = context.createMetadata(MutableBeanMetadata.class); 293 beanProcessor.setId(".camelBlueprint.processor.bean." + contextId); 294 beanProcessor.setRuntimeClass(CamelInjector.class); 295 beanProcessor.setFactoryComponent(beanProcessorFactory); 296 beanProcessor.setFactoryMethod("call"); 297 beanProcessor.setProcessor(true); 298 beanProcessor.addProperty("blueprintContainer", createRef(context, "blueprintContainer")); 299 context.getComponentDefinitionRegistry().registerComponentDefinition(beanProcessor); 300 301 MutablePassThroughMetadata regProcessorFactory = context.createMetadata(MutablePassThroughMetadata.class); 302 regProcessorFactory.setId(".camelBlueprint.processor.registry.passThrough." + contextId); 303 regProcessorFactory.setObject(new PassThroughCallable<Object>(new CamelDependenciesFinder(contextId, context))); 304 305 MutableBeanMetadata regProcessor = context.createMetadata(MutableBeanMetadata.class); 306 regProcessor.setId(".camelBlueprint.processor.registry." + contextId); 307 regProcessor.setRuntimeClass(CamelDependenciesFinder.class); 308 regProcessor.setFactoryComponent(regProcessorFactory); 309 regProcessor.setFactoryMethod("call"); 310 regProcessor.setProcessor(true); 311 regProcessor.addDependsOn(".camelBlueprint.processor.bean." + contextId); 312 regProcessor.addProperty("blueprintContainer", createRef(context, "blueprintContainer")); 313 context.getComponentDefinitionRegistry().registerComponentDefinition(regProcessor); 314 315 // lets inject the namespaces into any namespace aware POJOs 316 injectNamespaces(element, binder); 317 318 LOG.trace("Parsing CamelContext done, returning {}", ctx); 319 return ctx; 320 } 321 322 protected void injectNamespaces(Element element, Binder<Node> binder) { 323 NodeList list = element.getChildNodes(); 324 Namespaces namespaces = null; 325 int size = list.getLength(); 326 for (int i = 0; i < size; i++) { 327 Node child = list.item(i); 328 if (child instanceof Element) { 329 Element childElement = (Element) child; 330 Object object = binder.getJAXBNode(child); 331 if (object instanceof NamespaceAware) { 332 NamespaceAware namespaceAware = (NamespaceAware) object; 333 if (namespaces == null) { 334 namespaces = new Namespaces(element); 335 } 336 namespaces.configure(namespaceAware); 337 } 338 injectNamespaces(childElement, binder); 339 } 340 } 341 } 342 343 private Metadata parseRouteContextNode(Element element, ParserContext context) { 344 LOG.trace("Parsing RouteContext {}", element); 345 // now parse the routes with JAXB 346 Binder<Node> binder; 347 try { 348 binder = getJaxbContext().createBinder(); 349 } catch (JAXBException e) { 350 351 throw new ComponentDefinitionException("Failed to create the JAXB binder : " + e, e); 352 } 353 Object value = parseUsingJaxb(element, context, binder); 354 if (!(value instanceof CamelRouteContextFactoryBean)) { 355 throw new ComponentDefinitionException("Expected an instance of " + CamelRouteContextFactoryBean.class); 356 } 357 358 CamelRouteContextFactoryBean rcfb = (CamelRouteContextFactoryBean) value; 359 String id = rcfb.getId(); 360 361 MutablePassThroughMetadata factory = context.createMetadata(MutablePassThroughMetadata.class); 362 factory.setId(".camelBlueprint.passThrough." + id); 363 factory.setObject(new PassThroughCallable<Object>(rcfb)); 364 365 MutableBeanMetadata factory2 = context.createMetadata(MutableBeanMetadata.class); 366 factory2.setId(".camelBlueprint.factory." + id); 367 factory2.setFactoryComponent(factory); 368 factory2.setFactoryMethod("call"); 369 370 MutableBeanMetadata ctx = context.createMetadata(MutableBeanMetadata.class); 371 ctx.setId(id); 372 ctx.setRuntimeClass(List.class); 373 ctx.setFactoryComponent(factory2); 374 ctx.setFactoryMethod("getRoutes"); 375 // must be lazy as we want CamelContext to be activated first 376 ctx.setActivation(ACTIVATION_LAZY); 377 378 // lets inject the namespaces into any namespace aware POJOs 379 injectNamespaces(element, binder); 380 381 LOG.trace("Parsing RouteContext done, returning {}", element, ctx); 382 return ctx; 383 } 384 385 private Metadata parseRestContextNode(Element element, ParserContext context) { 386 LOG.trace("Parsing RestContext {}", element); 387 // now parse the rests with JAXB 388 Binder<Node> binder; 389 try { 390 binder = getJaxbContext().createBinder(); 391 } catch (JAXBException e) { 392 throw new ComponentDefinitionException("Failed to create the JAXB binder : " + e, e); 393 } 394 Object value = parseUsingJaxb(element, context, binder); 395 if (!(value instanceof CamelRestContextFactoryBean)) { 396 throw new ComponentDefinitionException("Expected an instance of " + CamelRestContextFactoryBean.class); 397 } 398 399 CamelRestContextFactoryBean rcfb = (CamelRestContextFactoryBean) value; 400 String id = rcfb.getId(); 401 402 MutablePassThroughMetadata factory = context.createMetadata(MutablePassThroughMetadata.class); 403 factory.setId(".camelBlueprint.passThrough." + id); 404 factory.setObject(new PassThroughCallable<Object>(rcfb)); 405 406 MutableBeanMetadata factory2 = context.createMetadata(MutableBeanMetadata.class); 407 factory2.setId(".camelBlueprint.factory." + id); 408 factory2.setFactoryComponent(factory); 409 factory2.setFactoryMethod("call"); 410 411 MutableBeanMetadata ctx = context.createMetadata(MutableBeanMetadata.class); 412 ctx.setId(id); 413 ctx.setRuntimeClass(List.class); 414 ctx.setFactoryComponent(factory2); 415 ctx.setFactoryMethod("getRests"); 416 // must be lazy as we want CamelContext to be activated first 417 ctx.setActivation(ACTIVATION_LAZY); 418 419 // lets inject the namespaces into any namespace aware POJOs 420 injectNamespaces(element, binder); 421 422 LOG.trace("Parsing RestContext done, returning {}", element, ctx); 423 return ctx; 424 } 425 426 private Metadata parseEndpointNode(Element element, ParserContext context) { 427 LOG.trace("Parsing Endpoint {}", element); 428 // now parse the rests with JAXB 429 Binder<Node> binder; 430 try { 431 binder = getJaxbContext().createBinder(); 432 } catch (JAXBException e) { 433 throw new ComponentDefinitionException("Failed to create the JAXB binder : " + e, e); 434 } 435 Object value = parseUsingJaxb(element, context, binder); 436 if (!(value instanceof CamelEndpointFactoryBean)) { 437 throw new ComponentDefinitionException("Expected an instance of " + CamelEndpointFactoryBean.class); 438 } 439 440 CamelEndpointFactoryBean rcfb = (CamelEndpointFactoryBean) value; 441 String id = rcfb.getId(); 442 443 MutablePassThroughMetadata factory = context.createMetadata(MutablePassThroughMetadata.class); 444 factory.setId(".camelBlueprint.passThrough." + id); 445 factory.setObject(new PassThroughCallable<Object>(rcfb)); 446 447 MutableBeanMetadata factory2 = context.createMetadata(MutableBeanMetadata.class); 448 factory2.setId(".camelBlueprint.factory." + id); 449 factory2.setFactoryComponent(factory); 450 factory2.setFactoryMethod("call"); 451 factory2.setInitMethod("afterPropertiesSet"); 452 factory2.setDestroyMethod("destroy"); 453 factory2.addProperty("blueprintContainer", createRef(context, "blueprintContainer")); 454 455 MutableBeanMetadata ctx = context.createMetadata(MutableBeanMetadata.class); 456 ctx.setId(id); 457 ctx.setRuntimeClass(Endpoint.class); 458 ctx.setFactoryComponent(factory2); 459 ctx.setFactoryMethod("getObject"); 460 // must be lazy as we want CamelContext to be activated first 461 ctx.setActivation(ACTIVATION_LAZY); 462 463 LOG.trace("Parsing endpoint done, returning {}", element, ctx); 464 return ctx; 465 } 466 467 private Metadata parseKeyStoreParametersNode(Element element, ParserContext context) { 468 LOG.trace("Parsing KeyStoreParameters {}", element); 469 // now parse the key store parameters with JAXB 470 Binder<Node> binder; 471 try { 472 binder = getJaxbContext().createBinder(); 473 } catch (JAXBException e) { 474 throw new ComponentDefinitionException("Failed to create the JAXB binder : " + e, e); 475 } 476 Object value = parseUsingJaxb(element, context, binder); 477 if (!(value instanceof KeyStoreParametersFactoryBean)) { 478 throw new ComponentDefinitionException("Expected an instance of " + KeyStoreParametersFactoryBean.class); 479 } 480 481 KeyStoreParametersFactoryBean kspfb = (KeyStoreParametersFactoryBean) value; 482 String id = kspfb.getId(); 483 484 MutablePassThroughMetadata factory = context.createMetadata(MutablePassThroughMetadata.class); 485 factory.setId(".camelBlueprint.passThrough." + id); 486 factory.setObject(new PassThroughCallable<Object>(kspfb)); 487 488 MutableBeanMetadata factory2 = context.createMetadata(MutableBeanMetadata.class); 489 factory2.setId(".camelBlueprint.factory." + id); 490 factory2.setFactoryComponent(factory); 491 factory2.setFactoryMethod("call"); 492 factory2.setInitMethod("afterPropertiesSet"); 493 factory2.setDestroyMethod("destroy"); 494 factory2.addProperty("blueprintContainer", createRef(context, "blueprintContainer")); 495 496 MutableBeanMetadata ctx = context.createMetadata(MutableBeanMetadata.class); 497 ctx.setId(id); 498 ctx.setRuntimeClass(KeyStoreParameters.class); 499 ctx.setFactoryComponent(factory2); 500 ctx.setFactoryMethod("getObject"); 501 // must be lazy as we want CamelContext to be activated first 502 ctx.setActivation(ACTIVATION_LAZY); 503 504 LOG.trace("Parsing KeyStoreParameters done, returning {}", ctx); 505 return ctx; 506 } 507 508 private Metadata parseSecureRandomParametersNode(Element element, ParserContext context) { 509 LOG.trace("Parsing SecureRandomParameters {}", element); 510 // now parse the key store parameters with JAXB 511 Binder<Node> binder; 512 try { 513 binder = getJaxbContext().createBinder(); 514 } catch (JAXBException e) { 515 throw new ComponentDefinitionException("Failed to create the JAXB binder : " + e, e); 516 } 517 Object value = parseUsingJaxb(element, context, binder); 518 if (!(value instanceof SecureRandomParametersFactoryBean)) { 519 throw new ComponentDefinitionException("Expected an instance of " + SecureRandomParametersFactoryBean.class); 520 } 521 522 SecureRandomParametersFactoryBean srfb = (SecureRandomParametersFactoryBean) value; 523 String id = srfb.getId(); 524 525 MutablePassThroughMetadata factory = context.createMetadata(MutablePassThroughMetadata.class); 526 factory.setId(".camelBlueprint.passThrough." + id); 527 factory.setObject(new PassThroughCallable<Object>(srfb)); 528 529 MutableBeanMetadata factory2 = context.createMetadata(MutableBeanMetadata.class); 530 factory2.setId(".camelBlueprint.factory." + id); 531 factory2.setFactoryComponent(factory); 532 factory2.setFactoryMethod("call"); 533 factory2.setInitMethod("afterPropertiesSet"); 534 factory2.setDestroyMethod("destroy"); 535 factory2.addProperty("blueprintContainer", createRef(context, "blueprintContainer")); 536 537 MutableBeanMetadata ctx = context.createMetadata(MutableBeanMetadata.class); 538 ctx.setId(id); 539 ctx.setRuntimeClass(SecureRandomParameters.class); 540 ctx.setFactoryComponent(factory2); 541 ctx.setFactoryMethod("getObject"); 542 // must be lazy as we want CamelContext to be activated first 543 ctx.setActivation(ACTIVATION_LAZY); 544 545 LOG.trace("Parsing SecureRandomParameters done, returning {}", ctx); 546 return ctx; 547 } 548 549 private Metadata parseSSLContextParametersNode(Element element, ParserContext context) { 550 LOG.trace("Parsing SSLContextParameters {}", element); 551 // now parse the key store parameters with JAXB 552 Binder<Node> binder; 553 try { 554 binder = getJaxbContext().createBinder(); 555 } catch (JAXBException e) { 556 throw new ComponentDefinitionException("Failed to create the JAXB binder : " + e, e); 557 } 558 Object value = parseUsingJaxb(element, context, binder); 559 if (!(value instanceof SSLContextParametersFactoryBean)) { 560 throw new ComponentDefinitionException("Expected an instance of " + SSLContextParametersFactoryBean.class); 561 } 562 563 SSLContextParametersFactoryBean scpfb = (SSLContextParametersFactoryBean) value; 564 String id = scpfb.getId(); 565 566 MutablePassThroughMetadata factory = context.createMetadata(MutablePassThroughMetadata.class); 567 factory.setId(".camelBlueprint.passThrough." + id); 568 factory.setObject(new PassThroughCallable<Object>(scpfb)); 569 570 MutableBeanMetadata factory2 = context.createMetadata(MutableBeanMetadata.class); 571 factory2.setId(".camelBlueprint.factory." + id); 572 factory2.setFactoryComponent(factory); 573 factory2.setFactoryMethod("call"); 574 factory2.setInitMethod("afterPropertiesSet"); 575 factory2.setDestroyMethod("destroy"); 576 factory2.addProperty("blueprintContainer", createRef(context, "blueprintContainer")); 577 578 MutableBeanMetadata ctx = context.createMetadata(MutableBeanMetadata.class); 579 ctx.setId(id); 580 ctx.setRuntimeClass(SSLContextParameters.class); 581 ctx.setFactoryComponent(factory2); 582 ctx.setFactoryMethod("getObject"); 583 // must be lazy as we want CamelContext to be activated first 584 ctx.setActivation(ACTIVATION_LAZY); 585 586 LOG.trace("Parsing SSLContextParameters done, returning {}", ctx); 587 return ctx; 588 } 589 590 private void registerBeans(ParserContext context, String contextId, List<?> beans) { 591 if (beans != null) { 592 for (Object bean : beans) { 593 if (bean instanceof AbstractCamelFactoryBean) { 594 registerBean(context, contextId, (AbstractCamelFactoryBean<?>) bean); 595 } 596 } 597 } 598 } 599 600 protected void registerBean(ParserContext context, String contextId, AbstractCamelFactoryBean<?> fact) { 601 String id = fact.getId(); 602 603 fact.setCamelContextId(contextId); 604 605 MutablePassThroughMetadata eff = context.createMetadata(MutablePassThroughMetadata.class); 606 eff.setId(".camelBlueprint.bean.passthrough." + id); 607 eff.setObject(new PassThroughCallable<Object>(fact)); 608 609 MutableBeanMetadata ef = context.createMetadata(MutableBeanMetadata.class); 610 ef.setId(".camelBlueprint.bean.factory." + id); 611 ef.setFactoryComponent(eff); 612 ef.setFactoryMethod("call"); 613 ef.addProperty("blueprintContainer", createRef(context, "blueprintContainer")); 614 ef.setInitMethod("afterPropertiesSet"); 615 ef.setDestroyMethod("destroy"); 616 617 MutableBeanMetadata e = context.createMetadata(MutableBeanMetadata.class); 618 e.setId(id); 619 e.setRuntimeClass(fact.getObjectType()); 620 e.setFactoryComponent(ef); 621 e.setFactoryMethod("getObject"); 622 e.addDependsOn(".camelBlueprint.processor.bean." + contextId); 623 624 context.getComponentDefinitionRegistry().registerComponentDefinition(e); 625 } 626 627 protected BlueprintContainer getBlueprintContainer(ParserContext context) { 628 PassThroughMetadata ptm = (PassThroughMetadata) context.getComponentDefinitionRegistry().getComponentDefinition("blueprintContainer"); 629 return (BlueprintContainer) ptm.getObject(); 630 } 631 632 public ComponentMetadata decorate(Node node, ComponentMetadata component, ParserContext context) { 633 return null; 634 } 635 636 protected Object parseUsingJaxb(Element element, ParserContext parserContext, Binder<Node> binder) { 637 try { 638 return binder.unmarshal(element); 639 } catch (JAXBException e) { 640 throw new ComponentDefinitionException("Failed to parse JAXB element: " + e, e); 641 } 642 } 643 644 public JAXBContext getJaxbContext() throws JAXBException { 645 if (jaxbContext == null) { 646 jaxbContext = new BlueprintModelJAXBContextFactory(getClass().getClassLoader()).newJAXBContext(); 647 } 648 return jaxbContext; 649 } 650 651 private RefMetadata createRef(ParserContext context, String value) { 652 MutableRefMetadata r = context.createMetadata(MutableRefMetadata.class); 653 r.setComponentId(value); 654 return r; 655 } 656 657 private static ComponentMetadata getDataformatResolverReference(ParserContext context, String dataformat) { 658 // we cannot resolve dataformat names using property placeholders at this point in time 659 if (dataformat.startsWith(PropertiesComponent.DEFAULT_PREFIX_TOKEN)) { 660 return null; 661 } 662 ComponentDefinitionRegistry componentDefinitionRegistry = context.getComponentDefinitionRegistry(); 663 ComponentMetadata cm = componentDefinitionRegistry.getComponentDefinition(".camelBlueprint.dataformatResolver." + dataformat); 664 if (cm == null) { 665 MutableReferenceMetadata svc = context.createMetadata(MutableReferenceMetadata.class); 666 svc.setId(".camelBlueprint.dataformatResolver." + dataformat); 667 svc.setFilter("(dataformat=" + dataformat + ")"); 668 svc.setAvailability(componentDefinitionRegistry.containsComponentDefinition(dataformat) ? AVAILABILITY_OPTIONAL : AVAILABILITY_MANDATORY); 669 try { 670 // Try to set the runtime interface (only with aries blueprint > 0.1 671 svc.getClass().getMethod("setRuntimeInterface", Class.class).invoke(svc, DataFormatResolver.class); 672 } catch (Throwable t) { 673 // Check if the bundle can see the class 674 try { 675 PassThroughMetadata ptm = (PassThroughMetadata) componentDefinitionRegistry.getComponentDefinition("blueprintBundle"); 676 Bundle b = (Bundle) ptm.getObject(); 677 if (b.loadClass(DataFormatResolver.class.getName()) != DataFormatResolver.class) { 678 throw new UnsupportedOperationException(); 679 } 680 svc.setInterface(DataFormatResolver.class.getName()); 681 } catch (Throwable t2) { 682 throw new UnsupportedOperationException(); 683 } 684 } 685 componentDefinitionRegistry.registerComponentDefinition(svc); 686 cm = svc; 687 } 688 return cm; 689 } 690 691 private static ComponentMetadata getLanguageResolverReference(ParserContext context, String language) { 692 // we cannot resolve language names using property placeholders at this point in time 693 if (language.startsWith(PropertiesComponent.DEFAULT_PREFIX_TOKEN)) { 694 return null; 695 } 696 ComponentDefinitionRegistry componentDefinitionRegistry = context.getComponentDefinitionRegistry(); 697 ComponentMetadata cm = componentDefinitionRegistry.getComponentDefinition(".camelBlueprint.languageResolver." + language); 698 if (cm == null) { 699 MutableReferenceMetadata svc = context.createMetadata(MutableReferenceMetadata.class); 700 svc.setId(".camelBlueprint.languageResolver." + language); 701 svc.setFilter("(language=" + language + ")"); 702 svc.setAvailability(componentDefinitionRegistry.containsComponentDefinition(language) ? AVAILABILITY_OPTIONAL : AVAILABILITY_MANDATORY); 703 try { 704 // Try to set the runtime interface (only with aries blueprint > 0.1 705 svc.getClass().getMethod("setRuntimeInterface", Class.class).invoke(svc, LanguageResolver.class); 706 } catch (Throwable t) { 707 // Check if the bundle can see the class 708 try { 709 PassThroughMetadata ptm = (PassThroughMetadata) componentDefinitionRegistry.getComponentDefinition("blueprintBundle"); 710 Bundle b = (Bundle) ptm.getObject(); 711 if (b.loadClass(LanguageResolver.class.getName()) != LanguageResolver.class) { 712 throw new UnsupportedOperationException(); 713 } 714 svc.setInterface(LanguageResolver.class.getName()); 715 } catch (Throwable t2) { 716 throw new UnsupportedOperationException(); 717 } 718 } 719 componentDefinitionRegistry.registerComponentDefinition(svc); 720 cm = svc; 721 } 722 return cm; 723 } 724 725 private static ComponentMetadata getComponentResolverReference(ParserContext context, String component) { 726 // we cannot resolve component names using property placeholders at this point in time 727 if (component.startsWith(PropertiesComponent.DEFAULT_PREFIX_TOKEN)) { 728 return null; 729 } 730 ComponentDefinitionRegistry componentDefinitionRegistry = context.getComponentDefinitionRegistry(); 731 ComponentMetadata cm = componentDefinitionRegistry.getComponentDefinition(".camelBlueprint.componentResolver." + component); 732 if (cm == null) { 733 MutableReferenceMetadata svc = context.createMetadata(MutableReferenceMetadata.class); 734 svc.setId(".camelBlueprint.componentResolver." + component); 735 svc.setFilter("(component=" + component + ")"); 736 svc.setAvailability(componentDefinitionRegistry.containsComponentDefinition(component) ? AVAILABILITY_OPTIONAL : AVAILABILITY_MANDATORY); 737 try { 738 // Try to set the runtime interface (only with aries blueprint > 0.1 739 svc.getClass().getMethod("setRuntimeInterface", Class.class).invoke(svc, ComponentResolver.class); 740 } catch (Throwable t) { 741 // Check if the bundle can see the class 742 try { 743 PassThroughMetadata ptm = (PassThroughMetadata) componentDefinitionRegistry.getComponentDefinition("blueprintBundle"); 744 Bundle b = (Bundle) ptm.getObject(); 745 if (b.loadClass(ComponentResolver.class.getName()) != ComponentResolver.class) { 746 throw new UnsupportedOperationException(); 747 } 748 svc.setInterface(ComponentResolver.class.getName()); 749 } catch (Throwable t2) { 750 throw new UnsupportedOperationException(); 751 } 752 } 753 componentDefinitionRegistry.registerComponentDefinition(svc); 754 cm = svc; 755 } 756 return cm; 757 } 758 759 public static class PassThroughCallable<T> implements Callable<T> { 760 761 private T value; 762 763 public PassThroughCallable(T value) { 764 this.value = value; 765 } 766 767 public T call() throws Exception { 768 return value; 769 } 770 } 771 772 public static class CamelInjector extends CamelPostProcessorHelper implements BeanProcessor { 773 774 private final String camelContextName; 775 private BlueprintContainer blueprintContainer; 776 777 public CamelInjector(String camelContextName) { 778 this.camelContextName = camelContextName; 779 } 780 781 public void setBlueprintContainer(BlueprintContainer blueprintContainer) { 782 this.blueprintContainer = blueprintContainer; 783 } 784 785 @Override 786 public CamelContext getCamelContext() { 787 if (blueprintContainer != null) { 788 CamelContext answer = (CamelContext) blueprintContainer.getComponentInstance(camelContextName); 789 return answer; 790 } 791 return null; 792 } 793 794 public Object beforeInit(Object bean, String beanName, BeanCreator beanCreator, BeanMetadata beanMetadata) { 795 LOG.trace("Before init of bean: {} -> {}", beanName, bean); 796 // prefer to inject later in afterInit 797 return bean; 798 } 799 800 /** 801 * A strategy method to allow implementations to perform some custom JBI 802 * based injection of the POJO 803 * 804 * @param bean the bean to be injected 805 */ 806 protected void injectFields(final Object bean, final String beanName) { 807 Class<?> clazz = bean.getClass(); 808 do { 809 Field[] fields = clazz.getDeclaredFields(); 810 for (Field field : fields) { 811 PropertyInject propertyInject = field.getAnnotation(PropertyInject.class); 812 if (propertyInject != null && matchContext(propertyInject.context())) { 813 injectFieldProperty(field, propertyInject.value(), propertyInject.defaultValue(), bean, beanName); 814 } 815 816 BeanInject beanInject = field.getAnnotation(BeanInject.class); 817 if (beanInject != null && matchContext(beanInject.context())) { 818 injectFieldBean(field, beanInject.value(), bean, beanName); 819 } 820 821 EndpointInject endpointInject = field.getAnnotation(EndpointInject.class); 822 if (endpointInject != null && matchContext(endpointInject.context())) { 823 injectField(field, endpointInject.uri(), endpointInject.ref(), endpointInject.property(), bean, beanName); 824 } 825 826 Produce produce = field.getAnnotation(Produce.class); 827 if (produce != null && matchContext(produce.context())) { 828 injectField(field, produce.uri(), produce.ref(), produce.property(), bean, beanName); 829 } 830 } 831 clazz = clazz.getSuperclass(); 832 } while (clazz != null && clazz != Object.class); 833 } 834 835 protected void injectField(Field field, String endpointUri, String endpointRef, String endpointProperty, Object bean, String beanName) { 836 setField(field, bean, getInjectionValue(field.getType(), endpointUri, endpointRef, endpointProperty, field.getName(), bean, beanName)); 837 } 838 839 protected void injectFieldProperty(Field field, String propertyName, String propertyDefaultValue, Object bean, String beanName) { 840 setField(field, bean, getInjectionPropertyValue(field.getType(), propertyName, propertyDefaultValue, field.getName(), bean, beanName)); 841 } 842 843 public void injectFieldBean(Field field, String name, Object bean, String beanName) { 844 setField(field, bean, getInjectionBeanValue(field.getType(), name)); 845 } 846 847 protected static void setField(Field field, Object instance, Object value) { 848 try { 849 boolean oldAccessible = field.isAccessible(); 850 boolean shouldSetAccessible = !Modifier.isPublic(field.getModifiers()) && !oldAccessible; 851 if (shouldSetAccessible) { 852 field.setAccessible(true); 853 } 854 field.set(instance, value); 855 if (shouldSetAccessible) { 856 field.setAccessible(oldAccessible); 857 } 858 } catch (IllegalArgumentException ex) { 859 throw new UnsupportedOperationException("Cannot inject value of class: " + value.getClass() + " into: " + field); 860 } catch (IllegalAccessException ex) { 861 throw new IllegalStateException("Could not access method: " + ex.getMessage()); 862 } 863 } 864 865 protected void injectMethods(final Object bean, final String beanName) { 866 Class<?> clazz = bean.getClass(); 867 do { 868 Method[] methods = clazz.getDeclaredMethods(); 869 for (Method method : methods) { 870 setterInjection(method, bean, beanName); 871 consumerInjection(method, bean, beanName); 872 } 873 clazz = clazz.getSuperclass(); 874 } while (clazz != null && clazz != Object.class); 875 } 876 877 protected void setterInjection(Method method, Object bean, String beanName) { 878 PropertyInject propertyInject = method.getAnnotation(PropertyInject.class); 879 if (propertyInject != null && matchContext(propertyInject.context())) { 880 setterPropertyInjection(method, propertyInject.value(), propertyInject.defaultValue(), bean, beanName); 881 } 882 883 BeanInject beanInject = method.getAnnotation(BeanInject.class); 884 if (beanInject != null && matchContext(beanInject.context())) { 885 setterBeanInjection(method, beanInject.value(), bean, beanName); 886 } 887 888 EndpointInject endpointInject = method.getAnnotation(EndpointInject.class); 889 if (endpointInject != null && matchContext(endpointInject.context())) { 890 setterInjection(method, bean, beanName, endpointInject.uri(), endpointInject.ref(), endpointInject.property()); 891 } 892 893 Produce produce = method.getAnnotation(Produce.class); 894 if (produce != null && matchContext(produce.context())) { 895 setterInjection(method, bean, beanName, produce.uri(), produce.ref(), produce.property()); 896 } 897 } 898 899 protected void setterPropertyInjection(Method method, String propertyValue, String propertyDefaultValue, Object bean, String beanName) { 900 Class<?>[] parameterTypes = method.getParameterTypes(); 901 if (parameterTypes != null) { 902 if (parameterTypes.length != 1) { 903 LOG.warn("Ignoring badly annotated method for injection due to incorrect number of parameters: " + method); 904 } else { 905 String propertyName = ObjectHelper.getPropertyName(method); 906 Object value = getInjectionPropertyValue(parameterTypes[0], propertyValue, propertyDefaultValue, propertyName, bean, beanName); 907 ObjectHelper.invokeMethod(method, bean, value); 908 } 909 } 910 } 911 912 protected void setterBeanInjection(Method method, String name, Object bean, String beanName) { 913 Class<?>[] parameterTypes = method.getParameterTypes(); 914 if (parameterTypes != null) { 915 if (parameterTypes.length != 1) { 916 LOG.warn("Ignoring badly annotated method for injection due to incorrect number of parameters: " + method); 917 } else { 918 Object value = getInjectionBeanValue(parameterTypes[0], name); 919 ObjectHelper.invokeMethod(method, bean, value); 920 } 921 } 922 } 923 924 protected void setterInjection(Method method, Object bean, String beanName, String endpointUri, String endpointRef, String endpointProperty) { 925 Class<?>[] parameterTypes = method.getParameterTypes(); 926 if (parameterTypes != null) { 927 if (parameterTypes.length != 1) { 928 LOG.warn("Ignoring badly annotated method for injection due to incorrect number of parameters: " + method); 929 } else { 930 String propertyName = ObjectHelper.getPropertyName(method); 931 Object value = getInjectionValue(parameterTypes[0], endpointUri, endpointRef, endpointProperty, propertyName, bean, beanName); 932 ObjectHelper.invokeMethod(method, bean, value); 933 } 934 } 935 } 936 937 public Object afterInit(Object bean, String beanName, BeanCreator beanCreator, BeanMetadata beanMetadata) { 938 LOG.trace("After init of bean: {} -> {}", beanName, bean); 939 // we cannot inject CamelContextAware beans as the CamelContext may not be ready 940 injectFields(bean, beanName); 941 injectMethods(bean, beanName); 942 return bean; 943 } 944 945 public void beforeDestroy(Object bean, String beanName) { 946 } 947 948 public void afterDestroy(Object bean, String beanName) { 949 } 950 951 @Override 952 protected boolean isSingleton(Object bean, String beanName) { 953 if (beanName != null) { 954 ComponentMetadata meta = blueprintContainer.getComponentMetadata(beanName); 955 if (meta != null && meta instanceof BeanMetadata) { 956 String scope = ((BeanMetadata) meta).getScope(); 957 if (scope != null) { 958 return BeanMetadata.SCOPE_SINGLETON.equals(scope); 959 } 960 } 961 } 962 // fallback to super, which will assume singleton 963 // for beans not implementing Camel's IsSingleton interface 964 return super.isSingleton(bean, beanName); 965 } 966 } 967 968 public static class CamelDependenciesFinder implements ComponentDefinitionRegistryProcessor { 969 970 private final String camelContextName; 971 private final ParserContext context; 972 private BlueprintContainer blueprintContainer; 973 974 public CamelDependenciesFinder(String camelContextName, ParserContext context) { 975 this.camelContextName = camelContextName; 976 this.context = context; 977 } 978 979 public void setBlueprintContainer(BlueprintContainer blueprintContainer) { 980 this.blueprintContainer = blueprintContainer; 981 } 982 983 @SuppressWarnings("deprecation") 984 public void process(ComponentDefinitionRegistry componentDefinitionRegistry) { 985 CamelContextFactoryBean ccfb = (CamelContextFactoryBean) blueprintContainer.getComponentInstance(".camelBlueprint.factory." + camelContextName); 986 CamelContext camelContext = ccfb.getContext(); 987 988 Set<String> components = new HashSet<String>(); 989 Set<String> languages = new HashSet<String>(); 990 Set<String> dataformats = new HashSet<String>(); 991 992 // regular camel routes 993 for (RouteDefinition rd : camelContext.getRouteDefinitions()) { 994 findInputComponents(rd.getInputs(), components, languages, dataformats); 995 findOutputComponents(rd.getOutputs(), components, languages, dataformats); 996 } 997 998 // rest services can have embedded routes or a singular to 999 for (RestDefinition rd : camelContext.getRestDefinitions()) { 1000 for (VerbDefinition vd : rd.getVerbs()) { 1001 Object o = vd.getToOrRoute(); 1002 if (o instanceof RouteDefinition) { 1003 RouteDefinition route = (RouteDefinition) o; 1004 findInputComponents(route.getInputs(), components, languages, dataformats); 1005 findOutputComponents(route.getOutputs(), components, languages, dataformats); 1006 } else if (o instanceof ToDefinition) { 1007 findUriComponent(((ToDefinition) o).getUri(), components); 1008 } else if (o instanceof ToDynamicDefinition) { 1009 findUriComponent(((ToDynamicDefinition) o).getUri(), components); 1010 } 1011 } 1012 } 1013 1014 if (ccfb.getRestConfiguration() != null) { 1015 // rest configuration may refer to a component to use 1016 String component = ccfb.getRestConfiguration().getComponent(); 1017 if (component != null) { 1018 components.add(component); 1019 } 1020 component = ccfb.getRestConfiguration().getApiComponent(); 1021 if (component != null) { 1022 components.add(component); 1023 } 1024 1025 // check what data formats are used in binding mode 1026 RestBindingMode mode = ccfb.getRestConfiguration().getBindingMode(); 1027 String json = ccfb.getRestConfiguration().getJsonDataFormat(); 1028 if (json == null && mode != null) { 1029 if (RestBindingMode.json.equals(mode) || RestBindingMode.json_xml.equals(mode)) { 1030 // jackson is the default json data format 1031 json = "json-jackson"; 1032 } 1033 } 1034 if (json != null) { 1035 dataformats.add(json); 1036 } 1037 String xml = ccfb.getRestConfiguration().getXmlDataFormat(); 1038 if (xml == null && mode != null) { 1039 if (RestBindingMode.xml.equals(mode) || RestBindingMode.json_xml.equals(mode)) { 1040 // jaxb is the default xml data format 1041 dataformats.add("jaxb"); 1042 } 1043 } 1044 if (xml != null) { 1045 dataformats.add(xml); 1046 } 1047 } 1048 1049 // We can only add service references to resolvers, but we can't make the factory depends on those 1050 // because the factory has already been instantiated 1051 try { 1052 for (String component : components) { 1053 getComponentResolverReference(context, component); 1054 } 1055 for (String language : languages) { 1056 getLanguageResolverReference(context, language); 1057 } 1058 for (String dataformat : dataformats) { 1059 getDataformatResolverReference(context, dataformat); 1060 } 1061 } catch (UnsupportedOperationException e) { 1062 LOG.warn("Unable to add dependencies to Camel components OSGi services. " 1063 + "The Apache Aries blueprint implementation used is too old and the blueprint bundle cannot see the org.apache.camel.spi package."); 1064 components.clear(); 1065 languages.clear(); 1066 dataformats.clear(); 1067 } 1068 1069 } 1070 1071 private void findInputComponents(List<FromDefinition> defs, Set<String> components, Set<String> languages, Set<String> dataformats) { 1072 if (defs != null) { 1073 for (FromDefinition def : defs) { 1074 findUriComponent(def.getUri(), components); 1075 findSchedulerUriComponent(def.getUri(), components); 1076 } 1077 } 1078 } 1079 1080 @SuppressWarnings({"rawtypes"}) 1081 private void findOutputComponents(List<ProcessorDefinition<?>> defs, Set<String> components, Set<String> languages, Set<String> dataformats) { 1082 if (defs != null) { 1083 for (ProcessorDefinition<?> def : defs) { 1084 if (def instanceof SendDefinition) { 1085 findUriComponent(((SendDefinition) def).getUri(), components); 1086 } 1087 if (def instanceof MarshalDefinition) { 1088 findDataFormat(((MarshalDefinition) def).getDataFormatType(), dataformats); 1089 } 1090 if (def instanceof UnmarshalDefinition) { 1091 findDataFormat(((UnmarshalDefinition) def).getDataFormatType(), dataformats); 1092 } 1093 if (def instanceof ExpressionNode) { 1094 findLanguage(((ExpressionNode) def).getExpression(), languages); 1095 } 1096 if (def instanceof ResequenceDefinition) { 1097 findLanguage(((ResequenceDefinition) def).getExpression(), languages); 1098 } 1099 if (def instanceof AggregateDefinition) { 1100 findLanguage(((AggregateDefinition) def).getExpression(), languages); 1101 findLanguage(((AggregateDefinition) def).getCorrelationExpression(), languages); 1102 findLanguage(((AggregateDefinition) def).getCompletionPredicate(), languages); 1103 findLanguage(((AggregateDefinition) def).getCompletionTimeoutExpression(), languages); 1104 findLanguage(((AggregateDefinition) def).getCompletionSizeExpression(), languages); 1105 } 1106 if (def instanceof CatchDefinition) { 1107 findLanguage(((CatchDefinition) def).getHandled(), languages); 1108 } 1109 if (def instanceof OnExceptionDefinition) { 1110 findLanguage(((OnExceptionDefinition) def).getRetryWhile(), languages); 1111 findLanguage(((OnExceptionDefinition) def).getHandled(), languages); 1112 findLanguage(((OnExceptionDefinition) def).getContinued(), languages); 1113 } 1114 if (def instanceof SortDefinition) { 1115 findLanguage(((SortDefinition) def).getExpression(), languages); 1116 } 1117 if (def instanceof WireTapDefinition) { 1118 findLanguage(((WireTapDefinition<?>) def).getNewExchangeExpression(), languages); 1119 } 1120 findOutputComponents(def.getOutputs(), components, languages, dataformats); 1121 } 1122 } 1123 } 1124 1125 private void findLanguage(ExpressionDefinition expression, Set<String> languages) { 1126 if (expression != null) { 1127 String lang = expression.getLanguage(); 1128 if (lang != null && lang.length() > 0) { 1129 languages.add(lang); 1130 } 1131 } 1132 } 1133 1134 private void findLanguage(ExpressionSubElementDefinition expression, Set<String> languages) { 1135 if (expression != null) { 1136 findLanguage(expression.getExpressionType(), languages); 1137 } 1138 } 1139 1140 private void findDataFormat(DataFormatDefinition dfd, Set<String> dataformats) { 1141 if (dfd != null && dfd.getDataFormatName() != null) { 1142 dataformats.add(dfd.getDataFormatName()); 1143 } 1144 } 1145 1146 private void findUriComponent(String uri, Set<String> components) { 1147 // if the uri is a placeholder then skip it 1148 if (uri != null && uri.startsWith(PropertiesComponent.DEFAULT_PREFIX_TOKEN)) { 1149 return; 1150 } 1151 1152 if (uri != null) { 1153 String splitURI[] = ObjectHelper.splitOnCharacter(uri, ":", 2); 1154 if (splitURI[1] != null) { 1155 String scheme = splitURI[0]; 1156 components.add(scheme); 1157 } 1158 } 1159 } 1160 1161 private void findSchedulerUriComponent(String uri, Set<String> components) { 1162 1163 // the input may use a scheduler which can be quartz or spring 1164 if (uri != null) { 1165 try { 1166 URI u = new URI(uri); 1167 Map<String, Object> parameters = URISupport.parseParameters(u); 1168 Object value = parameters.get("scheduler"); 1169 if (value == null) { 1170 value = parameters.get("consumer.scheduler"); 1171 } 1172 if (value != null) { 1173 // the scheduler can be quartz2 or spring based, so add reference to camel component 1174 // from these components os blueprint knows about the requirement 1175 String name = value.toString(); 1176 if ("quartz2".equals(name)) { 1177 components.add("quartz2"); 1178 } else if ("spring".equals(name)) { 1179 components.add("spring-event"); 1180 } 1181 } 1182 } catch (URISyntaxException e) { 1183 // ignore 1184 } 1185 } 1186 } 1187 1188 } 1189 1190}