You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by as...@apache.org on 2016/04/19 14:58:56 UTC
[4/6] camel git commit: CAMEL-9882: Support importing Camel XML
configuration files in Camel CDI
CAMEL-9882: Support importing Camel XML configuration files in Camel CDI
Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/ba1172ad
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/ba1172ad
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/ba1172ad
Branch: refs/heads/master
Commit: ba1172adca9a61827fb7f115d728d091ba96c503
Parents: 3e0795c
Author: Antonin Stefanutti <an...@stefanutti.fr>
Authored: Mon Apr 18 17:31:29 2016 +0200
Committer: Antonin Stefanutti <an...@stefanutti.fr>
Committed: Tue Apr 19 14:49:35 2016 +0200
----------------------------------------------------------------------
components/camel-cdi/pom.xml | 11 +
.../camel/cdi/ApplicationScopedLiteral.java | 31 +
.../org/apache/camel/cdi/BeanManagerHelper.java | 5 +-
.../camel/cdi/CamelContextDefaultProducer.java | 55 --
.../camel/cdi/CdiCamelContextAnnotated.java | 65 --
.../apache/camel/cdi/CdiCamelContextBean.java | 120 ----
.../org/apache/camel/cdi/CdiCamelExtension.java | 146 +++-
.../java/org/apache/camel/cdi/CdiSpiHelper.java | 95 +++
.../org/apache/camel/cdi/ImportResource.java | 29 +
.../apache/camel/cdi/ListParameterizedType.java | 45 ++
.../java/org/apache/camel/cdi/NamedLiteral.java | 41 ++
.../org/apache/camel/cdi/ResourceHelper.java | 38 +
.../main/java/org/apache/camel/cdi/Startup.java | 39 +
.../apache/camel/cdi/SyntheticAnnotated.java | 82 +++
.../org/apache/camel/cdi/SyntheticBean.java | 102 +++
.../camel/cdi/SyntheticBeanAttributes.java | 77 ++
.../camel/cdi/SyntheticInjectionTarget.java | 81 +++
.../org/apache/camel/cdi/XmlCdiBeanFactory.java | 464 ++++++++++++
.../apache/camel/cdi/XmlCdiJaxbContexts.java | 44 ++
.../camel/cdi/XmlErrorHandlerFactoryBean.java | 139 ++++
.../cdi/XmlFactoryBeanInjectionTarget.java | 56 ++
.../apache/camel/cdi/XmlProxyFactoryBean.java | 103 +++
.../camel/cdi/XmlServiceExporterBean.java | 95 +++
.../cdi/xml/ApplicationContextFactoryBean.java | 105 +++
.../apache/camel/cdi/xml/BeanManagerAware.java | 25 +
.../apache/camel/cdi/xml/BeanManagerHelper.java | 38 +
.../camel/cdi/xml/CamelContextFactoryBean.java | 719 +++++++++++++++++++
.../cdi/xml/ConsumerTemplateFactoryBean.java | 53 ++
.../cdi/xml/ContextScanRouteBuilderFinder.java | 86 +++
.../camel/cdi/xml/EndpointFactoryBean.java | 53 ++
.../camel/cdi/xml/ErrorHandlerDefinition.java | 210 ++++++
.../apache/camel/cdi/xml/ErrorHandlerType.java | 62 ++
.../apache/camel/cdi/xml/ImportDefinition.java | 42 ++
.../cdi/xml/PackageScanRouteBuilderFinder.java | 92 +++
.../cdi/xml/ProducerTemplateFactoryBean.java | 62 ++
.../camel/cdi/xml/ProxyFactoryDefinition.java | 87 +++
.../cdi/xml/RedeliveryPolicyFactoryBean.java | 52 ++
.../camel/cdi/xml/RestContextDefinition.java | 44 ++
.../camel/cdi/xml/RouteContextDefinition.java | 44 ++
.../cdi/xml/ServiceExporterDefinition.java | 75 ++
.../camel/cdi/xml/ThreadPoolFactoryBean.java | 53 ++
.../org/apache/camel/cdi/xml/package-info.java | 25 +
.../src/main/resources/META-INF/beans.xml | 7 +
.../org/apache/camel/cdi/xml/jaxb.index | 28 +
.../java/org/apache/camel/cdi/bean/Service.java | 23 +
.../cdi/mock/DummyRestConsumerFactory.java | 66 ++
.../org/apache/camel/cdi/rule/LogEvent.java | 44 ++
.../apache/camel/cdi/rule/LogEventMatcher.java | 98 +++
.../apache/camel/cdi/rule/LogEventVerifier.java | 39 +
.../org/apache/camel/cdi/rule/LogVerifier.java | 6 +-
.../cdi/test/RouteDefinitionsFromXmlTest.java | 2 +-
.../org/apache/camel/cdi/test/XmlBeansTest.java | 76 ++
.../camel/cdi/test/XmlConsumerTemplateTest.java | 89 +++
.../apache/camel/cdi/test/XmlEndpointTest.java | 111 +++
.../cdi/test/XmlErrorHandlerLoggingTest.java | 132 ++++
.../cdi/test/XmlErrorHandlerPolicyTest.java | 141 ++++
.../camel/cdi/test/XmlErrorHandlerTest.java | 105 +++
.../camel/cdi/test/XmlMultiContextsTest.java | 142 ++++
.../camel/cdi/test/XmlProducerTemplateTest.java | 95 +++
.../cdi/test/XmlPropertyPlaceholderTest.java | 62 ++
.../camel/cdi/test/XmlProxyFactoryTest.java | 70 ++
.../camel/cdi/test/XmlRestContextTest.java | 105 +++
.../cdi/test/XmlRouteContextImportTest.java | 101 +++
.../cdi/test/XmlRouteContextResourceTest.java | 80 +++
.../camel/cdi/test/XmlRoutesDefinitionTest.java | 74 ++
.../camel/cdi/test/XmlServiceExporterTest.java | 81 +++
.../cdi/test/XmlThreadPoolProfileTest.java | 81 +++
.../camel/cdi/test/XmlThreadPoolTest.java | 77 ++
.../src/test/resources/camel-context-beans.xml | 34 +
.../test/resources/camel-context-consumer.xml | 27 +
.../test/resources/camel-context-endpoint.xml | 30 +
.../camel-context-errorHandler-logging.xml | 42 ++
.../camel-context-errorHandler-policy.xml | 43 ++
.../resources/camel-context-errorHandler.xml | 49 ++
.../src/test/resources/camel-context-export.xml | 26 +
.../test/resources/camel-context-multiples.xml | 37 +
.../test/resources/camel-context-producer.xml | 27 +
.../test/resources/camel-context-properties.xml | 22 +
.../src/test/resources/camel-context-proxy.xml | 31 +
.../resources/camel-context-restContext.xml | 24 +
.../resources/camel-context-restContextRef.xml | 30 +
.../resources/camel-context-routeContext.xml | 30 +
.../camel-context-routeContextRef-import.xml | 39 +
.../resources/camel-context-routeContextRef.xml | 40 ++
.../src/test/resources/camel-context-routes.xml | 23 +
.../test/resources/camel-context-threadPool.xml | 41 ++
.../camel-context-threadPoolProfile.xml | 40 ++
.../camel-cdi/src/test/resources/routes.xml | 24 -
88 files changed, 6179 insertions(+), 305 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/camel/blob/ba1172ad/components/camel-cdi/pom.xml
----------------------------------------------------------------------
diff --git a/components/camel-cdi/pom.xml b/components/camel-cdi/pom.xml
index a9ca2fb..f47c765 100644
--- a/components/camel-cdi/pom.xml
+++ b/components/camel-cdi/pom.xml
@@ -89,6 +89,13 @@
<dependency>
<groupId>org.apache.camel</groupId>
+ <artifactId>camel-core-xml</artifactId>
+ <version>${project.version}</version>
+ <optional>true</optional>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.camel</groupId>
<artifactId>camel-core-osgi</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
@@ -266,6 +273,8 @@
<exclude>**/UnstoppedCamelContext*Test.java</exclude>
<!-- Reactivate when OWB-1122 is fixed -->
<exclude>**/ProgrammaticLookupTest.java</exclude>
+ <!-- Reactivate when OWB-1126 is fixed -->
+ <exclude>**/Xml*Test.java</exclude>
</excludes>
</configuration>
</plugin>
@@ -328,6 +337,8 @@
<excludes>
<!-- Reactivate when OWB-1122 is fixed -->
<exclude>**/ProgrammaticLookupTest.java</exclude>
+ <!-- Reactivate when OWB-1126 is fixed -->
+ <exclude>**/Xml*Test.java</exclude>
</excludes>
</configuration>
</plugin>
http://git-wip-us.apache.org/repos/asf/camel/blob/ba1172ad/components/camel-cdi/src/main/java/org/apache/camel/cdi/ApplicationScopedLiteral.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/ApplicationScopedLiteral.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/ApplicationScopedLiteral.java
new file mode 100755
index 0000000..185c1a4
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/ApplicationScopedLiteral.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.context.ApplicationScoped;
+import javax.enterprise.util.AnnotationLiteral;
+
+@Vetoed
+final class ApplicationScopedLiteral extends AnnotationLiteral<ApplicationScoped> implements ApplicationScoped {
+
+ static final ApplicationScoped APPLICATION_SCOPED = new ApplicationScopedLiteral();
+
+ private static final long serialVersionUID = 1L;
+
+ private ApplicationScopedLiteral() {
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/ba1172ad/components/camel-cdi/src/main/java/org/apache/camel/cdi/BeanManagerHelper.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/BeanManagerHelper.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/BeanManagerHelper.java
index 9da35c1..d454270 100644
--- a/components/camel-cdi/src/main/java/org/apache/camel/cdi/BeanManagerHelper.java
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/BeanManagerHelper.java
@@ -16,13 +16,14 @@
*/
package org.apache.camel.cdi;
-import javax.enterprise.inject.spi.Bean;
-import javax.enterprise.inject.spi.BeanManager;
import java.lang.annotation.Annotation;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+
@Vetoed
final class BeanManagerHelper {
http://git-wip-us.apache.org/repos/asf/camel/blob/ba1172ad/components/camel-cdi/src/main/java/org/apache/camel/cdi/CamelContextDefaultProducer.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CamelContextDefaultProducer.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CamelContextDefaultProducer.java
deleted file mode 100644
index 6412bc7..0000000
--- a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CamelContextDefaultProducer.java
+++ /dev/null
@@ -1,55 +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 java.util.Collections;
-import java.util.Set;
-import javax.enterprise.context.spi.CreationalContext;
-import javax.enterprise.inject.spi.InjectionPoint;
-import javax.enterprise.inject.spi.InjectionTarget;
-
-import org.apache.camel.impl.DefaultCamelContext;
-
-@Vetoed
-final class CamelContextDefaultProducer implements InjectionTarget<DefaultCamelContext> {
-
- @Override
- public DefaultCamelContext produce(CreationalContext<DefaultCamelContext> ctx) {
- return new DefaultCamelContext();
- }
-
- @Override
- public void inject(DefaultCamelContext instance, CreationalContext<DefaultCamelContext> ctx) {
- }
-
- @Override
- public void postConstruct(DefaultCamelContext instance) {
- }
-
- @Override
- public void preDestroy(DefaultCamelContext instance) {
- }
-
- @Override
- public void dispose(DefaultCamelContext instance) {
- }
-
- @Override
- public Set<InjectionPoint> getInjectionPoints() {
- return Collections.emptySet();
- }
-}
http://git-wip-us.apache.org/repos/asf/camel/blob/ba1172ad/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelContextAnnotated.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelContextAnnotated.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelContextAnnotated.java
deleted file mode 100644
index 39d932d..0000000
--- a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelContextAnnotated.java
+++ /dev/null
@@ -1,65 +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 java.lang.annotation.Annotation;
-import java.lang.reflect.Type;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-import javax.enterprise.inject.spi.Annotated;
-import javax.enterprise.inject.spi.BeanManager;
-
-import org.apache.camel.impl.DefaultCamelContext;
-
-final class CdiCamelContextAnnotated implements Annotated {
-
- private final Set<Type> types;
-
- private final Set<Annotation> annotations;
-
- CdiCamelContextAnnotated(BeanManager manager, Annotation... annotations) {
- this.types = Collections.unmodifiableSet(manager.createAnnotatedType(DefaultCamelContext.class).getTypeClosure());
- this.annotations = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(annotations)));
- }
-
- @Override
- public Type getBaseType() {
- return DefaultCamelContext.class;
- }
-
- @Override
- public Set<Type> getTypeClosure() {
- return types;
- }
-
- @Override
- public <U extends Annotation> U getAnnotation(Class<U> annotationType) {
- return CdiSpiHelper.getFirstElementOfType(getAnnotations(), annotationType);
- }
-
- @Override
- public Set<Annotation> getAnnotations() {
- return annotations;
- }
-
- @Override
- public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
- return getAnnotation(annotationType) != null;
- }
-}
http://git-wip-us.apache.org/repos/asf/camel/blob/ba1172ad/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelContextBean.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelContextBean.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelContextBean.java
deleted file mode 100644
index 63db497..0000000
--- a/components/camel-cdi/src/main/java/org/apache/camel/cdi/CdiCamelContextBean.java
+++ /dev/null
@@ -1,120 +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 java.lang.annotation.Annotation;
-import java.lang.reflect.Type;
-import java.util.Collections;
-import java.util.Set;
-import javax.enterprise.context.ApplicationScoped;
-import javax.enterprise.context.spi.CreationalContext;
-import javax.enterprise.inject.spi.Bean;
-import javax.enterprise.inject.spi.InjectionPoint;
-import javax.enterprise.inject.spi.InjectionTarget;
-import javax.enterprise.inject.spi.PassivationCapable;
-
-import org.apache.camel.impl.DefaultCamelContext;
-
-final class CdiCamelContextBean implements Bean<DefaultCamelContext>, PassivationCapable {
-
- private final Set<Annotation> qualifiers;
-
- private final Set<Type> types;
-
- private final InjectionTarget<DefaultCamelContext> target;
-
- private final String name;
-
- CdiCamelContextBean(CdiCamelContextAnnotated annotated, InjectionTarget<DefaultCamelContext> target) {
- this.qualifiers = annotated.getAnnotations();
- this.types = annotated.getTypeClosure();
- this.target = target;
- this.name = annotated.isAnnotationPresent(ContextName.class) ? annotated.getAnnotation(ContextName.class).value() : "Default";
- }
-
- @Override
- public Class<? extends Annotation> getScope() {
- return ApplicationScoped.class;
- }
-
- @Override
- public Set<Annotation> getQualifiers() {
- return qualifiers;
- }
-
- @Override
- public DefaultCamelContext create(CreationalContext<DefaultCamelContext> creational) {
- DefaultCamelContext context = target.produce(creational);
- target.inject(context, creational);
- target.postConstruct(context);
- creational.push(context);
- return context;
- }
-
- @Override
- public void destroy(DefaultCamelContext instance, CreationalContext<DefaultCamelContext> creational) {
- target.preDestroy(instance);
- target.dispose(instance);
- creational.release();
- }
-
- @Override
- public Class<DefaultCamelContext> getBeanClass() {
- return DefaultCamelContext.class;
- }
-
- @Override
- public Set<InjectionPoint> getInjectionPoints() {
- return Collections.emptySet();
- }
-
- @Override
- public String getName() {
- // Not called as this is not a named bean
- return null;
- }
-
- @Override
- public String toString() {
- return "Camel context bean [" + name + "]";
- }
-
- @Override
- public Set<Class<? extends Annotation>> getStereotypes() {
- return Collections.emptySet();
- }
-
- @Override
- public Set<Type> getTypes() {
- return types;
- }
-
- @Override
- public boolean isAlternative() {
- return false;
- }
-
- @Override
- public boolean isNullable() {
- return false;
- }
-
- @Override
- public String getId() {
- return getClass().getName() + "[" + name + "]";
- }
-}
http://git-wip-us.apache.org/repos/asf/camel/blob/ba1172ad/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
index ea4a0c1..69a205b 100755
--- 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
@@ -28,6 +28,8 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Stream;
+
import static java.util.Collections.newSetFromMap;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.Default;
@@ -64,15 +66,23 @@ import org.apache.camel.ProducerTemplate;
import org.apache.camel.PropertyInject;
import org.apache.camel.RoutesBuilder;
import org.apache.camel.ServiceStatus;
+import org.apache.camel.impl.DefaultCamelContext;
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.AnyLiteral.ANY;
+import static org.apache.camel.cdi.ApplicationScopedLiteral.APPLICATION_SCOPED;
+import static org.apache.camel.cdi.BeanManagerHelper.getReference;
+import static org.apache.camel.cdi.BeanManagerHelper.getReferencesByType;
+import static org.apache.camel.cdi.CdiSpiHelper.excludeElementOfTypes;
+import static org.apache.camel.cdi.CdiSpiHelper.getQualifiers;
+import static org.apache.camel.cdi.CdiSpiHelper.getRawType;
import static org.apache.camel.cdi.CdiSpiHelper.hasAnnotation;
import static org.apache.camel.cdi.DefaultLiteral.DEFAULT;
import static org.apache.camel.cdi.Excluded.EXCLUDED;
+import static org.apache.camel.cdi.Startup.Literal.STARTUP;
public class CdiCamelExtension implements Extension {
@@ -88,6 +98,8 @@ public class CdiCamelExtension implements Extension {
private final Map<InjectionPoint, ForwardingObserverMethod<?>> cdiEventEndpoints = new ConcurrentHashMap<>();
+ private final Set<Bean<?>> contextBeans = newSetFromMap(new ConcurrentHashMap<Bean<?>, Boolean>());
+
private final Set<Annotation> contextQualifiers = newSetFromMap(new ConcurrentHashMap<Annotation, Boolean>());
private final Set<Annotation> eventQualifiers = newSetFromMap(new ConcurrentHashMap<Annotation, Boolean>());
@@ -98,6 +110,8 @@ public class CdiCamelExtension implements Extension {
private final Set<ContextName> contextNames = newSetFromMap(new ConcurrentHashMap<ContextName, Boolean>());
+ private final Set<ImportResource> resources = newSetFromMap(new ConcurrentHashMap<>());
+
ForwardingObserverMethod<?> getObserverMethod(InjectionPoint ip) {
return cdiEventEndpoints.get(ip);
}
@@ -123,6 +137,9 @@ public class CdiCamelExtension implements Extension {
if (hasAnnotation(pat.getAnnotatedType(), Consume.class)) {
eagerBeans.add(pat.getAnnotatedType());
}
+ if (hasAnnotation(pat.getAnnotatedType(), ImportResource.class)) {
+ resources.add(pat.getAnnotatedType().getAnnotation(ImportResource.class));
+ }
}
private void camelContextAware(@Observes ProcessAnnotatedType<? extends CamelContextAware> pat) {
@@ -145,7 +162,7 @@ public class CdiCamelExtension implements Extension {
private void cdiEventEndpoints(@Observes ProcessBean<?> pb) {
for (InjectionPoint ip : pb.getBean().getInjectionPoints()) {
- if (!CdiEventEndpoint.class.equals(CdiSpiHelper.getRawType(ip.getType()))) {
+ if (!CdiEventEndpoint.class.equals(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
@@ -176,11 +193,11 @@ public class CdiCamelExtension implements Extension {
if (!am.isAnnotationPresent(Produces.class)) {
continue;
}
- Class<?> type = CdiSpiHelper.getRawType(am.getBaseType());
+ Class<?> type = getRawType(am.getBaseType());
if (Endpoint.class.isAssignableFrom(type)
|| ConsumerTemplate.class.equals(type)
|| ProducerTemplate.class.equals(type)) {
- Set<Annotation> qualifiers = CdiSpiHelper.getQualifiers(am, manager);
+ Set<Annotation> qualifiers = getQualifiers(am, manager);
producerQualifiers.put(am.getJavaMember(), qualifiers);
Set<Annotation> annotations = new HashSet<>(am.getAnnotations());
annotations.removeAll(qualifiers);
@@ -207,35 +224,80 @@ public class CdiCamelExtension implements Extension {
}
private <T extends CamelContext> void camelContextBeans(@Observes ProcessBean<T> pb) {
- contextQualifiers.addAll(pb.getBean().getQualifiers());
+ contextBeans.add(pb.getBean());
}
private <T extends CamelContext> void camelContextProducerFields(@Observes ProcessProducerField<T, ?> pb) {
- contextQualifiers.addAll(pb.getBean().getQualifiers());
+ contextBeans.add(pb.getBean());
}
private <T extends CamelContext> void camelContextProducerMethods(@Observes ProcessProducerMethod<T, ?> pb) {
- contextQualifiers.addAll(pb.getBean().getQualifiers());
+ contextBeans.add(pb.getBean());
}
private void afterBeanDiscovery(@Observes AfterBeanDiscovery abd, BeanManager manager) {
- // Missing @ContextName Camel context qualifiers
- contextNames.removeAll(contextQualifiers);
- if (contextQualifiers.isEmpty() && contextNames.isEmpty()) {
- // Add a @Default Camel context bean if any
- abd.addBean(camelContextBean(manager, ANY, DEFAULT));
- } else if (contextQualifiers.isEmpty() && contextNames.size() == 1) {
- // Add a @ContextName and @Default Camel context bean if only one
- abd.addBean(camelContextBean(manager, ANY, DEFAULT, contextNames.iterator().next()));
- } else {
- // Add missing @ContextName Camel context beans
- for (ContextName name : contextNames) {
- abd.addBean(camelContextBean(manager, ANY, name));
+ // The set of programmatic beans to be added
+ Set<SyntheticBean<?>> beans = new HashSet<>();
+
+ // Add beans from Camel XML resources
+ for (ImportResource resource : resources) {
+ XmlCdiBeanFactory factory = XmlCdiBeanFactory.with(manager, environment, this);
+ for (String path : resource.value()) {
+ try {
+ beans.addAll(factory.beansFrom(path));
+ } catch (NoClassDefFoundError cause) {
+ if (cause.getMessage().contains("AbstractCamelContextFactoryBean")) {
+ logger.error("Importing Camel XML requires to have the 'camel-core-xml' dependency in the classpath!");
+ }
+ throw cause;
+ } catch (Exception cause) {
+ abd.addDefinitionError(
+ new InjectionException(
+ "Error while importing resource [" + ResourceHelper.getResource(path) + "]", cause));
+ }
+ }
+ }
+
+ // The set of all the Camel context beans
+ Set<Bean<?>> contexts = new HashSet<>();
+
+ // From the discovered annotated types
+ contextBeans.stream()
+ .peek(contexts::add)
+ .map(Bean::getQualifiers)
+ .forEach(contextQualifiers::addAll);
+
+ // From the imported Camel XML
+ beans.stream()
+ .filter(bean -> bean.getTypes().contains(CamelContext.class))
+ .peek(contexts::add)
+ .map(Bean::getQualifiers)
+ .forEach(contextQualifiers::addAll);
+
+ // From the @ContextName qualifiers on RoutesBuilder beans
+ contextNames.stream()
+ .filter(name -> !contextQualifiers.contains(name))
+ .peek(contextQualifiers::add)
+ .map(name -> camelContextBean(manager, ANY, name, APPLICATION_SCOPED))
+ .peek(contexts::add)
+ .forEach(beans::add);
+
+ if (contexts.size() == 0) {
+ // Add @Default Camel context bean if any
+ beans.add(camelContextBean(manager, ANY, DEFAULT, APPLICATION_SCOPED));
+ } else if (contexts.size() == 1) {
+ // Add the @Default qualifier if there is only one Camel context bean
+ Bean<?> context = contexts.iterator().next();
+ if (!context.getQualifiers().contains(DEFAULT)) {
+ // Only decorate if that's a programmatic bean
+ if (context instanceof SyntheticBean) {
+ ((SyntheticBean<?>) context).addQualifier(DEFAULT);
+ }
}
}
- // Update @ContextName Camel context qualifiers
- contextQualifiers.addAll(contextNames);
+ // Finally add the beans to the deployment
+ beans.forEach(abd::addBean);
// Then update the Camel producer beans
for (Map.Entry<Method, Bean<?>> producer : producerBeans.entrySet()) {
@@ -250,7 +312,7 @@ public class CdiCamelExtension implements Extension {
if (Endpoint.class.isAssignableFrom(type)
|| ConsumerTemplate.class.equals(type)
|| ProducerTemplate.class.equals(type)) {
- qualifiers.addAll(CdiSpiHelper.excludeElementOfTypes(contextQualifiers, Default.class, Named.class));
+ qualifiers.addAll(excludeElementOfTypes(contextQualifiers, Default.class, Named.class));
}
}
// TODO: would be more correct to add a bean for each Camel context bean
@@ -263,15 +325,19 @@ public class CdiCamelExtension implements Extension {
}
}
- private Bean<?> camelContextBean(BeanManager manager, Annotation... qualifiers) {
- CdiCamelContextAnnotated annotated = new CdiCamelContextAnnotated(manager, qualifiers);
- return new CdiCamelContextBean(annotated, environment.camelContextInjectionTarget(new CamelContextDefaultProducer(), annotated, manager, this));
+ private SyntheticBean<?> camelContextBean(BeanManager manager, Annotation... qualifiers) {
+ SyntheticAnnotated annotated = new SyntheticAnnotated(DefaultCamelContext.class,
+ manager.createAnnotatedType(DefaultCamelContext.class).getTypeClosure(), qualifiers);
+ return new SyntheticBean<>(manager, annotated, DefaultCamelContext.class,
+ environment.camelContextInjectionTarget(
+ new SyntheticInjectionTarget<>(DefaultCamelContext::new), annotated, manager, this), bean ->
+ "Default Camel context bean with qualifiers " + bean.getQualifiers());
}
private void afterDeploymentValidation(@Observes AfterDeploymentValidation adv, BeanManager manager) {
Collection<CamelContext> contexts = new ArrayList<>();
for (Bean<?> context : manager.getBeans(CamelContext.class, ANY)) {
- contexts.add(BeanManagerHelper.getReference(manager, CamelContext.class, context));
+ contexts.add(getReference(manager, CamelContext.class, context));
}
// Add type converters to Camel contexts
@@ -300,11 +366,16 @@ public class CdiCamelExtension implements Extension {
return;
}
- // Trigger eager beans instantiation
+ // Trigger eager beans instantiation (calling toString is necessary to force
+ // the initialization of normal-scoped beans).
+ // FIXME: This does not work with OpenWebBeans for bean whose bean type is an
+ // interface as the Object methods does not get forwarded to the bean instances!
for (AnnotatedType<?> type : eagerBeans) {
// Calling toString is necessary to force the initialization of normal-scoped beans
- BeanManagerHelper.getReferencesByType(manager, type.getJavaClass(), ANY).toString();
+ getReferencesByType(manager, type.getJavaClass(), ANY).toString();
}
+ manager.getBeans(Object.class, ANY, STARTUP).stream()
+ .forEach(bean -> getReference(manager, bean.getBeanClass(), bean).toString());
// Start Camel contexts
for (CamelContext context : contexts) {
@@ -320,29 +391,30 @@ public class CdiCamelExtension implements Extension {
}
// Clean-up
- converters.clear();
- camelBeans.clear();
- eagerBeans.clear();
- producerBeans.clear();
- producerQualifiers.clear();
- contextNames.clear();
+ Stream.of(converters, camelBeans, eagerBeans, contextBeans, contextNames).forEach(Set::clear);
+ Stream.of(producerBeans, producerQualifiers).forEach(Map::clear);
}
private boolean addRouteToContext(Bean<?> routeBean, Bean<?> contextBean, BeanManager manager, AfterDeploymentValidation adv) {
try {
- CamelContext context = BeanManagerHelper.getReference(manager, CamelContext.class, contextBean);
+ CamelContext context = getReference(manager, CamelContext.class, contextBean);
try {
- Object route = BeanManagerHelper.getReference(manager, Object.class, routeBean);
+ Object route = 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!");
+ 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));
+ adv.addDeploymentProblem(
+ new InjectionException(
+ "Error adding routes of type [" + routeBean.getBeanClass().getName() + "] "
+ + "to Camel context [" + context.getName() + "]", cause));
}
} catch (Exception exception) {
adv.addDeploymentProblem(exception);
http://git-wip-us.apache.org/repos/asf/camel/blob/ba1172ad/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
index e1e6f62..341fefa 100644
--- 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
@@ -19,18 +19,26 @@ package org.apache.camel.cdi;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
+import java.util.StringJoiner;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
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.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.InjectionPoint;
@@ -147,4 +155,91 @@ final class CdiSpiHelper {
qualifiers.add(ANY);
return qualifiers;
}
+
+ /**
+ * Generates a unique signature for {@link Bean}.
+ */
+ static String createBeanId(Bean<?> bean) {
+ return Stream.of(bean.getName(),
+ bean.getScope().getName(),
+ createAnnotationCollectionId(bean.getQualifiers()),
+ createTypeCollectionId(bean.getTypes()))
+ .filter(s -> s != null)
+ .collect(Collectors.joining(","));
+ }
+
+ /**
+ * Generates a unique signature of a collection of types.
+ */
+ private static String createTypeCollectionId(Collection<? extends Type> types) {
+ return types.stream()
+ .sorted((t1, t2) -> createTypeId(t1).compareTo(createTypeId(t2)))
+ .map(CdiSpiHelper::createTypeId)
+ .collect(Collectors.joining(",", "[", "]"));
+ }
+
+ /**
+ * Generates a unique signature for a {@link Type}.
+ */
+ private static String createTypeId(Type type) {
+ if (type instanceof Class<?>) {
+ return Class.class.cast(type).getName();
+ }
+
+ if (type instanceof ParameterizedType) {
+ return createTypeId(((ParameterizedType) type).getRawType())
+ + Stream.of(((ParameterizedType) type).getActualTypeArguments())
+ .map(CdiSpiHelper::createTypeId)
+ .collect(Collectors.joining(",", "<", ">"));
+ }
+
+ if (type instanceof TypeVariable<?>) {
+ return TypeVariable.class.cast(type).getName();
+ }
+
+ if (type instanceof GenericArrayType) {
+ return createTypeId(GenericArrayType.class.cast(type).getGenericComponentType());
+ }
+
+ throw new UnsupportedOperationException("Unable to create type id for type [" + type + "]");
+ }
+
+ /**
+ * Generates a unique signature for a collection of annotations.
+ */
+ private static String createAnnotationCollectionId(Collection<Annotation> annotations) {
+ if (annotations.isEmpty()) {
+ return "";
+ }
+
+ return annotations.stream()
+ .sorted((a1, a2) -> a1.annotationType().getName().compareTo(a2.annotationType().getName()))
+ .map(CdiSpiHelper::createAnnotationId)
+ .collect(Collectors.joining(",", "[", "]"));
+ }
+
+ /**
+ * Generates a unique signature for an {@link Annotation}.
+ */
+ private static String createAnnotationId(Annotation annotation) {
+ Method[] methods = AccessController.doPrivileged(
+ (PrivilegedAction<Method[]>) () -> annotation.annotationType().getDeclaredMethods());
+
+ return Stream.of(methods)
+ .sorted((m1, m2) -> m1.getName().compareTo(m2.getName()))
+ .collect(() -> new StringJoiner(",", "@(", ")"),
+ (joiner, method) -> {
+ try {
+ joiner
+ .add(method.getName()).add("=")
+ .add(method.invoke(annotation).toString());
+ } catch (NullPointerException | IllegalArgumentException | IllegalAccessException | InvocationTargetException cause) {
+ throw new RuntimeException(
+ "Error while accessing member [" + method.getName() + "]"
+ + " of annotation [" + annotation.annotationType().getName() + "]", cause);
+ }
+ },
+ StringJoiner::merge)
+ .toString();
+ }
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/camel/blob/ba1172ad/components/camel-cdi/src/main/java/org/apache/camel/cdi/ImportResource.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/ImportResource.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/ImportResource.java
new file mode 100644
index 0000000..b21c757
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/ImportResource.java
@@ -0,0 +1,29 @@
+/**
+ * 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;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+public @interface ImportResource {
+
+ String[] value() default {};
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/ba1172ad/components/camel-cdi/src/main/java/org/apache/camel/cdi/ListParameterizedType.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/ListParameterizedType.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/ListParameterizedType.java
new file mode 100644
index 0000000..e177e47
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/ListParameterizedType.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.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.List;
+
+final class ListParameterizedType implements ParameterizedType {
+
+ private final Type argument;
+
+ ListParameterizedType(Type argument) {
+ this.argument = argument;
+ }
+
+ @Override
+ public Type[] getActualTypeArguments() {
+ return new Type[]{argument};
+ }
+
+ @Override
+ public Type getRawType() {
+ return List.class;
+ }
+
+ @Override
+ public Type getOwnerType() {
+ return null;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/camel/blob/ba1172ad/components/camel-cdi/src/main/java/org/apache/camel/cdi/NamedLiteral.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/NamedLiteral.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/NamedLiteral.java
new file mode 100755
index 0000000..c8e1a66
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/NamedLiteral.java
@@ -0,0 +1,41 @@
+/**
+ * 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.util.AnnotationLiteral;
+import javax.inject.Named;
+
+@Vetoed
+final class NamedLiteral extends AnnotationLiteral<Named> implements Named {
+
+ private static final long serialVersionUID = 1L;
+
+ private final String name;
+
+ private NamedLiteral(String name) {
+ this.name = name;
+ }
+
+ public static Named of(String name) {
+ return new NamedLiteral(name);
+ }
+
+ @Override
+ public String value() {
+ return name;
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/ba1172ad/components/camel-cdi/src/main/java/org/apache/camel/cdi/ResourceHelper.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/ResourceHelper.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/ResourceHelper.java
new file mode 100644
index 0000000..0cfef7e
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/ResourceHelper.java
@@ -0,0 +1,38 @@
+/**
+ * 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.net.URL;
+
+@Vetoed
+final class ResourceHelper {
+
+ private ResourceHelper() {
+ }
+
+ static URL getResource(String path) {
+ ClassLoader loader = Thread.currentThread().getContextClassLoader();
+ if (loader == null) {
+ loader = ResourceHelper.class.getClassLoader();
+ }
+ if (loader == null) {
+ loader = ClassLoader.getSystemClassLoader();
+ }
+
+ return loader.getResource(path);
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/ba1172ad/components/camel-cdi/src/main/java/org/apache/camel/cdi/Startup.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/Startup.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/Startup.java
new file mode 100755
index 0000000..936fdd6
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/Startup.java
@@ -0,0 +1,39 @@
+/**
+ * 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;
+
+@Qualifier
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
+@interface Startup {
+
+ @Vetoed
+ final class Literal extends AnnotationLiteral<Startup> implements Startup {
+
+ static final Startup STARTUP = new Literal();
+
+ private Literal() {
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/ba1172ad/components/camel-cdi/src/main/java/org/apache/camel/cdi/SyntheticAnnotated.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/SyntheticAnnotated.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/SyntheticAnnotated.java
new file mode 100644
index 0000000..803e41c
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/SyntheticAnnotated.java
@@ -0,0 +1,82 @@
+/**
+ * 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.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import javax.enterprise.inject.spi.Annotated;
+
+@Vetoed
+final class SyntheticAnnotated implements Annotated {
+
+ private final Class<?> type;
+
+ private final Set<Type> types;
+
+ private final Set<Annotation> annotations;
+
+ SyntheticAnnotated(Class<?> type, Set<Type> types, Annotation... annotations) {
+ this(type, types, Arrays.asList(annotations));
+ }
+
+ SyntheticAnnotated(Class<?> type, Set<Type> types, Collection<Annotation> annotations) {
+ this.type = type;
+ this.types = types;
+ this.annotations = new HashSet<>(annotations);
+ }
+
+ <A extends Annotation> void addAnnotation(A annotation) {
+ annotations.add(annotation);
+ }
+
+ @Override
+ public Type getBaseType() {
+ return type;
+ }
+
+ @Override
+ public Set<Type> getTypeClosure() {
+ return Collections.unmodifiableSet(types);
+ }
+
+ @Override
+ public Set<Annotation> getAnnotations() {
+ return Collections.unmodifiableSet(annotations);
+ }
+
+ @Override
+ public <T extends Annotation> T getAnnotation(Class<T> type) {
+ return annotations.stream()
+ .filter(a -> a.annotationType().equals(type))
+ .findAny()
+ .map(type::cast)
+ .orElse(null);
+ }
+
+ @Override
+ public boolean isAnnotationPresent(Class<? extends Annotation> type) {
+ return annotations.stream()
+ .filter(a -> a.annotationType().equals(type))
+ .findAny()
+ .isPresent();
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/ba1172ad/components/camel-cdi/src/main/java/org/apache/camel/cdi/SyntheticBean.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/SyntheticBean.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/SyntheticBean.java
new file mode 100644
index 0000000..bd280f9
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/SyntheticBean.java
@@ -0,0 +1,102 @@
+/**
+ * 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.Collections;
+import java.util.Set;
+import java.util.StringJoiner;
+import java.util.function.Function;
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.CreationException;
+import javax.enterprise.inject.InjectionException;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.enterprise.inject.spi.InjectionPoint;
+import javax.enterprise.inject.spi.InjectionTarget;
+import javax.enterprise.inject.spi.PassivationCapable;
+
+import static org.apache.camel.cdi.CdiSpiHelper.createBeanId;
+
+class SyntheticBean<T> extends SyntheticBeanAttributes<T> implements Bean<T>, PassivationCapable {
+
+ private final Class<?> type;
+
+ private final InjectionTarget<T> target;
+
+ private final Function<Bean<T>, String> toString;
+
+ SyntheticBean(BeanManager manager, SyntheticAnnotated annotated, Class<?> type, InjectionTarget<T> target, Function<Bean<T>, String> toString) {
+ super(manager, annotated);
+ this.type = type;
+ this.target = target;
+ this.toString = toString;
+ }
+
+ @Override
+ public Class<?> getBeanClass() {
+ return type;
+ }
+
+ @Override
+ public T create(CreationalContext<T> creationalContext) {
+ try {
+ T instance = target.produce(creationalContext);
+ target.inject(instance, creationalContext);
+ target.postConstruct(instance);
+ return instance;
+ } catch (Exception cause) {
+ throw new CreationException("Error while instantiating " + this, cause);
+ }
+ }
+
+ @Override
+ public void destroy(T instance, CreationalContext<T> creationalContext) {
+ try {
+ target.preDestroy(instance);
+ target.dispose(instance);
+ } catch (Exception cause) {
+ throw new InjectionException("Error while destroying " + this, cause);
+ } finally {
+ creationalContext.release();
+ }
+ }
+
+ @Override
+ public Set<InjectionPoint> getInjectionPoints() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public boolean isNullable() {
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toString.apply(this);
+ }
+
+ @Override
+ public String getId() {
+ return new StringJoiner("%")
+ .add("CAMEL-CDI")
+ .add(getClass().getSimpleName())
+ .add(type.getName())
+ .add(createBeanId(this))
+ .toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/ba1172ad/components/camel-cdi/src/main/java/org/apache/camel/cdi/SyntheticBeanAttributes.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/SyntheticBeanAttributes.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/SyntheticBeanAttributes.java
new file mode 100644
index 0000000..f59caf1
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/SyntheticBeanAttributes.java
@@ -0,0 +1,77 @@
+/**
+ * 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.Collections;
+import java.util.Set;
+import java.util.stream.Collectors;
+import javax.enterprise.context.Dependent;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.inject.Named;
+
+class SyntheticBeanAttributes<T> {
+
+ private final BeanManager manager;
+
+ private final SyntheticAnnotated annotated;
+
+ SyntheticBeanAttributes(BeanManager manager, SyntheticAnnotated annotated) {
+ this.manager = manager;
+ this.annotated = annotated;
+ }
+
+ <A extends Annotation> void addQualifier(A qualifier) {
+ annotated.addAnnotation(qualifier);
+ }
+
+ public Class<? extends Annotation> getScope() {
+ return annotated.getAnnotations().stream()
+ .map(Annotation::annotationType)
+ .filter(manager::isScope)
+ .findAny()
+ .orElse(Dependent.class);
+ }
+
+ public Set<Annotation> getQualifiers() {
+ return annotated.getAnnotations().stream()
+ .filter(a -> manager.isQualifier(a.annotationType()))
+ .collect(Collectors.toSet());
+ }
+
+ public String getName() {
+ return annotated.getAnnotations().stream()
+ .filter(a -> Named.class.equals(a.annotationType()))
+ .map(Named.class::cast)
+ .map(Named::value)
+ .findFirst()
+ .orElse(null);
+ }
+
+ public Set<Class<? extends Annotation>> getStereotypes() {
+ return Collections.emptySet();
+ }
+
+ public Set<Type> getTypes() {
+ return annotated.getTypeClosure();
+ }
+
+ public boolean isAlternative() {
+ return false;
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/ba1172ad/components/camel-cdi/src/main/java/org/apache/camel/cdi/SyntheticInjectionTarget.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/SyntheticInjectionTarget.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/SyntheticInjectionTarget.java
new file mode 100644
index 0000000..76ee6a3
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/SyntheticInjectionTarget.java
@@ -0,0 +1,81 @@
+/**
+ * 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.Collections;
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.spi.InjectionPoint;
+import javax.enterprise.inject.spi.InjectionTarget;
+
+@Vetoed
+class SyntheticInjectionTarget<T> implements InjectionTarget<T> {
+
+ private final Supplier<T> produce;
+
+ private final Consumer<T> postConstruct;
+
+ private final Consumer<T> preDestroy;
+
+ SyntheticInjectionTarget(Supplier<T> produce) {
+ this(produce, t -> {
+ });
+ }
+
+ SyntheticInjectionTarget(Supplier<T> produce, Consumer<T> postConstruct) {
+ this(produce, postConstruct, t -> {
+ });
+ }
+
+ SyntheticInjectionTarget(Supplier<T> produce, Consumer<T> postConstruct, Consumer<T> preDestroy) {
+ this.produce = produce;
+ this.postConstruct = postConstruct;
+ this.preDestroy = preDestroy;
+ }
+
+ @Override
+ public void inject(T instance, CreationalContext<T> ctx) {
+
+ }
+
+ @Override
+ public void postConstruct(T instance) {
+ postConstruct.accept(instance);
+ }
+
+ @Override
+ public void preDestroy(T instance) {
+ preDestroy.accept(instance);
+ }
+
+ @Override
+ public T produce(CreationalContext<T> ctx) {
+ return produce.get();
+ }
+
+ @Override
+ public void dispose(T instance) {
+
+ }
+
+ @Override
+ public Set<InjectionPoint> getInjectionPoints() {
+ return Collections.emptySet();
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/ba1172ad/components/camel-cdi/src/main/java/org/apache/camel/cdi/XmlCdiBeanFactory.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/XmlCdiBeanFactory.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/XmlCdiBeanFactory.java
new file mode 100644
index 0000000..9caa6e5
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/XmlCdiBeanFactory.java
@@ -0,0 +1,464 @@
+/**
+ * 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.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.net.URL;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static java.lang.String.format;
+
+import javax.enterprise.inject.CreationException;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.xml.bind.JAXBException;
+
+import org.apache.camel.cdi.xml.ApplicationContextFactoryBean;
+import org.apache.camel.cdi.xml.BeanManagerAware;
+import org.apache.camel.cdi.xml.CamelContextFactoryBean;
+import org.apache.camel.cdi.xml.ErrorHandlerDefinition;
+import org.apache.camel.cdi.xml.ErrorHandlerType;
+import org.apache.camel.cdi.xml.ImportDefinition;
+import org.apache.camel.cdi.xml.ProxyFactoryDefinition;
+import org.apache.camel.cdi.xml.RestContextDefinition;
+import org.apache.camel.cdi.xml.RouteContextDefinition;
+import org.apache.camel.cdi.xml.ServiceExporterDefinition;
+import org.apache.camel.core.xml.AbstractCamelFactoryBean;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.model.RouteDefinition;
+import org.apache.camel.model.RoutesDefinition;
+import org.apache.camel.model.rest.RestDefinition;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.apache.camel.cdi.AnyLiteral.ANY;
+import static org.apache.camel.cdi.ApplicationScopedLiteral.APPLICATION_SCOPED;
+import static org.apache.camel.cdi.DefaultLiteral.DEFAULT;
+import static org.apache.camel.cdi.Startup.Literal.STARTUP;
+import static org.apache.camel.util.ObjectHelper.isNotEmpty;
+
+final class XmlCdiBeanFactory {
+
+ private final Logger logger = LoggerFactory.getLogger(XmlCdiBeanFactory.class);
+
+ private final BeanManager manager;
+
+ private final CdiCamelEnvironment environment;
+
+ private final CdiCamelExtension extension;
+
+ private XmlCdiBeanFactory(BeanManager manager, CdiCamelEnvironment environment, CdiCamelExtension extension) {
+ this.manager = manager;
+ this.environment = environment;
+ this.extension = extension;
+ }
+
+ static XmlCdiBeanFactory with(BeanManager manager, CdiCamelEnvironment environment, CdiCamelExtension extension) {
+ return new XmlCdiBeanFactory(manager, environment, extension);
+ }
+
+ Set<SyntheticBean<?>> beansFrom(String path) throws JAXBException, IOException {
+ URL url = ResourceHelper.getResource(path);
+ if (url == null) {
+ logger.warn("Unable to locate resource [{}] for import!", path);
+ return Collections.emptySet();
+ }
+ return beansFrom(url);
+ }
+
+ Set<SyntheticBean<?>> beansFrom(URL url) throws JAXBException, IOException {
+ try (InputStream xml = url.openStream()) {
+ Object node = XmlCdiJaxbContexts.CAMEL_CDI.instance()
+ .createUnmarshaller()
+ .unmarshal(xml);
+ if (node instanceof RoutesDefinition) {
+ RoutesDefinition routes = (RoutesDefinition) node;
+ return Collections.singleton(routesDefinitionBean(routes, url));
+ } else if (node instanceof ApplicationContextFactoryBean) {
+ ApplicationContextFactoryBean app = (ApplicationContextFactoryBean) node;
+ Set<SyntheticBean<?>> beans = new HashSet<>();
+ for (CamelContextFactoryBean factory : app.getContexts()) {
+ SyntheticBean<?> bean = camelContextBean(factory, url);
+ beans.add(bean);
+ beans.addAll(camelContextBeans(factory, bean, url));
+ }
+ for (ErrorHandlerDefinition definition : app.getErrorHandlers()) {
+ beans.add(errorHandlerBean(definition, url));
+ }
+ for (ImportDefinition definition : app.getImports()) {
+ // Get the base URL as imports are relative to this
+ String path = url.getFile().substring(0, url.getFile().lastIndexOf('/'));
+ String base = url.getProtocol() + "://" + url.getHost() + path;
+ beans.addAll(beansFrom(base + "/" + definition.getResource()));
+ }
+ for (RestContextDefinition factory : app.getRestContexts()) {
+ beans.add(restContextBean(factory, url));
+ }
+ for (RouteContextDefinition factory : app.getRouteContexts()) {
+ beans.add(routeContextBean(factory, url));
+ }
+ for (AbstractCamelFactoryBean<?> factory : app.getBeans()) {
+ if (factory.getId() != null) {
+ beans.add(camelContextBean(null, factory, url));
+ }
+ }
+ return beans;
+ } else if (node instanceof CamelContextFactoryBean) {
+ CamelContextFactoryBean factory = (CamelContextFactoryBean) node;
+ Set<SyntheticBean<?>> beans = new HashSet<>();
+ SyntheticBean<?> bean = camelContextBean(factory, url);
+ beans.add(bean);
+ beans.addAll(camelContextBeans(factory, bean, url));
+ return beans;
+ } else if (node instanceof RestContextDefinition) {
+ RestContextDefinition factory = (RestContextDefinition) node;
+ return Collections.singleton(restContextBean(factory, url));
+ } else if (node instanceof RouteContextDefinition) {
+ RouteContextDefinition factory = (RouteContextDefinition) node;
+ return Collections.singleton(routeContextBean(factory, url));
+ }
+ }
+ return Collections.emptySet();
+ }
+
+ private SyntheticBean<?> camelContextBean(CamelContextFactoryBean factory, URL url) {
+ Set<Annotation> annotations = new HashSet<>();
+ annotations.add(ANY);
+ if (factory.getId() != null) {
+ Collections.addAll(annotations,
+ ContextName.Literal.of(factory.getId()), NamedLiteral.of(factory.getId()));
+ } else {
+ annotations.add(DEFAULT);
+ factory.setImplicitId(true);
+ factory.setId(new CdiCamelContextNameStrategy().getNextName());
+ }
+
+ annotations.add(APPLICATION_SCOPED);
+ SyntheticAnnotated annotated = new SyntheticAnnotated(DefaultCamelContext.class,
+ manager.createAnnotatedType(DefaultCamelContext.class).getTypeClosure(),
+ annotations);
+ return new SyntheticBean<>(manager, annotated, DefaultCamelContext.class,
+ environment.camelContextInjectionTarget(
+ new SyntheticInjectionTarget<>(() -> {
+ DefaultCamelContext context = new DefaultCamelContext();
+ factory.setContext(context);
+ factory.setBeanManager(manager);
+ return context;
+ }, context -> {
+ try {
+ factory.afterPropertiesSet();
+ } catch (Exception cause) {
+ throw new CreationException(cause);
+ }
+ }),
+ annotated, manager, extension), bean ->
+ "imported Camel context with "
+ + (factory.isImplicitId() ? "implicit " : "")
+ + "id [" + factory.getId() + "] "
+ + "from resource [" + url + "] "
+ + "with qualifiers " + bean.getQualifiers());
+ }
+
+ private Set<SyntheticBean<?>> camelContextBeans(CamelContextFactoryBean factory, Bean<?> context, URL url) {
+ Set<SyntheticBean<?>> beans = new HashSet<>();
+
+ // TODO: WARN log if the definition doesn't have an id
+ if (factory.getBeans() != null) {
+ factory.getBeans().stream()
+ .filter(bean -> bean.getId() != null)
+ .map(bean -> camelContextBean(context, bean, url))
+ .forEach(beans::add);
+ }
+
+ // TODO: define in beans
+ if (factory.getEndpoints() != null) {
+ factory.getEndpoints().stream()
+ .filter(endpoint -> endpoint.getId() != null)
+ .map(endpoint -> camelContextBean(context, endpoint, url))
+ .forEach(beans::add);
+ }
+
+ if (factory.getErrorHandlers() != null) {
+ factory.getErrorHandlers().stream()
+ .filter(handler -> handler.getId() != null)
+ .map(handler -> errorHandlerBean(handler, url))
+ .forEach(beans::add);
+ }
+
+ if (factory.getExports() != null) {
+ factory.getExports().stream()
+ .map(export -> serviceExporterBean(context, export, url))
+ .forEach(beans::add);
+ }
+
+ if (factory.getProxies() != null) {
+ factory.getProxies().stream()
+ .filter(proxy -> proxy.getId() != null)
+ .map(proxy -> proxyFactoryBean(context, proxy, url))
+ .forEach(beans::add);
+ }
+
+ // TODO: define in beans
+ if (factory.getRedeliveryPolicies() != null) {
+ factory.getRedeliveryPolicies().stream()
+ .filter(policy -> policy.getId() != null)
+ .map(policy -> camelContextBean(context, policy, url))
+ .forEach(beans::add);
+ }
+
+ return beans;
+ }
+
+ private SyntheticBean<?> camelContextBean(Bean<?> context, AbstractCamelFactoryBean<?> factory, URL url) {
+ if (factory instanceof BeanManagerAware) {
+ ((BeanManagerAware) factory).setBeanManager(manager);
+ }
+
+ Set<Annotation> annotations = new HashSet<>();
+ annotations.add(ANY);
+ // FIXME: should add @ContextName if the Camel context bean has it
+ annotations.add(factory.getId() != null ? NamedLiteral.of(factory.getId()) : DEFAULT);
+
+ // TODO: should that be @Singleton to enable injection points with bean instance type?
+ if (factory.isSingleton()) {
+ annotations.add(APPLICATION_SCOPED);
+ }
+
+ return new SyntheticBean<>(manager,
+ new SyntheticAnnotated(factory.getObjectType(),
+ manager.createAnnotatedType(factory.getObjectType()).getTypeClosure(),
+ annotations),
+ factory.getObjectType(),
+ new XmlFactoryBeanInjectionTarget<>(manager, factory, context), bean ->
+ "imported bean [" + factory.getId() + "] "
+ + "from resource [" + url + "] "
+ + "with qualifiers " + bean.getQualifiers());
+ }
+
+ private SyntheticBean<?> proxyFactoryBean(Bean<?> context, ProxyFactoryDefinition proxy, URL url) {
+ if (ObjectHelper.isEmpty(proxy.getServiceRef()) && ObjectHelper.isEmpty(proxy.getServiceUrl())) {
+ throw new CreationException(
+ format("Missing [%s] or [%s] attribute for imported bean [%s] from resource [%s]",
+ "serviceRef", "serviceUrl", proxy.getId(), url));
+ }
+
+ return new XmlProxyFactoryBean<>(manager,
+ new SyntheticAnnotated(proxy.getServiceInterface(),
+ manager.createAnnotatedType(proxy.getServiceInterface()).getTypeClosure(),
+ APPLICATION_SCOPED, ANY, NamedLiteral.of(proxy.getId())),
+ proxy.getServiceInterface(), bean ->
+ "imported bean [" + proxy.getId() + "] "
+ + "from resource [" + url + "] "
+ + "with qualifiers " + bean.getQualifiers(),
+ context, proxy);
+ }
+
+ private SyntheticBean<?> serviceExporterBean(Bean<?> context, ServiceExporterDefinition exporter, URL url) {
+ // TODO: replace with CreationException
+ Objects.requireNonNull(exporter.getServiceRef(),
+ () -> format("Missing [%s] attribute for imported bean [%s] from resource [%s]",
+ "serviceRef", Objects.toString(exporter.getId(), "export"), url));
+
+ Class<?> type;
+ if (exporter.getServiceInterface() != null) {
+ type = exporter.getServiceInterface();
+ } else {
+ Bean<?> bean = manager.resolve(manager.getBeans(exporter.getServiceRef()));
+ if (bean != null) {
+ type = bean.getBeanClass();
+ } else {
+ Objects.requireNonNull(exporter.getServiceInterface(),
+ () -> format("Missing [%s] attribute for imported bean [%s] from resource [%s]",
+ "serviceInterface", Objects.toString(exporter.getId(), "export"), url));
+ type = exporter.getServiceInterface();
+ }
+ }
+
+ Set<Type> types = new HashSet<>(manager.createAnnotatedType(type).getTypeClosure());
+ // Weld does not add Object.class for interfaces as they do not extend Object.class.
+ // Though let's add it so that it's possible to lookup by bean type Object.class
+ // beans whose bean class is an interface (for startup beans).
+ types.add(Object.class);
+
+ return new XmlServiceExporterBean<>(manager,
+ new SyntheticAnnotated(type, types, APPLICATION_SCOPED, ANY, STARTUP,
+ exporter.getId() != null ? NamedLiteral.of(exporter.getId()) : DEFAULT),
+ type, bean ->
+ "imported bean [" + Objects.toString(exporter.getId(), "export") + "] "
+ + "from resource [" + url + "] "
+ + "with qualifiers " + bean.getQualifiers(),
+ context, exporter);
+ }
+
+ private SyntheticBean<?> restContextBean(RestContextDefinition definition, URL url) {
+ Objects.requireNonNull(definition.getId(),
+ () -> format("Missing [%s] attribute for imported bean [%s] from resource [%s]",
+ "id", "restContext", url));
+
+ return new SyntheticBean<>(manager,
+ new SyntheticAnnotated(List.class,
+ Stream.of(List.class, new ListParameterizedType(RestDefinition.class))
+ .collect(Collectors.toSet()),
+ ANY, NamedLiteral.of(definition.getId())),
+ List.class,
+ new SyntheticInjectionTarget<>(definition::getRests), bean ->
+ "imported rest context with "
+ + "id [" + definition.getId() + "] "
+ + "from resource [" + url + "] "
+ + "with qualifiers " + bean.getQualifiers());
+ }
+
+ private SyntheticBean<?> routeContextBean(RouteContextDefinition definition, URL url) {
+ Objects.requireNonNull(definition.getId(),
+ () -> format("Missing [%s] attribute for imported bean [%s] from resource [%s]",
+ "id", "routeContext", url));
+
+ return new SyntheticBean<>(manager,
+ new SyntheticAnnotated(List.class,
+ Stream.of(List.class, new ListParameterizedType(RouteDefinition.class))
+ .collect(Collectors.toSet()),
+ ANY, NamedLiteral.of(definition.getId())),
+ List.class,
+ new SyntheticInjectionTarget<>(definition::getRoutes), bean ->
+ "imported route context with "
+ + "id [" + definition.getId() + "] "
+ + "from resource [" + url + "] "
+ + "with qualifiers " + bean.getQualifiers());
+ }
+
+ private SyntheticBean<?> routesDefinitionBean(RoutesDefinition definition, URL url) {
+ return new SyntheticBean<>(manager,
+ // TODO: should be @Named if the id is set
+ new SyntheticAnnotated(RoutesDefinition.class,
+ manager.createAnnotatedType(RoutesDefinition.class).getTypeClosure(),
+ ANY, DEFAULT),
+ RoutesDefinition.class,
+ new SyntheticInjectionTarget<>(() -> definition), bean ->
+ "imported routes definition "
+ + (definition.getId() != null ? "[" + definition.getId() + "] " : "")
+ + "from resource [" + url + "]");
+ }
+
+ private SyntheticBean<?> errorHandlerBean(ErrorHandlerDefinition definition, URL url) {
+ ErrorHandlerType type = definition.getType();
+
+ // Validate attributes according to type
+ if (isNotEmpty(definition.getDeadLetterUri())
+ && !type.equals(ErrorHandlerType.DeadLetterChannel)) {
+ throw attributeNotSupported("deadLetterUri", type, definition.getId());
+ }
+
+ if (isNotEmpty(definition.getDeadLetterHandleNewException())
+ && !type.equals(ErrorHandlerType.DeadLetterChannel)) {
+ throw attributeNotSupported("deadLetterHandleNewException", type, definition.getId());
+ }
+
+ if (isNotEmpty(definition.getTransactionTemplateRef())
+ && !type.equals(ErrorHandlerType.TransactionErrorHandler)) {
+ throw attributeNotSupported("transactionTemplateRef", type, definition.getId());
+ }
+
+ if (isNotEmpty(definition.getTransactionManagerRef())
+ && !type.equals(ErrorHandlerType.TransactionErrorHandler)) {
+ throw attributeNotSupported("transactionManagerRef", type, definition.getId());
+ }
+
+ if (isNotEmpty(definition.getRollbackLoggingLevel())
+ && (!type.equals(ErrorHandlerType.TransactionErrorHandler))) {
+ throw attributeNotSupported("rollbackLoggingLevel", type, definition.getId());
+ }
+
+ if (isNotEmpty(definition.getUseOriginalMessage())
+ && (type.equals(ErrorHandlerType.LoggingErrorHandler)
+ || type.equals(ErrorHandlerType.NoErrorHandler))) {
+ throw attributeNotSupported("useOriginalMessage", type, definition.getId());
+ }
+
+ if (isNotEmpty(definition.getOnRedeliveryRef())
+ && (type.equals(ErrorHandlerType.LoggingErrorHandler)
+ || type.equals(ErrorHandlerType.NoErrorHandler))) {
+ throw attributeNotSupported("onRedeliveryRef", type, definition.getId());
+ }
+
+ if (isNotEmpty(definition.getOnExceptionOccurredRef())
+ && (type.equals(ErrorHandlerType.LoggingErrorHandler)
+ || type.equals(ErrorHandlerType.NoErrorHandler))) {
+ throw attributeNotSupported("onExceptionOccurredRef", type, definition.getId());
+ }
+
+ if (isNotEmpty(definition.getOnPrepareFailureRef())
+ && (type.equals(ErrorHandlerType.TransactionErrorHandler)
+ || type.equals(ErrorHandlerType.LoggingErrorHandler)
+ || type.equals(ErrorHandlerType.NoErrorHandler))) {
+ throw attributeNotSupported("onPrepareFailureRef", type, definition.getId());
+ }
+
+ if (isNotEmpty(definition.getRetryWhileRef())
+ && (type.equals(ErrorHandlerType.LoggingErrorHandler)
+ || type.equals(ErrorHandlerType.NoErrorHandler))) {
+ throw attributeNotSupported("retryWhileRef", type, definition.getId());
+ }
+
+ if (isNotEmpty(definition.getOnRedeliveryRef())
+ && (type.equals(ErrorHandlerType.LoggingErrorHandler)
+ || type.equals(ErrorHandlerType.NoErrorHandler))) {
+ throw attributeNotSupported("redeliveryPolicyRef", type, definition.getId());
+ }
+
+ if (isNotEmpty(definition.getExecutorServiceRef())
+ && (type.equals(ErrorHandlerType.LoggingErrorHandler)
+ || type.equals(ErrorHandlerType.NoErrorHandler))) {
+ throw attributeNotSupported("executorServiceRef", type, definition.getId());
+ }
+
+ if (isNotEmpty(definition.getLogName())
+ && (!type.equals(ErrorHandlerType.LoggingErrorHandler))) {
+ throw attributeNotSupported("logName", type, definition.getId());
+ }
+
+ if (isNotEmpty(definition.getLevel())
+ && (!type.equals(ErrorHandlerType.LoggingErrorHandler))) {
+ throw attributeNotSupported("level", type, definition.getId());
+ }
+
+ return new XmlErrorHandlerFactoryBean(manager,
+ new SyntheticAnnotated(type.getTypeAsClass(),
+ manager.createAnnotatedType(type.getTypeAsClass()).getTypeClosure(),
+ ANY, NamedLiteral.of(definition.getId())),
+ type.getTypeAsClass(), bean -> "imported error handler with "
+ + "id [" + definition.getId() + "] "
+ + "from resource [" + url + "] "
+ + "with qualifiers " + bean.getQualifiers(),
+ definition);
+ }
+
+ private static CreationException attributeNotSupported(String attribute, ErrorHandlerType type, String id) {
+ return new CreationException(
+ format("Attribute [%s] is not supported by error handler type [%s], in error handler with id [%s]",
+ attribute, type, id));
+ }
+}
http://git-wip-us.apache.org/repos/asf/camel/blob/ba1172ad/components/camel-cdi/src/main/java/org/apache/camel/cdi/XmlCdiJaxbContexts.java
----------------------------------------------------------------------
diff --git a/components/camel-cdi/src/main/java/org/apache/camel/cdi/XmlCdiJaxbContexts.java b/components/camel-cdi/src/main/java/org/apache/camel/cdi/XmlCdiJaxbContexts.java
new file mode 100644
index 0000000..7803324
--- /dev/null
+++ b/components/camel-cdi/src/main/java/org/apache/camel/cdi/XmlCdiJaxbContexts.java
@@ -0,0 +1,44 @@
+/**
+ * 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.Arrays;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+
+import org.apache.camel.cdi.xml.ApplicationContextFactoryBean;
+import org.apache.camel.model.Constants;
+
+enum XmlCdiJaxbContexts {
+
+ CAMEL_CDI(Constants.JAXB_CONTEXT_PACKAGES, ApplicationContextFactoryBean.class.getPackage().getName());
+
+ private final JAXBContext context;
+
+ XmlCdiJaxbContexts(String... packages) {
+ try {
+ context = JAXBContext.newInstance(String.join(":", packages));
+ } catch (JAXBException cause) {
+ throw new IllegalStateException("Error while creating JAXB context for packages " + Arrays.toString(packages), cause);
+ }
+ }
+
+ JAXBContext instance() {
+ return context;
+ }
+}