You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2016/01/15 14:44:16 UTC
[8/9] camel git commit: CAMEL-9201: Improved Camel CDI component
http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelContextNameStrategy.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelContextNameStrategy.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelContextNameStrategy.java
new file mode 100644
index 0000000..4b14b9d
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelContextNameStrategy.java
@@ -0,0 +1,45 @@
+/**
+ * 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.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.camel.impl.DefaultCamelContextNameStrategy;
+import org.apache.camel.spi.CamelContextNameStrategy;
+
+/**
+ * A {@link CamelContextNameStrategy} for Camel contexts that are managed by Camel CDI.
+ *
+ * As opposed to {@link org.apache.camel.impl.DefaultCamelContextNameStrategy},
+ * this implementation does not increment the suffix for proxies that are created
+ * each time a contextual reference to a normal-scoped bean is retrieved.
+ *
+ * It is used by Camel CDI for custom Camel context beans that do not override
+ * the context name nor the naming strategy.
+ *
+ * @see CamelContextNameStrategy
+ */
+@Vetoed
+final class CdiCamelContextNameStrategy extends DefaultCamelContextNameStrategy implements CamelContextNameStrategy {
+
+ private static final AtomicInteger CONTEXT_COUNTER = new AtomicInteger(0);
+
+ @Override
+ public String getNextName() {
+ return "camel" + "-" + CONTEXT_COUNTER.incrementAndGet();
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelEnvironment.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelEnvironment.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelEnvironment.java
new file mode 100644
index 0000000..b5cbf58
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelEnvironment.java
@@ -0,0 +1,66 @@
+/**
+ * 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 javax.enterprise.inject.spi.Annotated;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.InjectionTarget;
+import javax.enterprise.inject.spi.Producer;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.core.osgi.utils.BundleContextUtils;
+
+@Vetoed
+final class CdiCamelEnvironment {
+
+ private final boolean hasBundleContext;
+
+ CdiCamelEnvironment() {
+ hasBundleContext = isCamelCoreOsgiPresent() && hasBundleContext(CdiCamelExtension.class);
+ }
+
+ <T extends CamelContext> Producer<T> camelContextProducer(Producer<T> delegate, Annotated annotated, BeanManager manager, CdiCamelExtension extension) {
+ CamelContextProducer<T> producer = new CamelContextProducer<>(delegate, annotated, manager, extension);
+ return hasBundleContext ? new CamelContextOsgiProducer<>(producer) : producer;
+ }
+
+ <T extends CamelContext> InjectionTarget<T> camelContextInjectionTarget(InjectionTarget<T> delegate, Annotated annotated, BeanManager manager, CdiCamelExtension extension) {
+ CamelContextProducer<T> producer = new CamelContextProducer<>(delegate, annotated, manager, extension);
+ return new CamelContextInjectionTarget<>(delegate, hasBundleContext ? new CamelContextOsgiProducer<>(producer) : producer);
+ }
+
+ private static boolean isCamelCoreOsgiPresent() {
+ try {
+ getClassLoader(CdiCamelExtension.class).loadClass("org.apache.camel.core.osgi.OsgiCamelContextHelper");
+ return true;
+ } catch (ClassNotFoundException cause) {
+ return false;
+ }
+ }
+
+ private static boolean hasBundleContext(Class clazz) {
+ return BundleContextUtils.getBundleContext(clazz) != null;
+ }
+
+ private static ClassLoader getClassLoader(Class<?> clazz) {
+ if (Thread.currentThread().getContextClassLoader() != null) {
+ return Thread.currentThread().getContextClassLoader();
+ } else {
+ return clazz.getClassLoader();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelExtension.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelExtension.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelExtension.java
new file mode 100755
index 0000000..6951cc3
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelExtension.java
@@ -0,0 +1,328 @@
+/**
+ * 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.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EventObject;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import static java.util.Collections.newSetFromMap;
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.Any;
+import javax.enterprise.inject.Default;
+import javax.enterprise.inject.InjectionException;
+import javax.enterprise.inject.Produces;
+import javax.enterprise.inject.spi.AfterBeanDiscovery;
+import javax.enterprise.inject.spi.AfterDeploymentValidation;
+import javax.enterprise.inject.spi.Annotated;
+import javax.enterprise.inject.spi.AnnotatedMethod;
+import javax.enterprise.inject.spi.AnnotatedType;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.Extension;
+import javax.enterprise.inject.spi.InjectionPoint;
+import javax.enterprise.inject.spi.ObserverMethod;
+import javax.enterprise.inject.spi.ProcessAnnotatedType;
+import javax.enterprise.inject.spi.ProcessBean;
+import javax.enterprise.inject.spi.ProcessInjectionTarget;
+import javax.enterprise.inject.spi.ProcessObserverMethod;
+import javax.enterprise.inject.spi.ProcessProducer;
+import javax.enterprise.inject.spi.ProcessProducerField;
+import javax.enterprise.inject.spi.ProcessProducerMethod;
+import javax.inject.Named;
+
+import org.apache.camel.BeanInject;
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.Consume;
+import org.apache.camel.Converter;
+import org.apache.camel.Endpoint;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.PropertyInject;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.ServiceStatus;
+import org.apache.camel.management.event.AbstractExchangeEvent;
+import org.apache.camel.model.RouteContainer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.camel.cdi.CdiSpiHelper.hasAnnotation;
+
+public class CdiCamelExtension implements Extension {
+
+ private final Logger logger = LoggerFactory.getLogger(CdiCamelExtension.class);
+
+ private final CdiCamelEnvironment environment = new CdiCamelEnvironment();
+
+ private final Set<Class<?>> converters = newSetFromMap(new ConcurrentHashMap<Class<?>, Boolean>());
+
+ private final Set<AnnotatedType<?>> camelBeans = newSetFromMap(new ConcurrentHashMap<AnnotatedType<?>, Boolean>());
+
+ private final Set<AnnotatedType<?>> eagerBeans = newSetFromMap(new ConcurrentHashMap<AnnotatedType<?>, Boolean>());
+
+ private final Map<InjectionPoint, ForwardingObserverMethod<?>> cdiEventEndpoints = new ConcurrentHashMap<>();
+
+ private final Map<Annotated, Bean<?>> contextBeans = new ConcurrentHashMap<>();
+
+ private final Set<Annotation> contextQualifiers = newSetFromMap(new ConcurrentHashMap<Annotation, Boolean>());
+
+ private final Set<Annotation> eventQualifiers = newSetFromMap(new ConcurrentHashMap<Annotation, Boolean>());
+
+ private final Map<Method, Bean<?>> producerBeans = new ConcurrentHashMap<>();
+
+ private final Map<Method, Set<Annotation>> producerQualifiers = new ConcurrentHashMap<>();
+
+ ForwardingObserverMethod<?> getObserverMethod(InjectionPoint ip) {
+ return cdiEventEndpoints.get(ip);
+ }
+
+ Set<Annotation> getObserverEvents() {
+ return eventQualifiers;
+ }
+
+ Bean<?> getContextBean(Annotated annotated) {
+ return contextBeans.get(annotated);
+ }
+
+ Set<Annotation> getContextQualifiers() {
+ return contextQualifiers;
+ }
+
+ private void processAnnotatedType(@Observes ProcessAnnotatedType<?> pat) {
+ if (pat.getAnnotatedType().isAnnotationPresent(Vetoed.class)) {
+ pat.veto();
+ }
+ if (hasAnnotation(pat.getAnnotatedType(), Converter.class)) {
+ converters.add(pat.getAnnotatedType().getJavaClass());
+ }
+ if (hasAnnotation(pat.getAnnotatedType(), BeanInject.class, Consume.class, EndpointInject.class, Produce.class, PropertyInject.class)) {
+ camelBeans.add(pat.getAnnotatedType());
+ }
+ if (hasAnnotation(pat.getAnnotatedType(), Consume.class)) {
+ eagerBeans.add(pat.getAnnotatedType());
+ }
+ }
+
+ private void camelContextAware(@Observes ProcessAnnotatedType<? extends CamelContextAware> pat) {
+ camelBeans.add(pat.getAnnotatedType());
+ }
+
+ private <T extends CamelContext> void camelContextBeans(@Observes ProcessInjectionTarget<T> pit, BeanManager manager) {
+ pit.setInjectionTarget(environment.camelContextInjectionTarget(pit.getInjectionTarget(), pit.getAnnotatedType(), manager, this));
+ }
+
+ private <T extends CamelContext> void camelContextProducers(@Observes ProcessProducer<?, T> pp, BeanManager manager) {
+ pp.setProducer(environment.camelContextProducer(pp.getProducer(), pp.getAnnotatedMember(), manager, this));
+ }
+
+ private <T> void camelBeansPostProcessor(@Observes ProcessInjectionTarget<T> pit, BeanManager manager) {
+ if (camelBeans.contains(pit.getAnnotatedType())) {
+ pit.setInjectionTarget(new CamelBeanInjectionTarget<>(pit.getInjectionTarget(), manager));
+ }
+ }
+
+ private void cdiEventEndpoints(@Observes ProcessBean<?> pb) {
+ for (InjectionPoint ip : pb.getBean().getInjectionPoints()) {
+ if (!CdiEventEndpoint.class.equals(CdiSpiHelper.getRawType(ip.getType()))) {
+ continue;
+ }
+ // TODO: refine the key to the type and qualifiers instead of the whole injection point as it leads to registering redundant observers
+ if (ip.getType() instanceof ParameterizedType) {
+ cdiEventEndpoints.put(ip, new ForwardingObserverMethod<>(((ParameterizedType) ip.getType()).getActualTypeArguments()[0], ip.getQualifiers()));
+ } else if (ip.getType() instanceof Class) {
+ cdiEventEndpoints.put(ip, new ForwardingObserverMethod<>(Object.class, ip.getQualifiers()));
+ }
+ }
+ }
+
+ private <T extends Endpoint> void endpointBeans(@Observes ProcessProducerMethod<T, CdiCamelFactory> ppm) {
+ producerBeans.put(ppm.getAnnotatedProducerMethod().getJavaMember(), ppm.getBean());
+ }
+
+ private void producerTemplateBeans(@Observes ProcessProducerMethod<ProducerTemplate, CdiCamelFactory> ppm) {
+ producerBeans.put(ppm.getAnnotatedProducerMethod().getJavaMember(), ppm.getBean());
+ }
+
+ private void camelFactoryProducers(@Observes ProcessAnnotatedType<CdiCamelFactory> pat, BeanManager manager) {
+ AnnotatedType<CdiCamelFactory> at = pat.getAnnotatedType();
+ Set<AnnotatedMethod<? super CdiCamelFactory>> methods = new HashSet<>();
+ for (AnnotatedMethod<? super CdiCamelFactory> am : pat.getAnnotatedType().getMethods()) {
+ if (!am.isAnnotationPresent(Produces.class)) {
+ continue;
+ }
+ Class<?> type = CdiSpiHelper.getRawType(am.getBaseType());
+ if (Endpoint.class.isAssignableFrom(type) || ProducerTemplate.class.equals(type)) {
+ Set<Annotation> qualifiers = CdiSpiHelper.getQualifiers(am, manager);
+ producerQualifiers.put(am.getJavaMember(), qualifiers.isEmpty() ? Collections.<Annotation>singleton(DefaultLiteral.INSTANCE) : qualifiers);
+ Set<Annotation> annotations = new HashSet<>(am.getAnnotations());
+ annotations.removeAll(qualifiers);
+ annotations.add(Excluded.INSTANCE);
+ methods.add(new AnnotatedMethodDelegate<>(am, annotations));
+ }
+ }
+ pat.setAnnotatedType(new AnnotatedTypeDelegate<>(at, methods));
+ }
+
+ private <T extends EventObject> void camelEventNotifiers(@Observes ProcessObserverMethod<T, ?> pom) {
+ // Only activate Camel event notifiers for explicit Camel event observers, that is, an observer method for a super type won't activate notifiers.
+ Type type = pom.getObserverMethod().getObservedType();
+ // Camel events are raw types
+ if (type instanceof Class && Class.class.cast(type).getPackage().equals(AbstractExchangeEvent.class.getPackage())) {
+ eventQualifiers.addAll(pom.getObserverMethod().getObservedQualifiers().isEmpty() ? Collections.singleton(AnyLiteral.INSTANCE) : pom.getObserverMethod().getObservedQualifiers());
+ }
+ }
+
+ private <T extends CamelContext> void camelContextBeans(@Observes ProcessBean<T> pb) {
+ processCamelContextBean(pb.getAnnotated(), pb.getBean());
+ }
+
+ private <T extends CamelContext> void camelContextProducerFields(@Observes ProcessProducerField<T, ?> pb) {
+ processCamelContextBean(pb.getAnnotated(), pb.getBean());
+ }
+
+ private <T extends CamelContext> void camelContextProducerMethods(@Observes ProcessProducerMethod<T, ?> pb) {
+ processCamelContextBean(pb.getAnnotated(), pb.getBean());
+ }
+
+ private void processCamelContextBean(Annotated annotated, Bean<?> bean) {
+ contextQualifiers.addAll(bean.getQualifiers());
+ // Annotated must be wrapped because of OWB-1099
+ contextBeans.put(new AnnotatedWrapper(annotated), bean);
+ }
+
+ private void cdiCamelFactoryProducers(@Observes AfterBeanDiscovery abd) {
+ for (Map.Entry<Method, Bean<?>> producer : producerBeans.entrySet()) {
+ Bean<?> bean = producer.getValue();
+ Set<Annotation> qualifiers = new HashSet<>(producerQualifiers.get(producer.getKey()));
+ Class<?> type = producer.getKey().getReturnType();
+ if (CdiEventEndpoint.class.equals(type)) {
+ for (InjectionPoint ip : cdiEventEndpoints.keySet()) {
+ qualifiers.addAll(ip.getQualifiers());
+ }
+ } else {
+ if (Endpoint.class.isAssignableFrom(type) || ProducerTemplate.class.isAssignableFrom(type)) {
+ qualifiers.addAll(CdiSpiHelper.excludeElementOfTypes(contextQualifiers, Any.class, Default.class, Named.class));
+ }
+ }
+ // TODO: would be more correct to add a bean for each Camel context bean
+ abd.addBean(new BeanDelegate<>(bean, qualifiers));
+ }
+ }
+
+ private void addDefaultCamelContext(@Observes AfterBeanDiscovery abd, BeanManager manager) {
+ if (contextBeans.isEmpty()) {
+ abd.addBean(new CdiCamelContextBean(manager, environment.camelContextInjectionTarget(new CamelContextDefaultProducer(), null, manager, CdiCamelExtension.this)));
+ }
+ }
+
+ private void addCdiEventObserverMethods(@Observes AfterBeanDiscovery abd) {
+ for (ObserverMethod method : cdiEventEndpoints.values()) {
+ abd.addObserverMethod(method);
+ }
+ }
+
+ private void createCamelContexts(@Observes AfterDeploymentValidation adv, BeanManager manager) {
+ Collection<CamelContext> contexts = new ArrayList<>();
+ for (Bean<?> context : manager.getBeans(CamelContext.class, AnyLiteral.INSTANCE)) {
+ contexts.add(BeanManagerHelper.getReference(manager, CamelContext.class, context));
+ }
+
+ // Add type converters to Camel contexts
+ CdiTypeConverterLoader loader = new CdiTypeConverterLoader();
+ for (Class<?> converter : converters) {
+ for (CamelContext context : contexts) {
+ loader.loadConverterMethods(context.getTypeConverterRegistry(), converter);
+ }
+ }
+
+ // Add routes to Camel contexts
+ boolean deploymentException = false;
+ Set<Bean<?>> routes = new HashSet<>(manager.getBeans(RoutesBuilder.class, AnyLiteral.INSTANCE));
+ routes.addAll(manager.getBeans(RouteContainer.class, AnyLiteral.INSTANCE));
+ for (Bean<?> context : manager.getBeans(CamelContext.class, AnyLiteral.INSTANCE)) {
+ for (Bean<?> route : routes) {
+ Set<Annotation> qualifiers = new HashSet<>(context.getQualifiers());
+ qualifiers.retainAll(route.getQualifiers());
+ if (qualifiers.size() > 1) {
+ deploymentException |= !addRouteToContext(route, context, manager, adv);
+ }
+ }
+ }
+ // Let's return to avoid starting misconfigured contexts
+ if (deploymentException) {
+ return;
+ }
+
+ // Trigger eager beans instantiation
+ for (AnnotatedType<?> type : eagerBeans) {
+ // Calling toString is necessary to force the initialization of normal-scoped beans
+ BeanManagerHelper.getReferencesByType(manager, type.getJavaClass(), AnyLiteral.INSTANCE).toString();
+ }
+
+ // Start Camel contexts
+ for (CamelContext context : contexts) {
+ if (ServiceStatus.Started.equals(context.getStatus())) {
+ continue;
+ }
+ logger.info("Camel CDI is starting Camel context [{}]", context.getName());
+ try {
+ context.start();
+ } catch (Exception exception) {
+ adv.addDeploymentProblem(exception);
+ }
+ }
+
+ // Clean-up
+ converters.clear();
+ camelBeans.clear();
+ eagerBeans.clear();
+ producerBeans.clear();
+ producerQualifiers.clear();
+ }
+
+ private boolean addRouteToContext(Bean<?> routeBean, Bean<?> contextBean, BeanManager manager, AfterDeploymentValidation adv) {
+ try {
+ CamelContext context = BeanManagerHelper.getReference(manager, CamelContext.class, contextBean);
+ try {
+ Object route = BeanManagerHelper.getReference(manager, Object.class, routeBean);
+ if (route instanceof RoutesBuilder) {
+ context.addRoutes((RoutesBuilder) route);
+ } else if (route instanceof RouteContainer) {
+ context.addRouteDefinitions(((RouteContainer) route).getRoutes());
+ } else {
+ throw new IllegalArgumentException("Invalid routes type [" + routeBean.getBeanClass().getName() + "], must be either of type RoutesBuilder or RouteContainer!");
+ }
+ return true;
+ } catch (Exception cause) {
+ adv.addDeploymentProblem(new InjectionException("Error adding routes of type [" + routeBean.getBeanClass().getName() + "] to Camel context [" + context.getName() + "]", cause));
+ }
+ } catch (Exception exception) {
+ adv.addDeploymentProblem(exception);
+ }
+ return false;
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelFactory.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelFactory.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelFactory.java
new file mode 100755
index 0000000..cdb2336
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelFactory.java
@@ -0,0 +1,211 @@
+/**
+ * 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.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import javax.enterprise.event.Event;
+import javax.enterprise.inject.Any;
+import javax.enterprise.inject.InjectionException;
+import javax.enterprise.inject.Instance;
+import javax.enterprise.inject.Produces;
+import javax.enterprise.inject.Typed;
+import javax.enterprise.inject.UnsatisfiedResolutionException;
+import javax.enterprise.inject.spi.InjectionPoint;
+import javax.enterprise.util.TypeLiteral;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Endpoint;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.TypeConverter;
+import org.apache.camel.component.mock.MockEndpoint;
+
+final class CdiCamelFactory {
+
+ @Produces
+ private static TypeConverter typeConverter(InjectionPoint ip, @Any Instance<CamelContext> instance, CdiCamelExtension extension) {
+ return selectContext(ip, instance, extension).getTypeConverter();
+ }
+
+ @Uri("")
+ @Produces
+ // Qualifiers are dynamically added in CdiCamelExtension
+ private static ProducerTemplate producerTemplate(InjectionPoint ip, @Any Instance<CamelContext> instance, CdiCamelExtension extension) {
+ Uri uri = CdiSpiHelper.getQualifierByType(ip, Uri.class);
+ try {
+ CamelContext context = uri.context().isEmpty() ? selectContext(ip, instance, extension) : selectContext(uri.context(), instance);
+ ProducerTemplate producerTemplate = context.createProducerTemplate();
+ // FIXME: avoid NPE caused by missing @Uri qualifier when injection point is @ContextName qualified
+ Endpoint endpoint = context.getEndpoint(uri.value(), Endpoint.class);
+ producerTemplate.setDefaultEndpoint(endpoint);
+ return producerTemplate;
+ } catch (Exception cause) {
+ throw new InjectionException("Error injecting producer template annotated with " + uri + " into " + ip, cause);
+ }
+ }
+
+ @Produces
+ @Typed(MockEndpoint.class)
+ // Qualifiers are dynamically added in CdiCamelExtension
+ private static MockEndpoint mockEndpointFromMember(InjectionPoint ip, @Any Instance<CamelContext> instance, CdiCamelExtension extension) {
+ String uri = "mock:" + ip.getMember().getName();
+ try {
+ return selectContext(ip, instance, extension).getEndpoint(uri, MockEndpoint.class);
+ } catch (Exception cause) {
+ throw new InjectionException("Error injecting mock endpoint into " + ip, cause);
+ }
+ }
+
+ @Uri("")
+ @Produces
+ @Typed(MockEndpoint.class)
+ // Qualifiers are dynamically added in CdiCamelExtension
+ private static MockEndpoint mockEndpointFromUri(InjectionPoint ip, @Any Instance<CamelContext> instance, CdiCamelExtension extension) {
+ Uri uri = CdiSpiHelper.getQualifierByType(ip, Uri.class);
+ try {
+ CamelContext context = uri.context().isEmpty() ? selectContext(ip, instance, extension) : selectContext(uri.context(), instance);
+ return context.getEndpoint(uri.value(), MockEndpoint.class);
+ } catch (Exception cause) {
+ throw new InjectionException("Error injecting mock endpoint annotated with " + uri
+ + " into " + ip, cause);
+ }
+ }
+
+ // Maintained for backward compatibility reason though this is redundant with @Uri
+ // see https://issues.apache.org/jira/browse/CAMEL-5553?focusedCommentId=13445936&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-13445936
+ @Mock("")
+ @Produces
+ @Typed(MockEndpoint.class)
+ // Qualifiers are dynamically added in CdiCamelExtension
+ private static MockEndpoint createMockEndpoint(InjectionPoint ip, @Any Instance<CamelContext> instance, CdiCamelExtension extension) {
+ Mock mock = CdiSpiHelper.getQualifierByType(ip, Mock.class);
+ try {
+ CamelContext context = mock.context().isEmpty() ? selectContext(ip, instance, extension) : selectContext(mock.context(), instance);
+ return context.getEndpoint(mock.value(), MockEndpoint.class);
+ } catch (Exception cause) {
+ throw new InjectionException("Error injecting mock endpoint annotated with " + mock + " into " + ip, cause);
+ }
+ }
+
+ @Uri("")
+ @Produces
+ // Qualifiers are dynamically added in CdiCamelExtension
+ private static Endpoint endpoint(InjectionPoint ip, @Any Instance<CamelContext> instance, CdiCamelExtension extension) {
+ Uri uri = CdiSpiHelper.getQualifierByType(ip, Uri.class);
+ try {
+ CamelContext context = uri.context().isEmpty() ? selectContext(ip, instance, extension) : selectContext(uri.context(), instance);
+ return context.getEndpoint(uri.value(), Endpoint.class);
+ } catch (Exception cause) {
+ throw new InjectionException("Error injecting endpoint annotated with " + uri + " into " + ip, cause);
+ }
+ }
+
+ @Produces
+ @SuppressWarnings("unchecked")
+ // Qualifiers are dynamically added in CdiCamelExtension
+ private static <T> CdiEventEndpoint<T> cdiEventEndpoint(InjectionPoint ip, @Any Instance<CamelContext> instance, CdiCamelExtension extension, @Any Event<Object> event) throws Exception {
+ CamelContext context = selectContext(ip, instance, extension);
+ Type type = Object.class;
+ if (ip.getType() instanceof ParameterizedType) {
+ type = ((ParameterizedType) ip.getType()).getActualTypeArguments()[0];
+ }
+ String uri = eventEndpointUri(type, ip.getQualifiers());
+ if (context.hasEndpoint(uri) == null) {
+ // FIXME: to be replaced once event firing with dynamic parameterized type is properly supported (see https://issues.jboss.org/browse/CDI-516)
+ TypeLiteral<T> literal = new TypeLiteral<T>() {
+ };
+ for (Field field : TypeLiteral.class.getDeclaredFields()) {
+ if (field.getType().equals(Type.class)) {
+ field.setAccessible(true);
+ field.set(literal, type);
+ break;
+ }
+ }
+ context.addEndpoint(uri,
+ new CdiEventEndpoint<>(
+ event.select(literal, ip.getQualifiers().toArray(new Annotation[ip.getQualifiers().size()])), uri, context, (ForwardingObserverMethod<T>) extension.getObserverMethod(ip)));
+ }
+ return context.getEndpoint(uri, CdiEventEndpoint.class);
+ }
+
+ private static <T extends CamelContext> T selectContext(String name, Instance<T> instance) {
+ for (T context : instance) {
+ if (name.equals(context.getName())) {
+ return context;
+ }
+ }
+ throw new UnsatisfiedResolutionException("No Camel context with name [" + name + "] is deployed!");
+ }
+
+ private static <T extends CamelContext> T selectContext(InjectionPoint ip, Instance<T> instance, CdiCamelExtension extension) {
+ Collection<Annotation> qualifiers = new HashSet<>(ip.getQualifiers());
+ qualifiers.retainAll(extension.getContextQualifiers());
+ if (qualifiers.isEmpty() && !instance.select(DefaultLiteral.INSTANCE).isUnsatisfied()) {
+ return instance.select(DefaultLiteral.INSTANCE).get();
+ }
+ return instance.select(qualifiers.toArray(new Annotation[qualifiers.size()])).get();
+ }
+
+ private static String eventEndpointUri(Type type, Set<Annotation> qualifiers) {
+ String uri = "cdi-event://" + authorityFromType(type);
+ StringBuilder parameters = new StringBuilder();
+ Iterator<Annotation> it = qualifiers.iterator();
+ while (it.hasNext()) {
+ parameters.append(it.next().annotationType().getCanonicalName());
+ if (it.hasNext()) {
+ parameters.append("%2C");
+ }
+ }
+ if (parameters.length() > 0) {
+ uri += "?qualifiers=" + parameters.toString();
+ }
+ return uri;
+ }
+
+ private static String authorityFromType(Type type) {
+ if (type instanceof Class) {
+ return Class.class.cast(type).getName();
+ }
+ if (type instanceof ParameterizedType) {
+ ParameterizedType pt = (ParameterizedType) type;
+ StringBuilder builder = new StringBuilder(authorityFromType(pt.getRawType()));
+ Iterator<Type> it = Arrays.asList(pt.getActualTypeArguments()).iterator();
+ builder.append("%3C");
+ while (it.hasNext()) {
+ builder.append(authorityFromType(it.next()));
+ if (it.hasNext()) {
+ builder.append("%2C");
+ }
+ }
+ builder.append("%3E");
+ return builder.toString();
+ }
+ if (type instanceof GenericArrayType) {
+ GenericArrayType arrayType = (GenericArrayType) type;
+ return authorityFromType(arrayType.getGenericComponentType()) + "%5B%5D";
+ }
+ throw new IllegalArgumentException("Cannot create URI authority for event type [" + type + "]");
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelInjector.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelInjector.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelInjector.java
new file mode 100755
index 0000000..471b7f0
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelInjector.java
@@ -0,0 +1,48 @@
+/**
+ * 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 javax.enterprise.inject.spi.BeanManager;
+
+import org.apache.camel.spi.Injector;
+
+final class CdiCamelInjector implements Injector {
+
+ private final Injector injector;
+
+ private final BeanManager manager;
+
+ CdiCamelInjector(Injector injector, BeanManager manager) {
+ this.injector = injector;
+ this.manager = manager;
+ }
+
+ @Override
+ public <T> T newInstance(Class<T> type) {
+ T instance = BeanManagerHelper.getReferenceByType(manager, type);
+ if (instance != null) {
+ return instance;
+ } else {
+ return injector.newInstance(type);
+ }
+ }
+
+ @Override
+ public <T> T newInstance(Class<T> type, Object instance) {
+ return injector.newInstance(type, instance);
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelRegistry.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelRegistry.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelRegistry.java
new file mode 100755
index 0000000..946fecf
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelRegistry.java
@@ -0,0 +1,98 @@
+/**
+ * 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.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+
+import org.apache.camel.component.properties.PropertiesComponent;
+import org.apache.camel.spi.Registry;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The {@link Registry} used by Camel to perform lookup into the CDI {@link BeanManager}.
+ */
+@Vetoed
+final class CdiCamelRegistry implements Registry {
+
+ private final Logger logger = LoggerFactory.getLogger(CdiCamelRegistry.class);
+
+ private final BeanManager manager;
+
+ CdiCamelRegistry(BeanManager manager) {
+ this.manager = manager;
+ }
+
+ @Override
+ public Object lookupByName(String name) {
+ ObjectHelper.notEmpty(name, "name");
+ logger.trace("Looking up bean with name [{}]", name);
+ // Work-around for WELD-2089
+ if ("properties".equals(name) && findByTypeWithName(PropertiesComponent.class).containsKey("properties")) {
+ return BeanManagerHelper.getReferenceByName(manager, name, PropertiesComponent.class);
+ }
+ return BeanManagerHelper.getReferenceByName(manager, name, Object.class);
+ }
+
+ @Override
+ public <T> T lookupByNameAndType(String name, Class<T> type) {
+ ObjectHelper.notEmpty(name, "name");
+ ObjectHelper.notNull(type, "type");
+ logger.trace("Looking up bean with name [{}] of type [{}]", name, type);
+ return BeanManagerHelper.getReferenceByName(manager, name, type);
+ }
+
+ @Override
+ public <T> Map<String, T> findByTypeWithName(Class<T> type) {
+ ObjectHelper.notNull(type, "type");
+ logger.trace("Looking up named beans of type [{}]", type);
+ Map<String, T> references = new HashMap<>();
+ for (Bean<?> bean : manager.getBeans(type, AnyLiteral.INSTANCE)) {
+ if (bean.getName() != null) {
+ references.put(bean.getName(), BeanManagerHelper.getReference(manager, type, bean));
+ }
+ }
+ return references;
+ }
+
+ @Override
+ public <T> Set<T> findByType(Class<T> type) {
+ ObjectHelper.notNull(type, "type");
+ logger.trace("Looking up beans of type [{}]", type);
+ return BeanManagerHelper.getReferencesByType(manager, type, AnyLiteral.INSTANCE);
+ }
+
+ @Override
+ public Object lookup(String name) {
+ return lookupByName(name);
+ }
+
+ @Override
+ public <T> T lookup(String name, Class<T> type) {
+ return lookupByNameAndType(name, type);
+ }
+
+ @Override
+ public <T> Map<String, T> lookupByType(Class<T> type) {
+ return findByTypeWithName(type);
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventComponent.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventComponent.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventComponent.java
new file mode 100644
index 0000000..ffc4d89
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventComponent.java
@@ -0,0 +1,53 @@
+/**
+ * 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.util.Map;
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Named;
+
+import org.apache.camel.Endpoint;
+import org.apache.camel.impl.DefaultComponent;
+
+@Named("cdi-event")
+@ApplicationScoped
+/* package-private */ class CdiEventComponent extends DefaultComponent {
+
+ @Override
+ protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) {
+ /* The CDI event endpoint URI follows the format hereafter:
+
+ cdi-event://PayloadType<T1,...,Tn>[?qualifiers=QualifierType1[,...[,QualifierTypeN]...]]
+
+ with the authority PayloadType (respectively the QualifierType) being the URI escaped fully
+ qualified name of the payload (respectively qualifier) raw type followed by the type parameters
+ section delimited by angle brackets for payload parameterized type.
+
+ Which leads to unfriendly URIs, e.g.:
+
+ cdi-event://org.apache.camel.cdi.se.pojo.EventPayload%3Cjava.lang.Integer%3E?qualifiers=org.apache.camel.cdi.se.qualifier.FooQualifier%2Corg.apache.camel.cdi.se.qualifier.BarQualifier
+
+ From the conceptual standpoint, that shows the high impedance between the typesafe nature of CDI
+ and the dynamic nature of the Camel component model.
+
+ From the implementation standpoint, that would prevent efficient binding between the endpoint
+ instances and observer methods as the CDI container doesn't have any ways of discovering the
+ Camel context model during the deployment phase.
+ */
+ throw new UnsupportedOperationException("Creating CDI event endpoint isn't supported. Use @Inject " + CdiEventEndpoint.class.getSimpleName() + " instead");
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventConsumer.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventConsumer.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventConsumer.java
new file mode 100644
index 0000000..f479163
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventConsumer.java
@@ -0,0 +1,71 @@
+/**
+ * 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 org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.RuntimeExchangeException;
+import org.apache.camel.impl.DefaultConsumer;
+import org.apache.camel.management.event.AbstractExchangeEvent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/* package-private */ final class CdiEventConsumer<T> extends DefaultConsumer {
+
+ private final Logger logger = LoggerFactory.getLogger(CdiEventConsumer.class);
+
+ private final CdiEventEndpoint<T> endpoint;
+
+ CdiEventConsumer(CdiEventEndpoint<T> endpoint, Processor processor) {
+ super(endpoint, processor);
+ this.endpoint = endpoint;
+ }
+
+ @Override
+ protected void doStart() throws Exception {
+ super.doStart();
+ endpoint.registerConsumer(this);
+ }
+
+ @Override
+ protected void doStop() throws Exception {
+ endpoint.unregisterConsumer(this);
+ super.doStop();
+ }
+
+ void notify(T event) {
+ logger.debug("Consuming CDI event [{}] with {}", event, this);
+
+ Exchange exchange = getEndpoint().createExchange();
+ // TODO: would that be possible to propagate the event metadata?
+ exchange.getIn().setBody(event);
+
+ // Avoid infinite loop of exchange events
+ if (event instanceof AbstractExchangeEvent) {
+ exchange.setProperty(Exchange.NOTIFY_EVENT, Boolean.TRUE);
+ }
+ try {
+ getProcessor().process(exchange);
+ } catch (Exception cause) {
+ throw new RuntimeExchangeException("Error while processing CDI event", exchange, cause);
+ } finally {
+ if (event instanceof AbstractExchangeEvent) {
+ exchange.setProperty(Exchange.NOTIFY_EVENT, Boolean.FALSE);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventEndpoint.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventEndpoint.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventEndpoint.java
new file mode 100644
index 0000000..a003609
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventEndpoint.java
@@ -0,0 +1,127 @@
+/**
+ * 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.util.ArrayList;
+import java.util.List;
+import javax.enterprise.event.Event;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Consumer;
+import org.apache.camel.Endpoint;
+import org.apache.camel.Processor;
+import org.apache.camel.Producer;
+import org.apache.camel.impl.DefaultEndpoint;
+
+/**
+ * A Camel {@link Endpoint} that bridges the CDI events facility with Camel routes so that CDI events
+ * can be seamlessly observed / consumed (respectively produced / fired) from Camel consumers (respectively by Camel producers).
+ * <p/>
+ * The {@code CdiEventEndpoint<T>} bean can be used to observe / consume CDI events whose event type is {@code T}, for example:
+ * <pre><code>
+ * {@literal @}Inject
+ * CdiEventEndpoint{@literal <}String{@literal >} cdiEventEndpoint;
+ *
+ * from(cdiEventEndpoint).log("CDI event received: ${body}");
+ * </code></pre>
+ *
+ * Conversely, the {@code CdiEventEndpoint<T>} bean can be used to produce / fire CDI events whose event type is {@code T}, for example:
+ * <pre><code>
+ * {@literal @}Inject
+ * CdiEventEndpoint{@literal <}String{@literal >} cdiEventEndpoint;
+ *
+ * from("direct:event").to(cdiEventEndpoint).log("CDI event sent: ${body}");
+ * </code></pre>
+ *
+ * The type variable {@code T}, respectively the qualifiers, of a particular {@code CdiEventEndpoint<T>} injection point
+ * are automatically translated into the parameterized <i>event type</i>, respectively into the <i>event qualifiers</i>, e.g.:
+ * <pre><code>
+ * {@literal @}Inject
+ * {@literal @}FooQualifier
+ * CdiEventEndpoint{@literal <}List{@literal <}String{@literal >}{@literal >} cdiEventEndpoint;
+ *
+ * from("direct:event").to(cdiEventEndpoint);
+ *
+ * void observeCdiEvents({@literal @}Observes {@literal @}FooQualifier List{@literal <}String{@literal >} event) {
+ * logger.info("CDI event: {}", event);
+ * }
+ * </code></pre>
+ *
+ * When multiple Camel contexts exist in the CDI container, the {@code @ContextName} qualifier can be used
+ * to qualify the {@code CdiEventEndpoint<T>} injection points, e.g.:
+ * <pre><code>
+ * {@literal @}Inject
+ * {@literal @}ContextName("foo")
+ * CdiEventEndpoint{@literal <}List{@literal <}String{@literal >}{@literal >} cdiEventEndpoint;
+ *
+ * // Only observe / consume events having the {@literal @}ContextName("foo") qualifier
+ * from(cdiEventEndpoint).log("Camel context 'foo' > CDI event received: ${body}");
+ *
+ * // Produce / fire events with the {@literal @}ContextName("foo") qualifier
+ * from("...").to(cdiEventEndpoint);
+ *
+ * void observeCdiEvents({@literal @}Observes {@literal @}ContextName("foo") List{@literal <}String{@literal >} event) {
+ * logger.info("Camel context 'foo' > CDI event: {}", event);
+ * }
+ * </code></pre>
+ */
+public final class CdiEventEndpoint<T> extends DefaultEndpoint {
+
+ private final List<CdiEventConsumer<T>> consumers = new ArrayList<>();
+
+ private final Event<T> event;
+
+ CdiEventEndpoint(Event<T> event, String endpointUri, CamelContext context, ForwardingObserverMethod<T> observer) {
+ super(endpointUri, context);
+ this.event = event;
+ observer.setObserver(this);
+ }
+
+ public Consumer createConsumer(Processor processor) {
+ return new CdiEventConsumer<>(this, processor);
+ }
+
+ @Override
+ public Producer createProducer() {
+ return new CdiEventProducer<>(this, event);
+ }
+
+ @Override
+ public boolean isSingleton() {
+ return true;
+ }
+
+ void registerConsumer(CdiEventConsumer<T> consumer) {
+ synchronized (consumers) {
+ consumers.add(consumer);
+ }
+ }
+
+ void unregisterConsumer(CdiEventConsumer<T> consumer) {
+ synchronized (consumers) {
+ consumers.remove(consumer);
+ }
+ }
+
+ void notify(T t) {
+ synchronized (consumers) {
+ for (CdiEventConsumer<T> consumer : consumers) {
+ consumer.notify(t);
+ }
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventNotifier.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventNotifier.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventNotifier.java
new file mode 100644
index 0000000..e9d27e7
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventNotifier.java
@@ -0,0 +1,47 @@
+/**
+ * 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.annotation.Annotation;
+import java.util.Collection;
+import java.util.EventObject;
+import javax.enterprise.inject.spi.BeanManager;
+
+import org.apache.camel.support.EventNotifierSupport;
+
+final class CdiEventNotifier extends EventNotifierSupport {
+
+ private final BeanManager manager;
+
+ private final Annotation[] qualifiers;
+
+ CdiEventNotifier(BeanManager manager, Collection<Annotation> qualifiers) {
+ this.manager = manager;
+ this.qualifiers = qualifiers.toArray(new Annotation[qualifiers.size()]);
+ // TODO: be more fine grained for the kind of events that are emitted depending on the observed event types
+ }
+
+ @Override
+ public void notify(EventObject event) {
+ manager.fireEvent(event, qualifiers);
+ }
+
+ @Override
+ public boolean isEnabled(EventObject event) {
+ return true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventProducer.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventProducer.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventProducer.java
new file mode 100644
index 0000000..11cb274
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiEventProducer.java
@@ -0,0 +1,47 @@
+/**
+ * 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 javax.enterprise.event.Event;
+import org.apache.camel.Exchange;
+
+import org.apache.camel.impl.DefaultProducer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/* package-private */ final class CdiEventProducer<T> extends DefaultProducer {
+
+ private final Logger logger = LoggerFactory.getLogger(CdiEventProducer.class);
+
+ private final Event<T> event;
+
+ CdiEventProducer(CdiEventEndpoint<T> endpoint, Event<T> event) {
+ super(endpoint);
+ this.event = event;
+ }
+
+ @Override
+ public void process(Exchange exchange) {
+ logger.debug("Firing CDI event [{}] with {}", event, this);
+ // TODO: leverage Camel type converter mechanism based on the endpoint type
+ // The EventMetadata injection point will be that of the event which is not very useful
+ // for the end user. Using BeanManager.fire would be a way to hide that internal though
+ // it will be necessary to check whether the exchange event type is assignable to the
+ // endpoint event type.
+ event.fire((T) exchange.getIn().getBody());
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiInjector.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiInjector.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiInjector.java
deleted file mode 100644
index afb3a49..0000000
--- a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiInjector.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/**
- * 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 org.apache.camel.IsSingleton;
-import org.apache.camel.spi.Injector;
-import org.apache.camel.util.ReflectionInjector;
-import org.apache.deltaspike.core.api.provider.BeanProvider;
-
-/**
- * Injector implementation which performs injection with CDI bean provider.
- */
-public class CdiInjector implements Injector {
-
- /**
- * Fallback injector used when there is bean of given type registered in CDI.
- */
- private Injector injector;
-
- public CdiInjector() {
- this(new ReflectionInjector());
- }
-
- public CdiInjector(Injector parent) {
- this.injector = parent;
- }
-
- @Override
- public <T> T newInstance(Class<T> type) {
- T bean = BeanProvider.getContextualReference(type, true);
- if (bean != null) {
- return type.cast(bean);
- }
- return injector.newInstance(type);
- }
-
- @Override
- public <T> T newInstance(Class<T> type, Object instance) {
- if (instance instanceof IsSingleton) {
- boolean singleton = ((IsSingleton) instance).isSingleton();
- if (singleton) {
- return type.cast(instance);
- }
- }
- return newInstance(type);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiSpiHelper.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiSpiHelper.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiSpiHelper.java
new file mode 100644
index 0000000..5bf852e
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiSpiHelper.java
@@ -0,0 +1,143 @@
+/**
+ * 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.annotation.Annotation;
+import java.lang.reflect.Array;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.lang.reflect.WildcardType;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+import javax.enterprise.inject.spi.Annotated;
+import javax.enterprise.inject.spi.AnnotatedConstructor;
+import javax.enterprise.inject.spi.AnnotatedField;
+import javax.enterprise.inject.spi.AnnotatedMethod;
+import javax.enterprise.inject.spi.AnnotatedType;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.InjectionPoint;
+
+import org.apache.camel.util.ObjectHelper;
+
+@Vetoed
+final class CdiSpiHelper {
+
+ private CdiSpiHelper() {
+ }
+
+ static <T extends Annotation> T getQualifierByType(InjectionPoint ip, Class<T> type) {
+ return getFirstElementOfType(ip.getQualifiers(), type);
+ }
+
+ private static <E, T extends E> T getFirstElementOfType(Collection<E> collection, Class<T> type) {
+ for (E item : collection) {
+ if ((item != null) && type.isAssignableFrom(item.getClass())) {
+ return ObjectHelper.cast(type, item);
+ }
+ }
+ return null;
+ }
+
+ @SafeVarargs
+ static <T> Set<T> excludeElementOfTypes(Set<T> annotations, Class<? extends T>... exclusions) {
+ Set<T> set = new HashSet<>();
+ for (T qualifier : annotations) {
+ boolean exclude = false;
+ for (Class<? extends T> exclusion : exclusions) {
+ if (exclusion.isAssignableFrom(qualifier.getClass())) {
+ exclude = true;
+ break;
+ }
+ }
+ if (!exclude) {
+ set.add(qualifier);
+ }
+ }
+ return set;
+ }
+
+ static Class<?> getRawType(Type type) {
+ if (type instanceof Class<?>) {
+ return Class.class.cast(type);
+ } else if (type instanceof ParameterizedType) {
+ return getRawType(ParameterizedType.class.cast(type).getRawType());
+ } else if (type instanceof TypeVariable<?>) {
+ return getBound(TypeVariable.class.cast(type).getBounds());
+ } else if (type instanceof WildcardType) {
+ return getBound(WildcardType.class.cast(type).getUpperBounds());
+ } else if (type instanceof GenericArrayType) {
+ Class<?> rawType = getRawType(GenericArrayType.class.cast(type).getGenericComponentType());
+ if (rawType != null) {
+ return Array.newInstance(rawType, 0).getClass();
+ }
+ }
+ throw new UnsupportedOperationException("Unable to retrieve raw type for [" + type + "]");
+ }
+
+ private static Class<?> getBound(Type[] bounds) {
+ if (bounds.length == 0) {
+ return Object.class;
+ } else {
+ return getRawType(bounds[0]);
+ }
+ }
+
+ @SafeVarargs
+ static boolean hasAnnotation(AnnotatedType<?> type, Class<? extends Annotation>... annotations) {
+ for (Class<? extends Annotation> annotation : annotations) {
+ if (hasAnnotation(type, annotation)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ static boolean hasAnnotation(AnnotatedType<?> type, Class<? extends Annotation> annotation) {
+ if (type.isAnnotationPresent(annotation)) {
+ return true;
+ }
+ for (AnnotatedMethod<?> method : type.getMethods()) {
+ if (method.isAnnotationPresent(annotation)) {
+ return true;
+ }
+ }
+ for (AnnotatedConstructor<?> constructor : type.getConstructors()) {
+ if (constructor.isAnnotationPresent(annotation)) {
+ return true;
+ }
+ }
+ for (AnnotatedField<?> field : type.getFields()) {
+ if (field.isAnnotationPresent(annotation)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ static Set<Annotation> getQualifiers(Annotated annotated, BeanManager manager) {
+ Set<Annotation> qualifiers = new HashSet<>();
+ for (Annotation annotation : annotated.getAnnotations()) {
+ if (manager.isQualifier(annotation.annotationType())) {
+ qualifiers.add(annotation);
+ }
+ }
+ return qualifiers;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiTypeConverterLoader.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiTypeConverterLoader.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiTypeConverterLoader.java
new file mode 100644
index 0000000..b8991e6
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiTypeConverterLoader.java
@@ -0,0 +1,33 @@
+/**
+ * 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 org.apache.camel.impl.converter.AnnotationTypeConverterLoader;
+import org.apache.camel.spi.TypeConverterRegistry;
+
+@Vetoed
+final class CdiTypeConverterLoader extends AnnotationTypeConverterLoader {
+
+ CdiTypeConverterLoader() {
+ super(null);
+ }
+
+ @Override
+ protected void loadConverterMethods(TypeConverterRegistry registry, Class<?> type) {
+ super.loadConverterMethods(registry, type);
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/ContextName.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/ContextName.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/ContextName.java
index f34cb49..2006e71 100644
--- a/components/camel-cdi/src/main/java/org/apache/camel/cdi/ContextName.java
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/ContextName.java
@@ -1,40 +1,91 @@
-/**
- * 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.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-import org.apache.camel.CamelContext;
-import org.apache.camel.builder.RouteBuilder;
-
-/**
- * Used to bind objects to a named {@link CamelContext} instance
- * such as {@link RouteBuilder} instances.
- */
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
-public @interface ContextName {
-
- /**
- * Returns the name of the CamelContext to add the routes to.
- * If no value is specified then the default CamelContext is used.
- */
- String value() default "";
-}
+/**
+ * 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.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import javax.enterprise.util.AnnotationLiteral;
+import javax.inject.Qualifier;
+
+/**
+ * CDI qualifier to be used for multi Camel contexts CDI deployment.
+ * {@code CamelContext} beans can be annotated with the {@code @ContextName} qualifier
+ * so that the Camel context is named accordingly, e.g.:
+ *
+ * <pre><code>
+ * {@literal @}ApplicationScoped
+ * {@literal @}ContextName("foo")
+ * public class FooCamelContext extends DefaultCamelContext {
+ * }
+ * </code></pre>
+ *
+ * Camel resources like route builders, endpoints and producer templates can be annotated with
+ * the {@code @ContextName} qualifier as well so that they are associated with the
+ * corresponding Camel context, e.g.:
+ *
+ * <pre><code>
+ * {@literal @}ContextName("foo")
+ * public class FooRouteBuilder extends RouteBuilder {
+ *
+ * {@literal @}Override
+ * public void configure() {
+ * from("direct:bar").to("mock:bar");
+ * }
+ * }
+ *
+ * {@literal @}Inject
+ * {@literal @}ContextName("foo")
+ * {@literal @}Uri("direct:bar")
+ * ProducerTemplate barProducer;
+ *
+ * {@literal @}Inject
+ * {@literal @}ContextName("foo")
+ * {@literal @}Uri("mock:bar")
+ * MockEndpoint barMockEndpoint;
+ * </code></pre>
+ *
+ * @see org.apache.camel.CamelContext
+ *
+ */
+@Qualifier
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
+public @interface ContextName {
+
+ /**
+ * Returns the name of the Camel context.
+ */
+ String value();
+
+ final class Literal extends AnnotationLiteral<ContextName> implements ContextName {
+
+ private static final long serialVersionUID = 1L;
+
+ private final String name;
+
+ public Literal(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String value() {
+ return name;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/DefaultLiteral.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/DefaultLiteral.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/DefaultLiteral.java
new file mode 100644
index 0000000..c78d6c0
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/DefaultLiteral.java
@@ -0,0 +1,31 @@
+/**
+ * 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 javax.enterprise.inject.Default;
+import javax.enterprise.util.AnnotationLiteral;
+
+@Vetoed
+final class DefaultLiteral extends AnnotationLiteral<Default> implements Default {
+
+ static final Default INSTANCE = new DefaultLiteral();
+
+ private static final long serialVersionUID = 1L;
+
+ private DefaultLiteral() {
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/DelegateInjectionTarget.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/DelegateInjectionTarget.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/DelegateInjectionTarget.java
new file mode 100644
index 0000000..9fef662
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/DelegateInjectionTarget.java
@@ -0,0 +1,51 @@
+/**
+ * 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 javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.spi.InjectionTarget;
+import javax.enterprise.inject.spi.Producer;
+
+abstract class DelegateInjectionTarget<T> extends DelegateProducer<T> implements InjectionTarget<T> {
+
+ private final InjectionTarget<T> delegate;
+
+ DelegateInjectionTarget(InjectionTarget<T> delegate) {
+ super(delegate);
+ this.delegate = delegate;
+ }
+
+ DelegateInjectionTarget(InjectionTarget<T> target, Producer<T> producer) {
+ super(producer);
+ this.delegate = target;
+ }
+
+ @Override
+ public void inject(T instance, CreationalContext<T> ctx) {
+ delegate.inject(instance, ctx);
+ }
+
+ @Override
+ public void postConstruct(T instance) {
+ delegate.postConstruct(instance);
+ }
+
+ @Override
+ public void preDestroy(T instance) {
+ delegate.preDestroy(instance);
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/DelegateProducer.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/DelegateProducer.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/DelegateProducer.java
new file mode 100644
index 0000000..05f8516
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/DelegateProducer.java
@@ -0,0 +1,51 @@
+/**
+ * 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.util.Set;
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.spi.InjectionPoint;
+import javax.enterprise.inject.spi.Producer;
+
+abstract class DelegateProducer<T> implements Producer<T> {
+
+ private final Producer<T> delegate;
+
+ DelegateProducer(Producer<T> delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public T produce(CreationalContext<T> ctx) {
+ return delegate.produce(ctx);
+ }
+
+ @Override
+ public void dispose(T instance) {
+ delegate.dispose(instance);
+ }
+
+ @Override
+ public Set<InjectionPoint> getInjectionPoints() {
+ return delegate.getInjectionPoints();
+ }
+
+ @Override
+ public String toString() {
+ return delegate.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/Excluded.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/Excluded.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/Excluded.java
new file mode 100644
index 0000000..eccf446
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/Excluded.java
@@ -0,0 +1,40 @@
+/**
+ * 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.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import javax.enterprise.util.AnnotationLiteral;
+import javax.inject.Qualifier;
+
+@Qualifier
+@Documented
+@Retention(value = RUNTIME)
+@Target(value = { TYPE, METHOD, PARAMETER, FIELD })
+@interface Excluded {
+
+ Excluded INSTANCE = new ExcludedLiteral();
+
+ final class ExcludedLiteral extends AnnotationLiteral<Excluded>implements Excluded {
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/ForwardingObserverMethod.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/ForwardingObserverMethod.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/ForwardingObserverMethod.java
new file mode 100644
index 0000000..3f2b565
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/ForwardingObserverMethod.java
@@ -0,0 +1,78 @@
+/**
+ * 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.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+import javax.enterprise.event.Reception;
+import javax.enterprise.event.TransactionPhase;
+import javax.enterprise.inject.spi.ObserverMethod;
+
+import org.apache.camel.CamelContext;
+
+/* package-private */ final class ForwardingObserverMethod<T> implements ObserverMethod<T> {
+
+ // Should be replaced with the Java 8 functional interface Consumer<T>
+ private final AtomicReference<CdiEventEndpoint<T>> observer = new AtomicReference<>();
+
+ private final Type type;
+
+ private final Set<Annotation> qualifiers;
+
+ ForwardingObserverMethod(Type type, Set<Annotation> qualifiers) {
+ this.type = type;
+ this.qualifiers = qualifiers;
+ }
+
+ void setObserver(CdiEventEndpoint<T> observer) {
+ this.observer.set(observer);
+ }
+
+ @Override
+ public Class<?> getBeanClass() {
+ return CamelContext.class;
+ }
+
+ @Override
+ public Type getObservedType() {
+ return type;
+ }
+
+ @Override
+ public Set<Annotation> getObservedQualifiers() {
+ return qualifiers;
+ }
+
+ @Override
+ public Reception getReception() {
+ return Reception.ALWAYS;
+ }
+
+ @Override
+ public TransactionPhase getTransactionPhase() {
+ return TransactionPhase.IN_PROGRESS;
+ }
+
+ @Override
+ public void notify(T event) {
+ if (observer.get() != null) {
+ observer.get().notify(event);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/0421c24d/components/camel-cdi/src/main/java/org/apache/camel/cdi/Main.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/Main.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/Main.java
index 0532870..cd55010 100644
--- a/components/camel-cdi/src/main/java/org/apache/camel/cdi/Main.java
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/Main.java
@@ -17,37 +17,42 @@
package org.apache.camel.cdi;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
-import javax.xml.bind.JAXBContext;
+import javax.enterprise.inject.UnsatisfiedResolutionException;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
import org.apache.camel.CamelContext;
import org.apache.camel.ProducerTemplate;
-import org.apache.camel.impl.DefaultModelJAXBContextFactory;
import org.apache.camel.main.MainSupport;
-import org.apache.camel.spi.ModelJAXBContextFactory;
-import org.apache.deltaspike.core.api.provider.BeanProvider;
+import org.apache.deltaspike.cdise.api.CdiContainer;
/**
- * Allows Camel and CDI applications to be booted up on the command line as a Java Application
+ * Camel CDI boot integration. Allows Camel and CDI to be booted up on the command line as a JVM process.
+ * See http://camel.apache.org/camel-boot.html.
*/
-public abstract class Main extends MainSupport { // abstract to prevent cdi management
- private static Main instance;
- private JAXBContext jaxbContext;
- private Object cdiContainer; // we don't want to need cdictrl API in OSGi
+@Vetoed
+public class Main extends MainSupport {
- public Main() {
- // add options...
+ static {
+ // Since version 2.3.0.Final and WELD-1915, Weld SE registers a shutdown hook that conflicts
+ // with Camel main support. See WELD-2051. The system property above is available starting
+ // Weld 2.3.1.Final to deactivate the registration of the shutdown hook.
+ System.setProperty("org.jboss.weld.se.shutdownHook", String.valueOf(Boolean.FALSE));
}
+ private static Main instance;
+
+ private CdiContainer cdiContainer;
+
public static void main(String... args) throws Exception {
- Main main = new Main() { };
+ Main main = new Main();
instance = main;
main.run(args);
}
/**
- * Returns the currently executing main
+ * Returns the currently executing instance.
*
* @return the current running instance
*/
@@ -57,46 +62,42 @@ public abstract class Main extends MainSupport { // abstract to prevent cdi mana
@Override
protected ProducerTemplate findOrCreateCamelTemplate() {
- ProducerTemplate answer = BeanProvider.getContextualReference(ProducerTemplate.class, true);
- if (answer != null) {
- return answer;
+ BeanManager manager = cdiContainer.getBeanManager();
+ Bean<?> bean = manager.resolve(manager.getBeans(CamelContext.class));
+ if (bean == null) {
+ throw new UnsatisfiedResolutionException("No default Camel context is deployed, cannot create default ProducerTemplate!");
}
- if (getCamelContexts().isEmpty()) {
- throw new IllegalArgumentException(
- "No CamelContexts are available so cannot create a ProducerTemplate!");
- }
- return getCamelContexts().get(0).createProducerTemplate();
+ CamelContext context = (CamelContext) manager.getReference(bean, CamelContext.class, manager.createCreationalContext(bean));
+ return context.createProducerTemplate();
}
@Override
protected Map<String, CamelContext> getCamelContextMap() {
- List<CamelContext> contexts = BeanProvider.getContextualReferences(CamelContext.class, true);
- Map<String, CamelContext> answer = new HashMap<String, CamelContext>();
- for (CamelContext context : contexts) {
- String name = context.getName();
- answer.put(name, context);
+ BeanManager manager = cdiContainer.getBeanManager();
+ Map<String, CamelContext> answer = new HashMap<>();
+ for (Bean<?> bean : manager.getBeans(CamelContext.class, AnyLiteral.INSTANCE)) {
+ CamelContext context = (CamelContext) manager.getReference(bean, CamelContext.class, manager.createCreationalContext(bean));
+ answer.put(context.getName(), context);
}
return answer;
}
- public ModelJAXBContextFactory getModelJAXBContextFactory() {
- return new DefaultModelJAXBContextFactory();
- }
-
@Override
protected void doStart() throws Exception {
+ // TODO: Use standard CDI Java SE support when CDI 2.0 becomes a prerequisite
org.apache.deltaspike.cdise.api.CdiContainer container = org.apache.deltaspike.cdise.api.CdiContainerLoader.getCdiContainer();
container.boot();
container.getContextControl().startContexts();
cdiContainer = container;
super.doStart();
+ postProcessContext();
}
@Override
protected void doStop() throws Exception {
super.doStop();
if (cdiContainer != null) {
- ((org.apache.deltaspike.cdise.api.CdiContainer) cdiContainer).shutdown();
+ cdiContainer.shutdown();
}
}
}