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