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