/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.camel.cdi; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; import javax.enterprise.inject.InjectionException; import javax.enterprise.inject.UnsatisfiedResolutionException; import javax.enterprise.inject.spi.BeanManager; import org.apache.camel.BeanInject; import org.apache.camel.CamelContext; import org.apache.camel.EndpointInject; import org.apache.camel.Produce; import org.apache.camel.PropertyInject; import org.apache.camel.impl.CamelPostProcessorHelper; import org.apache.camel.impl.DefaultCamelBeanPostProcessor; import org.apache.camel.util.ReflectionHelper; import static org.apache.camel.cdi.BeanManagerHelper.getReferenceByType; import static org.apache.camel.cdi.DefaultLiteral.DEFAULT; @Vetoed final class CdiCamelBeanPostProcessor extends DefaultCamelBeanPostProcessor { private final BeanManager manager; private final Map<String, CamelPostProcessorHelper> postProcessorHelpers = new HashMap<>(); // TODO: proper support for multi Camel contexts and custom context qualifiers CdiCamelBeanPostProcessor(BeanManager manager) { this.manager = manager; } protected void injectFields(final Object bean, final String beanName) { ReflectionHelper.doWithFields(bean.getClass(), field -> { PropertyInject propertyInject = field.getAnnotation(PropertyInject.class); if (propertyInject != null) { try { injectFieldProperty(field, propertyInject.value(), propertyInject.defaultValue(), propertyInject.context(), bean, beanName); } catch (Exception cause) { throw new InjectionException("Injection of [" + propertyInject + "] for field [" + field + "] failed!", cause); } } BeanInject beanInject = field.getAnnotation(BeanInject.class); // TODO: proper support for multi Camel contexts if (beanInject != null && getPostProcessorHelper().matchContext(beanInject.context())) { try { injectFieldBean(field, beanInject.value(), bean, beanName); } catch (Exception cause) { throw new InjectionException("Injection of [" + beanInject + "] for field [" + field + "] failed!", cause); } } EndpointInject endpointInject = field.getAnnotation(EndpointInject.class); if (endpointInject != null) { try { injectField(field, endpointInject.uri(), endpointInject.ref(), endpointInject.property(), endpointInject.context(), bean, beanName); } catch (Exception cause) { throw new InjectionException("Injection of [" + endpointInject + "] for field [" + field + "] failed!", cause); } } Produce produce = field.getAnnotation(Produce.class); if (produce != null) { try { injectField(field, produce.uri(), produce.ref(), produce.property(), produce.context(), bean, beanName); } catch (Exception cause) { throw new InjectionException("Injection of [" + produce + "] for field [" + field + "] failed!", cause); } } }); } private void injectField(Field field, String uri, String ref, String property, String context, Object bean, String beanName) { ReflectionHelper.setField(field, bean, getPostProcessorHelper(context).getInjectionValue(field.getType(), uri, ref, property, field.getName(), bean, beanName)); } private void injectFieldProperty(Field field, String property, String defaultValue, String context, Object bean, String beanName) { ReflectionHelper.setField(field, bean, getPostProcessorHelper(context).getInjectionPropertyValue(field.getType(), property, defaultValue, field.getName(), bean, beanName)); } private CamelPostProcessorHelper getPostProcessorHelper(String contextName) { return postProcessorHelpers.computeIfAbsent(contextName, k -> new CamelPostProcessorHelper(getOrLookupCamelContext(k))); } private CamelContext getOrLookupCamelContext(String contextName) { // TODO: proper support for custom context qualifiers return getReferenceByType(manager, CamelContext.class, contextName.isEmpty() ? DEFAULT : ContextName.Literal.of(contextName)) .orElseThrow(() -> new UnsatisfiedResolutionException("No Camel context with name [" + contextName + "] is deployed!")); } @Override public CamelContext getOrLookupCamelContext() { return getReferenceByType(manager, CamelContext.class).orElse(null); } }