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