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