001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 package org.apache.camel.blueprint.handler; 018 019 import java.lang.reflect.Field; 020 import java.lang.reflect.Method; 021 import java.lang.reflect.Modifier; 022 import java.net.URL; 023 import java.util.Arrays; 024 import java.util.HashSet; 025 import java.util.List; 026 import java.util.Set; 027 import java.util.concurrent.Callable; 028 import javax.xml.bind.Binder; 029 import javax.xml.bind.JAXBContext; 030 import javax.xml.bind.JAXBException; 031 032 import org.w3c.dom.Document; 033 import org.w3c.dom.Element; 034 import org.w3c.dom.Node; 035 import org.w3c.dom.NodeList; 036 037 import org.apache.aries.blueprint.BeanProcessor; 038 import org.apache.aries.blueprint.ComponentDefinitionRegistry; 039 import org.apache.aries.blueprint.ComponentDefinitionRegistryProcessor; 040 import org.apache.aries.blueprint.NamespaceHandler; 041 import org.apache.aries.blueprint.ParserContext; 042 import org.apache.aries.blueprint.PassThroughMetadata; 043 import org.apache.aries.blueprint.mutable.MutableBeanMetadata; 044 import org.apache.aries.blueprint.mutable.MutablePassThroughMetadata; 045 import org.apache.aries.blueprint.mutable.MutableRefMetadata; 046 import org.apache.aries.blueprint.mutable.MutableReferenceMetadata; 047 import org.apache.aries.blueprint.mutable.MutableValueMetadata; 048 import org.apache.camel.CamelContext; 049 import org.apache.camel.CamelContextAware; 050 import org.apache.camel.EndpointInject; 051 import org.apache.camel.Produce; 052 import org.apache.camel.blueprint.BlueprintCamelContext; 053 import org.apache.camel.blueprint.CamelContextFactoryBean; 054 import org.apache.camel.blueprint.CamelRouteContextFactoryBean; 055 import org.apache.camel.core.xml.AbstractCamelContextFactoryBean; 056 import org.apache.camel.core.xml.AbstractCamelFactoryBean; 057 import org.apache.camel.impl.CamelPostProcessorHelper; 058 import org.apache.camel.impl.DefaultCamelContextNameStrategy; 059 import org.apache.camel.model.AggregateDefinition; 060 import org.apache.camel.model.CatchDefinition; 061 import org.apache.camel.model.DataFormatDefinition; 062 import org.apache.camel.model.ExpressionNode; 063 import org.apache.camel.model.ExpressionSubElementDefinition; 064 import org.apache.camel.model.FromDefinition; 065 import org.apache.camel.model.MarshalDefinition; 066 import org.apache.camel.model.OnExceptionDefinition; 067 import org.apache.camel.model.ProcessorDefinition; 068 import org.apache.camel.model.ResequenceDefinition; 069 import org.apache.camel.model.RouteDefinition; 070 import org.apache.camel.model.SendDefinition; 071 import org.apache.camel.model.SortDefinition; 072 import org.apache.camel.model.UnmarshalDefinition; 073 import org.apache.camel.model.WireTapDefinition; 074 import org.apache.camel.model.language.ExpressionDefinition; 075 import org.apache.camel.spi.CamelContextNameStrategy; 076 import org.apache.camel.spi.ComponentResolver; 077 import org.apache.camel.spi.DataFormatResolver; 078 import org.apache.camel.spi.LanguageResolver; 079 import org.apache.camel.util.ObjectHelper; 080 import org.osgi.framework.Bundle; 081 import org.osgi.service.blueprint.container.BlueprintContainer; 082 import org.osgi.service.blueprint.container.ComponentDefinitionException; 083 import org.osgi.service.blueprint.reflect.BeanMetadata; 084 import org.osgi.service.blueprint.reflect.ComponentMetadata; 085 import org.osgi.service.blueprint.reflect.Metadata; 086 import org.osgi.service.blueprint.reflect.RefMetadata; 087 import org.osgi.service.blueprint.reflect.ValueMetadata; 088 import org.slf4j.Logger; 089 import org.slf4j.LoggerFactory; 090 091 import static org.osgi.service.blueprint.reflect.ServiceReferenceMetadata.AVAILABILITY_MANDATORY; 092 import static org.osgi.service.blueprint.reflect.ServiceReferenceMetadata.AVAILABILITY_OPTIONAL; 093 094 public class CamelNamespaceHandler implements NamespaceHandler { 095 096 private static final String CAMEL_CONTEXT = "camelContext"; 097 private static final String ROUTE_CONTEXT = "routeContext"; 098 099 private static final String SPRING_NS = "http://camel.apache.org/schema/spring"; 100 private static final String BLUEPRINT_NS = "http://camel.apache.org/schema/blueprint"; 101 102 private static final transient Logger LOG = LoggerFactory.getLogger(CamelNamespaceHandler.class); 103 104 private JAXBContext jaxbContext; 105 106 public static void renameNamespaceRecursive(Node node) { 107 if (node.getNodeType() == Node.ELEMENT_NODE) { 108 Document doc = node.getOwnerDocument(); 109 if (((Element) node).getNamespaceURI().equals(BLUEPRINT_NS)) { 110 doc.renameNode(node, SPRING_NS, node.getLocalName()); 111 } 112 } 113 NodeList list = node.getChildNodes(); 114 for (int i = 0; i < list.getLength(); ++i) { 115 renameNamespaceRecursive(list.item(i)); 116 } 117 } 118 119 public URL getSchemaLocation(String namespace) { 120 return getClass().getClassLoader().getResource("camel-blueprint.xsd"); 121 } 122 123 @SuppressWarnings("unchecked") 124 public Set<Class> getManagedClasses() { 125 return new HashSet<Class>(Arrays.asList(BlueprintCamelContext.class)); 126 } 127 128 public Metadata parse(Element element, ParserContext context) { 129 renameNamespaceRecursive(element); 130 if (element.getLocalName().equals(CAMEL_CONTEXT)) { 131 // Find the id, generate one if needed 132 String contextId = element.getAttribute("id"); 133 boolean implicitId = false; 134 135 // lets avoid folks having to explicitly give an ID to a camel context 136 if (ObjectHelper.isEmpty(contextId)) { 137 // if no explicit id was set then use a default auto generated name 138 CamelContextNameStrategy strategy = new DefaultCamelContextNameStrategy(); 139 contextId = strategy.getName(); 140 element.setAttribute("id", contextId); 141 implicitId = true; 142 } 143 144 // now lets parse the routes with JAXB 145 Binder<Node> binder; 146 try { 147 binder = getJaxbContext().createBinder(); 148 } catch (JAXBException e) { 149 throw new ComponentDefinitionException("Failed to create the JAXB binder : " + e, e); 150 } 151 Object value = parseUsingJaxb(element, context, binder); 152 if (!(value instanceof CamelContextFactoryBean)) { 153 throw new ComponentDefinitionException("Expected an instance of " + CamelContextFactoryBean.class); 154 } 155 156 CamelContextFactoryBean ccfb = (CamelContextFactoryBean) value; 157 ccfb.setImplicitId(implicitId); 158 159 MutablePassThroughMetadata factory = context.createMetadata(MutablePassThroughMetadata.class); 160 factory.setId(".camelBlueprint.passThrough." + contextId); 161 factory.setObject(new PassThroughCallable<Object>(value)); 162 163 MutableBeanMetadata factory2 = context.createMetadata(MutableBeanMetadata.class); 164 factory2.setId(".camelBlueprint.factory." + contextId); 165 factory2.setFactoryComponent(factory); 166 factory2.setFactoryMethod("call"); 167 factory2.setInitMethod("afterPropertiesSet"); 168 factory2.setDestroyMethod("destroy"); 169 factory2.addProperty("blueprintContainer", createRef(context, "blueprintContainer")); 170 factory2.addProperty("bundleContext", createRef(context, "blueprintBundleContext")); 171 172 MutableBeanMetadata ctx = context.createMetadata(MutableBeanMetadata.class); 173 ctx.setId(contextId); 174 ctx.setRuntimeClass(BlueprintCamelContext.class); 175 ctx.setFactoryComponent(factory2); 176 ctx.setFactoryMethod("getContext"); 177 ctx.setInitMethod("init"); 178 ctx.setDestroyMethod("destroy"); 179 180 // Register objects 181 registerBeans(context, contextId, ccfb.getEndpoints()); 182 registerBeans(context, contextId, ccfb.getThreadPools()); 183 registerBeans(context, contextId, ccfb.getBeans()); 184 185 // Register processors 186 MutablePassThroughMetadata beanProcessorFactory = context.createMetadata(MutablePassThroughMetadata.class); 187 beanProcessorFactory.setId(".camelBlueprint.processor.bean.passThrough." + contextId); 188 beanProcessorFactory.setObject(new PassThroughCallable<Object>(new CamelInjector(contextId))); 189 190 MutableBeanMetadata beanProcessor = context.createMetadata(MutableBeanMetadata.class); 191 beanProcessor.setId(".camelBlueprint.processor.bean." + contextId); 192 beanProcessor.setRuntimeClass(CamelInjector.class); 193 beanProcessor.setFactoryComponent(beanProcessorFactory); 194 beanProcessor.setFactoryMethod("call"); 195 beanProcessor.setProcessor(true); 196 beanProcessor.addProperty("blueprintContainer", createRef(context, "blueprintContainer")); 197 context.getComponentDefinitionRegistry().registerComponentDefinition(beanProcessor); 198 199 MutablePassThroughMetadata regProcessorFactory = context.createMetadata(MutablePassThroughMetadata.class); 200 regProcessorFactory.setId(".camelBlueprint.processor.registry.passThrough." + contextId); 201 regProcessorFactory.setObject(new PassThroughCallable<Object>(new CamelDependenciesFinder(contextId, context))); 202 203 MutableBeanMetadata regProcessor = context.createMetadata(MutableBeanMetadata.class); 204 regProcessor.setId(".camelBlueprint.processor.registry." + contextId); 205 regProcessor.setRuntimeClass(CamelDependenciesFinder.class); 206 regProcessor.setFactoryComponent(regProcessorFactory); 207 regProcessor.setFactoryMethod("call"); 208 regProcessor.setProcessor(true); 209 regProcessor.addDependsOn(".camelBlueprint.processor.bean." + contextId); 210 regProcessor.addProperty("blueprintContainer", createRef(context, "blueprintContainer")); 211 context.getComponentDefinitionRegistry().registerComponentDefinition(regProcessor); 212 213 return ctx; 214 } 215 if (element.getLocalName().equals(ROUTE_CONTEXT)) { 216 // now lets parse the routes with JAXB 217 Binder<Node> binder; 218 try { 219 binder = getJaxbContext().createBinder(); 220 } catch (JAXBException e) { 221 throw new ComponentDefinitionException("Failed to create the JAXB binder : " + e, e); 222 } 223 Object value = parseUsingJaxb(element, context, binder); 224 if (!(value instanceof CamelRouteContextFactoryBean)) { 225 throw new ComponentDefinitionException("Expected an instance of " + CamelRouteContextFactoryBean.class); 226 } 227 228 CamelRouteContextFactoryBean rcfb = (CamelRouteContextFactoryBean) value; 229 String id = rcfb.getId(); 230 231 MutablePassThroughMetadata factory = context.createMetadata(MutablePassThroughMetadata.class); 232 factory.setId(".camelBlueprint.passThrough." + id); 233 factory.setObject(new PassThroughCallable<Object>(rcfb)); 234 235 MutableBeanMetadata factory2 = context.createMetadata(MutableBeanMetadata.class); 236 factory2.setId(".camelBlueprint.factory." + id); 237 factory2.setFactoryComponent(factory); 238 factory2.setFactoryMethod("call"); 239 240 MutableBeanMetadata ctx = context.createMetadata(MutableBeanMetadata.class); 241 ctx.setId(id); 242 ctx.setRuntimeClass(List.class); 243 ctx.setFactoryComponent(factory2); 244 ctx.setFactoryMethod("getRoutes"); 245 246 return ctx; 247 } 248 return null; 249 } 250 251 private void registerBeans(ParserContext context, String contextId, List<?> beans) { 252 if (beans != null) { 253 for (Object bean : beans) { 254 if (bean instanceof AbstractCamelFactoryBean) { 255 registerBean(context, contextId, (AbstractCamelFactoryBean) bean); 256 } 257 } 258 } 259 } 260 261 protected void registerBean(ParserContext context, String contextId, AbstractCamelFactoryBean<?> fact) { 262 String id = fact.getId(); 263 264 fact.setCamelContextId(contextId); 265 266 MutablePassThroughMetadata eff = context.createMetadata(MutablePassThroughMetadata.class); 267 eff.setId(".camelBlueprint.bean.passthrough." + id); 268 eff.setObject(new PassThroughCallable<Object>(fact)); 269 270 MutableBeanMetadata ef = context.createMetadata(MutableBeanMetadata.class); 271 ef.setId(".camelBlueprint.bean.factory." + id); 272 ef.setFactoryComponent(eff); 273 ef.setFactoryMethod("call"); 274 ef.addProperty("blueprintContainer", createRef(context, "blueprintContainer")); 275 ef.setInitMethod("afterPropertiesSet"); 276 ef.setDestroyMethod("destroy"); 277 278 MutableBeanMetadata e = context.createMetadata(MutableBeanMetadata.class); 279 e.setId(id); 280 e.setRuntimeClass(fact.getObjectType()); 281 e.setFactoryComponent(ef); 282 e.setFactoryMethod("getObject"); 283 284 context.getComponentDefinitionRegistry().registerComponentDefinition(e); 285 } 286 287 protected BlueprintContainer getBlueprintContainer(ParserContext context) { 288 PassThroughMetadata ptm = (PassThroughMetadata) context.getComponentDefinitionRegistry().getComponentDefinition("blueprintContainer"); 289 return (BlueprintContainer) ptm.getObject(); 290 } 291 292 public ComponentMetadata decorate(Node node, ComponentMetadata component, ParserContext context) { 293 return null; 294 } 295 296 protected Object parseUsingJaxb(Element element, ParserContext parserContext, Binder<Node> binder) { 297 try { 298 return binder.unmarshal(element); 299 } catch (JAXBException e) { 300 throw new ComponentDefinitionException("Failed to parse JAXB element: " + e, e); 301 } 302 } 303 304 public JAXBContext getJaxbContext() throws JAXBException { 305 if (jaxbContext == null) { 306 jaxbContext = createJaxbContext(); 307 } 308 return jaxbContext; 309 } 310 311 protected JAXBContext createJaxbContext() throws JAXBException { 312 StringBuilder packages = new StringBuilder(); 313 for (Class cl : getJaxbPackages()) { 314 if (packages.length() > 0) { 315 packages.append(":"); 316 } 317 packages.append(cl.getName().substring(0, cl.getName().lastIndexOf('.'))); 318 } 319 return JAXBContext.newInstance(packages.toString(), getClass().getClassLoader()); 320 } 321 322 protected Set<Class> getJaxbPackages() { 323 Set<Class> classes = new HashSet<Class>(); 324 classes.add(CamelContextFactoryBean.class); 325 classes.add(AbstractCamelContextFactoryBean.class); 326 classes.add(org.apache.camel.ExchangePattern.class); 327 classes.add(org.apache.camel.model.RouteDefinition.class); 328 classes.add(org.apache.camel.model.config.StreamResequencerConfig.class); 329 classes.add(org.apache.camel.model.dataformat.DataFormatsDefinition.class); 330 classes.add(org.apache.camel.model.language.ExpressionDefinition.class); 331 classes.add(org.apache.camel.model.loadbalancer.RoundRobinLoadBalancerDefinition.class); 332 return classes; 333 } 334 335 private ValueMetadata createValue(ParserContext context, String value) { 336 MutableValueMetadata v = context.createMetadata(MutableValueMetadata.class); 337 v.setStringValue(value); 338 return v; 339 } 340 341 private RefMetadata createRef(ParserContext context, String value) { 342 MutableRefMetadata r = context.createMetadata(MutableRefMetadata.class); 343 r.setComponentId(value); 344 return r; 345 } 346 347 public static class PassThroughCallable<T> implements Callable<T> { 348 349 private T value; 350 351 public PassThroughCallable(T value) { 352 this.value = value; 353 } 354 355 public T call() throws Exception { 356 return value; 357 } 358 } 359 360 public static class CamelInjector extends CamelPostProcessorHelper implements BeanProcessor { 361 362 private final String camelContextName; 363 private BlueprintContainer blueprintContainer; 364 365 public CamelInjector(String camelContextName) { 366 this.camelContextName = camelContextName; 367 } 368 369 public void setBlueprintContainer(BlueprintContainer blueprintContainer) { 370 this.blueprintContainer = blueprintContainer; 371 } 372 373 public Object beforeInit(Object bean, String beanName, BeanCreator beanCreator, BeanMetadata beanMetadata) { 374 injectFields(bean, beanName); 375 injectMethods(bean, beanName); 376 if (bean instanceof CamelContextAware) { 377 ((CamelContextAware) bean).setCamelContext(getCamelContext()); 378 } 379 return bean; 380 } 381 382 @Override 383 public CamelContext getCamelContext() { 384 return (CamelContext) blueprintContainer.getComponentInstance(camelContextName); 385 } 386 387 /** 388 * A strategy method to allow implementations to perform some custom JBI 389 * based injection of the POJO 390 * 391 * @param bean the bean to be injected 392 */ 393 protected void injectFields(final Object bean, final String beanName) { 394 Class clazz = bean.getClass(); 395 do { 396 Field[] fields = clazz.getDeclaredFields(); 397 for (Field field : fields) { 398 EndpointInject endpointInject = field.getAnnotation(EndpointInject.class); 399 if (endpointInject != null && matchContext(endpointInject.context())) { 400 injectField(field, endpointInject.uri(), endpointInject.ref(), bean, beanName); 401 } 402 403 Produce produce = field.getAnnotation(Produce.class); 404 if (produce != null && matchContext(produce.context())) { 405 injectField(field, produce.uri(), produce.ref(), bean, beanName); 406 } 407 } 408 clazz = clazz.getSuperclass(); 409 } while (clazz != null && clazz != Object.class); 410 } 411 412 protected void injectField(Field field, String endpointUri, String endpointRef, Object bean, String beanName) { 413 setField(field, bean, getInjectionValue(field.getType(), endpointUri, endpointRef, field.getName(), bean, beanName)); 414 } 415 416 protected static void setField(Field field, Object instance, Object value) { 417 try { 418 boolean oldAccessible = field.isAccessible(); 419 boolean shouldSetAccessible = !Modifier.isPublic(field.getModifiers()) && !oldAccessible; 420 if (shouldSetAccessible) { 421 field.setAccessible(true); 422 } 423 field.set(instance, value); 424 if (shouldSetAccessible) { 425 field.setAccessible(oldAccessible); 426 } 427 } catch (IllegalArgumentException ex) { 428 throw new UnsupportedOperationException("Cannot inject value of class: " + value.getClass() + " into: " + field); 429 } catch (IllegalAccessException ex) { 430 throw new IllegalStateException("Could not access method: " + ex.getMessage()); 431 } 432 } 433 434 protected void injectMethods(final Object bean, final String beanName) { 435 Class clazz = bean.getClass(); 436 do { 437 Method[] methods = clazz.getDeclaredMethods(); 438 for (Method method : methods) { 439 setterInjection(method, bean, beanName); 440 consumerInjection(method, bean, beanName); 441 } 442 clazz = clazz.getSuperclass(); 443 } while (clazz != null && clazz != Object.class); 444 } 445 446 protected void setterInjection(Method method, Object bean, String beanName) { 447 EndpointInject endpointInject = method.getAnnotation(EndpointInject.class); 448 if (endpointInject != null && matchContext(endpointInject.context())) { 449 setterInjection(method, bean, beanName, endpointInject.uri(), endpointInject.ref()); 450 } 451 452 Produce produce = method.getAnnotation(Produce.class); 453 if (produce != null && matchContext(produce.context())) { 454 setterInjection(method, bean, beanName, produce.uri(), produce.ref()); 455 } 456 } 457 458 protected void setterInjection(Method method, Object bean, String beanName, String endpointUri, String endpointRef) { 459 Class<?>[] parameterTypes = method.getParameterTypes(); 460 if (parameterTypes != null) { 461 if (parameterTypes.length != 1) { 462 LOG.warn("Ignoring badly annotated method for injection due to incorrect number of parameters: " + method); 463 } else { 464 String propertyName = ObjectHelper.getPropertyName(method); 465 Object value = getInjectionValue(parameterTypes[0], endpointUri, endpointRef, propertyName, bean, beanName); 466 ObjectHelper.invokeMethod(method, bean, value); 467 } 468 } 469 } 470 471 public Object afterInit(Object o, String s, BeanCreator beanCreator, BeanMetadata beanMetadata) { 472 return o; 473 } 474 475 public void beforeDestroy(Object o, String s) { 476 } 477 478 public void afterDestroy(Object o, String s) { 479 } 480 481 } 482 483 public static class CamelDependenciesFinder implements ComponentDefinitionRegistryProcessor { 484 485 private final String camelContextName; 486 private final ParserContext context; 487 private BlueprintContainer blueprintContainer; 488 489 public CamelDependenciesFinder(String camelContextName, ParserContext context) { 490 this.camelContextName = camelContextName; 491 this.context = context; 492 } 493 494 public void setBlueprintContainer(BlueprintContainer blueprintContainer) { 495 this.blueprintContainer = blueprintContainer; 496 } 497 498 public void process(ComponentDefinitionRegistry componentDefinitionRegistry) { 499 CamelContext camelContext = (CamelContext) blueprintContainer.getComponentInstance(camelContextName); 500 501 Set<String> components = new HashSet<String>(); 502 Set<String> languages = new HashSet<String>(); 503 Set<String> dataformats = new HashSet<String>(); 504 Set<String> dependsOn = new HashSet<String>(); 505 for (RouteDefinition rd : camelContext.getRouteDefinitions()) { 506 findInputComponents(rd.getInputs(), components, languages, dataformats); 507 findOutputComponents(rd.getOutputs(), components, languages, dataformats); 508 } 509 try { 510 for (String component : components) { 511 ComponentMetadata cm = componentDefinitionRegistry.getComponentDefinition(".camelBlueprint.componentResolver." + component); 512 if (cm == null) { 513 MutableReferenceMetadata svc = createMetadata(MutableReferenceMetadata.class); 514 svc.setId(".camelBlueprint.componentResolver." + component); 515 svc.setFilter("(component=" + component + ")"); 516 svc.setAvailability(componentDefinitionRegistry.containsComponentDefinition(component) ? AVAILABILITY_OPTIONAL : AVAILABILITY_MANDATORY); 517 try { 518 // Try to set the runtime interface (only with aries blueprint > 0.1 519 svc.getClass().getMethod("setRuntimeInterface", Class.class).invoke(svc, ComponentResolver.class); 520 } catch (Throwable t) { 521 // Check if the bundle can see the class 522 try { 523 PassThroughMetadata ptm = (PassThroughMetadata) componentDefinitionRegistry.getComponentDefinition("blueprintBundle"); 524 Bundle b = (Bundle) ptm.getObject(); 525 if (b.loadClass(ComponentResolver.class.getName()) != ComponentResolver.class) { 526 throw new UnsupportedOperationException(); 527 } 528 svc.setInterface(ComponentResolver.class.getName()); 529 } catch (Throwable t2) { 530 throw new UnsupportedOperationException(); 531 } 532 } 533 componentDefinitionRegistry.registerComponentDefinition(svc); 534 dependsOn.add(svc.getId()); 535 } 536 } 537 for (String language : languages) { 538 ComponentMetadata cm = componentDefinitionRegistry.getComponentDefinition(".camelBlueprint.languageResolver." + language); 539 if (cm == null) { 540 MutableReferenceMetadata svc = createMetadata(MutableReferenceMetadata.class); 541 svc.setId(".camelBlueprint.languageResolver." + language); 542 svc.setFilter("(language=" + language + ")"); 543 svc.setAvailability(componentDefinitionRegistry.containsComponentDefinition(language) ? AVAILABILITY_OPTIONAL : AVAILABILITY_MANDATORY); 544 try { 545 // Try to set the runtime interface (only with aries blueprint > 0.1 546 svc.getClass().getMethod("setRuntimeInterface", Class.class).invoke(svc, LanguageResolver.class); 547 } catch (Throwable t) { 548 // Check if the bundle can see the class 549 try { 550 PassThroughMetadata ptm = (PassThroughMetadata) componentDefinitionRegistry.getComponentDefinition("blueprintBundle"); 551 Bundle b = (Bundle) ptm.getObject(); 552 if (b.loadClass(LanguageResolver.class.getName()) != LanguageResolver.class) { 553 throw new UnsupportedOperationException(); 554 } 555 svc.setInterface(LanguageResolver.class.getName()); 556 } catch (Throwable t2) { 557 throw new UnsupportedOperationException(); 558 } 559 } 560 componentDefinitionRegistry.registerComponentDefinition(svc); 561 dependsOn.add(svc.getId()); 562 } 563 } 564 for (String dataformat : dataformats) { 565 ComponentMetadata cm = componentDefinitionRegistry.getComponentDefinition(".camelBlueprint.dataformatResolver." + dataformat); 566 if (cm == null) { 567 MutableReferenceMetadata svc = createMetadata(MutableReferenceMetadata.class); 568 svc.setId(".camelBlueprint.dataformatResolver." + dataformat); 569 svc.setFilter("(dataformat=" + dataformat + ")"); 570 svc.setAvailability(componentDefinitionRegistry.containsComponentDefinition(dataformat) ? AVAILABILITY_OPTIONAL : AVAILABILITY_MANDATORY); 571 try { 572 // Try to set the runtime interface (only with aries blueprint > 0.1 573 svc.getClass().getMethod("setRuntimeInterface", Class.class).invoke(svc, DataFormatResolver.class); 574 } catch (Throwable t) { 575 // Check if the bundle can see the class 576 try { 577 PassThroughMetadata ptm = (PassThroughMetadata) componentDefinitionRegistry.getComponentDefinition("blueprintBundle"); 578 Bundle b = (Bundle) ptm.getObject(); 579 if (b.loadClass(DataFormatResolver.class.getName()) != DataFormatResolver.class) { 580 throw new UnsupportedOperationException(); 581 } 582 svc.setInterface(DataFormatResolver.class.getName()); 583 } catch (Throwable t2) { 584 throw new UnsupportedOperationException(); 585 } 586 } 587 componentDefinitionRegistry.registerComponentDefinition(svc); 588 dependsOn.add(svc.getId()); 589 } 590 } 591 } catch (UnsupportedOperationException e) { 592 LOG.warn("Unable to add dependencies on to camel components OSGi services. " 593 + "The Apache Aries blueprint implementation used it too old and the blueprint bundle can not see the org.apache.camel.spi package."); 594 components.clear(); 595 languages.clear(); 596 dataformats.clear(); 597 } 598 599 } 600 601 public <T extends org.osgi.service.blueprint.reflect.Metadata> T createMetadata(java.lang.Class<T> tClass) { 602 return context.createMetadata(tClass); 603 } 604 605 private void findInputComponents(List<FromDefinition> defs, Set<String> components, Set<String> languages, Set<String> dataformats) { 606 if (defs != null) { 607 for (FromDefinition def : defs) { 608 findUriComponent(def.getUri(), components); 609 } 610 } 611 } 612 613 @SuppressWarnings("unchecked") 614 private void findOutputComponents(List<ProcessorDefinition> defs, Set<String> components, Set<String> languages, Set<String> dataformats) { 615 if (defs != null) { 616 for (ProcessorDefinition def : defs) { 617 if (def instanceof SendDefinition) { 618 findUriComponent(((SendDefinition) def).getUri(), components); 619 } 620 if (def instanceof MarshalDefinition) { 621 findDataFormat(((MarshalDefinition) def).getDataFormatType(), dataformats); 622 } 623 if (def instanceof UnmarshalDefinition) { 624 findDataFormat(((UnmarshalDefinition) def).getDataFormatType(), dataformats); 625 } 626 if (def instanceof ExpressionNode) { 627 findLanguage(((ExpressionNode) def).getExpression(), languages); 628 } 629 if (def instanceof ResequenceDefinition) { 630 findLanguage(((ResequenceDefinition) def).getExpression(), languages); 631 } 632 if (def instanceof AggregateDefinition) { 633 findLanguage(((AggregateDefinition) def).getExpression(), languages); 634 findLanguage(((AggregateDefinition) def).getCorrelationExpression(), languages); 635 findLanguage(((AggregateDefinition) def).getCompletionPredicate(), languages); 636 findLanguage(((AggregateDefinition) def).getCompletionTimeoutExpression(), languages); 637 findLanguage(((AggregateDefinition) def).getCompletionSizeExpression(), languages); 638 } 639 if (def instanceof CatchDefinition) { 640 findLanguage(((CatchDefinition) def).getHandled(), languages); 641 } 642 if (def instanceof OnExceptionDefinition) { 643 findLanguage(((OnExceptionDefinition) def).getRetryWhile(), languages); 644 findLanguage(((OnExceptionDefinition) def).getHandled(), languages); 645 findLanguage(((OnExceptionDefinition) def).getContinued(), languages); 646 } 647 if (def instanceof SortDefinition) { 648 findLanguage(((SortDefinition) def).getExpression(), languages); 649 } 650 if (def instanceof WireTapDefinition) { 651 findLanguage(((WireTapDefinition) def).getNewExchangeExpression(), languages); 652 } 653 findOutputComponents(def.getOutputs(), components, languages, dataformats); 654 } 655 } 656 } 657 658 private void findLanguage(ExpressionDefinition expression, Set<String> languages) { 659 if (expression != null) { 660 String lang = expression.getLanguage(); 661 if (lang != null && lang.length() > 0) { 662 languages.add(lang); 663 } 664 } 665 } 666 667 private void findLanguage(List<ExpressionDefinition> expressions, Set<String> languages) { 668 if (expressions != null) { 669 for (ExpressionDefinition e : expressions) { 670 findLanguage(e, languages); 671 } 672 } 673 } 674 675 private void findLanguage(ExpressionSubElementDefinition expression, Set<String> languages) { 676 if (expression != null) { 677 findLanguage(expression.getExpressionType(), languages); 678 } 679 } 680 681 private void findDataFormat(DataFormatDefinition dfd, Set<String> dataformats) { 682 if (dfd != null && dfd.getDataFormatName() != null) { 683 dataformats.add(dfd.getDataFormatName()); 684 } 685 } 686 687 private void findUriComponent(String uri, Set<String> components) { 688 if (uri != null) { 689 String splitURI[] = ObjectHelper.splitOnCharacter(uri, ":", 2); 690 if (splitURI[1] != null) { 691 String scheme = splitURI[0]; 692 components.add(scheme); 693 } 694 } 695 } 696 697 } 698 699 }