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.apache.commons.logging.Log;
081 import org.apache.commons.logging.LogFactory;
082
083 import org.osgi.framework.Bundle;
084 import org.osgi.service.blueprint.container.BlueprintContainer;
085 import org.osgi.service.blueprint.container.ComponentDefinitionException;
086 import org.osgi.service.blueprint.reflect.BeanMetadata;
087 import org.osgi.service.blueprint.reflect.ComponentMetadata;
088 import org.osgi.service.blueprint.reflect.Metadata;
089 import org.osgi.service.blueprint.reflect.RefMetadata;
090 import org.osgi.service.blueprint.reflect.ValueMetadata;
091
092 public class CamelNamespaceHandler implements NamespaceHandler {
093
094 private static final String CAMEL_CONTEXT = "camelContext";
095 private static final String ROUTE_CONTEXT = "routeContext";
096
097 private static final String SPRING_NS = "http://camel.apache.org/schema/spring";
098 private static final String BLUEPRINT_NS = "http://camel.apache.org/schema/blueprint";
099
100 private static final transient Log LOG = LogFactory.getLog(CamelNamespaceHandler.class);
101
102 private JAXBContext jaxbContext;
103
104 public static void renameNamespaceRecursive(Node node) {
105 if (node.getNodeType() == Node.ELEMENT_NODE) {
106 Document doc = node.getOwnerDocument();
107 if (((Element) node).getNamespaceURI().equals(BLUEPRINT_NS)) {
108 doc.renameNode(node, SPRING_NS, node.getNodeName());
109 }
110 }
111 NodeList list = node.getChildNodes();
112 for (int i = 0; i < list.getLength(); ++i) {
113 renameNamespaceRecursive(list.item(i));
114 }
115 }
116
117 public URL getSchemaLocation(String namespace) {
118 return getClass().getClassLoader().getResource("camel-blueprint.xsd");
119 }
120
121 @SuppressWarnings("unchecked")
122 public Set<Class> getManagedClasses() {
123 return new HashSet<Class>(Arrays.asList(
124 BlueprintCamelContext.class
125 ));
126 }
127
128 public Metadata parse(Element element, ParserContext context) {
129 renameNamespaceRecursive(element);
130 if (element.getNodeName().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.getNodeName().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 try {
517 // Try to set the runtime interface (only with aries blueprint > 0.1
518 svc.getClass().getMethod("setRuntimeInterface", Class.class).invoke(svc, ComponentResolver.class);
519 } catch (Throwable t) {
520 // Check if the bundle can see the class
521 try {
522 PassThroughMetadata ptm = (PassThroughMetadata) componentDefinitionRegistry.getComponentDefinition("blueprintBundle");
523 Bundle b = (Bundle) ptm.getObject();
524 if (b.loadClass(ComponentResolver.class.getName()) != ComponentResolver.class) {
525 throw new UnsupportedOperationException();
526 }
527 svc.setInterface(ComponentResolver.class.getName());
528 } catch (Throwable t2) {
529 throw new UnsupportedOperationException();
530 }
531 }
532 componentDefinitionRegistry.registerComponentDefinition(svc);
533 dependsOn.add(svc.getId());
534 }
535 }
536 for (String language : languages) {
537 ComponentMetadata cm = componentDefinitionRegistry.getComponentDefinition(".camelBlueprint.languageResolver." + language);
538 if (cm == null) {
539 MutableReferenceMetadata svc = createMetadata(MutableReferenceMetadata.class);
540 svc.setId(".camelBlueprint.languageResolver." + language);
541 svc.setFilter("(language=" + language + ")");
542 try {
543 // Try to set the runtime interface (only with aries blueprint > 0.1
544 svc.getClass().getMethod("setRuntimeInterface", Class.class).invoke(svc, LanguageResolver.class);
545 } catch (Throwable t) {
546 // Check if the bundle can see the class
547 try {
548 PassThroughMetadata ptm = (PassThroughMetadata) componentDefinitionRegistry.getComponentDefinition("blueprintBundle");
549 Bundle b = (Bundle) ptm.getObject();
550 if (b.loadClass(LanguageResolver.class.getName()) != LanguageResolver.class) {
551 throw new UnsupportedOperationException();
552 }
553 svc.setInterface(LanguageResolver.class.getName());
554 } catch (Throwable t2) {
555 throw new UnsupportedOperationException();
556 }
557 }
558 componentDefinitionRegistry.registerComponentDefinition(svc);
559 dependsOn.add(svc.getId());
560 }
561 }
562 for (String dataformat : dataformats) {
563 ComponentMetadata cm = componentDefinitionRegistry.getComponentDefinition(".camelBlueprint.dataformatResolver." + dataformat);
564 if (cm == null) {
565 MutableReferenceMetadata svc = createMetadata(MutableReferenceMetadata.class);
566 svc.setId(".camelBlueprint.dataformatResolver." + dataformat);
567 svc.setFilter("(dataformat=" + dataformat + ")");
568 try {
569 // Try to set the runtime interface (only with aries blueprint > 0.1
570 svc.getClass().getMethod("setRuntimeInterface", Class.class).invoke(svc, DataFormatResolver.class);
571 } catch (Throwable t) {
572 // Check if the bundle can see the class
573 try {
574 PassThroughMetadata ptm = (PassThroughMetadata) componentDefinitionRegistry.getComponentDefinition("blueprintBundle");
575 Bundle b = (Bundle) ptm.getObject();
576 if (b.loadClass(DataFormatResolver.class.getName()) != DataFormatResolver.class) {
577 throw new UnsupportedOperationException();
578 }
579 svc.setInterface(DataFormatResolver.class.getName());
580 } catch (Throwable t2) {
581 throw new UnsupportedOperationException();
582 }
583 }
584 componentDefinitionRegistry.registerComponentDefinition(svc);
585 dependsOn.add(svc.getId());
586 }
587 }
588 } catch (UnsupportedOperationException e) {
589 LOG.warn("Unable to add dependencies on to camel components OSGi services. "
590 + "The Apache Aries blueprint implementation used it too old and the blueprint bundle can not see the org.apache.camel.spi package.");
591 components.clear();
592 languages.clear();
593 dataformats.clear();
594 }
595
596
597 }
598
599 public <T extends org.osgi.service.blueprint.reflect.Metadata> T createMetadata(java.lang.Class<T> tClass) {
600 return context.createMetadata(tClass);
601 }
602
603 private void findInputComponents(List<FromDefinition> defs, Set<String> components, Set<String> languages, Set<String> dataformats) {
604 if (defs != null) {
605 for (FromDefinition def : defs) {
606 findUriComponent(def.getUri(), components);
607 }
608 }
609 }
610
611 @SuppressWarnings("unchecked")
612 private void findOutputComponents(List<ProcessorDefinition> defs, Set<String> components, Set<String> languages, Set<String> dataformats) {
613 if (defs != null) {
614 for (ProcessorDefinition def : defs) {
615 if (def instanceof SendDefinition) {
616 findUriComponent(((SendDefinition) def).getUri(), components);
617 }
618 if (def instanceof MarshalDefinition) {
619 findDataFormat(((MarshalDefinition) def).getDataFormatType(), dataformats);
620 }
621 if (def instanceof UnmarshalDefinition) {
622 findDataFormat(((UnmarshalDefinition) def).getDataFormatType(), dataformats);
623 }
624 if (def instanceof ExpressionNode) {
625 findLanguage(((ExpressionNode) def).getExpression(), languages);
626 }
627 if (def instanceof ResequenceDefinition) {
628 findLanguage(((ResequenceDefinition) def).getExpressions(), languages);
629 }
630 if (def instanceof AggregateDefinition) {
631 findLanguage(((AggregateDefinition) def).getExpression(), languages);
632 findLanguage(((AggregateDefinition) def).getCorrelationExpression(), languages);
633 findLanguage(((AggregateDefinition) def).getCompletionPredicate(), languages);
634 findLanguage(((AggregateDefinition) def).getCompletionTimeoutExpression(), languages);
635 findLanguage(((AggregateDefinition) def).getCompletionSizeExpression(), languages);
636 }
637 if (def instanceof CatchDefinition) {
638 findLanguage(((CatchDefinition) def).getHandled(), languages);
639 }
640 if (def instanceof OnExceptionDefinition) {
641 findLanguage(((OnExceptionDefinition) def).getRetryWhile(), languages);
642 findLanguage(((OnExceptionDefinition) def).getHandled(), languages);
643 findLanguage(((OnExceptionDefinition) def).getContinued(), languages);
644 }
645 if (def instanceof SortDefinition) {
646 findLanguage(((SortDefinition) def).getExpression(), languages);
647 }
648 if (def instanceof WireTapDefinition) {
649 findLanguage(((WireTapDefinition) def).getNewExchangeExpression(), languages);
650 }
651 findOutputComponents(def.getOutputs(), components, languages, dataformats);
652 }
653 }
654 }
655
656 private void findLanguage(ExpressionDefinition expression, Set<String> languages) {
657 if (expression != null) {
658 String lang = expression.getLanguage();
659 if (lang != null && lang.length() > 0) {
660 languages.add(lang);
661 }
662 }
663 }
664
665 private void findLanguage(List<ExpressionDefinition> expressions, Set<String> languages) {
666 if (expressions != null) {
667 for (ExpressionDefinition e : expressions) {
668 findLanguage(e, languages);
669 }
670 }
671 }
672
673 private void findLanguage(ExpressionSubElementDefinition expression, Set<String> languages) {
674 if (expression != null) {
675 findLanguage(expression.getExpressionType(), languages);
676 }
677 }
678
679 private void findDataFormat(DataFormatDefinition dfd, Set<String> dataformats) {
680 if (dfd != null && dfd.getDataFormatName() != null) {
681 dataformats.add(dfd.getDataFormatName());
682 }
683 }
684
685 private void findUriComponent(String uri, Set<String> components) {
686 if (uri != null) {
687 String splitURI[] = ObjectHelper.splitOnCharacter(uri, ":", 2);
688 if (splitURI[1] != null) {
689 String scheme = splitURI[0];
690 components.add(scheme);
691 }
692 }
693 }
694
695 }
696
697 }